diff --git a/TypeScript b/TypeScript index 2379000..c302893 160000 --- a/TypeScript +++ b/TypeScript @@ -1 +1 @@ -Subproject commit 2379000f8a9b2bbd1fface413387927ea2b31876 +Subproject commit c302893a6201cbd822d6040b8361ad7a0ee506fa diff --git a/bin/lib.d.ts b/bin/lib.d.ts index a65770c..3a7f0bb 100644 --- a/bin/lib.d.ts +++ b/bin/lib.d.ts @@ -1076,6 +1076,12 @@ interface ReadonlyArray { * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. */ map(callbackfn: (value: T, index: number, array: ReadonlyArray) => U, thisArg?: any): U[]; + /** + * Returns the elements of an array that meet the condition specified in a callback function. + * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. + */ + filter(callbackfn: (value: T, index: number, array: ReadonlyArray) => value is S, thisArg?: any): S[]; /** * Returns the elements of an array that meet the condition specified in a callback function. * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array. @@ -1281,13 +1287,44 @@ declare type PromiseConstructorLike = new (executor: (resolve: (value?: T | P interface PromiseLike { /** - * Attaches callbacks for the resolution and/or rejection of the Promise. - * @param onfulfilled The callback to execute when the Promise is resolved. - * @param onrejected The callback to execute when the Promise is rejected. - * @returns A Promise for the completion of which ever callback is executed. - */ - then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => TResult | PromiseLike): PromiseLike; - then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => void): PromiseLike; + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then( + onfulfilled?: ((value: T) => T | PromiseLike) | undefined | null, + onrejected?: ((reason: any) => T | PromiseLike) | undefined | null): PromiseLike; + + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then( + onfulfilled: ((value: T) => T | PromiseLike) | undefined | null, + onrejected: (reason: any) => TResult | PromiseLike): PromiseLike; + + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then( + onfulfilled: (value: T) => TResult | PromiseLike, + onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): PromiseLike; + + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then( + onfulfilled: (value: T) => TResult1 | PromiseLike, + onrejected: (reason: any) => TResult2 | PromiseLike): PromiseLike; } interface ArrayLike { @@ -1547,7 +1584,7 @@ interface Int8Array { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -1555,7 +1592,7 @@ interface Int8Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -1820,7 +1857,7 @@ interface Uint8Array { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -1828,7 +1865,7 @@ interface Uint8Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -2094,7 +2131,7 @@ interface Uint8ClampedArray { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -2102,7 +2139,7 @@ interface Uint8ClampedArray { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -2367,7 +2404,7 @@ interface Int16Array { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -2375,7 +2412,7 @@ interface Int16Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -2641,7 +2678,7 @@ interface Uint16Array { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -2649,7 +2686,7 @@ interface Uint16Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -2914,7 +2951,7 @@ interface Int32Array { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -2922,7 +2959,7 @@ interface Int32Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -3187,7 +3224,7 @@ interface Uint32Array { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -3195,7 +3232,7 @@ interface Uint32Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -3460,7 +3497,7 @@ interface Float32Array { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -3468,7 +3505,7 @@ interface Float32Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -3734,7 +3771,7 @@ interface Float64Array { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -3742,7 +3779,7 @@ interface Float64Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -3959,12 +3996,9 @@ declare module Intl { resolvedOptions(): ResolvedCollatorOptions; } var Collator: { - new (locales?: string[], options?: CollatorOptions): Collator; - new (locale?: string, options?: CollatorOptions): Collator; - (locales?: string[], options?: CollatorOptions): Collator; - (locale?: string, options?: CollatorOptions): Collator; - supportedLocalesOf(locales: string[], options?: CollatorOptions): string[]; - supportedLocalesOf(locale: string, options?: CollatorOptions): string[]; + new (locales?: string | string[], options?: CollatorOptions): Collator; + (locales?: string | string[], options?: CollatorOptions): Collator; + supportedLocalesOf(locales: string | string[], options?: CollatorOptions): string[]; } interface NumberFormatOptions { @@ -3999,12 +4033,9 @@ declare module Intl { resolvedOptions(): ResolvedNumberFormatOptions; } var NumberFormat: { - new (locales?: string[], options?: NumberFormatOptions): NumberFormat; - new (locale?: string, options?: NumberFormatOptions): NumberFormat; - (locales?: string[], options?: NumberFormatOptions): NumberFormat; - (locale?: string, options?: NumberFormatOptions): NumberFormat; - supportedLocalesOf(locales: string[], options?: NumberFormatOptions): string[]; - supportedLocalesOf(locale: string, options?: NumberFormatOptions): string[]; + new (locales?: string | string[], options?: NumberFormatOptions): NumberFormat; + (locales?: string | string[], options?: NumberFormatOptions): NumberFormat; + supportedLocalesOf(locales: string | string[], options?: NumberFormatOptions): string[]; } interface DateTimeFormatOptions { @@ -4045,90 +4076,51 @@ declare module Intl { resolvedOptions(): ResolvedDateTimeFormatOptions; } var DateTimeFormat: { - new (locales?: string[], options?: DateTimeFormatOptions): DateTimeFormat; - new (locale?: string, options?: DateTimeFormatOptions): DateTimeFormat; - (locales?: string[], options?: DateTimeFormatOptions): DateTimeFormat; - (locale?: string, options?: DateTimeFormatOptions): DateTimeFormat; - supportedLocalesOf(locales: string[], options?: DateTimeFormatOptions): string[]; - supportedLocalesOf(locale: string, options?: DateTimeFormatOptions): string[]; + new (locales?: string | string[], options?: DateTimeFormatOptions): DateTimeFormat; + (locales?: string | string[], options?: DateTimeFormatOptions): DateTimeFormat; + supportedLocalesOf(locales: string | string[], options?: DateTimeFormatOptions): string[]; } } interface String { /** - * Determines whether two strings are equivalent in the current locale. + * Determines whether two strings are equivalent in the current or specified locale. * @param that String to compare to target string - * @param locales An array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. This parameter must conform to BCP 47 standards; see the Intl.Collator object for details. + * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. This parameter must conform to BCP 47 standards; see the Intl.Collator object for details. * @param options An object that contains one or more properties that specify comparison options. see the Intl.Collator object for details. */ - localeCompare(that: string, locales: string[], options?: Intl.CollatorOptions): number; - - /** - * Determines whether two strings are equivalent in the current locale. - * @param that String to compare to target string - * @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used. This parameter must conform to BCP 47 standards; see the Intl.Collator object for details. - * @param options An object that contains one or more properties that specify comparison options. see the Intl.Collator object for details. - */ - localeCompare(that: string, locale: string, options?: Intl.CollatorOptions): number; + localeCompare(that: string, locales?: string | string[], options?: Intl.CollatorOptions): number; } interface Number { /** * Converts a number to a string by using the current or specified locale. - * @param locales An array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. - * @param options An object that contains one or more properties that specify comparison options. - */ - toLocaleString(locales?: string[], options?: Intl.NumberFormatOptions): string; - - /** - * Converts a number to a string by using the current or specified locale. - * @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used. + * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. * @param options An object that contains one or more properties that specify comparison options. */ - toLocaleString(locale?: string, options?: Intl.NumberFormatOptions): string; + toLocaleString(locales?: string | string[], options?: Intl.NumberFormatOptions): string; } interface Date { /** * Converts a date and time to a string by using the current or specified locale. - * @param locales An array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. + * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. * @param options An object that contains one or more properties that specify comparison options. */ - toLocaleString(locales?: string[], options?: Intl.DateTimeFormatOptions): string; + toLocaleString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string; /** * Converts a date to a string by using the current or specified locale. - * @param locales An array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. + * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. * @param options An object that contains one or more properties that specify comparison options. */ - toLocaleDateString(locales?: string[], options?: Intl.DateTimeFormatOptions): string; + toLocaleDateString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string; /** * Converts a time to a string by using the current or specified locale. - * @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used. - * @param options An object that contains one or more properties that specify comparison options. - */ - toLocaleTimeString(locale?: string[], options?: Intl.DateTimeFormatOptions): string; - - /** - * Converts a date and time to a string by using the current or specified locale. - * @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used. - * @param options An object that contains one or more properties that specify comparison options. - */ - toLocaleString(locale?: string, options?: Intl.DateTimeFormatOptions): string; - - /** - * Converts a date to a string by using the current or specified locale. - * @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used. + * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. * @param options An object that contains one or more properties that specify comparison options. */ - toLocaleDateString(locale?: string, options?: Intl.DateTimeFormatOptions): string; - - /** - * Converts a time to a string by using the current or specified locale. - * @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used. - * @param options An object that contains one or more properties that specify comparison options. - */ - toLocaleTimeString(locale?: string, options?: Intl.DateTimeFormatOptions): string; + toLocaleTimeString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string; } ///////////////////////////// @@ -11668,11 +11660,12 @@ declare var HashChangeEvent: { interface History { readonly length: number; readonly state: any; - back(distance?: any): void; - forward(distance?: any): void; - go(delta?: any): void; - pushState(statedata: any, title?: string, url?: string): void; - replaceState(statedata: any, title?: string, url?: string): void; + scrollRestoration: ScrollRestoration; + back(): void; + forward(): void; + go(delta?: number): void; + pushState(data: any, title: string, url?: string | null): void; + replaceState(data: any, title: string, url?: string | null): void; } declare var History: { @@ -17244,7 +17237,6 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window addEventListener(type: "waiting", listener: (this: this, ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "wheel", listener: (this: this, ev: WheelEvent) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; - [index: number]: Window; } declare var Window: { @@ -17275,7 +17267,7 @@ declare var XMLDocument: { } interface XMLHttpRequest extends EventTarget, XMLHttpRequestEventTarget { - onreadystatechange: (this: this, ev: ProgressEvent) => any; + onreadystatechange: (this: this, ev: Event) => any; readonly readyState: number; readonly response: any; readonly responseText: string; @@ -17302,13 +17294,13 @@ interface XMLHttpRequest extends EventTarget, XMLHttpRequestEventTarget { readonly LOADING: number; readonly OPENED: number; readonly UNSENT: number; - addEventListener(type: "abort", listener: (this: this, ev: Event) => any, useCapture?: boolean): void; - addEventListener(type: "error", listener: (this: this, ev: ErrorEvent) => any, useCapture?: boolean): void; - addEventListener(type: "load", listener: (this: this, ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "abort", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; + addEventListener(type: "error", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; + addEventListener(type: "load", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; addEventListener(type: "loadend", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; - addEventListener(type: "loadstart", listener: (this: this, ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "loadstart", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; addEventListener(type: "progress", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; - addEventListener(type: "readystatechange", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; + addEventListener(type: "readystatechange", listener: (this: this, ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "timeout", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -17649,183 +17641,183 @@ interface NavigatorUserMedia { } interface NodeSelector { - querySelector(selectors: "a"): HTMLAnchorElement; - querySelector(selectors: "abbr"): HTMLElement; - querySelector(selectors: "acronym"): HTMLElement; - querySelector(selectors: "address"): HTMLElement; - querySelector(selectors: "applet"): HTMLAppletElement; - querySelector(selectors: "area"): HTMLAreaElement; - querySelector(selectors: "article"): HTMLElement; - querySelector(selectors: "aside"): HTMLElement; - querySelector(selectors: "audio"): HTMLAudioElement; - querySelector(selectors: "b"): HTMLElement; - querySelector(selectors: "base"): HTMLBaseElement; - querySelector(selectors: "basefont"): HTMLBaseFontElement; - querySelector(selectors: "bdo"): HTMLElement; - querySelector(selectors: "big"): HTMLElement; - querySelector(selectors: "blockquote"): HTMLQuoteElement; - querySelector(selectors: "body"): HTMLBodyElement; - querySelector(selectors: "br"): HTMLBRElement; - querySelector(selectors: "button"): HTMLButtonElement; - querySelector(selectors: "canvas"): HTMLCanvasElement; - querySelector(selectors: "caption"): HTMLTableCaptionElement; - querySelector(selectors: "center"): HTMLElement; - querySelector(selectors: "circle"): SVGCircleElement; - querySelector(selectors: "cite"): HTMLElement; - querySelector(selectors: "clippath"): SVGClipPathElement; - querySelector(selectors: "code"): HTMLElement; - querySelector(selectors: "col"): HTMLTableColElement; - querySelector(selectors: "colgroup"): HTMLTableColElement; - querySelector(selectors: "datalist"): HTMLDataListElement; - querySelector(selectors: "dd"): HTMLElement; - querySelector(selectors: "defs"): SVGDefsElement; - querySelector(selectors: "del"): HTMLModElement; - querySelector(selectors: "desc"): SVGDescElement; - querySelector(selectors: "dfn"): HTMLElement; - querySelector(selectors: "dir"): HTMLDirectoryElement; - querySelector(selectors: "div"): HTMLDivElement; - querySelector(selectors: "dl"): HTMLDListElement; - querySelector(selectors: "dt"): HTMLElement; - querySelector(selectors: "ellipse"): SVGEllipseElement; - querySelector(selectors: "em"): HTMLElement; - querySelector(selectors: "embed"): HTMLEmbedElement; - querySelector(selectors: "feblend"): SVGFEBlendElement; - querySelector(selectors: "fecolormatrix"): SVGFEColorMatrixElement; - querySelector(selectors: "fecomponenttransfer"): SVGFEComponentTransferElement; - querySelector(selectors: "fecomposite"): SVGFECompositeElement; - querySelector(selectors: "feconvolvematrix"): SVGFEConvolveMatrixElement; - querySelector(selectors: "fediffuselighting"): SVGFEDiffuseLightingElement; - querySelector(selectors: "fedisplacementmap"): SVGFEDisplacementMapElement; - querySelector(selectors: "fedistantlight"): SVGFEDistantLightElement; - querySelector(selectors: "feflood"): SVGFEFloodElement; - querySelector(selectors: "fefunca"): SVGFEFuncAElement; - querySelector(selectors: "fefuncb"): SVGFEFuncBElement; - querySelector(selectors: "fefuncg"): SVGFEFuncGElement; - querySelector(selectors: "fefuncr"): SVGFEFuncRElement; - querySelector(selectors: "fegaussianblur"): SVGFEGaussianBlurElement; - querySelector(selectors: "feimage"): SVGFEImageElement; - querySelector(selectors: "femerge"): SVGFEMergeElement; - querySelector(selectors: "femergenode"): SVGFEMergeNodeElement; - querySelector(selectors: "femorphology"): SVGFEMorphologyElement; - querySelector(selectors: "feoffset"): SVGFEOffsetElement; - querySelector(selectors: "fepointlight"): SVGFEPointLightElement; - querySelector(selectors: "fespecularlighting"): SVGFESpecularLightingElement; - querySelector(selectors: "fespotlight"): SVGFESpotLightElement; - querySelector(selectors: "fetile"): SVGFETileElement; - querySelector(selectors: "feturbulence"): SVGFETurbulenceElement; - querySelector(selectors: "fieldset"): HTMLFieldSetElement; - querySelector(selectors: "figcaption"): HTMLElement; - querySelector(selectors: "figure"): HTMLElement; - querySelector(selectors: "filter"): SVGFilterElement; - querySelector(selectors: "font"): HTMLFontElement; - querySelector(selectors: "footer"): HTMLElement; - querySelector(selectors: "foreignobject"): SVGForeignObjectElement; - querySelector(selectors: "form"): HTMLFormElement; - querySelector(selectors: "frame"): HTMLFrameElement; - querySelector(selectors: "frameset"): HTMLFrameSetElement; - querySelector(selectors: "g"): SVGGElement; - querySelector(selectors: "h1"): HTMLHeadingElement; - querySelector(selectors: "h2"): HTMLHeadingElement; - querySelector(selectors: "h3"): HTMLHeadingElement; - querySelector(selectors: "h4"): HTMLHeadingElement; - querySelector(selectors: "h5"): HTMLHeadingElement; - querySelector(selectors: "h6"): HTMLHeadingElement; - querySelector(selectors: "head"): HTMLHeadElement; - querySelector(selectors: "header"): HTMLElement; - querySelector(selectors: "hgroup"): HTMLElement; - querySelector(selectors: "hr"): HTMLHRElement; - querySelector(selectors: "html"): HTMLHtmlElement; - querySelector(selectors: "i"): HTMLElement; - querySelector(selectors: "iframe"): HTMLIFrameElement; - querySelector(selectors: "image"): SVGImageElement; - querySelector(selectors: "img"): HTMLImageElement; - querySelector(selectors: "input"): HTMLInputElement; - querySelector(selectors: "ins"): HTMLModElement; - querySelector(selectors: "isindex"): HTMLUnknownElement; - querySelector(selectors: "kbd"): HTMLElement; - querySelector(selectors: "keygen"): HTMLElement; - querySelector(selectors: "label"): HTMLLabelElement; - querySelector(selectors: "legend"): HTMLLegendElement; - querySelector(selectors: "li"): HTMLLIElement; - querySelector(selectors: "line"): SVGLineElement; - querySelector(selectors: "lineargradient"): SVGLinearGradientElement; - querySelector(selectors: "link"): HTMLLinkElement; - querySelector(selectors: "listing"): HTMLPreElement; - querySelector(selectors: "map"): HTMLMapElement; - querySelector(selectors: "mark"): HTMLElement; - querySelector(selectors: "marker"): SVGMarkerElement; - querySelector(selectors: "marquee"): HTMLMarqueeElement; - querySelector(selectors: "mask"): SVGMaskElement; - querySelector(selectors: "menu"): HTMLMenuElement; - querySelector(selectors: "meta"): HTMLMetaElement; - querySelector(selectors: "metadata"): SVGMetadataElement; - querySelector(selectors: "meter"): HTMLMeterElement; - querySelector(selectors: "nav"): HTMLElement; - querySelector(selectors: "nextid"): HTMLUnknownElement; - querySelector(selectors: "nobr"): HTMLElement; - querySelector(selectors: "noframes"): HTMLElement; - querySelector(selectors: "noscript"): HTMLElement; - querySelector(selectors: "object"): HTMLObjectElement; - querySelector(selectors: "ol"): HTMLOListElement; - querySelector(selectors: "optgroup"): HTMLOptGroupElement; - querySelector(selectors: "option"): HTMLOptionElement; - querySelector(selectors: "p"): HTMLParagraphElement; - querySelector(selectors: "param"): HTMLParamElement; - querySelector(selectors: "path"): SVGPathElement; - querySelector(selectors: "pattern"): SVGPatternElement; - querySelector(selectors: "picture"): HTMLPictureElement; - querySelector(selectors: "plaintext"): HTMLElement; - querySelector(selectors: "polygon"): SVGPolygonElement; - querySelector(selectors: "polyline"): SVGPolylineElement; - querySelector(selectors: "pre"): HTMLPreElement; - querySelector(selectors: "progress"): HTMLProgressElement; - querySelector(selectors: "q"): HTMLQuoteElement; - querySelector(selectors: "radialgradient"): SVGRadialGradientElement; - querySelector(selectors: "rect"): SVGRectElement; - querySelector(selectors: "rt"): HTMLElement; - querySelector(selectors: "ruby"): HTMLElement; - querySelector(selectors: "s"): HTMLElement; - querySelector(selectors: "samp"): HTMLElement; - querySelector(selectors: "script"): HTMLScriptElement; - querySelector(selectors: "section"): HTMLElement; - querySelector(selectors: "select"): HTMLSelectElement; - querySelector(selectors: "small"): HTMLElement; - querySelector(selectors: "source"): HTMLSourceElement; - querySelector(selectors: "span"): HTMLSpanElement; - querySelector(selectors: "stop"): SVGStopElement; - querySelector(selectors: "strike"): HTMLElement; - querySelector(selectors: "strong"): HTMLElement; - querySelector(selectors: "style"): HTMLStyleElement; - querySelector(selectors: "sub"): HTMLElement; - querySelector(selectors: "sup"): HTMLElement; - querySelector(selectors: "svg"): SVGSVGElement; - querySelector(selectors: "switch"): SVGSwitchElement; - querySelector(selectors: "symbol"): SVGSymbolElement; - querySelector(selectors: "table"): HTMLTableElement; - querySelector(selectors: "tbody"): HTMLTableSectionElement; - querySelector(selectors: "td"): HTMLTableDataCellElement; - querySelector(selectors: "template"): HTMLTemplateElement; - querySelector(selectors: "text"): SVGTextElement; - querySelector(selectors: "textpath"): SVGTextPathElement; - querySelector(selectors: "textarea"): HTMLTextAreaElement; - querySelector(selectors: "tfoot"): HTMLTableSectionElement; - querySelector(selectors: "th"): HTMLTableHeaderCellElement; - querySelector(selectors: "thead"): HTMLTableSectionElement; - querySelector(selectors: "title"): HTMLTitleElement; - querySelector(selectors: "tr"): HTMLTableRowElement; - querySelector(selectors: "track"): HTMLTrackElement; - querySelector(selectors: "tspan"): SVGTSpanElement; - querySelector(selectors: "tt"): HTMLElement; - querySelector(selectors: "u"): HTMLElement; - querySelector(selectors: "ul"): HTMLUListElement; - querySelector(selectors: "use"): SVGUseElement; - querySelector(selectors: "var"): HTMLElement; - querySelector(selectors: "video"): HTMLVideoElement; - querySelector(selectors: "view"): SVGViewElement; - querySelector(selectors: "wbr"): HTMLElement; - querySelector(selectors: "x-ms-webview"): MSHTMLWebViewElement; - querySelector(selectors: "xmp"): HTMLPreElement; - querySelector(selectors: string): Element; + querySelector(selectors: "a"): HTMLAnchorElement | null; + querySelector(selectors: "abbr"): HTMLElement | null; + querySelector(selectors: "acronym"): HTMLElement | null; + querySelector(selectors: "address"): HTMLElement | null; + querySelector(selectors: "applet"): HTMLAppletElement | null; + querySelector(selectors: "area"): HTMLAreaElement | null; + querySelector(selectors: "article"): HTMLElement | null; + querySelector(selectors: "aside"): HTMLElement | null; + querySelector(selectors: "audio"): HTMLAudioElement | null; + querySelector(selectors: "b"): HTMLElement | null; + querySelector(selectors: "base"): HTMLBaseElement | null; + querySelector(selectors: "basefont"): HTMLBaseFontElement | null; + querySelector(selectors: "bdo"): HTMLElement | null; + querySelector(selectors: "big"): HTMLElement | null; + querySelector(selectors: "blockquote"): HTMLQuoteElement | null; + querySelector(selectors: "body"): HTMLBodyElement | null; + querySelector(selectors: "br"): HTMLBRElement | null; + querySelector(selectors: "button"): HTMLButtonElement | null; + querySelector(selectors: "canvas"): HTMLCanvasElement | null; + querySelector(selectors: "caption"): HTMLTableCaptionElement | null; + querySelector(selectors: "center"): HTMLElement | null; + querySelector(selectors: "circle"): SVGCircleElement | null; + querySelector(selectors: "cite"): HTMLElement | null; + querySelector(selectors: "clippath"): SVGClipPathElement | null; + querySelector(selectors: "code"): HTMLElement | null; + querySelector(selectors: "col"): HTMLTableColElement | null; + querySelector(selectors: "colgroup"): HTMLTableColElement | null; + querySelector(selectors: "datalist"): HTMLDataListElement | null; + querySelector(selectors: "dd"): HTMLElement | null; + querySelector(selectors: "defs"): SVGDefsElement | null; + querySelector(selectors: "del"): HTMLModElement | null; + querySelector(selectors: "desc"): SVGDescElement | null; + querySelector(selectors: "dfn"): HTMLElement | null; + querySelector(selectors: "dir"): HTMLDirectoryElement | null; + querySelector(selectors: "div"): HTMLDivElement | null; + querySelector(selectors: "dl"): HTMLDListElement | null; + querySelector(selectors: "dt"): HTMLElement | null; + querySelector(selectors: "ellipse"): SVGEllipseElement | null; + querySelector(selectors: "em"): HTMLElement | null; + querySelector(selectors: "embed"): HTMLEmbedElement | null; + querySelector(selectors: "feblend"): SVGFEBlendElement | null; + querySelector(selectors: "fecolormatrix"): SVGFEColorMatrixElement | null; + querySelector(selectors: "fecomponenttransfer"): SVGFEComponentTransferElement | null; + querySelector(selectors: "fecomposite"): SVGFECompositeElement | null; + querySelector(selectors: "feconvolvematrix"): SVGFEConvolveMatrixElement | null; + querySelector(selectors: "fediffuselighting"): SVGFEDiffuseLightingElement | null; + querySelector(selectors: "fedisplacementmap"): SVGFEDisplacementMapElement | null; + querySelector(selectors: "fedistantlight"): SVGFEDistantLightElement | null; + querySelector(selectors: "feflood"): SVGFEFloodElement | null; + querySelector(selectors: "fefunca"): SVGFEFuncAElement | null; + querySelector(selectors: "fefuncb"): SVGFEFuncBElement | null; + querySelector(selectors: "fefuncg"): SVGFEFuncGElement | null; + querySelector(selectors: "fefuncr"): SVGFEFuncRElement | null; + querySelector(selectors: "fegaussianblur"): SVGFEGaussianBlurElement | null; + querySelector(selectors: "feimage"): SVGFEImageElement | null; + querySelector(selectors: "femerge"): SVGFEMergeElement | null; + querySelector(selectors: "femergenode"): SVGFEMergeNodeElement | null; + querySelector(selectors: "femorphology"): SVGFEMorphologyElement | null; + querySelector(selectors: "feoffset"): SVGFEOffsetElement | null; + querySelector(selectors: "fepointlight"): SVGFEPointLightElement | null; + querySelector(selectors: "fespecularlighting"): SVGFESpecularLightingElement | null; + querySelector(selectors: "fespotlight"): SVGFESpotLightElement | null; + querySelector(selectors: "fetile"): SVGFETileElement | null; + querySelector(selectors: "feturbulence"): SVGFETurbulenceElement | null; + querySelector(selectors: "fieldset"): HTMLFieldSetElement | null; + querySelector(selectors: "figcaption"): HTMLElement | null; + querySelector(selectors: "figure"): HTMLElement | null; + querySelector(selectors: "filter"): SVGFilterElement | null; + querySelector(selectors: "font"): HTMLFontElement | null; + querySelector(selectors: "footer"): HTMLElement | null; + querySelector(selectors: "foreignobject"): SVGForeignObjectElement | null; + querySelector(selectors: "form"): HTMLFormElement | null; + querySelector(selectors: "frame"): HTMLFrameElement | null; + querySelector(selectors: "frameset"): HTMLFrameSetElement | null; + querySelector(selectors: "g"): SVGGElement | null; + querySelector(selectors: "h1"): HTMLHeadingElement | null; + querySelector(selectors: "h2"): HTMLHeadingElement | null; + querySelector(selectors: "h3"): HTMLHeadingElement | null; + querySelector(selectors: "h4"): HTMLHeadingElement | null; + querySelector(selectors: "h5"): HTMLHeadingElement | null; + querySelector(selectors: "h6"): HTMLHeadingElement | null; + querySelector(selectors: "head"): HTMLHeadElement | null; + querySelector(selectors: "header"): HTMLElement | null; + querySelector(selectors: "hgroup"): HTMLElement | null; + querySelector(selectors: "hr"): HTMLHRElement | null; + querySelector(selectors: "html"): HTMLHtmlElement | null; + querySelector(selectors: "i"): HTMLElement | null; + querySelector(selectors: "iframe"): HTMLIFrameElement | null; + querySelector(selectors: "image"): SVGImageElement | null; + querySelector(selectors: "img"): HTMLImageElement | null; + querySelector(selectors: "input"): HTMLInputElement | null; + querySelector(selectors: "ins"): HTMLModElement | null; + querySelector(selectors: "isindex"): HTMLUnknownElement | null; + querySelector(selectors: "kbd"): HTMLElement | null; + querySelector(selectors: "keygen"): HTMLElement | null; + querySelector(selectors: "label"): HTMLLabelElement | null; + querySelector(selectors: "legend"): HTMLLegendElement | null; + querySelector(selectors: "li"): HTMLLIElement | null; + querySelector(selectors: "line"): SVGLineElement | null; + querySelector(selectors: "lineargradient"): SVGLinearGradientElement | null; + querySelector(selectors: "link"): HTMLLinkElement | null; + querySelector(selectors: "listing"): HTMLPreElement | null; + querySelector(selectors: "map"): HTMLMapElement | null; + querySelector(selectors: "mark"): HTMLElement | null; + querySelector(selectors: "marker"): SVGMarkerElement | null; + querySelector(selectors: "marquee"): HTMLMarqueeElement | null; + querySelector(selectors: "mask"): SVGMaskElement | null; + querySelector(selectors: "menu"): HTMLMenuElement | null; + querySelector(selectors: "meta"): HTMLMetaElement | null; + querySelector(selectors: "metadata"): SVGMetadataElement | null; + querySelector(selectors: "meter"): HTMLMeterElement | null; + querySelector(selectors: "nav"): HTMLElement | null; + querySelector(selectors: "nextid"): HTMLUnknownElement | null; + querySelector(selectors: "nobr"): HTMLElement | null; + querySelector(selectors: "noframes"): HTMLElement | null; + querySelector(selectors: "noscript"): HTMLElement | null; + querySelector(selectors: "object"): HTMLObjectElement | null; + querySelector(selectors: "ol"): HTMLOListElement | null; + querySelector(selectors: "optgroup"): HTMLOptGroupElement | null; + querySelector(selectors: "option"): HTMLOptionElement | null; + querySelector(selectors: "p"): HTMLParagraphElement | null; + querySelector(selectors: "param"): HTMLParamElement | null; + querySelector(selectors: "path"): SVGPathElement | null; + querySelector(selectors: "pattern"): SVGPatternElement | null; + querySelector(selectors: "picture"): HTMLPictureElement | null; + querySelector(selectors: "plaintext"): HTMLElement | null; + querySelector(selectors: "polygon"): SVGPolygonElement | null; + querySelector(selectors: "polyline"): SVGPolylineElement | null; + querySelector(selectors: "pre"): HTMLPreElement | null; + querySelector(selectors: "progress"): HTMLProgressElement | null; + querySelector(selectors: "q"): HTMLQuoteElement | null; + querySelector(selectors: "radialgradient"): SVGRadialGradientElement | null; + querySelector(selectors: "rect"): SVGRectElement | null; + querySelector(selectors: "rt"): HTMLElement | null; + querySelector(selectors: "ruby"): HTMLElement | null; + querySelector(selectors: "s"): HTMLElement | null; + querySelector(selectors: "samp"): HTMLElement | null; + querySelector(selectors: "script"): HTMLScriptElement | null; + querySelector(selectors: "section"): HTMLElement | null; + querySelector(selectors: "select"): HTMLSelectElement | null; + querySelector(selectors: "small"): HTMLElement | null; + querySelector(selectors: "source"): HTMLSourceElement | null; + querySelector(selectors: "span"): HTMLSpanElement | null; + querySelector(selectors: "stop"): SVGStopElement | null; + querySelector(selectors: "strike"): HTMLElement | null; + querySelector(selectors: "strong"): HTMLElement | null; + querySelector(selectors: "style"): HTMLStyleElement | null; + querySelector(selectors: "sub"): HTMLElement | null; + querySelector(selectors: "sup"): HTMLElement | null; + querySelector(selectors: "svg"): SVGSVGElement | null; + querySelector(selectors: "switch"): SVGSwitchElement | null; + querySelector(selectors: "symbol"): SVGSymbolElement | null; + querySelector(selectors: "table"): HTMLTableElement | null; + querySelector(selectors: "tbody"): HTMLTableSectionElement | null; + querySelector(selectors: "td"): HTMLTableDataCellElement | null; + querySelector(selectors: "template"): HTMLTemplateElement | null; + querySelector(selectors: "text"): SVGTextElement | null; + querySelector(selectors: "textpath"): SVGTextPathElement | null; + querySelector(selectors: "textarea"): HTMLTextAreaElement | null; + querySelector(selectors: "tfoot"): HTMLTableSectionElement | null; + querySelector(selectors: "th"): HTMLTableHeaderCellElement | null; + querySelector(selectors: "thead"): HTMLTableSectionElement | null; + querySelector(selectors: "title"): HTMLTitleElement | null; + querySelector(selectors: "tr"): HTMLTableRowElement | null; + querySelector(selectors: "track"): HTMLTrackElement | null; + querySelector(selectors: "tspan"): SVGTSpanElement | null; + querySelector(selectors: "tt"): HTMLElement | null; + querySelector(selectors: "u"): HTMLElement | null; + querySelector(selectors: "ul"): HTMLUListElement | null; + querySelector(selectors: "use"): SVGUseElement | null; + querySelector(selectors: "var"): HTMLElement | null; + querySelector(selectors: "video"): HTMLVideoElement | null; + querySelector(selectors: "view"): SVGViewElement | null; + querySelector(selectors: "wbr"): HTMLElement | null; + querySelector(selectors: "x-ms-webview"): MSHTMLWebViewElement | null; + querySelector(selectors: "xmp"): HTMLPreElement | null; + querySelector(selectors: string): Element | null; querySelectorAll(selectors: "a"): NodeListOf; querySelectorAll(selectors: "abbr"): NodeListOf; querySelectorAll(selectors: "acronym"): NodeListOf; @@ -18755,6 +18747,7 @@ type ScrollLogicalPosition = "start" | "center" | "end" | "nearest"; type IDBValidKey = number | string | Date | IDBArrayKey; type BufferSource = ArrayBuffer | ArrayBufferView; type MouseWheelEvent = WheelEvent; +type ScrollRestoration = "auto" | "manual"; ///////////////////////////// /// WorkerGlobalScope APIs ///////////////////////////// diff --git a/bin/lib.dom.d.ts b/bin/lib.dom.d.ts index 4e45a38..4c19c87 100644 --- a/bin/lib.dom.d.ts +++ b/bin/lib.dom.d.ts @@ -7552,11 +7552,12 @@ declare var HashChangeEvent: { interface History { readonly length: number; readonly state: any; - back(distance?: any): void; - forward(distance?: any): void; - go(delta?: any): void; - pushState(statedata: any, title?: string, url?: string): void; - replaceState(statedata: any, title?: string, url?: string): void; + scrollRestoration: ScrollRestoration; + back(): void; + forward(): void; + go(delta?: number): void; + pushState(data: any, title: string, url?: string | null): void; + replaceState(data: any, title: string, url?: string | null): void; } declare var History: { @@ -13128,7 +13129,6 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window addEventListener(type: "waiting", listener: (this: this, ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "wheel", listener: (this: this, ev: WheelEvent) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; - [index: number]: Window; } declare var Window: { @@ -13159,7 +13159,7 @@ declare var XMLDocument: { } interface XMLHttpRequest extends EventTarget, XMLHttpRequestEventTarget { - onreadystatechange: (this: this, ev: ProgressEvent) => any; + onreadystatechange: (this: this, ev: Event) => any; readonly readyState: number; readonly response: any; readonly responseText: string; @@ -13186,13 +13186,13 @@ interface XMLHttpRequest extends EventTarget, XMLHttpRequestEventTarget { readonly LOADING: number; readonly OPENED: number; readonly UNSENT: number; - addEventListener(type: "abort", listener: (this: this, ev: Event) => any, useCapture?: boolean): void; - addEventListener(type: "error", listener: (this: this, ev: ErrorEvent) => any, useCapture?: boolean): void; - addEventListener(type: "load", listener: (this: this, ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "abort", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; + addEventListener(type: "error", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; + addEventListener(type: "load", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; addEventListener(type: "loadend", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; - addEventListener(type: "loadstart", listener: (this: this, ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "loadstart", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; addEventListener(type: "progress", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; - addEventListener(type: "readystatechange", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; + addEventListener(type: "readystatechange", listener: (this: this, ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "timeout", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -13533,183 +13533,183 @@ interface NavigatorUserMedia { } interface NodeSelector { - querySelector(selectors: "a"): HTMLAnchorElement; - querySelector(selectors: "abbr"): HTMLElement; - querySelector(selectors: "acronym"): HTMLElement; - querySelector(selectors: "address"): HTMLElement; - querySelector(selectors: "applet"): HTMLAppletElement; - querySelector(selectors: "area"): HTMLAreaElement; - querySelector(selectors: "article"): HTMLElement; - querySelector(selectors: "aside"): HTMLElement; - querySelector(selectors: "audio"): HTMLAudioElement; - querySelector(selectors: "b"): HTMLElement; - querySelector(selectors: "base"): HTMLBaseElement; - querySelector(selectors: "basefont"): HTMLBaseFontElement; - querySelector(selectors: "bdo"): HTMLElement; - querySelector(selectors: "big"): HTMLElement; - querySelector(selectors: "blockquote"): HTMLQuoteElement; - querySelector(selectors: "body"): HTMLBodyElement; - querySelector(selectors: "br"): HTMLBRElement; - querySelector(selectors: "button"): HTMLButtonElement; - querySelector(selectors: "canvas"): HTMLCanvasElement; - querySelector(selectors: "caption"): HTMLTableCaptionElement; - querySelector(selectors: "center"): HTMLElement; - querySelector(selectors: "circle"): SVGCircleElement; - querySelector(selectors: "cite"): HTMLElement; - querySelector(selectors: "clippath"): SVGClipPathElement; - querySelector(selectors: "code"): HTMLElement; - querySelector(selectors: "col"): HTMLTableColElement; - querySelector(selectors: "colgroup"): HTMLTableColElement; - querySelector(selectors: "datalist"): HTMLDataListElement; - querySelector(selectors: "dd"): HTMLElement; - querySelector(selectors: "defs"): SVGDefsElement; - querySelector(selectors: "del"): HTMLModElement; - querySelector(selectors: "desc"): SVGDescElement; - querySelector(selectors: "dfn"): HTMLElement; - querySelector(selectors: "dir"): HTMLDirectoryElement; - querySelector(selectors: "div"): HTMLDivElement; - querySelector(selectors: "dl"): HTMLDListElement; - querySelector(selectors: "dt"): HTMLElement; - querySelector(selectors: "ellipse"): SVGEllipseElement; - querySelector(selectors: "em"): HTMLElement; - querySelector(selectors: "embed"): HTMLEmbedElement; - querySelector(selectors: "feblend"): SVGFEBlendElement; - querySelector(selectors: "fecolormatrix"): SVGFEColorMatrixElement; - querySelector(selectors: "fecomponenttransfer"): SVGFEComponentTransferElement; - querySelector(selectors: "fecomposite"): SVGFECompositeElement; - querySelector(selectors: "feconvolvematrix"): SVGFEConvolveMatrixElement; - querySelector(selectors: "fediffuselighting"): SVGFEDiffuseLightingElement; - querySelector(selectors: "fedisplacementmap"): SVGFEDisplacementMapElement; - querySelector(selectors: "fedistantlight"): SVGFEDistantLightElement; - querySelector(selectors: "feflood"): SVGFEFloodElement; - querySelector(selectors: "fefunca"): SVGFEFuncAElement; - querySelector(selectors: "fefuncb"): SVGFEFuncBElement; - querySelector(selectors: "fefuncg"): SVGFEFuncGElement; - querySelector(selectors: "fefuncr"): SVGFEFuncRElement; - querySelector(selectors: "fegaussianblur"): SVGFEGaussianBlurElement; - querySelector(selectors: "feimage"): SVGFEImageElement; - querySelector(selectors: "femerge"): SVGFEMergeElement; - querySelector(selectors: "femergenode"): SVGFEMergeNodeElement; - querySelector(selectors: "femorphology"): SVGFEMorphologyElement; - querySelector(selectors: "feoffset"): SVGFEOffsetElement; - querySelector(selectors: "fepointlight"): SVGFEPointLightElement; - querySelector(selectors: "fespecularlighting"): SVGFESpecularLightingElement; - querySelector(selectors: "fespotlight"): SVGFESpotLightElement; - querySelector(selectors: "fetile"): SVGFETileElement; - querySelector(selectors: "feturbulence"): SVGFETurbulenceElement; - querySelector(selectors: "fieldset"): HTMLFieldSetElement; - querySelector(selectors: "figcaption"): HTMLElement; - querySelector(selectors: "figure"): HTMLElement; - querySelector(selectors: "filter"): SVGFilterElement; - querySelector(selectors: "font"): HTMLFontElement; - querySelector(selectors: "footer"): HTMLElement; - querySelector(selectors: "foreignobject"): SVGForeignObjectElement; - querySelector(selectors: "form"): HTMLFormElement; - querySelector(selectors: "frame"): HTMLFrameElement; - querySelector(selectors: "frameset"): HTMLFrameSetElement; - querySelector(selectors: "g"): SVGGElement; - querySelector(selectors: "h1"): HTMLHeadingElement; - querySelector(selectors: "h2"): HTMLHeadingElement; - querySelector(selectors: "h3"): HTMLHeadingElement; - querySelector(selectors: "h4"): HTMLHeadingElement; - querySelector(selectors: "h5"): HTMLHeadingElement; - querySelector(selectors: "h6"): HTMLHeadingElement; - querySelector(selectors: "head"): HTMLHeadElement; - querySelector(selectors: "header"): HTMLElement; - querySelector(selectors: "hgroup"): HTMLElement; - querySelector(selectors: "hr"): HTMLHRElement; - querySelector(selectors: "html"): HTMLHtmlElement; - querySelector(selectors: "i"): HTMLElement; - querySelector(selectors: "iframe"): HTMLIFrameElement; - querySelector(selectors: "image"): SVGImageElement; - querySelector(selectors: "img"): HTMLImageElement; - querySelector(selectors: "input"): HTMLInputElement; - querySelector(selectors: "ins"): HTMLModElement; - querySelector(selectors: "isindex"): HTMLUnknownElement; - querySelector(selectors: "kbd"): HTMLElement; - querySelector(selectors: "keygen"): HTMLElement; - querySelector(selectors: "label"): HTMLLabelElement; - querySelector(selectors: "legend"): HTMLLegendElement; - querySelector(selectors: "li"): HTMLLIElement; - querySelector(selectors: "line"): SVGLineElement; - querySelector(selectors: "lineargradient"): SVGLinearGradientElement; - querySelector(selectors: "link"): HTMLLinkElement; - querySelector(selectors: "listing"): HTMLPreElement; - querySelector(selectors: "map"): HTMLMapElement; - querySelector(selectors: "mark"): HTMLElement; - querySelector(selectors: "marker"): SVGMarkerElement; - querySelector(selectors: "marquee"): HTMLMarqueeElement; - querySelector(selectors: "mask"): SVGMaskElement; - querySelector(selectors: "menu"): HTMLMenuElement; - querySelector(selectors: "meta"): HTMLMetaElement; - querySelector(selectors: "metadata"): SVGMetadataElement; - querySelector(selectors: "meter"): HTMLMeterElement; - querySelector(selectors: "nav"): HTMLElement; - querySelector(selectors: "nextid"): HTMLUnknownElement; - querySelector(selectors: "nobr"): HTMLElement; - querySelector(selectors: "noframes"): HTMLElement; - querySelector(selectors: "noscript"): HTMLElement; - querySelector(selectors: "object"): HTMLObjectElement; - querySelector(selectors: "ol"): HTMLOListElement; - querySelector(selectors: "optgroup"): HTMLOptGroupElement; - querySelector(selectors: "option"): HTMLOptionElement; - querySelector(selectors: "p"): HTMLParagraphElement; - querySelector(selectors: "param"): HTMLParamElement; - querySelector(selectors: "path"): SVGPathElement; - querySelector(selectors: "pattern"): SVGPatternElement; - querySelector(selectors: "picture"): HTMLPictureElement; - querySelector(selectors: "plaintext"): HTMLElement; - querySelector(selectors: "polygon"): SVGPolygonElement; - querySelector(selectors: "polyline"): SVGPolylineElement; - querySelector(selectors: "pre"): HTMLPreElement; - querySelector(selectors: "progress"): HTMLProgressElement; - querySelector(selectors: "q"): HTMLQuoteElement; - querySelector(selectors: "radialgradient"): SVGRadialGradientElement; - querySelector(selectors: "rect"): SVGRectElement; - querySelector(selectors: "rt"): HTMLElement; - querySelector(selectors: "ruby"): HTMLElement; - querySelector(selectors: "s"): HTMLElement; - querySelector(selectors: "samp"): HTMLElement; - querySelector(selectors: "script"): HTMLScriptElement; - querySelector(selectors: "section"): HTMLElement; - querySelector(selectors: "select"): HTMLSelectElement; - querySelector(selectors: "small"): HTMLElement; - querySelector(selectors: "source"): HTMLSourceElement; - querySelector(selectors: "span"): HTMLSpanElement; - querySelector(selectors: "stop"): SVGStopElement; - querySelector(selectors: "strike"): HTMLElement; - querySelector(selectors: "strong"): HTMLElement; - querySelector(selectors: "style"): HTMLStyleElement; - querySelector(selectors: "sub"): HTMLElement; - querySelector(selectors: "sup"): HTMLElement; - querySelector(selectors: "svg"): SVGSVGElement; - querySelector(selectors: "switch"): SVGSwitchElement; - querySelector(selectors: "symbol"): SVGSymbolElement; - querySelector(selectors: "table"): HTMLTableElement; - querySelector(selectors: "tbody"): HTMLTableSectionElement; - querySelector(selectors: "td"): HTMLTableDataCellElement; - querySelector(selectors: "template"): HTMLTemplateElement; - querySelector(selectors: "text"): SVGTextElement; - querySelector(selectors: "textpath"): SVGTextPathElement; - querySelector(selectors: "textarea"): HTMLTextAreaElement; - querySelector(selectors: "tfoot"): HTMLTableSectionElement; - querySelector(selectors: "th"): HTMLTableHeaderCellElement; - querySelector(selectors: "thead"): HTMLTableSectionElement; - querySelector(selectors: "title"): HTMLTitleElement; - querySelector(selectors: "tr"): HTMLTableRowElement; - querySelector(selectors: "track"): HTMLTrackElement; - querySelector(selectors: "tspan"): SVGTSpanElement; - querySelector(selectors: "tt"): HTMLElement; - querySelector(selectors: "u"): HTMLElement; - querySelector(selectors: "ul"): HTMLUListElement; - querySelector(selectors: "use"): SVGUseElement; - querySelector(selectors: "var"): HTMLElement; - querySelector(selectors: "video"): HTMLVideoElement; - querySelector(selectors: "view"): SVGViewElement; - querySelector(selectors: "wbr"): HTMLElement; - querySelector(selectors: "x-ms-webview"): MSHTMLWebViewElement; - querySelector(selectors: "xmp"): HTMLPreElement; - querySelector(selectors: string): Element; + querySelector(selectors: "a"): HTMLAnchorElement | null; + querySelector(selectors: "abbr"): HTMLElement | null; + querySelector(selectors: "acronym"): HTMLElement | null; + querySelector(selectors: "address"): HTMLElement | null; + querySelector(selectors: "applet"): HTMLAppletElement | null; + querySelector(selectors: "area"): HTMLAreaElement | null; + querySelector(selectors: "article"): HTMLElement | null; + querySelector(selectors: "aside"): HTMLElement | null; + querySelector(selectors: "audio"): HTMLAudioElement | null; + querySelector(selectors: "b"): HTMLElement | null; + querySelector(selectors: "base"): HTMLBaseElement | null; + querySelector(selectors: "basefont"): HTMLBaseFontElement | null; + querySelector(selectors: "bdo"): HTMLElement | null; + querySelector(selectors: "big"): HTMLElement | null; + querySelector(selectors: "blockquote"): HTMLQuoteElement | null; + querySelector(selectors: "body"): HTMLBodyElement | null; + querySelector(selectors: "br"): HTMLBRElement | null; + querySelector(selectors: "button"): HTMLButtonElement | null; + querySelector(selectors: "canvas"): HTMLCanvasElement | null; + querySelector(selectors: "caption"): HTMLTableCaptionElement | null; + querySelector(selectors: "center"): HTMLElement | null; + querySelector(selectors: "circle"): SVGCircleElement | null; + querySelector(selectors: "cite"): HTMLElement | null; + querySelector(selectors: "clippath"): SVGClipPathElement | null; + querySelector(selectors: "code"): HTMLElement | null; + querySelector(selectors: "col"): HTMLTableColElement | null; + querySelector(selectors: "colgroup"): HTMLTableColElement | null; + querySelector(selectors: "datalist"): HTMLDataListElement | null; + querySelector(selectors: "dd"): HTMLElement | null; + querySelector(selectors: "defs"): SVGDefsElement | null; + querySelector(selectors: "del"): HTMLModElement | null; + querySelector(selectors: "desc"): SVGDescElement | null; + querySelector(selectors: "dfn"): HTMLElement | null; + querySelector(selectors: "dir"): HTMLDirectoryElement | null; + querySelector(selectors: "div"): HTMLDivElement | null; + querySelector(selectors: "dl"): HTMLDListElement | null; + querySelector(selectors: "dt"): HTMLElement | null; + querySelector(selectors: "ellipse"): SVGEllipseElement | null; + querySelector(selectors: "em"): HTMLElement | null; + querySelector(selectors: "embed"): HTMLEmbedElement | null; + querySelector(selectors: "feblend"): SVGFEBlendElement | null; + querySelector(selectors: "fecolormatrix"): SVGFEColorMatrixElement | null; + querySelector(selectors: "fecomponenttransfer"): SVGFEComponentTransferElement | null; + querySelector(selectors: "fecomposite"): SVGFECompositeElement | null; + querySelector(selectors: "feconvolvematrix"): SVGFEConvolveMatrixElement | null; + querySelector(selectors: "fediffuselighting"): SVGFEDiffuseLightingElement | null; + querySelector(selectors: "fedisplacementmap"): SVGFEDisplacementMapElement | null; + querySelector(selectors: "fedistantlight"): SVGFEDistantLightElement | null; + querySelector(selectors: "feflood"): SVGFEFloodElement | null; + querySelector(selectors: "fefunca"): SVGFEFuncAElement | null; + querySelector(selectors: "fefuncb"): SVGFEFuncBElement | null; + querySelector(selectors: "fefuncg"): SVGFEFuncGElement | null; + querySelector(selectors: "fefuncr"): SVGFEFuncRElement | null; + querySelector(selectors: "fegaussianblur"): SVGFEGaussianBlurElement | null; + querySelector(selectors: "feimage"): SVGFEImageElement | null; + querySelector(selectors: "femerge"): SVGFEMergeElement | null; + querySelector(selectors: "femergenode"): SVGFEMergeNodeElement | null; + querySelector(selectors: "femorphology"): SVGFEMorphologyElement | null; + querySelector(selectors: "feoffset"): SVGFEOffsetElement | null; + querySelector(selectors: "fepointlight"): SVGFEPointLightElement | null; + querySelector(selectors: "fespecularlighting"): SVGFESpecularLightingElement | null; + querySelector(selectors: "fespotlight"): SVGFESpotLightElement | null; + querySelector(selectors: "fetile"): SVGFETileElement | null; + querySelector(selectors: "feturbulence"): SVGFETurbulenceElement | null; + querySelector(selectors: "fieldset"): HTMLFieldSetElement | null; + querySelector(selectors: "figcaption"): HTMLElement | null; + querySelector(selectors: "figure"): HTMLElement | null; + querySelector(selectors: "filter"): SVGFilterElement | null; + querySelector(selectors: "font"): HTMLFontElement | null; + querySelector(selectors: "footer"): HTMLElement | null; + querySelector(selectors: "foreignobject"): SVGForeignObjectElement | null; + querySelector(selectors: "form"): HTMLFormElement | null; + querySelector(selectors: "frame"): HTMLFrameElement | null; + querySelector(selectors: "frameset"): HTMLFrameSetElement | null; + querySelector(selectors: "g"): SVGGElement | null; + querySelector(selectors: "h1"): HTMLHeadingElement | null; + querySelector(selectors: "h2"): HTMLHeadingElement | null; + querySelector(selectors: "h3"): HTMLHeadingElement | null; + querySelector(selectors: "h4"): HTMLHeadingElement | null; + querySelector(selectors: "h5"): HTMLHeadingElement | null; + querySelector(selectors: "h6"): HTMLHeadingElement | null; + querySelector(selectors: "head"): HTMLHeadElement | null; + querySelector(selectors: "header"): HTMLElement | null; + querySelector(selectors: "hgroup"): HTMLElement | null; + querySelector(selectors: "hr"): HTMLHRElement | null; + querySelector(selectors: "html"): HTMLHtmlElement | null; + querySelector(selectors: "i"): HTMLElement | null; + querySelector(selectors: "iframe"): HTMLIFrameElement | null; + querySelector(selectors: "image"): SVGImageElement | null; + querySelector(selectors: "img"): HTMLImageElement | null; + querySelector(selectors: "input"): HTMLInputElement | null; + querySelector(selectors: "ins"): HTMLModElement | null; + querySelector(selectors: "isindex"): HTMLUnknownElement | null; + querySelector(selectors: "kbd"): HTMLElement | null; + querySelector(selectors: "keygen"): HTMLElement | null; + querySelector(selectors: "label"): HTMLLabelElement | null; + querySelector(selectors: "legend"): HTMLLegendElement | null; + querySelector(selectors: "li"): HTMLLIElement | null; + querySelector(selectors: "line"): SVGLineElement | null; + querySelector(selectors: "lineargradient"): SVGLinearGradientElement | null; + querySelector(selectors: "link"): HTMLLinkElement | null; + querySelector(selectors: "listing"): HTMLPreElement | null; + querySelector(selectors: "map"): HTMLMapElement | null; + querySelector(selectors: "mark"): HTMLElement | null; + querySelector(selectors: "marker"): SVGMarkerElement | null; + querySelector(selectors: "marquee"): HTMLMarqueeElement | null; + querySelector(selectors: "mask"): SVGMaskElement | null; + querySelector(selectors: "menu"): HTMLMenuElement | null; + querySelector(selectors: "meta"): HTMLMetaElement | null; + querySelector(selectors: "metadata"): SVGMetadataElement | null; + querySelector(selectors: "meter"): HTMLMeterElement | null; + querySelector(selectors: "nav"): HTMLElement | null; + querySelector(selectors: "nextid"): HTMLUnknownElement | null; + querySelector(selectors: "nobr"): HTMLElement | null; + querySelector(selectors: "noframes"): HTMLElement | null; + querySelector(selectors: "noscript"): HTMLElement | null; + querySelector(selectors: "object"): HTMLObjectElement | null; + querySelector(selectors: "ol"): HTMLOListElement | null; + querySelector(selectors: "optgroup"): HTMLOptGroupElement | null; + querySelector(selectors: "option"): HTMLOptionElement | null; + querySelector(selectors: "p"): HTMLParagraphElement | null; + querySelector(selectors: "param"): HTMLParamElement | null; + querySelector(selectors: "path"): SVGPathElement | null; + querySelector(selectors: "pattern"): SVGPatternElement | null; + querySelector(selectors: "picture"): HTMLPictureElement | null; + querySelector(selectors: "plaintext"): HTMLElement | null; + querySelector(selectors: "polygon"): SVGPolygonElement | null; + querySelector(selectors: "polyline"): SVGPolylineElement | null; + querySelector(selectors: "pre"): HTMLPreElement | null; + querySelector(selectors: "progress"): HTMLProgressElement | null; + querySelector(selectors: "q"): HTMLQuoteElement | null; + querySelector(selectors: "radialgradient"): SVGRadialGradientElement | null; + querySelector(selectors: "rect"): SVGRectElement | null; + querySelector(selectors: "rt"): HTMLElement | null; + querySelector(selectors: "ruby"): HTMLElement | null; + querySelector(selectors: "s"): HTMLElement | null; + querySelector(selectors: "samp"): HTMLElement | null; + querySelector(selectors: "script"): HTMLScriptElement | null; + querySelector(selectors: "section"): HTMLElement | null; + querySelector(selectors: "select"): HTMLSelectElement | null; + querySelector(selectors: "small"): HTMLElement | null; + querySelector(selectors: "source"): HTMLSourceElement | null; + querySelector(selectors: "span"): HTMLSpanElement | null; + querySelector(selectors: "stop"): SVGStopElement | null; + querySelector(selectors: "strike"): HTMLElement | null; + querySelector(selectors: "strong"): HTMLElement | null; + querySelector(selectors: "style"): HTMLStyleElement | null; + querySelector(selectors: "sub"): HTMLElement | null; + querySelector(selectors: "sup"): HTMLElement | null; + querySelector(selectors: "svg"): SVGSVGElement | null; + querySelector(selectors: "switch"): SVGSwitchElement | null; + querySelector(selectors: "symbol"): SVGSymbolElement | null; + querySelector(selectors: "table"): HTMLTableElement | null; + querySelector(selectors: "tbody"): HTMLTableSectionElement | null; + querySelector(selectors: "td"): HTMLTableDataCellElement | null; + querySelector(selectors: "template"): HTMLTemplateElement | null; + querySelector(selectors: "text"): SVGTextElement | null; + querySelector(selectors: "textpath"): SVGTextPathElement | null; + querySelector(selectors: "textarea"): HTMLTextAreaElement | null; + querySelector(selectors: "tfoot"): HTMLTableSectionElement | null; + querySelector(selectors: "th"): HTMLTableHeaderCellElement | null; + querySelector(selectors: "thead"): HTMLTableSectionElement | null; + querySelector(selectors: "title"): HTMLTitleElement | null; + querySelector(selectors: "tr"): HTMLTableRowElement | null; + querySelector(selectors: "track"): HTMLTrackElement | null; + querySelector(selectors: "tspan"): SVGTSpanElement | null; + querySelector(selectors: "tt"): HTMLElement | null; + querySelector(selectors: "u"): HTMLElement | null; + querySelector(selectors: "ul"): HTMLUListElement | null; + querySelector(selectors: "use"): SVGUseElement | null; + querySelector(selectors: "var"): HTMLElement | null; + querySelector(selectors: "video"): HTMLVideoElement | null; + querySelector(selectors: "view"): SVGViewElement | null; + querySelector(selectors: "wbr"): HTMLElement | null; + querySelector(selectors: "x-ms-webview"): MSHTMLWebViewElement | null; + querySelector(selectors: "xmp"): HTMLPreElement | null; + querySelector(selectors: string): Element | null; querySelectorAll(selectors: "a"): NodeListOf; querySelectorAll(selectors: "abbr"): NodeListOf; querySelectorAll(selectors: "acronym"): NodeListOf; @@ -14638,4 +14638,5 @@ type ScrollBehavior = "auto" | "instant" | "smooth"; type ScrollLogicalPosition = "start" | "center" | "end" | "nearest"; type IDBValidKey = number | string | Date | IDBArrayKey; type BufferSource = ArrayBuffer | ArrayBufferView; -type MouseWheelEvent = WheelEvent; \ No newline at end of file +type MouseWheelEvent = WheelEvent; +type ScrollRestoration = "auto" | "manual"; \ No newline at end of file diff --git a/bin/lib.dom.iterable.d.ts b/bin/lib.dom.iterable.d.ts index e9cf451..397e0ab 100644 --- a/bin/lib.dom.iterable.d.ts +++ b/bin/lib.dom.iterable.d.ts @@ -14,7 +14,7 @@ and limitations under the License. ***************************************************************************** */ /// -/// +/// interface DOMTokenList { [Symbol.iterator](): IterableIterator; diff --git a/bin/lib.es2015.collection.d.ts b/bin/lib.es2015.collection.d.ts index f014185..24c737d 100644 --- a/bin/lib.es2015.collection.d.ts +++ b/bin/lib.es2015.collection.d.ts @@ -17,7 +17,7 @@ and limitations under the License. interface Map { clear(): void; delete(key: K): boolean; - forEach(callbackfn: (value: V, index: K, map: Map) => void, thisArg?: any): void; + forEach(callbackfn: (value: V, key: K, map: Map) => void, thisArg?: any): void; get(key: K): V | undefined; has(key: K): boolean; set(key: K, value?: V): this; @@ -31,8 +31,14 @@ interface MapConstructor { } declare var Map: MapConstructor; +interface ReadonlyMap { + forEach(callbackfn: (value: V, key: K, map: ReadonlyMap) => void, thisArg?: any): void; + get(key: K): V|undefined; + has(key: K): boolean; + readonly size: number; +} + interface WeakMap { - clear(): void; delete(key: K): boolean; get(key: K): V | undefined; has(key: K): boolean; @@ -50,7 +56,7 @@ interface Set { add(value: T): this; clear(): void; delete(value: T): boolean; - forEach(callbackfn: (value: T, index: T, set: Set) => void, thisArg?: any): void; + forEach(callbackfn: (value: T, value2: T, set: Set) => void, thisArg?: any): void; has(value: T): boolean; readonly size: number; } @@ -62,9 +68,14 @@ interface SetConstructor { } declare var Set: SetConstructor; +interface ReadonlySet { + forEach(callbackfn: (value: T, value2: T, set: ReadonlySet) => void, thisArg?: any): void; + has(value: T): boolean; + readonly size: number; +} + interface WeakSet { add(value: T): this; - clear(): void; delete(value: T): boolean; has(value: T): boolean; } diff --git a/bin/lib.es2015.core.d.ts b/bin/lib.es2015.core.d.ts index f8eba59..49a81a2 100644 --- a/bin/lib.es2015.core.d.ts +++ b/bin/lib.es2015.core.d.ts @@ -29,15 +29,15 @@ interface Array { find(predicate: (value: T, index: number, obj: Array) => boolean, thisArg?: any): T | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending - * order, until it finds one where predicate returns true. If such an element is found, + * order, until it finds one where predicate returns true. If such an element is found, * findIndex immediately returns that element index. Otherwise, findIndex returns -1. * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: T) => boolean, thisArg?: any): number; + findIndex(predicate: (value: T, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Returns the this object after filling the section identified by start and end with value @@ -376,15 +376,15 @@ interface ReadonlyArray { find(predicate: (value: T, index: number, obj: ReadonlyArray) => boolean, thisArg?: any): T | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending - * order, until it finds one where predicate returns true. If such an element is found, + * order, until it finds one where predicate returns true. If such an element is found, * findIndex immediately returns that element index. Otherwise, findIndex returns -1. * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: T) => boolean, thisArg?: any): number; + findIndex(predicate: (value: T, index: number, obj: Array) => boolean, thisArg?: any): number; } interface RegExp { diff --git a/bin/lib.es2015.promise.d.ts b/bin/lib.es2015.promise.d.ts index 905cc13..36fe9e7 100644 --- a/bin/lib.es2015.promise.d.ts +++ b/bin/lib.es2015.promise.d.ts @@ -24,7 +24,7 @@ interface Promise { * @param onrejected The callback to execute when the Promise is rejected. * @returns A Promise for the completion of which ever callback is executed. */ - then(onfulfilled: (value: T) => TResult1 | PromiseLike, onrejected: (reason: any) => TResult2 | PromiseLike): Promise; + then(onfulfilled?: ((value: T) => T | PromiseLike) | undefined | null, onrejected?: ((reason: any) => T | PromiseLike) | undefined | null): Promise; /** * Attaches callbacks for the resolution and/or rejection of the Promise. @@ -32,34 +32,37 @@ interface Promise { * @param onrejected The callback to execute when the Promise is rejected. * @returns A Promise for the completion of which ever callback is executed. */ - then(onfulfilled: (value: T) => TResult | PromiseLike, onrejected: (reason: any) => TResult | PromiseLike): Promise; + then(onfulfilled: ((value: T) => T | PromiseLike) | undefined | null, onrejected: (reason: any) => TResult | PromiseLike): Promise; /** * Attaches callbacks for the resolution and/or rejection of the Promise. * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. * @returns A Promise for the completion of which ever callback is executed. */ - then(onfulfilled: (value: T) => TResult | PromiseLike): Promise; + then(onfulfilled: (value: T) => TResult | PromiseLike, onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): Promise; /** - * Creates a new Promise with the same internal state of this Promise. - * @returns A Promise. + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. */ - then(): Promise; + then(onfulfilled: (value: T) => TResult1 | PromiseLike, onrejected: (reason: any) => TResult2 | PromiseLike): Promise; /** * Attaches a callback for only the rejection of the Promise. * @param onrejected The callback to execute when the Promise is rejected. * @returns A Promise for the completion of the callback. */ - catch(onrejected: (reason: any) => TResult | PromiseLike): Promise; + catch(onrejected?: ((reason: any) => T | PromiseLike) | undefined | null): Promise; /** * Attaches a callback for only the rejection of the Promise. * @param onrejected The callback to execute when the Promise is rejected. * @returns A Promise for the completion of the callback. */ - catch(onrejected: (reason: any) => T | PromiseLike): Promise; + catch(onrejected: (reason: any) => TResult | PromiseLike): Promise; } interface PromiseConstructor { @@ -156,6 +159,86 @@ interface PromiseConstructor { */ all(values: (T | PromiseLike)[]): Promise; + /** + * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved + * or rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + race(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike, T9 | PromiseLike, T10 | PromiseLike]): Promise; + + /** + * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved + * or rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + race(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike, T9 | PromiseLike]): Promise; + + /** + * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved + * or rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + race(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike]): Promise; + + /** + * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved + * or rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + race(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike]): Promise; + + /** + * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved + * or rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + race(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike]): Promise; + + /** + * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved + * or rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + race(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike]): Promise; + + /** + * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved + * or rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + race(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike]): Promise; + + /** + * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved + * or rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + race(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike]): Promise; + + /** + * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved + * or rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + race(values: [T1 | PromiseLike, T2 | PromiseLike]): Promise; + + /** + * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved + * or rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + race(values: (T | PromiseLike)[]): Promise; + /** * Creates a new rejected promise for the provided reason. * @param reason The reason the promise was rejected. diff --git a/bin/lib.es2015.reflect.d.ts b/bin/lib.es2015.reflect.d.ts index c53cdaf..0f1a491 100644 --- a/bin/lib.es2015.reflect.d.ts +++ b/bin/lib.es2015.reflect.d.ts @@ -22,8 +22,7 @@ declare namespace Reflect { function get(target: any, propertyKey: PropertyKey, receiver?: any): any; function getOwnPropertyDescriptor(target: any, propertyKey: PropertyKey): PropertyDescriptor; function getPrototypeOf(target: any): any; - function has(target: any, propertyKey: string): boolean; - function has(target: any, propertyKey: symbol): boolean; + function has(target: any, propertyKey: PropertyKey): boolean; function isExtensible(target: any): boolean; function ownKeys(target: any): Array; function preventExtensions(target: any): boolean; diff --git a/bin/lib.es5.d.ts b/bin/lib.es5.d.ts index 666e5ef..5df0d7d 100644 --- a/bin/lib.es5.d.ts +++ b/bin/lib.es5.d.ts @@ -1076,6 +1076,12 @@ interface ReadonlyArray { * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. */ map(callbackfn: (value: T, index: number, array: ReadonlyArray) => U, thisArg?: any): U[]; + /** + * Returns the elements of an array that meet the condition specified in a callback function. + * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. + */ + filter(callbackfn: (value: T, index: number, array: ReadonlyArray) => value is S, thisArg?: any): S[]; /** * Returns the elements of an array that meet the condition specified in a callback function. * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array. @@ -1281,13 +1287,44 @@ declare type PromiseConstructorLike = new (executor: (resolve: (value?: T | P interface PromiseLike { /** - * Attaches callbacks for the resolution and/or rejection of the Promise. - * @param onfulfilled The callback to execute when the Promise is resolved. - * @param onrejected The callback to execute when the Promise is rejected. - * @returns A Promise for the completion of which ever callback is executed. - */ - then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => TResult | PromiseLike): PromiseLike; - then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => void): PromiseLike; + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then( + onfulfilled?: ((value: T) => T | PromiseLike) | undefined | null, + onrejected?: ((reason: any) => T | PromiseLike) | undefined | null): PromiseLike; + + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then( + onfulfilled: ((value: T) => T | PromiseLike) | undefined | null, + onrejected: (reason: any) => TResult | PromiseLike): PromiseLike; + + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then( + onfulfilled: (value: T) => TResult | PromiseLike, + onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): PromiseLike; + + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then( + onfulfilled: (value: T) => TResult1 | PromiseLike, + onrejected: (reason: any) => TResult2 | PromiseLike): PromiseLike; } interface ArrayLike { @@ -1547,7 +1584,7 @@ interface Int8Array { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -1555,7 +1592,7 @@ interface Int8Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -1820,7 +1857,7 @@ interface Uint8Array { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -1828,7 +1865,7 @@ interface Uint8Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -2094,7 +2131,7 @@ interface Uint8ClampedArray { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -2102,7 +2139,7 @@ interface Uint8ClampedArray { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -2367,7 +2404,7 @@ interface Int16Array { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -2375,7 +2412,7 @@ interface Int16Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -2641,7 +2678,7 @@ interface Uint16Array { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -2649,7 +2686,7 @@ interface Uint16Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -2914,7 +2951,7 @@ interface Int32Array { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -2922,7 +2959,7 @@ interface Int32Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -3187,7 +3224,7 @@ interface Uint32Array { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -3195,7 +3232,7 @@ interface Uint32Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -3460,7 +3497,7 @@ interface Float32Array { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -3468,7 +3505,7 @@ interface Float32Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -3734,7 +3771,7 @@ interface Float64Array { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -3742,7 +3779,7 @@ interface Float64Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -3959,12 +3996,9 @@ declare module Intl { resolvedOptions(): ResolvedCollatorOptions; } var Collator: { - new (locales?: string[], options?: CollatorOptions): Collator; - new (locale?: string, options?: CollatorOptions): Collator; - (locales?: string[], options?: CollatorOptions): Collator; - (locale?: string, options?: CollatorOptions): Collator; - supportedLocalesOf(locales: string[], options?: CollatorOptions): string[]; - supportedLocalesOf(locale: string, options?: CollatorOptions): string[]; + new (locales?: string | string[], options?: CollatorOptions): Collator; + (locales?: string | string[], options?: CollatorOptions): Collator; + supportedLocalesOf(locales: string | string[], options?: CollatorOptions): string[]; } interface NumberFormatOptions { @@ -3999,12 +4033,9 @@ declare module Intl { resolvedOptions(): ResolvedNumberFormatOptions; } var NumberFormat: { - new (locales?: string[], options?: NumberFormatOptions): NumberFormat; - new (locale?: string, options?: NumberFormatOptions): NumberFormat; - (locales?: string[], options?: NumberFormatOptions): NumberFormat; - (locale?: string, options?: NumberFormatOptions): NumberFormat; - supportedLocalesOf(locales: string[], options?: NumberFormatOptions): string[]; - supportedLocalesOf(locale: string, options?: NumberFormatOptions): string[]; + new (locales?: string | string[], options?: NumberFormatOptions): NumberFormat; + (locales?: string | string[], options?: NumberFormatOptions): NumberFormat; + supportedLocalesOf(locales: string | string[], options?: NumberFormatOptions): string[]; } interface DateTimeFormatOptions { @@ -4045,88 +4076,49 @@ declare module Intl { resolvedOptions(): ResolvedDateTimeFormatOptions; } var DateTimeFormat: { - new (locales?: string[], options?: DateTimeFormatOptions): DateTimeFormat; - new (locale?: string, options?: DateTimeFormatOptions): DateTimeFormat; - (locales?: string[], options?: DateTimeFormatOptions): DateTimeFormat; - (locale?: string, options?: DateTimeFormatOptions): DateTimeFormat; - supportedLocalesOf(locales: string[], options?: DateTimeFormatOptions): string[]; - supportedLocalesOf(locale: string, options?: DateTimeFormatOptions): string[]; + new (locales?: string | string[], options?: DateTimeFormatOptions): DateTimeFormat; + (locales?: string | string[], options?: DateTimeFormatOptions): DateTimeFormat; + supportedLocalesOf(locales: string | string[], options?: DateTimeFormatOptions): string[]; } } interface String { /** - * Determines whether two strings are equivalent in the current locale. + * Determines whether two strings are equivalent in the current or specified locale. * @param that String to compare to target string - * @param locales An array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. This parameter must conform to BCP 47 standards; see the Intl.Collator object for details. + * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. This parameter must conform to BCP 47 standards; see the Intl.Collator object for details. * @param options An object that contains one or more properties that specify comparison options. see the Intl.Collator object for details. */ - localeCompare(that: string, locales: string[], options?: Intl.CollatorOptions): number; - - /** - * Determines whether two strings are equivalent in the current locale. - * @param that String to compare to target string - * @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used. This parameter must conform to BCP 47 standards; see the Intl.Collator object for details. - * @param options An object that contains one or more properties that specify comparison options. see the Intl.Collator object for details. - */ - localeCompare(that: string, locale: string, options?: Intl.CollatorOptions): number; + localeCompare(that: string, locales?: string | string[], options?: Intl.CollatorOptions): number; } interface Number { /** * Converts a number to a string by using the current or specified locale. - * @param locales An array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. + * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. * @param options An object that contains one or more properties that specify comparison options. */ - toLocaleString(locales?: string[], options?: Intl.NumberFormatOptions): string; - - /** - * Converts a number to a string by using the current or specified locale. - * @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used. - * @param options An object that contains one or more properties that specify comparison options. - */ - toLocaleString(locale?: string, options?: Intl.NumberFormatOptions): string; + toLocaleString(locales?: string | string[], options?: Intl.NumberFormatOptions): string; } interface Date { /** * Converts a date and time to a string by using the current or specified locale. - * @param locales An array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. + * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. * @param options An object that contains one or more properties that specify comparison options. */ - toLocaleString(locales?: string[], options?: Intl.DateTimeFormatOptions): string; - /** - * Converts a date to a string by using the current or specified locale. - * @param locales An array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. - * @param options An object that contains one or more properties that specify comparison options. - */ - toLocaleDateString(locales?: string[], options?: Intl.DateTimeFormatOptions): string; - - /** - * Converts a time to a string by using the current or specified locale. - * @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used. - * @param options An object that contains one or more properties that specify comparison options. - */ - toLocaleTimeString(locale?: string[], options?: Intl.DateTimeFormatOptions): string; - - /** - * Converts a date and time to a string by using the current or specified locale. - * @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used. - * @param options An object that contains one or more properties that specify comparison options. - */ - toLocaleString(locale?: string, options?: Intl.DateTimeFormatOptions): string; - + toLocaleString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string; /** * Converts a date to a string by using the current or specified locale. - * @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used. + * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. * @param options An object that contains one or more properties that specify comparison options. */ - toLocaleDateString(locale?: string, options?: Intl.DateTimeFormatOptions): string; + toLocaleDateString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string; /** * Converts a time to a string by using the current or specified locale. - * @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used. + * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. * @param options An object that contains one or more properties that specify comparison options. */ - toLocaleTimeString(locale?: string, options?: Intl.DateTimeFormatOptions): string; + toLocaleTimeString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string; } diff --git a/bin/lib.es6.d.ts b/bin/lib.es6.d.ts index 084ed4e..23390a8 100644 --- a/bin/lib.es6.d.ts +++ b/bin/lib.es6.d.ts @@ -1076,6 +1076,12 @@ interface ReadonlyArray { * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. */ map(callbackfn: (value: T, index: number, array: ReadonlyArray) => U, thisArg?: any): U[]; + /** + * Returns the elements of an array that meet the condition specified in a callback function. + * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. + */ + filter(callbackfn: (value: T, index: number, array: ReadonlyArray) => value is S, thisArg?: any): S[]; /** * Returns the elements of an array that meet the condition specified in a callback function. * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array. @@ -1281,13 +1287,44 @@ declare type PromiseConstructorLike = new (executor: (resolve: (value?: T | P interface PromiseLike { /** - * Attaches callbacks for the resolution and/or rejection of the Promise. - * @param onfulfilled The callback to execute when the Promise is resolved. - * @param onrejected The callback to execute when the Promise is rejected. - * @returns A Promise for the completion of which ever callback is executed. - */ - then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => TResult | PromiseLike): PromiseLike; - then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => void): PromiseLike; + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then( + onfulfilled?: ((value: T) => T | PromiseLike) | undefined | null, + onrejected?: ((reason: any) => T | PromiseLike) | undefined | null): PromiseLike; + + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then( + onfulfilled: ((value: T) => T | PromiseLike) | undefined | null, + onrejected: (reason: any) => TResult | PromiseLike): PromiseLike; + + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then( + onfulfilled: (value: T) => TResult | PromiseLike, + onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): PromiseLike; + + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then( + onfulfilled: (value: T) => TResult1 | PromiseLike, + onrejected: (reason: any) => TResult2 | PromiseLike): PromiseLike; } interface ArrayLike { @@ -1547,7 +1584,7 @@ interface Int8Array { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -1555,7 +1592,7 @@ interface Int8Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -1820,7 +1857,7 @@ interface Uint8Array { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -1828,7 +1865,7 @@ interface Uint8Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -2094,7 +2131,7 @@ interface Uint8ClampedArray { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -2102,7 +2139,7 @@ interface Uint8ClampedArray { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -2367,7 +2404,7 @@ interface Int16Array { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -2375,7 +2412,7 @@ interface Int16Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -2641,7 +2678,7 @@ interface Uint16Array { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -2649,7 +2686,7 @@ interface Uint16Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -2914,7 +2951,7 @@ interface Int32Array { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -2922,7 +2959,7 @@ interface Int32Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -3187,7 +3224,7 @@ interface Uint32Array { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -3195,7 +3232,7 @@ interface Uint32Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -3460,7 +3497,7 @@ interface Float32Array { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -3468,7 +3505,7 @@ interface Float32Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -3734,7 +3771,7 @@ interface Float64Array { find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending * order, until it finds one where predicate returns true. If such an element is found, @@ -3742,7 +3779,7 @@ interface Float64Array { * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: number) => boolean, thisArg?: any): number; + findIndex(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. @@ -3959,12 +3996,9 @@ declare module Intl { resolvedOptions(): ResolvedCollatorOptions; } var Collator: { - new (locales?: string[], options?: CollatorOptions): Collator; - new (locale?: string, options?: CollatorOptions): Collator; - (locales?: string[], options?: CollatorOptions): Collator; - (locale?: string, options?: CollatorOptions): Collator; - supportedLocalesOf(locales: string[], options?: CollatorOptions): string[]; - supportedLocalesOf(locale: string, options?: CollatorOptions): string[]; + new (locales?: string | string[], options?: CollatorOptions): Collator; + (locales?: string | string[], options?: CollatorOptions): Collator; + supportedLocalesOf(locales: string | string[], options?: CollatorOptions): string[]; } interface NumberFormatOptions { @@ -3999,12 +4033,9 @@ declare module Intl { resolvedOptions(): ResolvedNumberFormatOptions; } var NumberFormat: { - new (locales?: string[], options?: NumberFormatOptions): NumberFormat; - new (locale?: string, options?: NumberFormatOptions): NumberFormat; - (locales?: string[], options?: NumberFormatOptions): NumberFormat; - (locale?: string, options?: NumberFormatOptions): NumberFormat; - supportedLocalesOf(locales: string[], options?: NumberFormatOptions): string[]; - supportedLocalesOf(locale: string, options?: NumberFormatOptions): string[]; + new (locales?: string | string[], options?: NumberFormatOptions): NumberFormat; + (locales?: string | string[], options?: NumberFormatOptions): NumberFormat; + supportedLocalesOf(locales: string | string[], options?: NumberFormatOptions): string[]; } interface DateTimeFormatOptions { @@ -4045,90 +4076,51 @@ declare module Intl { resolvedOptions(): ResolvedDateTimeFormatOptions; } var DateTimeFormat: { - new (locales?: string[], options?: DateTimeFormatOptions): DateTimeFormat; - new (locale?: string, options?: DateTimeFormatOptions): DateTimeFormat; - (locales?: string[], options?: DateTimeFormatOptions): DateTimeFormat; - (locale?: string, options?: DateTimeFormatOptions): DateTimeFormat; - supportedLocalesOf(locales: string[], options?: DateTimeFormatOptions): string[]; - supportedLocalesOf(locale: string, options?: DateTimeFormatOptions): string[]; + new (locales?: string | string[], options?: DateTimeFormatOptions): DateTimeFormat; + (locales?: string | string[], options?: DateTimeFormatOptions): DateTimeFormat; + supportedLocalesOf(locales: string | string[], options?: DateTimeFormatOptions): string[]; } } interface String { /** - * Determines whether two strings are equivalent in the current locale. - * @param that String to compare to target string - * @param locales An array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. This parameter must conform to BCP 47 standards; see the Intl.Collator object for details. - * @param options An object that contains one or more properties that specify comparison options. see the Intl.Collator object for details. - */ - localeCompare(that: string, locales: string[], options?: Intl.CollatorOptions): number; - - /** - * Determines whether two strings are equivalent in the current locale. + * Determines whether two strings are equivalent in the current or specified locale. * @param that String to compare to target string - * @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used. This parameter must conform to BCP 47 standards; see the Intl.Collator object for details. + * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. This parameter must conform to BCP 47 standards; see the Intl.Collator object for details. * @param options An object that contains one or more properties that specify comparison options. see the Intl.Collator object for details. */ - localeCompare(that: string, locale: string, options?: Intl.CollatorOptions): number; + localeCompare(that: string, locales?: string | string[], options?: Intl.CollatorOptions): number; } interface Number { /** * Converts a number to a string by using the current or specified locale. - * @param locales An array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. + * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. * @param options An object that contains one or more properties that specify comparison options. */ - toLocaleString(locales?: string[], options?: Intl.NumberFormatOptions): string; - - /** - * Converts a number to a string by using the current or specified locale. - * @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used. - * @param options An object that contains one or more properties that specify comparison options. - */ - toLocaleString(locale?: string, options?: Intl.NumberFormatOptions): string; + toLocaleString(locales?: string | string[], options?: Intl.NumberFormatOptions): string; } interface Date { /** * Converts a date and time to a string by using the current or specified locale. - * @param locales An array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. + * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. * @param options An object that contains one or more properties that specify comparison options. */ - toLocaleString(locales?: string[], options?: Intl.DateTimeFormatOptions): string; + toLocaleString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string; /** * Converts a date to a string by using the current or specified locale. - * @param locales An array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. + * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. * @param options An object that contains one or more properties that specify comparison options. */ - toLocaleDateString(locales?: string[], options?: Intl.DateTimeFormatOptions): string; + toLocaleDateString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string; /** * Converts a time to a string by using the current or specified locale. - * @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used. - * @param options An object that contains one or more properties that specify comparison options. - */ - toLocaleTimeString(locale?: string[], options?: Intl.DateTimeFormatOptions): string; - - /** - * Converts a date and time to a string by using the current or specified locale. - * @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used. + * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. * @param options An object that contains one or more properties that specify comparison options. */ - toLocaleString(locale?: string, options?: Intl.DateTimeFormatOptions): string; - - /** - * Converts a date to a string by using the current or specified locale. - * @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used. - * @param options An object that contains one or more properties that specify comparison options. - */ - toLocaleDateString(locale?: string, options?: Intl.DateTimeFormatOptions): string; - - /** - * Converts a time to a string by using the current or specified locale. - * @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used. - * @param options An object that contains one or more properties that specify comparison options. - */ - toLocaleTimeString(locale?: string, options?: Intl.DateTimeFormatOptions): string; + toLocaleTimeString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string; } declare type PropertyKey = string | number | symbol; @@ -4145,15 +4137,15 @@ interface Array { find(predicate: (value: T, index: number, obj: Array) => boolean, thisArg?: any): T | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending - * order, until it finds one where predicate returns true. If such an element is found, + * order, until it finds one where predicate returns true. If such an element is found, * findIndex immediately returns that element index. Otherwise, findIndex returns -1. * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: T) => boolean, thisArg?: any): number; + findIndex(predicate: (value: T, index: number, obj: Array) => boolean, thisArg?: any): number; /** * Returns the this object after filling the section identified by start and end with value @@ -4492,15 +4484,15 @@ interface ReadonlyArray { find(predicate: (value: T, index: number, obj: ReadonlyArray) => boolean, thisArg?: any): T | undefined; /** - * Returns the index of the first element in the array where predicate is true, and undefined + * Returns the index of the first element in the array where predicate is true, and -1 * otherwise. * @param predicate find calls predicate once for each element of the array, in ascending - * order, until it finds one where predicate returns true. If such an element is found, + * order, until it finds one where predicate returns true. If such an element is found, * findIndex immediately returns that element index. Otherwise, findIndex returns -1. * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ - findIndex(predicate: (value: T) => boolean, thisArg?: any): number; + findIndex(predicate: (value: T, index: number, obj: Array) => boolean, thisArg?: any): number; } interface RegExp { @@ -4657,7 +4649,7 @@ interface StringConstructor { interface Map { clear(): void; delete(key: K): boolean; - forEach(callbackfn: (value: V, index: K, map: Map) => void, thisArg?: any): void; + forEach(callbackfn: (value: V, key: K, map: Map) => void, thisArg?: any): void; get(key: K): V | undefined; has(key: K): boolean; set(key: K, value?: V): this; @@ -4671,8 +4663,14 @@ interface MapConstructor { } declare var Map: MapConstructor; +interface ReadonlyMap { + forEach(callbackfn: (value: V, key: K, map: ReadonlyMap) => void, thisArg?: any): void; + get(key: K): V|undefined; + has(key: K): boolean; + readonly size: number; +} + interface WeakMap { - clear(): void; delete(key: K): boolean; get(key: K): V | undefined; has(key: K): boolean; @@ -4690,7 +4688,7 @@ interface Set { add(value: T): this; clear(): void; delete(value: T): boolean; - forEach(callbackfn: (value: T, index: T, set: Set) => void, thisArg?: any): void; + forEach(callbackfn: (value: T, value2: T, set: Set) => void, thisArg?: any): void; has(value: T): boolean; readonly size: number; } @@ -4702,9 +4700,14 @@ interface SetConstructor { } declare var Set: SetConstructor; +interface ReadonlySet { + forEach(callbackfn: (value: T, value2: T, set: ReadonlySet) => void, thisArg?: any): void; + has(value: T): boolean; + readonly size: number; +} + interface WeakSet { add(value: T): this; - clear(): void; delete(value: T): boolean; has(value: T): boolean; } @@ -5181,7 +5184,7 @@ interface Promise { * @param onrejected The callback to execute when the Promise is rejected. * @returns A Promise for the completion of which ever callback is executed. */ - then(onfulfilled: (value: T) => TResult1 | PromiseLike, onrejected: (reason: any) => TResult2 | PromiseLike): Promise; + then(onfulfilled?: ((value: T) => T | PromiseLike) | undefined | null, onrejected?: ((reason: any) => T | PromiseLike) | undefined | null): Promise; /** * Attaches callbacks for the resolution and/or rejection of the Promise. @@ -5189,34 +5192,37 @@ interface Promise { * @param onrejected The callback to execute when the Promise is rejected. * @returns A Promise for the completion of which ever callback is executed. */ - then(onfulfilled: (value: T) => TResult | PromiseLike, onrejected: (reason: any) => TResult | PromiseLike): Promise; + then(onfulfilled: ((value: T) => T | PromiseLike) | undefined | null, onrejected: (reason: any) => TResult | PromiseLike): Promise; /** * Attaches callbacks for the resolution and/or rejection of the Promise. * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. * @returns A Promise for the completion of which ever callback is executed. */ - then(onfulfilled: (value: T) => TResult | PromiseLike): Promise; + then(onfulfilled: (value: T) => TResult | PromiseLike, onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): Promise; /** - * Creates a new Promise with the same internal state of this Promise. - * @returns A Promise. + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. */ - then(): Promise; + then(onfulfilled: (value: T) => TResult1 | PromiseLike, onrejected: (reason: any) => TResult2 | PromiseLike): Promise; /** * Attaches a callback for only the rejection of the Promise. * @param onrejected The callback to execute when the Promise is rejected. * @returns A Promise for the completion of the callback. */ - catch(onrejected: (reason: any) => TResult | PromiseLike): Promise; + catch(onrejected?: ((reason: any) => T | PromiseLike) | undefined | null): Promise; /** * Attaches a callback for only the rejection of the Promise. * @param onrejected The callback to execute when the Promise is rejected. * @returns A Promise for the completion of the callback. */ - catch(onrejected: (reason: any) => T | PromiseLike): Promise; + catch(onrejected: (reason: any) => TResult | PromiseLike): Promise; } interface PromiseConstructor { @@ -5313,6 +5319,86 @@ interface PromiseConstructor { */ all(values: (T | PromiseLike)[]): Promise; + /** + * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved + * or rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + race(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike, T9 | PromiseLike, T10 | PromiseLike]): Promise; + + /** + * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved + * or rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + race(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike, T9 | PromiseLike]): Promise; + + /** + * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved + * or rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + race(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike]): Promise; + + /** + * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved + * or rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + race(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike]): Promise; + + /** + * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved + * or rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + race(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike]): Promise; + + /** + * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved + * or rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + race(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike]): Promise; + + /** + * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved + * or rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + race(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike]): Promise; + + /** + * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved + * or rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + race(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike]): Promise; + + /** + * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved + * or rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + race(values: [T1 | PromiseLike, T2 | PromiseLike]): Promise; + + /** + * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved + * or rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + race(values: (T | PromiseLike)[]): Promise; + /** * Creates a new rejected promise for the provided reason. * @param reason The reason the promise was rejected. @@ -5370,8 +5456,7 @@ declare var Proxy: ProxyConstructor;declare namespace Reflect { function get(target: any, propertyKey: PropertyKey, receiver?: any): any; function getOwnPropertyDescriptor(target: any, propertyKey: PropertyKey): PropertyDescriptor; function getPrototypeOf(target: any): any; - function has(target: any, propertyKey: string): boolean; - function has(target: any, propertyKey: symbol): boolean; + function has(target: any, propertyKey: PropertyKey): boolean; function isExtensible(target: any): boolean; function ownKeys(target: any): Array; function preventExtensions(target: any): boolean; @@ -13276,11 +13361,12 @@ declare var HashChangeEvent: { interface History { readonly length: number; readonly state: any; - back(distance?: any): void; - forward(distance?: any): void; - go(delta?: any): void; - pushState(statedata: any, title?: string, url?: string): void; - replaceState(statedata: any, title?: string, url?: string): void; + scrollRestoration: ScrollRestoration; + back(): void; + forward(): void; + go(delta?: number): void; + pushState(data: any, title: string, url?: string | null): void; + replaceState(data: any, title: string, url?: string | null): void; } declare var History: { @@ -18852,7 +18938,6 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window addEventListener(type: "waiting", listener: (this: this, ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "wheel", listener: (this: this, ev: WheelEvent) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; - [index: number]: Window; } declare var Window: { @@ -18883,7 +18968,7 @@ declare var XMLDocument: { } interface XMLHttpRequest extends EventTarget, XMLHttpRequestEventTarget { - onreadystatechange: (this: this, ev: ProgressEvent) => any; + onreadystatechange: (this: this, ev: Event) => any; readonly readyState: number; readonly response: any; readonly responseText: string; @@ -18910,13 +18995,13 @@ interface XMLHttpRequest extends EventTarget, XMLHttpRequestEventTarget { readonly LOADING: number; readonly OPENED: number; readonly UNSENT: number; - addEventListener(type: "abort", listener: (this: this, ev: Event) => any, useCapture?: boolean): void; - addEventListener(type: "error", listener: (this: this, ev: ErrorEvent) => any, useCapture?: boolean): void; - addEventListener(type: "load", listener: (this: this, ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "abort", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; + addEventListener(type: "error", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; + addEventListener(type: "load", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; addEventListener(type: "loadend", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; - addEventListener(type: "loadstart", listener: (this: this, ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "loadstart", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; addEventListener(type: "progress", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; - addEventListener(type: "readystatechange", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; + addEventListener(type: "readystatechange", listener: (this: this, ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "timeout", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -19257,183 +19342,183 @@ interface NavigatorUserMedia { } interface NodeSelector { - querySelector(selectors: "a"): HTMLAnchorElement; - querySelector(selectors: "abbr"): HTMLElement; - querySelector(selectors: "acronym"): HTMLElement; - querySelector(selectors: "address"): HTMLElement; - querySelector(selectors: "applet"): HTMLAppletElement; - querySelector(selectors: "area"): HTMLAreaElement; - querySelector(selectors: "article"): HTMLElement; - querySelector(selectors: "aside"): HTMLElement; - querySelector(selectors: "audio"): HTMLAudioElement; - querySelector(selectors: "b"): HTMLElement; - querySelector(selectors: "base"): HTMLBaseElement; - querySelector(selectors: "basefont"): HTMLBaseFontElement; - querySelector(selectors: "bdo"): HTMLElement; - querySelector(selectors: "big"): HTMLElement; - querySelector(selectors: "blockquote"): HTMLQuoteElement; - querySelector(selectors: "body"): HTMLBodyElement; - querySelector(selectors: "br"): HTMLBRElement; - querySelector(selectors: "button"): HTMLButtonElement; - querySelector(selectors: "canvas"): HTMLCanvasElement; - querySelector(selectors: "caption"): HTMLTableCaptionElement; - querySelector(selectors: "center"): HTMLElement; - querySelector(selectors: "circle"): SVGCircleElement; - querySelector(selectors: "cite"): HTMLElement; - querySelector(selectors: "clippath"): SVGClipPathElement; - querySelector(selectors: "code"): HTMLElement; - querySelector(selectors: "col"): HTMLTableColElement; - querySelector(selectors: "colgroup"): HTMLTableColElement; - querySelector(selectors: "datalist"): HTMLDataListElement; - querySelector(selectors: "dd"): HTMLElement; - querySelector(selectors: "defs"): SVGDefsElement; - querySelector(selectors: "del"): HTMLModElement; - querySelector(selectors: "desc"): SVGDescElement; - querySelector(selectors: "dfn"): HTMLElement; - querySelector(selectors: "dir"): HTMLDirectoryElement; - querySelector(selectors: "div"): HTMLDivElement; - querySelector(selectors: "dl"): HTMLDListElement; - querySelector(selectors: "dt"): HTMLElement; - querySelector(selectors: "ellipse"): SVGEllipseElement; - querySelector(selectors: "em"): HTMLElement; - querySelector(selectors: "embed"): HTMLEmbedElement; - querySelector(selectors: "feblend"): SVGFEBlendElement; - querySelector(selectors: "fecolormatrix"): SVGFEColorMatrixElement; - querySelector(selectors: "fecomponenttransfer"): SVGFEComponentTransferElement; - querySelector(selectors: "fecomposite"): SVGFECompositeElement; - querySelector(selectors: "feconvolvematrix"): SVGFEConvolveMatrixElement; - querySelector(selectors: "fediffuselighting"): SVGFEDiffuseLightingElement; - querySelector(selectors: "fedisplacementmap"): SVGFEDisplacementMapElement; - querySelector(selectors: "fedistantlight"): SVGFEDistantLightElement; - querySelector(selectors: "feflood"): SVGFEFloodElement; - querySelector(selectors: "fefunca"): SVGFEFuncAElement; - querySelector(selectors: "fefuncb"): SVGFEFuncBElement; - querySelector(selectors: "fefuncg"): SVGFEFuncGElement; - querySelector(selectors: "fefuncr"): SVGFEFuncRElement; - querySelector(selectors: "fegaussianblur"): SVGFEGaussianBlurElement; - querySelector(selectors: "feimage"): SVGFEImageElement; - querySelector(selectors: "femerge"): SVGFEMergeElement; - querySelector(selectors: "femergenode"): SVGFEMergeNodeElement; - querySelector(selectors: "femorphology"): SVGFEMorphologyElement; - querySelector(selectors: "feoffset"): SVGFEOffsetElement; - querySelector(selectors: "fepointlight"): SVGFEPointLightElement; - querySelector(selectors: "fespecularlighting"): SVGFESpecularLightingElement; - querySelector(selectors: "fespotlight"): SVGFESpotLightElement; - querySelector(selectors: "fetile"): SVGFETileElement; - querySelector(selectors: "feturbulence"): SVGFETurbulenceElement; - querySelector(selectors: "fieldset"): HTMLFieldSetElement; - querySelector(selectors: "figcaption"): HTMLElement; - querySelector(selectors: "figure"): HTMLElement; - querySelector(selectors: "filter"): SVGFilterElement; - querySelector(selectors: "font"): HTMLFontElement; - querySelector(selectors: "footer"): HTMLElement; - querySelector(selectors: "foreignobject"): SVGForeignObjectElement; - querySelector(selectors: "form"): HTMLFormElement; - querySelector(selectors: "frame"): HTMLFrameElement; - querySelector(selectors: "frameset"): HTMLFrameSetElement; - querySelector(selectors: "g"): SVGGElement; - querySelector(selectors: "h1"): HTMLHeadingElement; - querySelector(selectors: "h2"): HTMLHeadingElement; - querySelector(selectors: "h3"): HTMLHeadingElement; - querySelector(selectors: "h4"): HTMLHeadingElement; - querySelector(selectors: "h5"): HTMLHeadingElement; - querySelector(selectors: "h6"): HTMLHeadingElement; - querySelector(selectors: "head"): HTMLHeadElement; - querySelector(selectors: "header"): HTMLElement; - querySelector(selectors: "hgroup"): HTMLElement; - querySelector(selectors: "hr"): HTMLHRElement; - querySelector(selectors: "html"): HTMLHtmlElement; - querySelector(selectors: "i"): HTMLElement; - querySelector(selectors: "iframe"): HTMLIFrameElement; - querySelector(selectors: "image"): SVGImageElement; - querySelector(selectors: "img"): HTMLImageElement; - querySelector(selectors: "input"): HTMLInputElement; - querySelector(selectors: "ins"): HTMLModElement; - querySelector(selectors: "isindex"): HTMLUnknownElement; - querySelector(selectors: "kbd"): HTMLElement; - querySelector(selectors: "keygen"): HTMLElement; - querySelector(selectors: "label"): HTMLLabelElement; - querySelector(selectors: "legend"): HTMLLegendElement; - querySelector(selectors: "li"): HTMLLIElement; - querySelector(selectors: "line"): SVGLineElement; - querySelector(selectors: "lineargradient"): SVGLinearGradientElement; - querySelector(selectors: "link"): HTMLLinkElement; - querySelector(selectors: "listing"): HTMLPreElement; - querySelector(selectors: "map"): HTMLMapElement; - querySelector(selectors: "mark"): HTMLElement; - querySelector(selectors: "marker"): SVGMarkerElement; - querySelector(selectors: "marquee"): HTMLMarqueeElement; - querySelector(selectors: "mask"): SVGMaskElement; - querySelector(selectors: "menu"): HTMLMenuElement; - querySelector(selectors: "meta"): HTMLMetaElement; - querySelector(selectors: "metadata"): SVGMetadataElement; - querySelector(selectors: "meter"): HTMLMeterElement; - querySelector(selectors: "nav"): HTMLElement; - querySelector(selectors: "nextid"): HTMLUnknownElement; - querySelector(selectors: "nobr"): HTMLElement; - querySelector(selectors: "noframes"): HTMLElement; - querySelector(selectors: "noscript"): HTMLElement; - querySelector(selectors: "object"): HTMLObjectElement; - querySelector(selectors: "ol"): HTMLOListElement; - querySelector(selectors: "optgroup"): HTMLOptGroupElement; - querySelector(selectors: "option"): HTMLOptionElement; - querySelector(selectors: "p"): HTMLParagraphElement; - querySelector(selectors: "param"): HTMLParamElement; - querySelector(selectors: "path"): SVGPathElement; - querySelector(selectors: "pattern"): SVGPatternElement; - querySelector(selectors: "picture"): HTMLPictureElement; - querySelector(selectors: "plaintext"): HTMLElement; - querySelector(selectors: "polygon"): SVGPolygonElement; - querySelector(selectors: "polyline"): SVGPolylineElement; - querySelector(selectors: "pre"): HTMLPreElement; - querySelector(selectors: "progress"): HTMLProgressElement; - querySelector(selectors: "q"): HTMLQuoteElement; - querySelector(selectors: "radialgradient"): SVGRadialGradientElement; - querySelector(selectors: "rect"): SVGRectElement; - querySelector(selectors: "rt"): HTMLElement; - querySelector(selectors: "ruby"): HTMLElement; - querySelector(selectors: "s"): HTMLElement; - querySelector(selectors: "samp"): HTMLElement; - querySelector(selectors: "script"): HTMLScriptElement; - querySelector(selectors: "section"): HTMLElement; - querySelector(selectors: "select"): HTMLSelectElement; - querySelector(selectors: "small"): HTMLElement; - querySelector(selectors: "source"): HTMLSourceElement; - querySelector(selectors: "span"): HTMLSpanElement; - querySelector(selectors: "stop"): SVGStopElement; - querySelector(selectors: "strike"): HTMLElement; - querySelector(selectors: "strong"): HTMLElement; - querySelector(selectors: "style"): HTMLStyleElement; - querySelector(selectors: "sub"): HTMLElement; - querySelector(selectors: "sup"): HTMLElement; - querySelector(selectors: "svg"): SVGSVGElement; - querySelector(selectors: "switch"): SVGSwitchElement; - querySelector(selectors: "symbol"): SVGSymbolElement; - querySelector(selectors: "table"): HTMLTableElement; - querySelector(selectors: "tbody"): HTMLTableSectionElement; - querySelector(selectors: "td"): HTMLTableDataCellElement; - querySelector(selectors: "template"): HTMLTemplateElement; - querySelector(selectors: "text"): SVGTextElement; - querySelector(selectors: "textpath"): SVGTextPathElement; - querySelector(selectors: "textarea"): HTMLTextAreaElement; - querySelector(selectors: "tfoot"): HTMLTableSectionElement; - querySelector(selectors: "th"): HTMLTableHeaderCellElement; - querySelector(selectors: "thead"): HTMLTableSectionElement; - querySelector(selectors: "title"): HTMLTitleElement; - querySelector(selectors: "tr"): HTMLTableRowElement; - querySelector(selectors: "track"): HTMLTrackElement; - querySelector(selectors: "tspan"): SVGTSpanElement; - querySelector(selectors: "tt"): HTMLElement; - querySelector(selectors: "u"): HTMLElement; - querySelector(selectors: "ul"): HTMLUListElement; - querySelector(selectors: "use"): SVGUseElement; - querySelector(selectors: "var"): HTMLElement; - querySelector(selectors: "video"): HTMLVideoElement; - querySelector(selectors: "view"): SVGViewElement; - querySelector(selectors: "wbr"): HTMLElement; - querySelector(selectors: "x-ms-webview"): MSHTMLWebViewElement; - querySelector(selectors: "xmp"): HTMLPreElement; - querySelector(selectors: string): Element; + querySelector(selectors: "a"): HTMLAnchorElement | null; + querySelector(selectors: "abbr"): HTMLElement | null; + querySelector(selectors: "acronym"): HTMLElement | null; + querySelector(selectors: "address"): HTMLElement | null; + querySelector(selectors: "applet"): HTMLAppletElement | null; + querySelector(selectors: "area"): HTMLAreaElement | null; + querySelector(selectors: "article"): HTMLElement | null; + querySelector(selectors: "aside"): HTMLElement | null; + querySelector(selectors: "audio"): HTMLAudioElement | null; + querySelector(selectors: "b"): HTMLElement | null; + querySelector(selectors: "base"): HTMLBaseElement | null; + querySelector(selectors: "basefont"): HTMLBaseFontElement | null; + querySelector(selectors: "bdo"): HTMLElement | null; + querySelector(selectors: "big"): HTMLElement | null; + querySelector(selectors: "blockquote"): HTMLQuoteElement | null; + querySelector(selectors: "body"): HTMLBodyElement | null; + querySelector(selectors: "br"): HTMLBRElement | null; + querySelector(selectors: "button"): HTMLButtonElement | null; + querySelector(selectors: "canvas"): HTMLCanvasElement | null; + querySelector(selectors: "caption"): HTMLTableCaptionElement | null; + querySelector(selectors: "center"): HTMLElement | null; + querySelector(selectors: "circle"): SVGCircleElement | null; + querySelector(selectors: "cite"): HTMLElement | null; + querySelector(selectors: "clippath"): SVGClipPathElement | null; + querySelector(selectors: "code"): HTMLElement | null; + querySelector(selectors: "col"): HTMLTableColElement | null; + querySelector(selectors: "colgroup"): HTMLTableColElement | null; + querySelector(selectors: "datalist"): HTMLDataListElement | null; + querySelector(selectors: "dd"): HTMLElement | null; + querySelector(selectors: "defs"): SVGDefsElement | null; + querySelector(selectors: "del"): HTMLModElement | null; + querySelector(selectors: "desc"): SVGDescElement | null; + querySelector(selectors: "dfn"): HTMLElement | null; + querySelector(selectors: "dir"): HTMLDirectoryElement | null; + querySelector(selectors: "div"): HTMLDivElement | null; + querySelector(selectors: "dl"): HTMLDListElement | null; + querySelector(selectors: "dt"): HTMLElement | null; + querySelector(selectors: "ellipse"): SVGEllipseElement | null; + querySelector(selectors: "em"): HTMLElement | null; + querySelector(selectors: "embed"): HTMLEmbedElement | null; + querySelector(selectors: "feblend"): SVGFEBlendElement | null; + querySelector(selectors: "fecolormatrix"): SVGFEColorMatrixElement | null; + querySelector(selectors: "fecomponenttransfer"): SVGFEComponentTransferElement | null; + querySelector(selectors: "fecomposite"): SVGFECompositeElement | null; + querySelector(selectors: "feconvolvematrix"): SVGFEConvolveMatrixElement | null; + querySelector(selectors: "fediffuselighting"): SVGFEDiffuseLightingElement | null; + querySelector(selectors: "fedisplacementmap"): SVGFEDisplacementMapElement | null; + querySelector(selectors: "fedistantlight"): SVGFEDistantLightElement | null; + querySelector(selectors: "feflood"): SVGFEFloodElement | null; + querySelector(selectors: "fefunca"): SVGFEFuncAElement | null; + querySelector(selectors: "fefuncb"): SVGFEFuncBElement | null; + querySelector(selectors: "fefuncg"): SVGFEFuncGElement | null; + querySelector(selectors: "fefuncr"): SVGFEFuncRElement | null; + querySelector(selectors: "fegaussianblur"): SVGFEGaussianBlurElement | null; + querySelector(selectors: "feimage"): SVGFEImageElement | null; + querySelector(selectors: "femerge"): SVGFEMergeElement | null; + querySelector(selectors: "femergenode"): SVGFEMergeNodeElement | null; + querySelector(selectors: "femorphology"): SVGFEMorphologyElement | null; + querySelector(selectors: "feoffset"): SVGFEOffsetElement | null; + querySelector(selectors: "fepointlight"): SVGFEPointLightElement | null; + querySelector(selectors: "fespecularlighting"): SVGFESpecularLightingElement | null; + querySelector(selectors: "fespotlight"): SVGFESpotLightElement | null; + querySelector(selectors: "fetile"): SVGFETileElement | null; + querySelector(selectors: "feturbulence"): SVGFETurbulenceElement | null; + querySelector(selectors: "fieldset"): HTMLFieldSetElement | null; + querySelector(selectors: "figcaption"): HTMLElement | null; + querySelector(selectors: "figure"): HTMLElement | null; + querySelector(selectors: "filter"): SVGFilterElement | null; + querySelector(selectors: "font"): HTMLFontElement | null; + querySelector(selectors: "footer"): HTMLElement | null; + querySelector(selectors: "foreignobject"): SVGForeignObjectElement | null; + querySelector(selectors: "form"): HTMLFormElement | null; + querySelector(selectors: "frame"): HTMLFrameElement | null; + querySelector(selectors: "frameset"): HTMLFrameSetElement | null; + querySelector(selectors: "g"): SVGGElement | null; + querySelector(selectors: "h1"): HTMLHeadingElement | null; + querySelector(selectors: "h2"): HTMLHeadingElement | null; + querySelector(selectors: "h3"): HTMLHeadingElement | null; + querySelector(selectors: "h4"): HTMLHeadingElement | null; + querySelector(selectors: "h5"): HTMLHeadingElement | null; + querySelector(selectors: "h6"): HTMLHeadingElement | null; + querySelector(selectors: "head"): HTMLHeadElement | null; + querySelector(selectors: "header"): HTMLElement | null; + querySelector(selectors: "hgroup"): HTMLElement | null; + querySelector(selectors: "hr"): HTMLHRElement | null; + querySelector(selectors: "html"): HTMLHtmlElement | null; + querySelector(selectors: "i"): HTMLElement | null; + querySelector(selectors: "iframe"): HTMLIFrameElement | null; + querySelector(selectors: "image"): SVGImageElement | null; + querySelector(selectors: "img"): HTMLImageElement | null; + querySelector(selectors: "input"): HTMLInputElement | null; + querySelector(selectors: "ins"): HTMLModElement | null; + querySelector(selectors: "isindex"): HTMLUnknownElement | null; + querySelector(selectors: "kbd"): HTMLElement | null; + querySelector(selectors: "keygen"): HTMLElement | null; + querySelector(selectors: "label"): HTMLLabelElement | null; + querySelector(selectors: "legend"): HTMLLegendElement | null; + querySelector(selectors: "li"): HTMLLIElement | null; + querySelector(selectors: "line"): SVGLineElement | null; + querySelector(selectors: "lineargradient"): SVGLinearGradientElement | null; + querySelector(selectors: "link"): HTMLLinkElement | null; + querySelector(selectors: "listing"): HTMLPreElement | null; + querySelector(selectors: "map"): HTMLMapElement | null; + querySelector(selectors: "mark"): HTMLElement | null; + querySelector(selectors: "marker"): SVGMarkerElement | null; + querySelector(selectors: "marquee"): HTMLMarqueeElement | null; + querySelector(selectors: "mask"): SVGMaskElement | null; + querySelector(selectors: "menu"): HTMLMenuElement | null; + querySelector(selectors: "meta"): HTMLMetaElement | null; + querySelector(selectors: "metadata"): SVGMetadataElement | null; + querySelector(selectors: "meter"): HTMLMeterElement | null; + querySelector(selectors: "nav"): HTMLElement | null; + querySelector(selectors: "nextid"): HTMLUnknownElement | null; + querySelector(selectors: "nobr"): HTMLElement | null; + querySelector(selectors: "noframes"): HTMLElement | null; + querySelector(selectors: "noscript"): HTMLElement | null; + querySelector(selectors: "object"): HTMLObjectElement | null; + querySelector(selectors: "ol"): HTMLOListElement | null; + querySelector(selectors: "optgroup"): HTMLOptGroupElement | null; + querySelector(selectors: "option"): HTMLOptionElement | null; + querySelector(selectors: "p"): HTMLParagraphElement | null; + querySelector(selectors: "param"): HTMLParamElement | null; + querySelector(selectors: "path"): SVGPathElement | null; + querySelector(selectors: "pattern"): SVGPatternElement | null; + querySelector(selectors: "picture"): HTMLPictureElement | null; + querySelector(selectors: "plaintext"): HTMLElement | null; + querySelector(selectors: "polygon"): SVGPolygonElement | null; + querySelector(selectors: "polyline"): SVGPolylineElement | null; + querySelector(selectors: "pre"): HTMLPreElement | null; + querySelector(selectors: "progress"): HTMLProgressElement | null; + querySelector(selectors: "q"): HTMLQuoteElement | null; + querySelector(selectors: "radialgradient"): SVGRadialGradientElement | null; + querySelector(selectors: "rect"): SVGRectElement | null; + querySelector(selectors: "rt"): HTMLElement | null; + querySelector(selectors: "ruby"): HTMLElement | null; + querySelector(selectors: "s"): HTMLElement | null; + querySelector(selectors: "samp"): HTMLElement | null; + querySelector(selectors: "script"): HTMLScriptElement | null; + querySelector(selectors: "section"): HTMLElement | null; + querySelector(selectors: "select"): HTMLSelectElement | null; + querySelector(selectors: "small"): HTMLElement | null; + querySelector(selectors: "source"): HTMLSourceElement | null; + querySelector(selectors: "span"): HTMLSpanElement | null; + querySelector(selectors: "stop"): SVGStopElement | null; + querySelector(selectors: "strike"): HTMLElement | null; + querySelector(selectors: "strong"): HTMLElement | null; + querySelector(selectors: "style"): HTMLStyleElement | null; + querySelector(selectors: "sub"): HTMLElement | null; + querySelector(selectors: "sup"): HTMLElement | null; + querySelector(selectors: "svg"): SVGSVGElement | null; + querySelector(selectors: "switch"): SVGSwitchElement | null; + querySelector(selectors: "symbol"): SVGSymbolElement | null; + querySelector(selectors: "table"): HTMLTableElement | null; + querySelector(selectors: "tbody"): HTMLTableSectionElement | null; + querySelector(selectors: "td"): HTMLTableDataCellElement | null; + querySelector(selectors: "template"): HTMLTemplateElement | null; + querySelector(selectors: "text"): SVGTextElement | null; + querySelector(selectors: "textpath"): SVGTextPathElement | null; + querySelector(selectors: "textarea"): HTMLTextAreaElement | null; + querySelector(selectors: "tfoot"): HTMLTableSectionElement | null; + querySelector(selectors: "th"): HTMLTableHeaderCellElement | null; + querySelector(selectors: "thead"): HTMLTableSectionElement | null; + querySelector(selectors: "title"): HTMLTitleElement | null; + querySelector(selectors: "tr"): HTMLTableRowElement | null; + querySelector(selectors: "track"): HTMLTrackElement | null; + querySelector(selectors: "tspan"): SVGTSpanElement | null; + querySelector(selectors: "tt"): HTMLElement | null; + querySelector(selectors: "u"): HTMLElement | null; + querySelector(selectors: "ul"): HTMLUListElement | null; + querySelector(selectors: "use"): SVGUseElement | null; + querySelector(selectors: "var"): HTMLElement | null; + querySelector(selectors: "video"): HTMLVideoElement | null; + querySelector(selectors: "view"): SVGViewElement | null; + querySelector(selectors: "wbr"): HTMLElement | null; + querySelector(selectors: "x-ms-webview"): MSHTMLWebViewElement | null; + querySelector(selectors: "xmp"): HTMLPreElement | null; + querySelector(selectors: string): Element | null; querySelectorAll(selectors: "a"): NodeListOf; querySelectorAll(selectors: "abbr"): NodeListOf; querySelectorAll(selectors: "acronym"): NodeListOf; @@ -20363,6 +20448,7 @@ type ScrollLogicalPosition = "start" | "center" | "end" | "nearest"; type IDBValidKey = number | string | Date | IDBArrayKey; type BufferSource = ArrayBuffer | ArrayBufferView; type MouseWheelEvent = WheelEvent; +type ScrollRestoration = "auto" | "manual"; ///////////////////////////// /// WorkerGlobalScope APIs ///////////////////////////// @@ -20659,7 +20745,7 @@ interface DateConstructor { interface Date { getVarDate: () => VarDate; } -/// +/// interface DOMTokenList { [Symbol.iterator](): IterableIterator; diff --git a/bin/lib.webworker.d.ts b/bin/lib.webworker.d.ts index 5b35d82..6cb14c5 100644 --- a/bin/lib.webworker.d.ts +++ b/bin/lib.webworker.d.ts @@ -744,7 +744,7 @@ declare var Worker: { } interface XMLHttpRequest extends EventTarget, XMLHttpRequestEventTarget { - onreadystatechange: (this: this, ev: ProgressEvent) => any; + onreadystatechange: (this: this, ev: Event) => any; readonly readyState: number; readonly response: any; readonly responseText: string; @@ -770,13 +770,13 @@ interface XMLHttpRequest extends EventTarget, XMLHttpRequestEventTarget { readonly LOADING: number; readonly OPENED: number; readonly UNSENT: number; - addEventListener(type: "abort", listener: (this: this, ev: Event) => any, useCapture?: boolean): void; - addEventListener(type: "error", listener: (this: this, ev: ErrorEvent) => any, useCapture?: boolean): void; - addEventListener(type: "load", listener: (this: this, ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "abort", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; + addEventListener(type: "error", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; + addEventListener(type: "load", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; addEventListener(type: "loadend", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; - addEventListener(type: "loadstart", listener: (this: this, ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "loadstart", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; addEventListener(type: "progress", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; - addEventListener(type: "readystatechange", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; + addEventListener(type: "readystatechange", listener: (this: this, ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "timeout", listener: (this: this, ev: ProgressEvent) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } diff --git a/bin/ntypescript.d.ts b/bin/ntypescript.d.ts index 7e622ca..0f242ff 100644 --- a/bin/ntypescript.d.ts +++ b/bin/ntypescript.d.ts @@ -14,6 +14,7 @@ declare namespace ts { contains(fileName: Path): boolean; remove(fileName: Path): void; forEachValue(f: (key: Path, v: T) => void): void; + getKeys(): Path[]; clear(): void; } interface TextRange { @@ -308,9 +309,13 @@ declare namespace ts { JSDocUndefinedKeyword = 284, JSDocNeverKeyword = 285, SyntaxList = 286, - Count = 287, + NotEmittedStatement = 287, + PartiallyEmittedExpression = 288, + Count = 289, FirstAssignment = 56, LastAssignment = 68, + FirstCompoundAssignment = 57, + LastCompoundAssignment = 68, FirstReservedWord = 70, LastReservedWord = 105, FirstKeyword = 70, @@ -338,6 +343,39 @@ declare namespace ts { LastJSDocTagNode = 285, } enum NodeFlags { + None = 0, + Let = 1, + Const = 2, + NestedNamespace = 4, + Synthesized = 8, + Namespace = 16, + ExportContext = 32, + ContainsThis = 64, + HasImplicitReturn = 128, + HasExplicitReturn = 256, + GlobalAugmentation = 512, + HasClassExtends = 1024, + HasDecorators = 2048, + HasParamDecorators = 4096, + HasAsyncFunctions = 8192, + HasJsxSpreadAttributes = 16384, + DisallowInContext = 32768, + YieldContext = 65536, + DecoratorContext = 131072, + AwaitContext = 262144, + ThisNodeHasError = 524288, + JavaScriptFile = 1048576, + ThisNodeOrAnySubNodesHasError = 2097152, + HasAggregatedChildData = 4194304, + BlockScoped = 3, + ReachabilityCheckFlags = 384, + EmitHelperFlags = 31744, + ReachabilityAndEmitFlags = 32128, + ContextFlags = 1540096, + TypeExcludesFlags = 327680, + } + type ModifiersArray = NodeArray; + enum ModifierFlags { None = 0, Export = 1, Ambient = 2, @@ -349,36 +387,11 @@ declare namespace ts { Abstract = 128, Async = 256, Default = 512, - Let = 1024, Const = 2048, - Namespace = 4096, - ExportContext = 8192, - ContainsThis = 16384, - HasImplicitReturn = 32768, - HasExplicitReturn = 65536, - GlobalAugmentation = 131072, - HasClassExtends = 262144, - HasDecorators = 524288, - HasParamDecorators = 1048576, - HasAsyncFunctions = 2097152, - DisallowInContext = 4194304, - YieldContext = 8388608, - DecoratorContext = 16777216, - AwaitContext = 33554432, - ThisNodeHasError = 67108864, - JavaScriptFile = 134217728, - ThisNodeOrAnySubNodesHasError = 268435456, - HasAggregatedChildData = 536870912, - HasJsxSpreadAttribute = 1073741824, - Modifier = 1023, + HasComputedFlags = 536870912, AccessibilityModifier = 28, ParameterPropertyModifier = 92, - BlockScoped = 3072, - ReachabilityCheckFlags = 98304, - EmitHelperFlags = 3932160, - ReachabilityAndEmitFlags = 4030464, - ContextFlags = 197132288, - TypeExcludesFlags = 41943040, + NonPublicAccessibilityModifier = 24, } enum JsxFlags { None = 0, @@ -396,31 +409,45 @@ declare namespace ts { interface Node extends TextRange { kind: SyntaxKind; flags: NodeFlags; + modifierFlagsCache?: ModifierFlags; + transformFlags?: TransformFlags; decorators?: NodeArray; modifiers?: ModifiersArray; id?: number; parent?: Node; - jsDocComments?: JSDocComment[]; + original?: Node; + startsOnNewLine?: boolean; + jsDocComments?: JSDoc[]; symbol?: Symbol; locals?: SymbolTable; nextContainer?: Node; localSymbol?: Symbol; flowNode?: FlowNode; + emitNode?: EmitNode; } - interface NodeArray extends Array, TextRange { + interface NodeArray extends Array, TextRange { hasTrailingComma?: boolean; } - interface ModifiersArray extends NodeArray { - flags: NodeFlags; - } interface Token extends Node { __tokenTag: any; } interface Modifier extends Token { } + enum GeneratedIdentifierKind { + None = 0, + Auto = 1, + Loop = 2, + Unique = 3, + Node = 4, + } interface Identifier extends PrimaryExpression { text: string; originalKeywordKind?: SyntaxKind; + autoGenerateKind?: GeneratedIdentifierKind; + autoGenerateId?: number; + } + interface TransientIdentifier extends Identifier { + resolvedSymbol: Symbol; } interface QualifiedName extends Node { left: EntityName; @@ -457,9 +484,10 @@ declare namespace ts { } interface ConstructSignatureDeclaration extends SignatureDeclaration, TypeElement { } + type BindingName = Identifier | BindingPattern; interface VariableDeclaration extends Declaration { parent?: VariableDeclarationList; - name: Identifier | BindingPattern; + name: BindingName; type?: TypeNode; initializer?: Expression; } @@ -468,7 +496,7 @@ declare namespace ts { } interface ParameterDeclaration extends Declaration { dotDotDotToken?: Node; - name: Identifier | BindingPattern; + name: BindingName; questionToken?: Node; type?: TypeNode; initializer?: Expression; @@ -476,7 +504,7 @@ declare namespace ts { interface BindingElement extends Declaration { propertyName?: PropertyName; dotDotDotToken?: Node; - name: Identifier | BindingPattern; + name: BindingName; initializer?: Expression; } interface PropertySignature extends TypeElement { @@ -495,6 +523,7 @@ declare namespace ts { _objectLiteralBrandBrand: any; name?: PropertyName; } + type ObjectLiteralElementLike = PropertyAssignment | ShorthandPropertyAssignment | MethodDeclaration | AccessorDeclaration; interface PropertyAssignment extends ObjectLiteralElement { _propertyAssignmentBrand: any; name: PropertyName; @@ -519,11 +548,14 @@ declare namespace ts { name: PropertyName; } interface BindingPattern extends Node { - elements: NodeArray; + elements: NodeArray; } interface ObjectBindingPattern extends BindingPattern { + elements: NodeArray; } + type ArrayBindingElement = BindingElement | OmittedExpression; interface ArrayBindingPattern extends BindingPattern { + elements: NodeArray; } /** * Several node kinds share function-like features such as a signature, @@ -617,12 +649,17 @@ declare namespace ts { } interface StringLiteral extends LiteralExpression { _stringLiteralBrand: any; + textSourceNode?: Identifier | StringLiteral; } interface Expression extends Node { _expressionBrand: any; contextualType?: Type; } interface OmittedExpression extends Expression { + _omittedExpressionBrand: any; + } + interface PartiallyEmittedExpression extends LeftHandSideExpression { + expression: Expression; } interface UnaryExpression extends Expression { _unaryExpressionBrand: any; @@ -697,9 +734,14 @@ declare namespace ts { interface LiteralExpression extends LiteralLikeNode, PrimaryExpression { _literalExpressionBrand: any; } + interface NumericLiteral extends LiteralExpression { + _numericLiteralBrand: any; + trailingComment?: string; + } interface TemplateLiteralFragment extends LiteralLikeNode { _templateLiteralFragmentBrand: any; } + type Template = TemplateExpression | LiteralExpression; interface TemplateExpression extends PrimaryExpression { head: TemplateLiteralFragment; templateSpans: NodeArray; @@ -718,8 +760,16 @@ declare namespace ts { interface SpreadElementExpression extends Expression { expression: Expression; } - interface ObjectLiteralExpression extends PrimaryExpression, Declaration { - properties: NodeArray; + /** + * This interface is a base interface for ObjectLiteralExpression and JSXAttributes to extend from. JSXAttributes is similar to + * ObjectLiteralExpression in that it contains array of properties; however, JSXAttributes' properties can only be + * JSXAttribute or JSXSpreadAttribute. ObjectLiteralExpression, on the other hand, can only have properties of type + * ObjectLiteralElement (e.g. PropertyAssignment, ShorthandPropertyAssignment etc.) + **/ + interface ObjectLiteralExpressionBase extends PrimaryExpression, Declaration { + properties: NodeArray; + } + interface ObjectLiteralExpression extends ObjectLiteralExpressionBase { multiLine?: boolean; } type EntityNameExpression = Identifier | PropertyAccessEntityNameExpression; @@ -750,7 +800,7 @@ declare namespace ts { } interface TaggedTemplateExpression extends MemberExpression { tag: LeftHandSideExpression; - template: LiteralExpression | TemplateExpression; + template: Template; } type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator; interface AsExpression extends Expression { @@ -780,9 +830,10 @@ declare namespace ts { _selfClosingElementBrand?: any; } type JsxOpeningLikeElement = JsxSelfClosingElement | JsxOpeningElement; + type JsxAttributeLike = JsxAttribute | JsxSpreadAttribute; interface JsxAttribute extends Node { name: Identifier; - initializer?: Expression; + initializer?: StringLiteral | JsxExpression; } interface JsxSpreadAttribute extends Node { expression: Expression; @@ -800,6 +851,8 @@ declare namespace ts { interface Statement extends Node { _statementBrand: any; } + interface NotEmittedStatement extends Statement { + } interface EmptyStatement extends Statement { } interface DebuggerStatement extends Statement { @@ -810,6 +863,7 @@ declare namespace ts { type BlockLike = SourceFile | Block | ModuleBlock | CaseClause; interface Block extends Statement { statements: NodeArray; + multiLine?: boolean; } interface VariableStatement extends Statement { declarationList: VariableDeclarationList; @@ -831,17 +885,18 @@ declare namespace ts { interface WhileStatement extends IterationStatement { expression: Expression; } + type ForInitializer = VariableDeclarationList | Expression; interface ForStatement extends IterationStatement { - initializer?: VariableDeclarationList | Expression; + initializer?: ForInitializer; condition?: Expression; incrementor?: Expression; } interface ForInStatement extends IterationStatement { - initializer: VariableDeclarationList | Expression; + initializer: ForInitializer; expression: Expression; } interface ForOfStatement extends IterationStatement { - initializer: VariableDeclarationList | Expression; + initializer: ForInitializer; expression: Expression; } interface BreakStatement extends Statement { @@ -927,7 +982,7 @@ declare namespace ts { type: TypeNode; } interface EnumMember extends Declaration { - name: DeclarationName; + name: PropertyName; initializer?: Expression; } interface EnumDeclaration extends DeclarationStatement { @@ -935,6 +990,7 @@ declare namespace ts { members: NodeArray; } type ModuleBody = ModuleBlock | ModuleDeclaration; + type ModuleName = Identifier | StringLiteral; interface ModuleDeclaration extends DeclarationStatement { name: Identifier | LiteralExpression; body?: ModuleBlock | ModuleDeclaration; @@ -942,9 +998,10 @@ declare namespace ts { interface ModuleBlock extends Node, Statement { statements: NodeArray; } + type ModuleReference = EntityName | ExternalModuleReference; interface ImportEqualsDeclaration extends DeclarationStatement { name: Identifier; - moduleReference: EntityName | ExternalModuleReference; + moduleReference: ModuleReference; } interface ExternalModuleReference extends Node { expression?: Expression; @@ -953,9 +1010,10 @@ declare namespace ts { importClause?: ImportClause; moduleSpecifier: Expression; } + type NamedImportBindings = NamespaceImport | NamedImports; interface ImportClause extends Declaration { name?: Identifier; - namedBindings?: NamespaceImport | NamedImports; + namedBindings?: NamedImportBindings; } interface NamespaceImport extends Declaration { name: Identifier; @@ -1023,7 +1081,7 @@ declare namespace ts { type: JSDocType; } interface JSDocRecordType extends JSDocType, TypeLiteralNode { - members: NodeArray; + literal: TypeLiteralNode; } interface JSDocTypeReference extends JSDocType { name: EntityName; @@ -1053,12 +1111,14 @@ declare namespace ts { name: Identifier | LiteralExpression; type?: JSDocType; } - interface JSDocComment extends Node { - tags: NodeArray; + interface JSDoc extends Node { + tags: NodeArray | undefined; + comment: string | undefined; } interface JSDocTag extends Node { atToken: Node; tagName: Identifier; + comment: string | undefined; } interface JSDocTemplateTag extends JSDocTag { typeParameters: NodeArray; @@ -1083,9 +1143,13 @@ declare namespace ts { jsDocTypeTag?: JSDocTypeTag; } interface JSDocParameterTag extends JSDocTag { + /** the parameter name, if provided *before* the type (TypeScript-style) */ preParameterName?: Identifier; typeExpression?: JSDocTypeExpression; + /** the parameter name, if provided *after* the type (JSDoc-standard) */ postParameterName?: Identifier; + /** the parameter name, regardless of the location it was provided */ + parameterName: Identifier; isBracketed: boolean; } enum FlowFlags { @@ -1174,6 +1238,7 @@ declare namespace ts { imports: LiteralExpression[]; moduleAugmentations: LiteralExpression[]; patternAmbientModules?: PatternAmbientModule[]; + externalHelpersModuleName?: Identifier; } interface ScriptReferenceHost { getCompilerOptions(): CompilerOptions; @@ -1189,6 +1254,7 @@ declare namespace ts { * @param path The path to test. */ fileExists(path: string): boolean; + readFile(path: string): string; } interface WriteFileCallback { (fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void, sourceFiles?: SourceFile[]): void; @@ -1219,7 +1285,7 @@ declare namespace ts { * used for writing the JavaScript and declaration files. Otherwise, the writeFile parameter * will be invoked when writing the JavaScript and declaration files. */ - emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken): EmitResult; + emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean): EmitResult; getOptionsDiagnostics(cancellationToken?: CancellationToken): Diagnostic[]; getGlobalDiagnostics(cancellationToken?: CancellationToken): Diagnostic[]; getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[]; @@ -1231,6 +1297,7 @@ declare namespace ts { getTypeChecker(): TypeChecker; getCommonSourceDirectory(): string; getDiagnosticsProducingTypeChecker(): TypeChecker; + dropDiagnosticsProducingTypeChecker(): void; getClassifiableNames(): Map; getNodeCount(): number; getIdentifierCount(): number; @@ -1322,6 +1389,7 @@ declare namespace ts { getJsxElementAttributesType(elementNode: JsxOpeningLikeElement): Type; getJsxIntrinsicTagNames(): Symbol[]; isOptionalParameter(node: ParameterDeclaration): boolean; + getAmbientModules(): Symbol[]; getDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[]; getGlobalDiagnostics(): Diagnostic[]; getEmitResolver(sourceFile?: SourceFile, cancellationToken?: CancellationToken): EmitResolver; @@ -1369,6 +1437,7 @@ declare namespace ts { UseFullyQualifiedType = 128, InFirstTypeArgument = 256, InTypeAlias = 512, + UseTypeAliasValue = 1024, } enum SymbolFormatFlags { None = 0, @@ -1411,18 +1480,19 @@ declare namespace ts { enum TypeReferenceSerializationKind { Unknown = 0, TypeWithConstructSignatureAndValue = 1, - VoidType = 2, + VoidNullableOrNeverType = 2, NumberLikeType = 3, StringLikeType = 4, BooleanType = 5, ArrayLikeType = 6, ESSymbolType = 7, - TypeWithCallSignature = 8, - ObjectType = 9, + Promise = 8, + TypeWithCallSignature = 9, + ObjectType = 10, } interface EmitResolver { hasGlobalName(name: string): boolean; - getReferencedExportContainer(node: Identifier): SourceFile | ModuleDeclaration | EnumDeclaration; + getReferencedExportContainer(node: Identifier, prefixLocals?: boolean): SourceFile | ModuleDeclaration | EnumDeclaration; getReferencedImportDeclaration(node: Identifier): Declaration; getReferencedDeclarationWithCollidingName(node: Identifier): Declaration; isDeclarationWithCollidingName(node: Declaration): boolean; @@ -1437,17 +1507,19 @@ declare namespace ts { writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; writeTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; writeBaseConstructorTypeOfClass(node: ClassLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; - isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessibilityResult; + isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, shouldComputeAliasToMarkVisible: boolean): SymbolAccessibilityResult; isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult; getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number; getReferencedValueDeclaration(reference: Identifier): Declaration; - getTypeReferenceSerializationKind(typeName: EntityName): TypeReferenceSerializationKind; + getTypeReferenceSerializationKind(typeName: EntityName, location?: Node): TypeReferenceSerializationKind; isOptionalParameter(node: ParameterDeclaration): boolean; moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean; isArgumentsLocalBinding(node: Identifier): boolean; getExternalModuleFileFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration): SourceFile; getTypeReferenceDirectivesForEntityName(name: EntityNameOrEntityNameExpression): string[]; getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[]; + isLiteralConstDeclaration(node: VariableDeclaration): boolean; + writeLiteralConstValue(node: VariableDeclaration, writer: SymbolWriter): void; } enum SymbolFlags { None = 0, @@ -1545,7 +1617,8 @@ declare namespace ts { mapper?: TypeMapper; referenced?: boolean; containingType?: UnionOrIntersectionType; - hasCommonType?: boolean; + hasNonUniformType?: boolean; + isPartial?: boolean; isDiscriminantProperty?: boolean; resolvedExports?: SymbolTable; exportsChecked?: boolean; @@ -1585,6 +1658,8 @@ declare namespace ts { BodyScopedClassBinding = 1048576, NeedsLoopOutParameter = 2097152, AssignmentsMarked = 4194304, + ClassWithConstructorReference = 8388608, + ConstructorReferenceInClass = 16777216, } interface NodeLinks { flags?: NodeCheckFlags; @@ -1626,7 +1701,7 @@ declare namespace ts { Anonymous = 2097152, Instantiated = 4194304, ObjectLiteral = 8388608, - FreshObjectLiteral = 16777216, + FreshLiteral = 16777216, ContainsWideningType = 33554432, ContainsObjectLiteral = 67108864, ContainsAnyFunctionType = 134217728, @@ -1634,6 +1709,7 @@ declare namespace ts { ObjectLiteralPatternWithComputedProperties = 536870912, Nullable = 6144, Literal = 480, + StringOrNumberLiteral = 96, DefinitelyFalsy = 7392, PossiblyFalsy = 7406, Intrinsic = 16015, @@ -1665,6 +1741,8 @@ declare namespace ts { } interface LiteralType extends Type { text: string; + freshType?: LiteralType; + regularType?: LiteralType; } interface EnumType extends Type { memberTypes: Map; @@ -1769,10 +1847,11 @@ declare namespace ts { interface TypeInferences { primary: Type[]; secondary: Type[]; + topLevel: boolean; isFixed: boolean; } interface InferenceContext { - typeParameters: TypeParameter[]; + signature: Signature; inferUnionTypes: boolean; inferences: TypeInferences[]; inferredTypes: Type[]; @@ -1844,6 +1923,7 @@ declare namespace ts { experimentalDecorators?: boolean; forceConsistentCasingInFileNames?: boolean; help?: boolean; + importHelpers?: boolean; init?: boolean; inlineSourceMap?: boolean; inlineSources?: boolean; @@ -1965,6 +2045,7 @@ declare namespace ts { raw?: any; errors: Diagnostic[]; wildcardDirectories?: MapLike; + compileOnSave?: boolean; } enum WatchDirectoryFlags { None = 0, @@ -2166,6 +2247,104 @@ declare namespace ts { * This method is a companion for 'resolveModuleNames' and is used to resolve 'types' references to actual type declaration files */ resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; + getEnvironmentVariable?(name: string): string; + } + enum TransformFlags { + None = 0, + TypeScript = 1, + ContainsTypeScript = 2, + Jsx = 4, + ContainsJsx = 8, + ES7 = 16, + ContainsES7 = 32, + ES6 = 64, + ContainsES6 = 128, + DestructuringAssignment = 256, + Generator = 512, + ContainsGenerator = 1024, + ContainsDecorators = 2048, + ContainsPropertyInitializer = 4096, + ContainsLexicalThis = 8192, + ContainsCapturedLexicalThis = 16384, + ContainsLexicalThisInComputedPropertyName = 32768, + ContainsDefaultValueAssignments = 65536, + ContainsParameterPropertyAssignments = 131072, + ContainsSpreadElementExpression = 262144, + ContainsComputedPropertyName = 524288, + ContainsBlockScopedBinding = 1048576, + ContainsBindingPattern = 2097152, + ContainsYield = 4194304, + ContainsHoistedDeclarationOrCompletion = 8388608, + HasComputedFlags = 536870912, + AssertTypeScript = 3, + AssertJsx = 12, + AssertES7 = 48, + AssertES6 = 192, + AssertGenerator = 1536, + NodeExcludes = 536871765, + ArrowFunctionExcludes = 550710101, + FunctionExcludes = 550726485, + ConstructorExcludes = 550593365, + MethodOrAccessorExcludes = 550593365, + ClassExcludes = 537590613, + ModuleExcludes = 546335573, + TypeExcludes = -3, + ObjectLiteralExcludes = 537430869, + ArrayLiteralOrCallOrNewExcludes = 537133909, + VariableDeclarationListExcludes = 538968917, + ParameterExcludes = 538968917, + TypeScriptClassSyntaxMask = 137216, + ES6FunctionSyntaxMask = 81920, + } + interface EmitNode { + flags?: EmitFlags; + commentRange?: TextRange; + sourceMapRange?: TextRange; + tokenSourceMapRanges?: Map; + annotatedNodes?: Node[]; + constantValue?: number; + } + enum EmitFlags { + EmitEmitHelpers = 1, + EmitExportStar = 2, + EmitSuperHelper = 4, + EmitAdvancedSuperHelper = 8, + UMDDefine = 16, + SingleLine = 32, + AdviseOnEmitNode = 64, + NoSubstitution = 128, + CapturesThis = 256, + NoLeadingSourceMap = 512, + NoTrailingSourceMap = 1024, + NoSourceMap = 1536, + NoNestedSourceMaps = 2048, + NoTokenLeadingSourceMaps = 4096, + NoTokenTrailingSourceMaps = 8192, + NoTokenSourceMaps = 12288, + NoLeadingComments = 16384, + NoTrailingComments = 32768, + NoComments = 49152, + NoNestedComments = 65536, + ExportName = 131072, + LocalName = 262144, + Indented = 524288, + NoIndentation = 1048576, + AsyncFunctionBody = 2097152, + ReuseTempVariableScope = 4194304, + CustomPrologue = 8388608, + } + enum EmitContext { + SourceFile = 0, + Expression = 1, + IdentifierName = 2, + Unspecified = 3, + } + /** Additional context provided to `visitEachChild` */ + interface LexicalEnvironment { + /** Starts a new lexical environment. */ + startLexicalEnvironment(): void; + /** Ends a lexical environment, returning any declarations. */ + endLexicalEnvironment(): Statement[]; } interface TextSpan { start: number; @@ -2260,6 +2439,12 @@ declare namespace ts { * If no such value is found, the callback is applied to each element of array and undefined is returned. */ function forEach(array: T[] | undefined, callback: (element: T, index: number) => U | undefined): U | undefined; + /** + * Iterates through `array` by index and performs the callback on each element of array until the callback + * returns a falsey value, then returns false. + * If no such value is found, the callback is applied to each element of array and `true` is returned. + */ + function every(array: T[], callback: (element: T, index: number) => boolean): boolean; /** Works like Array.prototype.find, returning `undefined` if no element satisfying the predicate is found. */ function find(array: T[], predicate: (element: T, index: number) => boolean): T | undefined; /** @@ -2270,20 +2455,55 @@ declare namespace ts { function contains(array: T[], value: T): boolean; function indexOf(array: T[], value: T): number; function indexOfAnyCharCode(text: string, charCodes: number[], start?: number): number; - function countWhere(array: T[], predicate: (x: T) => boolean): number; + function countWhere(array: T[], predicate: (x: T, i: number) => boolean): number; /** * Filters an array by a predicate function. Returns the same array instance if the predicate is * true for all elements, otherwise returns a new array instance containing the filtered subset. */ + function filter(array: T[], f: (x: T) => x is U): U[]; function filter(array: T[], f: (x: T) => boolean): T[]; function removeWhere(array: T[], f: (x: T) => boolean): boolean; function filterMutate(array: T[], f: (x: T) => boolean): void; - function map(array: T[], f: (x: T) => U): U[]; + function map(array: T[], f: (x: T, i: number) => U): U[]; + /** + * Flattens an array containing a mix of array or non-array elements. + * + * @param array The array to flatten. + */ + function flatten(array: (T | T[])[]): T[]; + /** + * Maps an array. If the mapped value is an array, it is spread into the result. + * + * @param array The array to map. + * @param mapfn The callback used to map the result into one or more values. + */ + function flatMap(array: T[], mapfn: (x: T, i: number) => U | U[]): U[]; + /** + * Computes the first matching span of elements and returns a tuple of the first span + * and the remaining elements. + */ + function span(array: T[], f: (x: T, i: number) => boolean): [T[], T[]]; + /** + * Maps contiguous spans of values with the same key. + * + * @param array The array to map. + * @param keyfn A callback used to select the key for an element. + * @param mapfn A callback used to map a contiguous chunk of values to a single value. + */ + function spanMap(array: T[], keyfn: (x: T, i: number) => K, mapfn: (chunk: T[], key: K, start: number, end: number) => U): U[]; + function mapObject(object: MapLike, f: (key: string, x: T) => [string, U]): MapLike; function concatenate(array1: T[], array2: T[]): T[]; function deduplicate(array: T[], areEqual?: (a: T, b: T) => boolean): T[]; + /** + * Compacts an array, removing any falsey elements. + */ + function compact(array: T[]): T[]; function sum(array: any[], prop: string): number; function addRange(to: T[], from: T[]): void; function rangeEquals(array1: T[], array2: T[], pos: number, end: number): boolean; + function firstOrUndefined(array: T[]): T; + function singleOrUndefined(array: T[]): T; + function singleOrMany(array: T[]): T | T[]; /** * Returns the last element of an array if non-empty, undefined otherwise. */ @@ -2295,11 +2515,11 @@ declare namespace ts { * @param array A sorted array whose first element must be no larger than number * @param number The value to be searched for in the array. */ - function binarySearch(array: number[], value: number): number; - function reduceLeft(array: T[], f: (a: T, x: T) => T): T; - function reduceLeft(array: T[], f: (a: U, x: T) => U, initial: U): U; - function reduceRight(array: T[], f: (a: T, x: T) => T): T; - function reduceRight(array: T[], f: (a: U, x: T) => U, initial: U): U; + function binarySearch(array: T[], value: T, comparer?: (v1: T, v2: T) => number): number; + function reduceLeft(array: T[], f: (memo: U, value: T, i: number) => U, initial: U, start?: number, count?: number): U; + function reduceLeft(array: T[], f: (memo: T, value: T, i: number) => T): T; + function reduceRight(array: T[], f: (memo: U, value: T, i: number) => U, initial: U, start?: number, count?: number): U; + function reduceRight(array: T[], f: (memo: T, value: T, i: number) => T): T; /** * Indicates whether a map-like contains an own property with the specified key. * @@ -2350,6 +2570,9 @@ declare namespace ts { * @param target A map to which properties should be copied. */ function copyProperties(source: Map, target: MapLike): void; + function assign, T2, T3>(t: T1, arg1: T2, arg2: T3): T1 & T2 & T3; + function assign, T2>(t: T1, arg1: T2): T1 & T2; + function assign>(t: T1, ...args: any[]): any; /** * Reduce the properties of a map. * @@ -2391,6 +2614,7 @@ declare namespace ts { */ function arrayToMap(array: T[], makeKey: (value: T) => string): Map; function arrayToMap(array: T[], makeKey: (value: T) => string, makeValue: (value: T) => U): Map; + function isEmpty(map: Map): boolean; function cloneMap(map: Map): Map; function clone(object: T): T; function extend(first: T1, second: T2): T1 & T2; @@ -2399,11 +2623,31 @@ declare namespace ts { * Creates the array if it does not already exist. */ function multiMapAdd(map: Map, key: string, value: V): V[]; + /** + * Removes a value from an array of values associated with the key. + * Does not preserve the order of those values. + * Does nothing if `key` is not in `map`, or `value` is not in `map[key]`. + */ + function multiMapRemove(map: Map, key: string, value: V): void; /** * Tests whether a value is an array. */ function isArray(value: any): value is any[]; function memoize(callback: () => T): () => T; + /** + * 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. + */ + function chain(...args: ((t: T) => (u: U) => U)[]): (t: T) => (u: 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. + */ + function compose(...args: ((t: T) => T)[]): (t: T) => T; let localizedDiagnosticMessages: Map; function getLocaleSpecificMessage(message: DiagnosticMessage): string; function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: any[]): Diagnostic; @@ -2419,12 +2663,19 @@ declare namespace ts { function deduplicateSortedDiagnostics(diagnostics: Diagnostic[]): Diagnostic[]; function normalizeSlashes(path: string): string; function getRootLength(path: string): number; - let directorySeparator: string; + const directorySeparator = "/"; function normalizePath(path: string): string; + /** A path ending with '/' refers to a directory only, never a file. */ + function pathEndsWithDirectorySeparator(path: string): boolean; function getDirectoryPath(path: Path): Path; function getDirectoryPath(path: string): string; function isUrl(path: string): boolean; + function isExternalModuleNameRelative(moduleName: string): boolean; + function getEmitScriptTarget(compilerOptions: CompilerOptions): ScriptTarget; + function getEmitModuleKind(compilerOptions: CompilerOptions): ModuleKind; + function hasZeroOrOneAsteriskCharacter(str: string): boolean; function isRootedDiskPath(path: string): boolean; + function convertToRelativePath(absoluteOrRelativePath: string, basePath: string, getCanonicalFileName: (path: string) => string): string; function getNormalizedPathComponents(path: string, currentDirectory: string): string[]; function getNormalizedAbsolutePath(fileName: string, currentDirectory: string): string; function getNormalizedPathFromPathComponents(pathComponents: string[]): string; @@ -2470,6 +2721,8 @@ declare namespace ts { const supportedTypescriptExtensionsForExtractExtension: string[]; const supportedJavascriptExtensions: string[]; function getSupportedExtensions(options?: CompilerOptions): string[]; + function hasJavaScriptFileExtension(fileName: string): boolean; + function hasTypeScriptFileExtension(fileName: string): boolean; function isSupportedSourceFileName(fileName: string, compilerOptions?: CompilerOptions): boolean; /** * Extension boundaries by priority. Lower numbers indicate higher priorities, and are @@ -2518,12 +2771,29 @@ declare namespace ts { function assert(expression: boolean, message?: string, verboseDebugInfo?: () => string): void; function fail(message?: string): void; } + function getEnvironmentVariable(name: string, host?: CompilerHost): string; /** Remove an item from an array, moving everything to its right one space left. */ function orderedRemoveItemAt(array: T[], index: number): void; function unorderedRemoveItemAt(array: T[], index: number): void; /** Remove the *first* occurrence of `item` from the array. */ function unorderedRemoveItem(array: T[], item: T): void; function createGetCanonicalFileName(useCaseSensitiveFileNames: boolean): (fileName: string) => string; + /** + * patternStrings contains both pattern strings (containing "*") and regular strings. + * Return an exact match if possible, or a pattern match, or undefined. + * (These are verified by verifyCompilerOptions to have 0 or 1 "*" characters.) + */ + function matchPatternOrExact(patternStrings: string[], candidate: string): string | Pattern | undefined; + function patternText({prefix, suffix}: Pattern): string; + /** + * Given that candidate matches pattern, returns the text matching the '*'. + * E.g.: matchedText(tryParsePattern("foo*baz"), "foobarbaz") === "bar" + */ + function matchedText(pattern: Pattern, candidate: string): string; + /** Return the object corresponding to the best pattern to match `candidate`. */ + function findBestPatternMatch(values: T[], getPattern: (value: T) => Pattern, candidate: string): T | undefined; + function tryParsePattern(pattern: string): Pattern | undefined; + function positionIsSynthesized(pos: number): boolean; } declare namespace ts { type FileWatcherCallback = (fileName: string, removed?: boolean) => void; @@ -2556,6 +2826,8 @@ declare namespace ts { getMemoryUsage?(): number; exit(exitCode?: number): void; realpath?(path: string): string; + getEnvironmentVariable(name: string): string; + tryEnableSourceMapsForHost?(): void; } interface FileWatcher { close(): void; @@ -2567,17 +2839,13 @@ declare namespace ts { var sys: System; } declare namespace ts { + const externalHelpersModuleNameText = "tslib"; interface ReferencePathMatchResult { fileReference?: FileReference; diagnosticMessage?: DiagnosticMessage; isNoDefaultLib?: boolean; isTypeReferenceDirective?: boolean; } - interface SynthesizedNode extends Node { - leadingCommentRanges?: CommentRange[]; - trailingCommentRanges?: CommentRange[]; - startsOnNewLine: boolean; - } function getDeclarationOfKind(symbol: Symbol, kind: SyntaxKind): Declaration; interface StringSymbolWriter extends SymbolWriter { string(): string; @@ -2594,7 +2862,7 @@ declare namespace ts { function getSingleLineStringWriter(): StringSymbolWriter; function releaseStringWriter(writer: StringSymbolWriter): void; function getFullWidth(node: Node): number; - function arrayIsEqualTo(array1: T[], array2: T[], equaler?: (a: T, b: T) => boolean): boolean; + function arrayIsEqualTo(array1: ReadonlyArray, array2: ReadonlyArray, equaler?: (a: T, b: T) => boolean): boolean; function hasResolvedModule(sourceFile: SourceFile, moduleNameText: string): boolean; function getResolvedModule(sourceFile: SourceFile, moduleNameText: string): ResolvedModule; function setResolvedModule(sourceFile: SourceFile, moduleNameText: string, resolvedModule: ResolvedModule): void; @@ -2608,6 +2876,7 @@ declare namespace ts { function getStartPositionOfLine(line: number, sourceFile: SourceFile): number; function nodePosToString(node: Node): string; function getStartPosOfNode(node: Node): number; + function isDefined(value: any): boolean; function getEndLinePosition(line: number, sourceFile: SourceFile): number; function nodeIsMissing(node: Node): boolean; function nodeIsPresent(node: Node): boolean; @@ -2618,15 +2887,18 @@ declare namespace ts { function getSourceTextOfNodeFromSourceFile(sourceFile: SourceFile, node: Node, includeTrivia?: boolean): string; function getTextOfNodeFromSourceText(sourceText: string, node: Node): string; function getTextOfNode(node: Node, includeTrivia?: boolean): string; + function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile, languageVersion: ScriptTarget): string; + function isBinaryOrOctalIntegerLiteral(node: LiteralLikeNode, text: string): boolean; function escapeIdentifier(identifier: string): string; function unescapeIdentifier(identifier: string): string; function makeIdentifierFromModuleName(moduleName: string): string; function isBlockOrCatchScoped(declaration: Declaration): boolean; function isAmbientModule(node: Node): boolean; - function isShorthandAmbientModule(node: Node): boolean; + function isShorthandAmbientModuleSymbol(moduleSymbol: Symbol): boolean; function isBlockScopedContainerTopLevel(node: Node): boolean; function isGlobalScopeAugmentation(module: ModuleDeclaration): boolean; function isExternalModuleAugmentation(node: Node): boolean; + function isBlockScope(node: Node, parentNode: Node): boolean; function getEnclosingBlockScopeContainer(node: Node): Node; function isCatchClauseVariableDeclaration(declaration: Declaration): boolean; function declarationNameToString(name: DeclarationName): string; @@ -2637,7 +2909,6 @@ declare namespace ts { function isExternalOrCommonJsModule(file: SourceFile): boolean; function isDeclarationFile(file: SourceFile): boolean; function isConstEnumDeclaration(node: Node): boolean; - function getCombinedNodeFlags(node: Node): NodeFlags; function isConst(node: Node): boolean; function isLet(node: Node): boolean; function isSuperCallExpression(n: Node): boolean; @@ -2649,7 +2920,7 @@ declare namespace ts { let fullTripleSlashReferencePathRegEx: RegExp; let fullTripleSlashReferenceTypeReferenceDirectiveRegEx: RegExp; let fullTripleSlashAMDReferencePathRegEx: RegExp; - function isTypeNode(node: Node): boolean; + function isPartOfTypeNode(node: Node): boolean; function forEachReturnStatement(body: Block, visitor: (stmt: ReturnStatement) => T): T; function forEachYieldExpression(body: Block, visitor: (expr: YieldExpression) => void): void; function isVariableLike(node: Node): node is VariableLikeDeclaration; @@ -2658,7 +2929,7 @@ declare namespace ts { function isFunctionLike(node: Node): node is FunctionLikeDeclaration; function isFunctionLikeKind(kind: SyntaxKind): boolean; function introducesArgumentsExoticObject(node: Node): boolean; - function isIterationStatement(node: Node, lookInLabeledStatements: boolean): boolean; + function isIterationStatement(node: Node, lookInLabeledStatements: boolean): node is IterationStatement; function isFunctionBlock(node: Node): boolean; function isObjectLiteralMethod(node: Node): node is MethodDeclaration; function isIdentifierTypePredicate(predicate: TypePredicate): predicate is IdentifierTypePredicate; @@ -2667,11 +2938,11 @@ declare namespace ts { function getContainingClass(node: Node): ClassLikeDeclaration; function getThisContainer(node: Node, includeArrowFunctions: boolean): Node; /** - * Given an super call\property node returns a closest node where either - * - super call\property is legal in the node and not legal in the parent node the node. + * Given an super call/property node, returns the closest node where + * - a super call/property access is legal in the node and not legal in the parent node the node. * i.e. super call is legal in constructor but not legal in the class body. - * - node is arrow function (so caller might need to call getSuperContainer in case it needs to climb higher) - * - super call\property is definitely illegal in the node (but might be legal in some subnode) + * - the container is an arrow function (so caller might need to call getSuperContainer again in case it needs to climb higher) + * - a super call/property is definitely illegal in the container (but might be legal in some subnode) * i.e. super property access is illegal in function declaration but can be legal in the statement list */ function getSuperContainer(node: Node, stopOnFunctions: boolean): Node; @@ -2679,17 +2950,16 @@ declare namespace ts { /** * Determines whether a node is a property or element access expression for super. */ - function isSuperPropertyOrElementAccess(node: Node): boolean; + function isSuperProperty(node: Node): node is (PropertyAccessExpression | ElementAccessExpression); function getEntityNameFromTypeNode(node: TypeNode): EntityNameOrEntityNameExpression; function isCallLikeExpression(node: Node): node is CallLikeExpression; function getInvokedExpression(node: CallLikeExpression): Expression; function nodeCanBeDecorated(node: Node): boolean; function nodeIsDecorated(node: Node): boolean; - function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression; - function isElementAccessExpression(node: Node): node is ElementAccessExpression; + function nodeOrChildIsDecorated(node: Node): boolean; + function childIsDecorated(node: Node): boolean; function isJSXTagName(node: Node): boolean; - function isExpression(node: Node): boolean; - function isExternalModuleNameRelative(moduleName: string): boolean; + function isPartOfExpression(node: Node): boolean; function isInstantiatedModule(node: ModuleDeclaration, preserveConstEnums: boolean): boolean; function isExternalModuleImportEqualsDeclaration(node: Node): boolean; function getExternalModuleImportEqualsDeclarationExpression(node: Node): Expression; @@ -2710,8 +2980,11 @@ declare namespace ts { function isDeclarationOfFunctionExpression(s: Symbol): boolean; function getSpecialPropertyAssignmentKind(expression: Node): SpecialPropertyAssignmentKind; function getExternalModuleName(node: Node): Expression; + function getNamespaceDeclarationNode(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): NamespaceImport; + function isDefaultImport(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): boolean; function hasQuestionToken(node: Node): boolean; function isJSDocConstructSignature(node: Node): boolean; + function getJSDocComments(node: Node, checkParentVariableStatement: boolean): string[]; function getJSDocTypeTag(node: Node): JSDocTypeTag; function getJSDocReturnTag(node: Node): JSDocReturnTag; function getJSDocTemplateTag(node: Node): JSDocTemplateTag; @@ -2720,16 +2993,9 @@ declare namespace ts { function hasDeclaredRestParameter(s: SignatureDeclaration): boolean; function isRestParameter(node: ParameterDeclaration): boolean; function isDeclaredRestParam(node: ParameterDeclaration): boolean; - function isLiteralKind(kind: SyntaxKind): boolean; - function isTextualLiteralKind(kind: SyntaxKind): boolean; - function isTemplateLiteralKind(kind: SyntaxKind): boolean; - function isBindingPattern(node: Node): node is BindingPattern; function isAssignmentTarget(node: Node): boolean; - function isNodeDescendentOf(node: Node, ancestor: Node): boolean; + function isNodeDescendantOf(node: Node, ancestor: Node): boolean; function isInAmbientContext(node: Node): boolean; - function isDeclaration(node: Node): boolean; - function isStatement(n: Node): boolean; - function isClassElement(n: Node): boolean; function isDeclarationName(name: Node): boolean; function isLiteralComputedPropertyDeclarationName(node: Node): boolean; function isIdentifierName(node: Identifier): boolean; @@ -2770,27 +3036,41 @@ declare namespace ts { function isModifierKind(token: SyntaxKind): boolean; function isParameterDeclaration(node: VariableLikeDeclaration): boolean; function getRootDeclaration(node: Node): Node; - function nodeStartsNewLexicalEnvironment(n: Node): boolean; - /** - * Creates a shallow, memberwise clone of a node. The "kind", "pos", "end", "flags", and "parent" - * properties are excluded by default, and can be provided via the "location", "flags", and - * "parent" parameters. - * @param node The node to clone. - * @param location An optional TextRange to use to supply the new position. - * @param flags The NodeFlags to use for the cloned node. - * @param parent The parent for the new node. + function nodeStartsNewLexicalEnvironment(node: Node): boolean; + function nodeIsSynthesized(node: TextRange): boolean; + function getOriginalNode(node: Node): Node; + /** + * Gets a value indicating whether a node originated in the parse tree. + * + * @param node The node to test. */ - function cloneNode(node: T, location?: TextRange, flags?: NodeFlags, parent?: Node): T; + function isParseTreeNode(node: Node): boolean; /** - * Creates a deep clone of an EntityName, with new parent pointers. - * @param node The EntityName to clone. - * @param parent The parent for the cloned node. + * Gets the original parse tree node for a node. + * + * @param node The original node. + * @returns The original parse tree node if found; otherwise, undefined. */ - function cloneEntityName(node: EntityName, parent?: Node): EntityName; - function isQualifiedName(node: Node): node is QualifiedName; - function nodeIsSynthesized(node: Node): boolean; - function createSynthesizedNode(kind: SyntaxKind, startsOnNewLine?: boolean): Node; - function createSynthesizedNodeArray(): NodeArray; + function getParseTreeNode(node: Node): Node; + /** + * Gets the original parse tree node for a node. + * + * @param node The original node. + * @param nodeTest A callback used to ensure the correct type of parse tree node is returned. + * @returns The original parse tree node if found; otherwise, undefined. + */ + function getParseTreeNode(node: Node, nodeTest?: (node: Node) => node is T): T; + function getOriginalSourceFiles(sourceFiles: SourceFile[]): SourceFile[]; + function getOriginalNodeId(node: Node): number; + enum Associativity { + Left = 0, + Right = 1, + } + function getExpressionAssociativity(expression: Expression): Associativity; + function getOperatorAssociativity(kind: SyntaxKind, operator: SyntaxKind, hasArguments?: boolean): Associativity; + function getExpressionPrecedence(expression: Expression): 0 | 1 | -1 | 2 | 4 | 3 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5; + function getOperator(expression: Expression): SyntaxKind; + function getOperatorPrecedence(nodeKind: SyntaxKind, operatorKind: SyntaxKind, hasArguments?: boolean): 0 | 1 | -1 | 2 | 4 | 3 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5; function createDiagnosticCollection(): DiagnosticCollection; /** * Based heavily on the abstract 'Quote'/'QuoteJSONString' operation from ECMA-262 (24.3.2.2), @@ -2813,60 +3093,98 @@ declare namespace ts { getLine(): number; getColumn(): number; getIndent(): number; + isAtStartOfLine(): boolean; reset(): void; } function getIndentString(level: number): string; function getIndentSize(): number; function createTextWriter(newLine: String): EmitTextWriter; + function getResolvedExternalModuleName(host: EmitHost, file: SourceFile): string; + function getExternalModuleNameFromDeclaration(host: EmitHost, resolver: EmitResolver, declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration): string; /** * Resolves a local path to a path which is absolute to the base of the emit */ function getExternalModuleNameFromPath(host: EmitHost, fileName: string): string; function getOwnEmitOutputFilePath(sourceFile: SourceFile, host: EmitHost, extension: string): string; function getDeclarationEmitOutputFilePath(sourceFile: SourceFile, host: EmitHost): string; - function getEmitScriptTarget(compilerOptions: CompilerOptions): ScriptTarget; - function getEmitModuleKind(compilerOptions: CompilerOptions): ModuleKind; interface EmitFileNames { jsFilePath: string; sourceMapFilePath: string; declarationFilePath: string; } - function forEachExpectedEmitFile(host: EmitHost, action: (emitFileNames: EmitFileNames, sourceFiles: SourceFile[], isBundledEmit: boolean) => void, targetSourceFile?: SourceFile): void; + /** + * Gets the source files that are expected to have an emit output. + * + * Originally part of `forEachExpectedEmitFile`, this functionality was extracted to support + * transformations. + * + * @param host An EmitHost. + * @param targetSourceFile An optional target source file to emit. + */ + function getSourceFilesToEmit(host: EmitHost, targetSourceFile?: SourceFile): SourceFile[]; + /** + * Iterates over each source file to emit. The source files are expected to have been + * transformed for use by the pretty printer. + * + * Originally part of `forEachExpectedEmitFile`, this functionality was extracted to support + * transformations. + * + * @param host An EmitHost. + * @param sourceFiles The transformed source files to emit. + * @param action The action to execute. + */ + function forEachTransformedEmitFile(host: EmitHost, sourceFiles: SourceFile[], action: (jsFilePath: string, sourceMapFilePath: string, declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) => void, emitOnlyDtsFiles?: boolean): void; + /** + * Iterates over the source files that are expected to have an emit output. This function + * is used by the legacy emitter and the declaration emitter and should not be used by + * the tree transforming emitter. + * + * @param host An EmitHost. + * @param action The action to execute. + * @param targetSourceFile An optional target source file to emit. + */ + function forEachExpectedEmitFile(host: EmitHost, action: (emitFileNames: EmitFileNames, sourceFiles: SourceFile[], isBundledEmit: boolean, emitOnlyDtsFiles: boolean) => void, targetSourceFile?: SourceFile, emitOnlyDtsFiles?: boolean): void; function getSourceFilePathInNewDir(sourceFile: SourceFile, host: EmitHost, newDirPath: string): string; function writeFile(host: EmitHost, diagnostics: DiagnosticCollection, fileName: string, data: string, writeByteOrderMark: boolean, sourceFiles?: SourceFile[]): void; function getLineOfLocalPosition(currentSourceFile: SourceFile, pos: number): number; function getLineOfLocalPositionFromLineMap(lineMap: number[], pos: number): number; function getFirstConstructorWithBody(node: ClassLikeDeclaration): ConstructorDeclaration; function getSetAccessorTypeAnnotationNode(accessor: AccessorDeclaration): TypeNode; - function getAllAccessorDeclarations(declarations: NodeArray, accessor: AccessorDeclaration): { + interface AllAccessorDeclarations { firstAccessor: AccessorDeclaration; secondAccessor: AccessorDeclaration; getAccessor: AccessorDeclaration; setAccessor: AccessorDeclaration; - }; + } + function getAllAccessorDeclarations(declarations: NodeArray, accessor: AccessorDeclaration): AllAccessorDeclarations; function emitNewLineBeforeLeadingComments(lineMap: number[], writer: EmitTextWriter, node: TextRange, leadingComments: CommentRange[]): void; - function emitComments(text: string, lineMap: number[], writer: EmitTextWriter, comments: CommentRange[], trailingSeparator: boolean, newLine: string, writeComment: (text: string, lineMap: number[], writer: EmitTextWriter, comment: CommentRange, newLine: string) => void): void; + function emitNewLineBeforeLeadingCommentsOfPosition(lineMap: number[], writer: EmitTextWriter, pos: number, leadingComments: CommentRange[]): void; + function emitNewLineBeforeLeadingCommentOfPosition(lineMap: number[], writer: EmitTextWriter, pos: number, commentPos: number): void; + function emitComments(text: string, lineMap: number[], writer: EmitTextWriter, comments: CommentRange[], leadingSeparator: boolean, trailingSeparator: boolean, newLine: string, writeComment: (text: string, lineMap: number[], writer: EmitTextWriter, commentPos: number, commentEnd: number, newLine: string) => void): void; /** * Detached comment is a comment at the top of file or function body that is separated from * the next statement by space. */ - function emitDetachedComments(text: string, lineMap: number[], writer: EmitTextWriter, writeComment: (text: string, lineMap: number[], writer: EmitTextWriter, comment: CommentRange, newLine: string) => void, node: TextRange, newLine: string, removeComments: boolean): { + function emitDetachedComments(text: string, lineMap: number[], writer: EmitTextWriter, writeComment: (text: string, lineMap: number[], writer: EmitTextWriter, commentPos: number, commentEnd: number, newLine: string) => void, node: TextRange, newLine: string, removeComments: boolean): { nodePos: number; detachedCommentEndPos: number; }; - function writeCommentRange(text: string, lineMap: number[], writer: EmitTextWriter, comment: CommentRange, newLine: string): void; - function modifierToFlag(token: SyntaxKind): NodeFlags; - function isLeftHandSideExpression(expr: Expression): boolean; + function writeCommentRange(text: string, lineMap: number[], writer: EmitTextWriter, commentPos: number, commentEnd: number, newLine: string): void; + function hasModifiers(node: Node): boolean; + function hasModifier(node: Node, flags: ModifierFlags): boolean; + function getModifierFlags(node: Node): ModifierFlags; + function modifierToFlag(token: SyntaxKind): ModifierFlags; + function isLogicalOperator(token: SyntaxKind): boolean; function isAssignmentOperator(token: SyntaxKind): boolean; /** Get `C` given `N` if `N` is in the position `class C extends N` where `N` is an ExpressionWithTypeArguments. */ function tryGetClassExtendingExpressionWithTypeArguments(node: Node): ClassLikeDeclaration | undefined; + function isDestructuringAssignment(node: Node): node is BinaryExpression; + function isSupportedExpressionWithTypeArguments(node: ExpressionWithTypeArguments): boolean; function isExpressionWithTypeArgumentsInClassExtendsClause(node: Node): boolean; function isEntityNameExpression(node: Expression): node is EntityNameExpression; function isRightSideOfQualifiedNameOrPropertyAccess(node: Node): boolean; function isEmptyObjectLiteralOrArrayLiteral(expression: Node): boolean; function getLocalSymbolForExportDefault(symbol: Symbol): Symbol; - function hasJavaScriptFileExtension(fileName: string): boolean; - function hasTypeScriptFileExtension(fileName: string): boolean; /** Return ".ts", ".d.ts", or ".tsx", if that is the extension. */ function tryExtractTypeScriptExtension(fileName: string): string | undefined; /** @@ -2878,8 +3196,189 @@ declare namespace ts { * Converts a string to a base-64 encoded ASCII string. */ function convertToBase64(input: string): string; - function convertToRelativePath(absoluteOrRelativePath: string, basePath: string, getCanonicalFileName: (path: string) => string): string; function getNewLineCharacter(options: CompilerOptions): string; + /** + * Tests whether a node and its subtree is simple enough to have its position + * information ignored when emitting source maps in a destructuring assignment. + * + * @param node The expression to test. + */ + function isSimpleExpression(node: Expression): boolean; + function formatSyntaxKind(kind: SyntaxKind): string; + /** + * Increases (or decreases) a position by the provided amount. + * + * @param pos The position. + * @param value The delta. + */ + function movePos(pos: number, value: number): number; + /** + * Creates a new TextRange from the provided pos and end. + * + * @param pos The start position. + * @param end The end position. + */ + function createRange(pos: number, end: number): TextRange; + /** + * Creates a new TextRange from a provided range with a new end position. + * + * @param range A TextRange. + * @param end The new end position. + */ + function moveRangeEnd(range: TextRange, end: number): TextRange; + /** + * Creates a new TextRange from a provided range with a new start position. + * + * @param range A TextRange. + * @param pos The new Start position. + */ + function moveRangePos(range: TextRange, pos: number): TextRange; + /** + * Moves the start position of a range past any decorators. + */ + function moveRangePastDecorators(node: Node): TextRange; + /** + * Moves the start position of a range past any decorators or modifiers. + */ + function moveRangePastModifiers(node: Node): TextRange; + /** + * Determines whether a TextRange has the same start and end positions. + * + * @param range A TextRange. + */ + function isCollapsedRange(range: TextRange): boolean; + /** + * Creates a new TextRange from a provided range with its end position collapsed to its + * start position. + * + * @param range A TextRange. + */ + function collapseRangeToStart(range: TextRange): TextRange; + /** + * Creates a new TextRange from a provided range with its start position collapsed to its + * end position. + * + * @param range A TextRange. + */ + function collapseRangeToEnd(range: TextRange): TextRange; + /** + * Creates a new TextRange for a token at the provides start position. + * + * @param pos The start position. + * @param token The token. + */ + function createTokenRange(pos: number, token: SyntaxKind): TextRange; + function rangeIsOnSingleLine(range: TextRange, sourceFile: SourceFile): boolean; + function rangeStartPositionsAreOnSameLine(range1: TextRange, range2: TextRange, sourceFile: SourceFile): boolean; + function rangeEndPositionsAreOnSameLine(range1: TextRange, range2: TextRange, sourceFile: SourceFile): boolean; + function rangeStartIsOnSameLineAsRangeEnd(range1: TextRange, range2: TextRange, sourceFile: SourceFile): boolean; + function rangeEndIsOnSameLineAsRangeStart(range1: TextRange, range2: TextRange, sourceFile: SourceFile): boolean; + function positionsAreOnSameLine(pos1: number, pos2: number, sourceFile: SourceFile): boolean; + function getStartPositionOfRange(range: TextRange, sourceFile: SourceFile): number; + function collectExternalModuleInfo(sourceFile: SourceFile, resolver: EmitResolver): { + externalImports: (ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration)[]; + exportSpecifiers: Map; + exportEquals: ExportAssignment; + hasExportStarsToExportValues: boolean; + }; + function getInitializedVariables(node: VariableDeclarationList): VariableDeclaration[]; + /** + * Gets a value indicating whether a node is merged with a class declaration in the same scope. + */ + function isMergedWithClass(node: Node): boolean; + /** + * Gets a value indicating whether a node is the first declaration of its kind. + * + * @param node A Declaration node. + * @param kind The SyntaxKind to find among related declarations. + */ + function isFirstDeclarationOfKind(node: Node, kind: SyntaxKind): boolean; + function isNodeArray(array: T[]): array is NodeArray; + function isNoSubstitutionTemplateLiteral(node: Node): node is LiteralExpression; + function isLiteralKind(kind: SyntaxKind): boolean; + function isTextualLiteralKind(kind: SyntaxKind): boolean; + function isLiteralExpression(node: Node): node is LiteralExpression; + function isTemplateLiteralKind(kind: SyntaxKind): boolean; + function isTemplateLiteralFragment(node: Node): node is TemplateLiteralFragment; + function isIdentifier(node: Node): node is Identifier; + function isGeneratedIdentifier(node: Node): boolean; + function isModifier(node: Node): node is Modifier; + function isQualifiedName(node: Node): node is QualifiedName; + function isComputedPropertyName(node: Node): node is ComputedPropertyName; + function isEntityName(node: Node): node is EntityName; + function isPropertyName(node: Node): node is PropertyName; + function isModuleName(node: Node): node is ModuleName; + function isBindingName(node: Node): node is BindingName; + function isTypeParameter(node: Node): node is TypeParameterDeclaration; + function isParameter(node: Node): node is ParameterDeclaration; + function isDecorator(node: Node): node is Decorator; + function isMethodDeclaration(node: Node): node is MethodDeclaration; + function isClassElement(node: Node): node is ClassElement; + function isObjectLiteralElementLike(node: Node): node is ObjectLiteralElementLike; + /** + * Node test that determines whether a node is a valid type node. + * This differs from the `isPartOfTypeNode` function which determines whether a node is *part* + * of a TypeNode. + */ + function isTypeNode(node: Node): node is TypeNode; + function isBindingPattern(node: Node): node is BindingPattern; + function isBindingElement(node: Node): node is BindingElement; + function isArrayBindingElement(node: Node): node is ArrayBindingElement; + function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression; + function isElementAccessExpression(node: Node): node is ElementAccessExpression; + function isBinaryExpression(node: Node): node is BinaryExpression; + function isConditionalExpression(node: Node): node is ConditionalExpression; + function isCallExpression(node: Node): node is CallExpression; + function isTemplate(node: Node): node is Template; + function isSpreadElementExpression(node: Node): node is SpreadElementExpression; + function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments; + function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression; + function isUnaryExpression(node: Node): node is UnaryExpression; + function isExpression(node: Node): node is Expression; + function isAssertionExpression(node: Node): node is AssertionExpression; + function isPartiallyEmittedExpression(node: Node): node is PartiallyEmittedExpression; + function isNotEmittedStatement(node: Node): node is NotEmittedStatement; + function isNotEmittedOrPartiallyEmittedNode(node: Node): node is NotEmittedStatement | PartiallyEmittedExpression; + function isOmittedExpression(node: Node): node is OmittedExpression; + function isTemplateSpan(node: Node): node is TemplateSpan; + function isBlock(node: Node): node is Block; + function isConciseBody(node: Node): node is ConciseBody; + function isFunctionBody(node: Node): node is FunctionBody; + function isForInitializer(node: Node): node is ForInitializer; + function isVariableDeclaration(node: Node): node is VariableDeclaration; + function isVariableDeclarationList(node: Node): node is VariableDeclarationList; + function isCaseBlock(node: Node): node is CaseBlock; + function isModuleBody(node: Node): node is ModuleBody; + function isImportEqualsDeclaration(node: Node): node is ImportEqualsDeclaration; + function isImportClause(node: Node): node is ImportClause; + function isNamedImportBindings(node: Node): node is NamedImportBindings; + function isImportSpecifier(node: Node): node is ImportSpecifier; + function isNamedExports(node: Node): node is NamedExports; + function isExportSpecifier(node: Node): node is ExportSpecifier; + function isModuleOrEnumDeclaration(node: Node): node is ModuleDeclaration | EnumDeclaration; + function isDeclaration(node: Node): node is Declaration; + function isDeclarationStatement(node: Node): node is DeclarationStatement; + /** + * Determines whether the node is a statement that is not also a declaration + */ + function isStatementButNotDeclaration(node: Node): node is Statement; + function isStatement(node: Node): node is Statement; + function isModuleReference(node: Node): node is ModuleReference; + function isJsxOpeningElement(node: Node): node is JsxOpeningElement; + function isJsxClosingElement(node: Node): node is JsxClosingElement; + function isJsxTagNameExpression(node: Node): node is JsxTagNameExpression; + function isJsxChild(node: Node): node is JsxChild; + function isJsxAttributeLike(node: Node): node is JsxAttributeLike; + function isJsxSpreadAttribute(node: Node): node is JsxSpreadAttribute; + function isJsxAttribute(node: Node): node is JsxAttribute; + function isStringLiteralOrJsxExpression(node: Node): node is StringLiteral | JsxExpression; + function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause; + function isHeritageClause(node: Node): node is HeritageClause; + function isCatchClause(node: Node): node is CatchClause; + function isPropertyAssignment(node: Node): node is PropertyAssignment; + function isShorthandPropertyAssignment(node: Node): node is ShorthandPropertyAssignment; + function isEnumMember(node: Node): node is EnumMember; + function isSourceFile(node: Node): node is SourceFile; function isWatchSet(options: CompilerOptions): boolean; } declare namespace ts { @@ -2912,6 +3411,8 @@ declare namespace ts { function collapseTextChangeRangesAcrossMultipleVersions(changes: TextChangeRange[]): TextChangeRange; function getTypeParameterOwner(d: Declaration): Declaration; function isParameterPropertyDeclaration(node: ParameterDeclaration): boolean; + function getCombinedModifierFlags(node: Node): ModifierFlags; + function getCombinedNodeFlags(node: Node): NodeFlags; } declare namespace ts { var Diagnostics: { @@ -4145,19 +4646,19 @@ declare namespace ts { key: string; message: string; }; - with_statements_are_not_allowed_in_an_async_function_block: { + A_const_initializer_in_an_ambient_context_must_be_a_string_or_numeric_literal: { code: number; category: DiagnosticCategory; key: string; message: string; }; - await_expression_is_only_allowed_within_an_async_function: { + with_statements_are_not_allowed_in_an_async_function_block: { code: number; category: DiagnosticCategory; key: string; message: string; }; - Async_functions_are_only_available_when_targeting_ECMAScript_2015_or_higher: { + await_expression_is_only_allowed_within_an_async_function: { code: number; category: DiagnosticCategory; key: string; @@ -4487,7 +4988,7 @@ declare namespace ts { key: string; message: string; }; - Cannot_invoke_an_expression_whose_type_lacks_a_call_signature: { + Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures: { code: number; category: DiagnosticCategory; key: string; @@ -4517,12 +5018,6 @@ declare namespace ts { key: string; message: string; }; - No_best_common_type_exists_among_return_expressions: { - code: number; - category: DiagnosticCategory; - key: string; - message: string; - }; A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value: { code: number; category: DiagnosticCategory; @@ -4841,7 +5336,7 @@ declare namespace ts { key: string; message: string; }; - All_symbols_within_a_with_block_will_be_resolved_to_any: { + The_with_statement_is_not_supported_All_symbols_in_a_with_block_will_have_type_any: { code: number; category: DiagnosticCategory; key: string; @@ -5369,12 +5864,6 @@ declare namespace ts { key: string; message: string; }; - No_best_common_type_exists_among_yield_expressions: { - code: number; - category: DiagnosticCategory; - key: string; - message: string; - }; A_generator_cannot_have_a_void_type_annotation: { code: number; category: DiagnosticCategory; @@ -5471,7 +5960,7 @@ declare namespace ts { key: string; message: string; }; - The_arguments_object_cannot_be_referenced_in_an_async_arrow_function_Consider_using_a_standard_async_function_expression: { + The_arguments_object_cannot_be_referenced_in_an_async_function_or_method_in_ES3_and_ES5_Consider_using_a_standard_function_or_method: { code: number; category: DiagnosticCategory; key: string; @@ -5855,6 +6344,30 @@ declare namespace ts { key: string; message: string; }; + _0_only_refers_to_a_type_but_is_being_used_as_a_value_here: { + code: number; + category: DiagnosticCategory; + key: string; + message: string; + }; + Namespace_0_has_no_exported_member_1: { + code: number; + category: DiagnosticCategory; + key: string; + message: string; + }; + Left_side_of_comma_operator_is_unused_and_has_no_side_effects: { + code: number; + category: DiagnosticCategory; + key: string; + message: string; + }; + The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead: { + code: number; + category: DiagnosticCategory; + key: string; + message: string; + }; Import_declaration_0_is_using_private_name_1: { code: number; category: DiagnosticCategory; @@ -6629,6 +7142,12 @@ declare namespace ts { key: string; message: string; }; + STRATEGY: { + code: number; + category: DiagnosticCategory; + key: string; + message: string; + }; Compilation_complete_Watching_for_file_changes: { code: number; category: DiagnosticCategory; @@ -7175,6 +7694,18 @@ declare namespace ts { key: string; message: string; }; + Import_emit_helpers_from_tslib: { + code: number; + category: DiagnosticCategory; + key: string; + message: string; + }; + Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using_cache_location_2: { + code: number; + category: DiagnosticCategory; + key: string; + message: string; + }; Variable_0_implicitly_has_an_1_type: { code: number; category: DiagnosticCategory; @@ -7487,6 +8018,18 @@ declare namespace ts { key: string; message: string; }; + Circularity_detected_while_resolving_configuration_Colon_0: { + code: number; + category: DiagnosticCategory; + key: string; + message: string; + }; + The_path_in_an_extends_options_must_be_relative_or_rooted: { + code: number; + category: DiagnosticCategory; + key: string; + message: string; + }; }; } declare namespace ts { @@ -7510,6 +8053,7 @@ declare namespace ts { reScanSlashToken(): SyntaxKind; reScanTemplateToken(): SyntaxKind; scanJsxIdentifier(): SyntaxKind; + scanJsxAttributeValue(): SyntaxKind; reScanJsxToken(): SyntaxKind; scanJsxToken(): SyntaxKind; scanJSDocToken(): SyntaxKind; @@ -7546,73 +8090,513 @@ declare namespace ts { function isOctalDigit(ch: number): boolean; function couldStartTrivia(text: string, pos: number): boolean; function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boolean, stopAtComments?: boolean): number; + function forEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: SyntaxKind, hasTrailingNewLine: boolean, state: T) => U, state?: T): U; + function forEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: SyntaxKind, hasTrailingNewLine: boolean, state: T) => U, state?: T): U; + function reduceEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: SyntaxKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U): U; + function reduceEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: SyntaxKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U): U; function getLeadingCommentRanges(text: string, pos: number): CommentRange[]; function getTrailingCommentRanges(text: string, pos: number): CommentRange[]; /** Optionally, get the shebang */ function getShebang(text: string): string; function isIdentifierStart(ch: number, languageVersion: ScriptTarget): boolean; function isIdentifierPart(ch: number, languageVersion: ScriptTarget): boolean; - function isIdentifier(name: string, languageVersion: ScriptTarget): boolean; + function isIdentifierText(name: string, languageVersion: ScriptTarget): boolean; function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean, languageVariant?: LanguageVariant, text?: string, onError?: ErrorCallback, start?: number, length?: number): Scanner; } declare namespace ts { - function createNode(kind: SyntaxKind, pos?: number, end?: number): Node; - function forEachChild(node: Node, cbNode: (node: Node) => T, cbNodeArray?: (nodes: Node[]) => T): T; - function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes?: boolean, scriptKind?: ScriptKind): SourceFile; - function isExternalModule(file: SourceFile): boolean; - function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile; - function parseIsolatedJSDocComment(content: string, start?: number, length?: number): { - jsDocComment: JSDocComment; - diagnostics: Diagnostic[]; - }; - function parseJSDocTypeExpressionForTests(content: string, start?: number, length?: number): { - jsDocTypeExpression: JSDocTypeExpression; - diagnostics: Diagnostic[]; - }; -} -declare namespace ts { - enum ModuleInstanceState { - NonInstantiated = 0, - Instantiated = 1, - ConstEnumOnly = 2, - } - function getModuleInstanceState(node: Node): ModuleInstanceState; - function bindSourceFile(file: SourceFile, options: CompilerOptions): void; -} -declare namespace ts { - function getNodeId(node: Node): number; - function getSymbolId(symbol: Symbol): number; - function createTypeChecker(host: TypeCheckerHost, produceDiagnostics: boolean): TypeChecker; -} -declare namespace ts { - const optionDeclarations: CommandLineOption[]; - let typingOptionDeclarations: CommandLineOption[]; - interface OptionNameMap { - optionNameMap: Map; - shortOptionNames: Map; - } - const defaultInitCompilerOptions: CompilerOptions; - function getOptionNameMap(): OptionNameMap; - function createCompilerDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType): Diagnostic; - function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: string, errors: Diagnostic[]): number | string; - function parseListTypeOption(opt: CommandLineOptionOfListType, value: string, errors: Diagnostic[]): (string | number)[] | undefined; - function parseCommandLine(commandLine: string[], readFile?: (path: string) => string): ParsedCommandLine; + function updateNode(updated: T, original: T): T; + function createNodeArray(elements?: T[], location?: TextRange, hasTrailingComma?: boolean): NodeArray; + function createSynthesizedNode(kind: SyntaxKind, startsOnNewLine?: boolean): Node; + function createSynthesizedNodeArray(elements?: T[]): NodeArray; /** - * Read tsconfig.json file - * @param fileName The path to the config file - */ - function readConfigFile(fileName: string, readFile: (path: string) => string): { - config?: any; - error?: Diagnostic; - }; + * Creates a shallow, memberwise clone of a node with no source map location. + */ + function getSynthesizedClone(node: T): T; /** - * Parse the text of the tsconfig.json file - * @param fileName The path to the config file - * @param jsonText The text of the config file - */ - function parseConfigFileTextToJson(fileName: string, jsonText: string): { - config?: any; - error?: Diagnostic; + * Creates a shallow, memberwise clone of a node for mutation. + */ + function getMutableClone(node: T): T; + function createLiteral(textSource: StringLiteral | Identifier, location?: TextRange): StringLiteral; + function createLiteral(value: string, location?: TextRange): StringLiteral; + function createLiteral(value: number, location?: TextRange): NumericLiteral; + function createLiteral(value: string | number | boolean, location?: TextRange): PrimaryExpression; + function createIdentifier(text: string, location?: TextRange): Identifier; + function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, location?: TextRange): Identifier; + function createLoopVariable(location?: TextRange): Identifier; + function createUniqueName(text: string, location?: TextRange): Identifier; + function getGeneratedNameForNode(node: Node, location?: TextRange): Identifier; + function createToken(token: SyntaxKind): Node; + function createSuper(): PrimaryExpression; + function createThis(location?: TextRange): PrimaryExpression; + function createNull(): PrimaryExpression; + function createComputedPropertyName(expression: Expression, location?: TextRange): ComputedPropertyName; + function updateComputedPropertyName(node: ComputedPropertyName, expression: Expression): ComputedPropertyName; + function createParameter(name: string | Identifier | BindingPattern, initializer?: Expression, location?: TextRange): ParameterDeclaration; + function createParameterDeclaration(decorators: Decorator[], modifiers: Modifier[], dotDotDotToken: Node, name: string | Identifier | BindingPattern, questionToken: Node, type: TypeNode, initializer: Expression, location?: TextRange, flags?: NodeFlags): ParameterDeclaration; + function updateParameterDeclaration(node: ParameterDeclaration, decorators: Decorator[], modifiers: Modifier[], name: BindingName, type: TypeNode, initializer: Expression): ParameterDeclaration; + function createProperty(decorators: Decorator[], modifiers: Modifier[], name: string | PropertyName, questionToken: Node, type: TypeNode, initializer: Expression, location?: TextRange): PropertyDeclaration; + function updateProperty(node: PropertyDeclaration, decorators: Decorator[], modifiers: Modifier[], name: PropertyName, type: TypeNode, initializer: Expression): PropertyDeclaration; + function createMethod(decorators: Decorator[], modifiers: Modifier[], asteriskToken: Node, name: string | PropertyName, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block, location?: TextRange, flags?: NodeFlags): MethodDeclaration; + function updateMethod(node: MethodDeclaration, decorators: Decorator[], modifiers: Modifier[], name: PropertyName, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block): MethodDeclaration; + function createConstructor(decorators: Decorator[], modifiers: Modifier[], parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags): ConstructorDeclaration; + function updateConstructor(node: ConstructorDeclaration, decorators: Decorator[], modifiers: Modifier[], parameters: ParameterDeclaration[], body: Block): ConstructorDeclaration; + function createGetAccessor(decorators: Decorator[], modifiers: Modifier[], name: string | PropertyName, parameters: ParameterDeclaration[], type: TypeNode, body: Block, location?: TextRange, flags?: NodeFlags): GetAccessorDeclaration; + function updateGetAccessor(node: GetAccessorDeclaration, decorators: Decorator[], modifiers: Modifier[], name: PropertyName, parameters: ParameterDeclaration[], type: TypeNode, body: Block): GetAccessorDeclaration; + function createSetAccessor(decorators: Decorator[], modifiers: Modifier[], name: string | PropertyName, parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags): SetAccessorDeclaration; + function updateSetAccessor(node: SetAccessorDeclaration, decorators: Decorator[], modifiers: Modifier[], name: PropertyName, parameters: ParameterDeclaration[], body: Block): SetAccessorDeclaration; + function createObjectBindingPattern(elements: BindingElement[], location?: TextRange): ObjectBindingPattern; + function updateObjectBindingPattern(node: ObjectBindingPattern, elements: BindingElement[]): ObjectBindingPattern; + function createArrayBindingPattern(elements: ArrayBindingElement[], location?: TextRange): ArrayBindingPattern; + function updateArrayBindingPattern(node: ArrayBindingPattern, elements: ArrayBindingElement[]): ArrayBindingPattern; + function createBindingElement(propertyName: string | PropertyName, dotDotDotToken: Node, name: string | BindingName, initializer?: Expression, location?: TextRange): BindingElement; + function updateBindingElement(node: BindingElement, propertyName: PropertyName, name: BindingName, initializer: Expression): BindingElement; + function createArrayLiteral(elements?: Expression[], location?: TextRange, multiLine?: boolean): ArrayLiteralExpression; + function updateArrayLiteral(node: ArrayLiteralExpression, elements: Expression[]): ArrayLiteralExpression; + function createObjectLiteral(properties?: ObjectLiteralElementLike[], location?: TextRange, multiLine?: boolean): ObjectLiteralExpression; + function updateObjectLiteral(node: ObjectLiteralExpression, properties: ObjectLiteralElementLike[]): ObjectLiteralExpression; + function createPropertyAccess(expression: Expression, name: string | Identifier, location?: TextRange, flags?: NodeFlags): PropertyAccessExpression; + function updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier): PropertyAccessExpression; + function createElementAccess(expression: Expression, index: number | Expression, location?: TextRange): ElementAccessExpression; + function updateElementAccess(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression): ElementAccessExpression; + function createCall(expression: Expression, typeArguments: TypeNode[], argumentsArray: Expression[], location?: TextRange, flags?: NodeFlags): CallExpression; + function updateCall(node: CallExpression, expression: Expression, typeArguments: TypeNode[], argumentsArray: Expression[]): CallExpression; + function createNew(expression: Expression, typeArguments: TypeNode[], argumentsArray: Expression[], location?: TextRange, flags?: NodeFlags): NewExpression; + function updateNew(node: NewExpression, expression: Expression, typeArguments: TypeNode[], argumentsArray: Expression[]): NewExpression; + function createTaggedTemplate(tag: Expression, template: Template, location?: TextRange): TaggedTemplateExpression; + function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: Template): TaggedTemplateExpression; + function createParen(expression: Expression, location?: TextRange): ParenthesizedExpression; + function updateParen(node: ParenthesizedExpression, expression: Expression): ParenthesizedExpression; + function createFunctionExpression(asteriskToken: Node, name: string | Identifier, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block, location?: TextRange, flags?: NodeFlags): FunctionExpression; + function updateFunctionExpression(node: FunctionExpression, name: Identifier, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block): FunctionExpression; + function createArrowFunction(modifiers: Modifier[], typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, equalsGreaterThanToken: Node, body: ConciseBody, location?: TextRange, flags?: NodeFlags): ArrowFunction; + function updateArrowFunction(node: ArrowFunction, modifiers: Modifier[], typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: ConciseBody): ArrowFunction; + function createDelete(expression: Expression, location?: TextRange): DeleteExpression; + function updateDelete(node: DeleteExpression, expression: Expression): Expression; + function createTypeOf(expression: Expression, location?: TextRange): TypeOfExpression; + function updateTypeOf(node: TypeOfExpression, expression: Expression): Expression; + function createVoid(expression: Expression, location?: TextRange): VoidExpression; + function updateVoid(node: VoidExpression, expression: Expression): VoidExpression; + function createAwait(expression: Expression, location?: TextRange): AwaitExpression; + function updateAwait(node: AwaitExpression, expression: Expression): AwaitExpression; + function createPrefix(operator: SyntaxKind, operand: Expression, location?: TextRange): PrefixUnaryExpression; + function updatePrefix(node: PrefixUnaryExpression, operand: Expression): PrefixUnaryExpression; + function createPostfix(operand: Expression, operator: SyntaxKind, location?: TextRange): PostfixUnaryExpression; + function updatePostfix(node: PostfixUnaryExpression, operand: Expression): PostfixUnaryExpression; + function createBinary(left: Expression, operator: SyntaxKind | Node, right: Expression, location?: TextRange): BinaryExpression; + function updateBinary(node: BinaryExpression, left: Expression, right: Expression): BinaryExpression; + function createConditional(condition: Expression, questionToken: Node, whenTrue: Expression, colonToken: Node, whenFalse: Expression, location?: TextRange): ConditionalExpression; + function updateConditional(node: ConditionalExpression, condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression; + function createTemplateExpression(head: TemplateLiteralFragment, templateSpans: TemplateSpan[], location?: TextRange): TemplateExpression; + function updateTemplateExpression(node: TemplateExpression, head: TemplateLiteralFragment, templateSpans: TemplateSpan[]): TemplateExpression; + function createYield(asteriskToken: Node, expression: Expression, location?: TextRange): YieldExpression; + function updateYield(node: YieldExpression, expression: Expression): YieldExpression; + function createSpread(expression: Expression, location?: TextRange): SpreadElementExpression; + function updateSpread(node: SpreadElementExpression, expression: Expression): SpreadElementExpression; + function createClassExpression(modifiers: Modifier[], name: Identifier, typeParameters: TypeParameterDeclaration[], heritageClauses: HeritageClause[], members: ClassElement[], location?: TextRange): ClassExpression; + function updateClassExpression(node: ClassExpression, modifiers: Modifier[], name: Identifier, typeParameters: TypeParameterDeclaration[], heritageClauses: HeritageClause[], members: ClassElement[]): ClassExpression; + function createOmittedExpression(location?: TextRange): OmittedExpression; + function createExpressionWithTypeArguments(typeArguments: TypeNode[], expression: Expression, location?: TextRange): ExpressionWithTypeArguments; + function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, typeArguments: TypeNode[], expression: Expression): ExpressionWithTypeArguments; + function createTemplateSpan(expression: Expression, literal: TemplateLiteralFragment, location?: TextRange): TemplateSpan; + function updateTemplateSpan(node: TemplateSpan, expression: Expression, literal: TemplateLiteralFragment): TemplateSpan; + function createBlock(statements: Statement[], location?: TextRange, multiLine?: boolean, flags?: NodeFlags): Block; + function updateBlock(node: Block, statements: Statement[]): Block; + function createVariableStatement(modifiers: Modifier[], declarationList: VariableDeclarationList | VariableDeclaration[], location?: TextRange, flags?: NodeFlags): VariableStatement; + function updateVariableStatement(node: VariableStatement, modifiers: Modifier[], declarationList: VariableDeclarationList): VariableStatement; + function createVariableDeclarationList(declarations: VariableDeclaration[], location?: TextRange, flags?: NodeFlags): VariableDeclarationList; + function updateVariableDeclarationList(node: VariableDeclarationList, declarations: VariableDeclaration[]): VariableDeclarationList; + function createVariableDeclaration(name: string | BindingPattern | Identifier, type?: TypeNode, initializer?: Expression, location?: TextRange, flags?: NodeFlags): VariableDeclaration; + function updateVariableDeclaration(node: VariableDeclaration, name: BindingName, type: TypeNode, initializer: Expression): VariableDeclaration; + function createEmptyStatement(location: TextRange): EmptyStatement; + function createStatement(expression: Expression, location?: TextRange, flags?: NodeFlags): ExpressionStatement; + function updateStatement(node: ExpressionStatement, expression: Expression): ExpressionStatement; + function createIf(expression: Expression, thenStatement: Statement, elseStatement?: Statement, location?: TextRange): IfStatement; + function updateIf(node: IfStatement, expression: Expression, thenStatement: Statement, elseStatement: Statement): IfStatement; + function createDo(statement: Statement, expression: Expression, location?: TextRange): DoStatement; + function updateDo(node: DoStatement, statement: Statement, expression: Expression): DoStatement; + function createWhile(expression: Expression, statement: Statement, location?: TextRange): WhileStatement; + function updateWhile(node: WhileStatement, expression: Expression, statement: Statement): WhileStatement; + function createFor(initializer: ForInitializer, condition: Expression, incrementor: Expression, statement: Statement, location?: TextRange): ForStatement; + function updateFor(node: ForStatement, initializer: ForInitializer, condition: Expression, incrementor: Expression, statement: Statement): ForStatement; + function createForIn(initializer: ForInitializer, expression: Expression, statement: Statement, location?: TextRange): ForInStatement; + function updateForIn(node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; + function createForOf(initializer: ForInitializer, expression: Expression, statement: Statement, location?: TextRange): ForOfStatement; + function updateForOf(node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; + function createContinue(label?: Identifier, location?: TextRange): BreakStatement; + function updateContinue(node: ContinueStatement, label: Identifier): BreakStatement; + function createBreak(label?: Identifier, location?: TextRange): BreakStatement; + function updateBreak(node: BreakStatement, label: Identifier): BreakStatement; + function createReturn(expression?: Expression, location?: TextRange): ReturnStatement; + function updateReturn(node: ReturnStatement, expression: Expression): ReturnStatement; + function createWith(expression: Expression, statement: Statement, location?: TextRange): WithStatement; + function updateWith(node: WithStatement, expression: Expression, statement: Statement): WithStatement; + function createSwitch(expression: Expression, caseBlock: CaseBlock, location?: TextRange): SwitchStatement; + function updateSwitch(node: SwitchStatement, expression: Expression, caseBlock: CaseBlock): SwitchStatement; + function createLabel(label: string | Identifier, statement: Statement, location?: TextRange): LabeledStatement; + function updateLabel(node: LabeledStatement, label: Identifier, statement: Statement): LabeledStatement; + function createThrow(expression: Expression, location?: TextRange): ThrowStatement; + function updateThrow(node: ThrowStatement, expression: Expression): ThrowStatement; + function createTry(tryBlock: Block, catchClause: CatchClause, finallyBlock: Block, location?: TextRange): TryStatement; + function updateTry(node: TryStatement, tryBlock: Block, catchClause: CatchClause, finallyBlock: Block): TryStatement; + function createCaseBlock(clauses: CaseOrDefaultClause[], location?: TextRange): CaseBlock; + function updateCaseBlock(node: CaseBlock, clauses: CaseOrDefaultClause[]): CaseBlock; + function createFunctionDeclaration(decorators: Decorator[], modifiers: Modifier[], asteriskToken: Node, name: string | Identifier, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block, location?: TextRange, flags?: NodeFlags): FunctionDeclaration; + function updateFunctionDeclaration(node: FunctionDeclaration, decorators: Decorator[], modifiers: Modifier[], name: Identifier, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block): FunctionDeclaration; + function createClassDeclaration(decorators: Decorator[], modifiers: Modifier[], name: Identifier, typeParameters: TypeParameterDeclaration[], heritageClauses: HeritageClause[], members: ClassElement[], location?: TextRange): ClassDeclaration; + function updateClassDeclaration(node: ClassDeclaration, decorators: Decorator[], modifiers: Modifier[], name: Identifier, typeParameters: TypeParameterDeclaration[], heritageClauses: HeritageClause[], members: ClassElement[]): ClassDeclaration; + function createImportDeclaration(decorators: Decorator[], modifiers: Modifier[], importClause: ImportClause, moduleSpecifier?: Expression, location?: TextRange): ImportDeclaration; + function updateImportDeclaration(node: ImportDeclaration, decorators: Decorator[], modifiers: Modifier[], importClause: ImportClause, moduleSpecifier: Expression): ImportDeclaration; + function createImportClause(name: Identifier, namedBindings: NamedImportBindings, location?: TextRange): ImportClause; + function updateImportClause(node: ImportClause, name: Identifier, namedBindings: NamedImportBindings): ImportClause; + function createNamespaceImport(name: Identifier, location?: TextRange): NamespaceImport; + function updateNamespaceImport(node: NamespaceImport, name: Identifier): NamespaceImport; + function createNamedImports(elements: ImportSpecifier[], location?: TextRange): NamedImports; + function updateNamedImports(node: NamedImports, elements: ImportSpecifier[]): NamedImports; + function createImportSpecifier(propertyName: Identifier, name: Identifier, location?: TextRange): ImportSpecifier; + function updateImportSpecifier(node: ImportSpecifier, propertyName: Identifier, name: Identifier): ImportSpecifier; + function createExportAssignment(decorators: Decorator[], modifiers: Modifier[], isExportEquals: boolean, expression: Expression, location?: TextRange): ExportAssignment; + function updateExportAssignment(node: ExportAssignment, decorators: Decorator[], modifiers: Modifier[], expression: Expression): ExportAssignment; + function createExportDeclaration(decorators: Decorator[], modifiers: Modifier[], exportClause: NamedExports, moduleSpecifier?: Expression, location?: TextRange): ExportDeclaration; + function updateExportDeclaration(node: ExportDeclaration, decorators: Decorator[], modifiers: Modifier[], exportClause: NamedExports, moduleSpecifier: Expression): ExportDeclaration; + function createNamedExports(elements: ExportSpecifier[], location?: TextRange): NamedExports; + function updateNamedExports(node: NamedExports, elements: ExportSpecifier[]): NamedExports; + function createExportSpecifier(name: string | Identifier, propertyName?: string | Identifier, location?: TextRange): ExportSpecifier; + function updateExportSpecifier(node: ExportSpecifier, name: Identifier, propertyName: Identifier): ExportSpecifier; + function createJsxElement(openingElement: JsxOpeningElement, children: JsxChild[], closingElement: JsxClosingElement, location?: TextRange): JsxElement; + function updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: JsxChild[], closingElement: JsxClosingElement): JsxElement; + function createJsxSelfClosingElement(tagName: JsxTagNameExpression, attributes: JsxAttributeLike[], location?: TextRange): JsxSelfClosingElement; + function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, attributes: JsxAttributeLike[]): JsxSelfClosingElement; + function createJsxOpeningElement(tagName: JsxTagNameExpression, attributes: JsxAttributeLike[], location?: TextRange): JsxOpeningElement; + function updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, attributes: JsxAttributeLike[]): JsxOpeningElement; + function createJsxClosingElement(tagName: JsxTagNameExpression, location?: TextRange): JsxClosingElement; + function updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression): JsxClosingElement; + function createJsxAttribute(name: Identifier, initializer: StringLiteral | JsxExpression, location?: TextRange): JsxAttribute; + function updateJsxAttribute(node: JsxAttribute, name: Identifier, initializer: StringLiteral | JsxExpression): JsxAttribute; + function createJsxSpreadAttribute(expression: Expression, location?: TextRange): JsxSpreadAttribute; + function updateJsxSpreadAttribute(node: JsxSpreadAttribute, expression: Expression): JsxSpreadAttribute; + function createJsxExpression(expression: Expression, location?: TextRange): JsxExpression; + function updateJsxExpression(node: JsxExpression, expression: Expression): JsxExpression; + function createHeritageClause(token: SyntaxKind, types: ExpressionWithTypeArguments[], location?: TextRange): HeritageClause; + function updateHeritageClause(node: HeritageClause, types: ExpressionWithTypeArguments[]): HeritageClause; + function createCaseClause(expression: Expression, statements: Statement[], location?: TextRange): CaseClause; + function updateCaseClause(node: CaseClause, expression: Expression, statements: Statement[]): CaseClause; + function createDefaultClause(statements: Statement[], location?: TextRange): DefaultClause; + function updateDefaultClause(node: DefaultClause, statements: Statement[]): DefaultClause; + function createCatchClause(variableDeclaration: string | VariableDeclaration, block: Block, location?: TextRange): CatchClause; + function updateCatchClause(node: CatchClause, variableDeclaration: VariableDeclaration, block: Block): CatchClause; + function createPropertyAssignment(name: string | PropertyName, initializer: Expression, location?: TextRange): PropertyAssignment; + function updatePropertyAssignment(node: PropertyAssignment, name: PropertyName, initializer: Expression): PropertyAssignment; + function createShorthandPropertyAssignment(name: string | Identifier, objectAssignmentInitializer: Expression, location?: TextRange): ShorthandPropertyAssignment; + function updateShorthandPropertyAssignment(node: ShorthandPropertyAssignment, name: Identifier, objectAssignmentInitializer: Expression): ShorthandPropertyAssignment; + function updateSourceFileNode(node: SourceFile, statements: Statement[]): SourceFile; + /** + * Creates a synthetic statement to act as a placeholder for a not-emitted statement in + * order to preserve comments. + * + * @param original The original statement. + */ + function createNotEmittedStatement(original: Node): NotEmittedStatement; + /** + * Creates a synthetic expression to act as a placeholder for a not-emitted expression in + * order to preserve comments or sourcemap positions. + * + * @param expression The inner expression to emit. + * @param original The original outer expression. + * @param location The location for the expression. Defaults to the positions from "original" if provided. + */ + function createPartiallyEmittedExpression(expression: Expression, original?: Node, location?: TextRange): PartiallyEmittedExpression; + function updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression): PartiallyEmittedExpression; + function createComma(left: Expression, right: Expression): Expression; + function createLessThan(left: Expression, right: Expression, location?: TextRange): Expression; + function createAssignment(left: Expression, right: Expression, location?: TextRange): BinaryExpression; + function createStrictEquality(left: Expression, right: Expression): BinaryExpression; + function createStrictInequality(left: Expression, right: Expression): BinaryExpression; + function createAdd(left: Expression, right: Expression): BinaryExpression; + function createSubtract(left: Expression, right: Expression): BinaryExpression; + function createPostfixIncrement(operand: Expression, location?: TextRange): PostfixUnaryExpression; + function createLogicalAnd(left: Expression, right: Expression): BinaryExpression; + function createLogicalOr(left: Expression, right: Expression): BinaryExpression; + function createLogicalNot(operand: Expression): PrefixUnaryExpression; + function createVoidZero(): VoidExpression; + function createMemberAccessForPropertyName(target: Expression, memberName: PropertyName, location?: TextRange): MemberExpression; + function createRestParameter(name: string | Identifier): ParameterDeclaration; + function createFunctionCall(func: Expression, thisArg: Expression, argumentsList: Expression[], location?: TextRange): CallExpression; + function createFunctionApply(func: Expression, thisArg: Expression, argumentsExpression: Expression, location?: TextRange): CallExpression; + function createArraySlice(array: Expression, start?: number | Expression): CallExpression; + function createArrayConcat(array: Expression, values: Expression[]): CallExpression; + function createMathPow(left: Expression, right: Expression, location?: TextRange): CallExpression; + function createReactCreateElement(reactNamespace: string, tagName: Expression, props: Expression, children: Expression[], parentElement: JsxOpeningLikeElement, location: TextRange): LeftHandSideExpression; + function createLetDeclarationList(declarations: VariableDeclaration[], location?: TextRange): VariableDeclarationList; + function createConstDeclarationList(declarations: VariableDeclaration[], location?: TextRange): VariableDeclarationList; + function createHelperName(externalHelpersModuleName: Identifier | undefined, name: string): Identifier | PropertyAccessExpression; + function createExtendsHelper(externalHelpersModuleName: Identifier | undefined, name: Identifier): CallExpression; + function createAssignHelper(externalHelpersModuleName: Identifier | undefined, attributesSegments: Expression[]): CallExpression; + function createParamHelper(externalHelpersModuleName: Identifier | undefined, expression: Expression, parameterOffset: number, location?: TextRange): CallExpression; + function createMetadataHelper(externalHelpersModuleName: Identifier | undefined, metadataKey: string, metadataValue: Expression): CallExpression; + function createDecorateHelper(externalHelpersModuleName: Identifier | undefined, decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression, location?: TextRange): CallExpression; + function createAwaiterHelper(externalHelpersModuleName: Identifier | undefined, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression, body: Block): CallExpression; + function createHasOwnProperty(target: LeftHandSideExpression, propertyName: Expression): CallExpression; + function createAdvancedAsyncSuperHelper(): VariableStatement; + function createSimpleAsyncSuperHelper(): VariableStatement; + interface CallBinding { + target: LeftHandSideExpression; + thisArg: Expression; + } + function createCallBinding(expression: Expression, recordTempVariable: (temp: Identifier) => void, languageVersion?: ScriptTarget, cacheIdentifiers?: boolean): CallBinding; + function inlineExpressions(expressions: Expression[]): Expression; + function createExpressionFromEntityName(node: EntityName | Expression): Expression; + function createExpressionForPropertyName(memberName: PropertyName): Expression; + function createExpressionForObjectLiteralElementLike(node: ObjectLiteralExpression, property: ObjectLiteralElementLike, receiver: Expression): Expression; + /** + * Add any necessary prologue-directives into target statement-array. + * The function needs to be called during each transformation step. + * This function needs to be called whenever we transform the statement + * list of a source file, namespace, or function-like body. + * + * @param target: result statements array + * @param source: origin statements array + * @param ensureUseStrict: boolean determining whether the function need to add prologue-directives + * @param visitor: Optional callback used to visit any custom prologue directives. + */ + function addPrologueDirectives(target: Statement[], source: Statement[], ensureUseStrict?: boolean, visitor?: (node: Node) => VisitResult): number; + /** + * Wraps the operand to a BinaryExpression in parentheses if they are needed to preserve the intended + * order of operations. + * + * @param binaryOperator The operator for the BinaryExpression. + * @param operand The operand for the BinaryExpression. + * @param isLeftSideOfBinary A value indicating whether the operand is the left side of the + * BinaryExpression. + */ + function parenthesizeBinaryOperand(binaryOperator: SyntaxKind, operand: Expression, isLeftSideOfBinary: boolean, leftOperand?: Expression): Expression; + /** + * Wraps an expression in parentheses if it is needed in order to use the expression + * as the expression of a NewExpression node. + * + * @param expression The Expression node. + */ + function parenthesizeForNew(expression: Expression): LeftHandSideExpression; + /** + * Wraps an expression in parentheses if it is needed in order to use the expression for + * property or element access. + * + * @param expr The expression node. + */ + function parenthesizeForAccess(expression: Expression): LeftHandSideExpression; + function parenthesizePostfixOperand(operand: Expression): LeftHandSideExpression; + function parenthesizePrefixOperand(operand: Expression): UnaryExpression; + function parenthesizeExpressionForList(expression: Expression): Expression; + function parenthesizeExpressionForExpressionStatement(expression: Expression): Expression; + function parenthesizeConciseBody(body: ConciseBody): ConciseBody; + enum OuterExpressionKinds { + Parentheses = 1, + Assertions = 2, + PartiallyEmittedExpressions = 4, + All = 7, + } + function skipOuterExpressions(node: Expression, kinds?: OuterExpressionKinds): Expression; + function skipOuterExpressions(node: Node, kinds?: OuterExpressionKinds): Node; + function skipParentheses(node: Expression): Expression; + function skipParentheses(node: Node): Node; + function skipAssertions(node: Expression): Expression; + function skipAssertions(node: Node): Node; + function skipPartiallyEmittedExpressions(node: Expression): Expression; + function skipPartiallyEmittedExpressions(node: Node): Node; + function startOnNewLine(node: T): T; + function setOriginalNode(node: T, original: Node): T; + /** + * Clears any EmitNode entries from parse-tree nodes. + * @param sourceFile A source file. + */ + function disposeEmitNodes(sourceFile: SourceFile): void; + /** + * Gets flags that control emit behavior of a node. + * + * @param node The node. + */ + function getEmitFlags(node: Node): EmitFlags; + /** + * Sets flags that control emit behavior of a node. + * + * @param node The node. + * @param emitFlags The NodeEmitFlags for the node. + */ + function setEmitFlags(node: T, emitFlags: EmitFlags): T; + /** + * Sets a custom text range to use when emitting source maps. + * + * @param node The node. + * @param range The text range. + */ + function setSourceMapRange(node: T, range: TextRange): T; + /** + * Sets the TextRange to use for source maps for a token of a node. + * + * @param node The node. + * @param token The token. + * @param range The text range. + */ + function setTokenSourceMapRange(node: T, token: SyntaxKind, range: TextRange): T; + /** + * Sets a custom text range to use when emitting comments. + */ + function setCommentRange(node: T, range: TextRange): T; + /** + * Gets a custom text range to use when emitting comments. + * + * @param node The node. + */ + function getCommentRange(node: Node): TextRange; + /** + * Gets a custom text range to use when emitting source maps. + * + * @param node The node. + */ + function getSourceMapRange(node: Node): TextRange; + /** + * Gets the TextRange to use for source maps for a token of a node. + * + * @param node The node. + * @param token The token. + */ + function getTokenSourceMapRange(node: Node, token: SyntaxKind): TextRange; + /** + * Gets the constant value to emit for an expression. + */ + function getConstantValue(node: PropertyAccessExpression | ElementAccessExpression): number; + /** + * Sets the constant value to emit for an expression. + */ + function setConstantValue(node: PropertyAccessExpression | ElementAccessExpression, value: number): PropertyAccessExpression | ElementAccessExpression; + function setTextRange(node: T, location: TextRange): T; + function setNodeFlags(node: T, flags: NodeFlags): T; + function setMultiLine(node: T, multiLine: boolean): T; + function setHasTrailingComma(nodes: NodeArray, hasTrailingComma: boolean): NodeArray; + /** + * Get the name of that target module from an import or export declaration + */ + function getLocalNameForExternalImport(node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile): Identifier; + /** + * Get the name of a target module from an import/export declaration as should be written in the emitted output. + * The emitted output name can be different from the input if: + * 1. The module has a /// + * 2. --out or --outFile is used, making the name relative to the rootDir + * 3- The containing SourceFile has an entry in renamedDependencies for the import as requested by some module loaders (e.g. System). + * Otherwise, a new StringLiteral node representing the module name will be returned. + */ + function getExternalModuleNameLiteral(importNode: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile, host: EmitHost, resolver: EmitResolver, compilerOptions: CompilerOptions): StringLiteral; + /** + * Get the name of a module as should be written in the emitted output. + * The emitted output name can be different from the input if: + * 1. The module has a /// + * 2. --out or --outFile is used, making the name relative to the rootDir + * Otherwise, a new StringLiteral node representing the module name will be returned. + */ + function tryGetModuleNameFromFile(file: SourceFile, host: EmitHost, options: CompilerOptions): StringLiteral; +} +declare namespace ts { + function createNode(kind: SyntaxKind, pos?: number, end?: number): Node; + function forEachChild(node: Node, cbNode: (node: Node) => T, cbNodeArray?: (nodes: Node[]) => T): T; + function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes?: boolean, scriptKind?: ScriptKind): SourceFile; + function isExternalModule(file: SourceFile): boolean; + function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile; + function parseIsolatedJSDocComment(content: string, start?: number, length?: number): { + jsDoc: JSDoc; + diagnostics: Diagnostic[]; + }; + function parseJSDocTypeExpressionForTests(content: string, start?: number, length?: number): { + jsDocTypeExpression: JSDocTypeExpression; + diagnostics: Diagnostic[]; + }; +} +declare namespace ts { + enum ModuleInstanceState { + NonInstantiated = 0, + Instantiated = 1, + ConstEnumOnly = 2, + } + function getModuleInstanceState(node: Node): ModuleInstanceState; + function bindSourceFile(file: SourceFile, options: CompilerOptions): void; + /** + * Computes the transform flags for a node, given the transform flags of its subtree + * + * @param node The node to analyze + * @param subtreeFlags Transform flags computed for this node's subtree + */ + function computeTransformFlagsForNode(node: Node, subtreeFlags: TransformFlags): TransformFlags; +} +declare namespace ts { + function trace(host: ModuleResolutionHost, message: DiagnosticMessage, ...args: any[]): void; + function isTraceEnabled(compilerOptions: CompilerOptions, host: ModuleResolutionHost): boolean; + function createResolvedModule(resolvedFileName: string, isExternalLibraryImport: boolean, failedLookupLocations: string[]): ResolvedModuleWithFailedLookupLocations; + interface ModuleResolutionState { + host: ModuleResolutionHost; + compilerOptions: CompilerOptions; + traceEnabled: boolean; + skipTsx: boolean; + } + function getEffectiveTypeRoots(options: CompilerOptions, host: { + directoryExists?: (directoryName: string) => boolean; + getCurrentDirectory?: () => string; + }): string[] | undefined; + /** + * @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. + * This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups + * is assumed to be the same as root directory of the project. + */ + function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string, options: CompilerOptions, host: ModuleResolutionHost): ResolvedTypeReferenceDirectiveWithFailedLookupLocations; + /** + * Given a set of options, returns the set of type directive names + * that should be included for this program automatically. + * This list could either come from the config file, + * or from enumerating the types root + initial secondary types lookup location. + * More type directives might appear in the program later as a result of loading actual source files; + * this list is only the set of defaults that are implicitly included. + */ + function getAutomaticTypeDirectiveNames(options: CompilerOptions, host: ModuleResolutionHost): string[]; + function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations; + function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations; + function directoryProbablyExists(directoryName: string, host: { + directoryExists?: (directoryName: string) => boolean; + }): boolean; + function loadModuleFromNodeModules(moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState, checkOneLevel: boolean): string; + function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations; +} +declare namespace ts { + function getNodeId(node: Node): number; + function getSymbolId(symbol: Symbol): number; + function createTypeChecker(host: TypeCheckerHost, produceDiagnostics: boolean): TypeChecker; +} +declare namespace ts { + const compileOnSaveCommandLineOption: CommandLineOption; + const optionDeclarations: CommandLineOption[]; + let typingOptionDeclarations: CommandLineOption[]; + interface OptionNameMap { + optionNameMap: Map; + shortOptionNames: Map; + } + const defaultInitCompilerOptions: CompilerOptions; + function getOptionNameMap(): OptionNameMap; + function createCompilerDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType): Diagnostic; + function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: string, errors: Diagnostic[]): string | number; + function parseListTypeOption(opt: CommandLineOptionOfListType, value: string, errors: Diagnostic[]): (string | number)[] | undefined; + function parseCommandLine(commandLine: string[], readFile?: (path: string) => string): ParsedCommandLine; + /** + * Read tsconfig.json file + * @param fileName The path to the config file + */ + function readConfigFile(fileName: string, readFile: (path: string) => string): { + config?: any; + error?: Diagnostic; + }; + /** + * Parse the text of the tsconfig.json file + * @param fileName The path to the config file + * @param jsonText The text of the config file + */ + function parseConfigFileTextToJson(fileName: string, jsonText: string, stripComments?: boolean): { + config?: any; + error?: Diagnostic; }; /** * Generate tsconfig configuration when running command line "--init" @@ -7629,63 +8613,311 @@ declare namespace ts { * @param basePath A root directory to resolve relative path entries in the config * file to. e.g. outDir */ - function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string): ParsedCommandLine; + function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[]): ParsedCommandLine; + function convertCompileOnSaveOptionFromJson(jsonOption: any, basePath: string, errors: Diagnostic[]): boolean; function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: CompilerOptions; errors: Diagnostic[]; }; function convertTypingOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { - options: CompilerOptions; + options: TypingOptions; errors: Diagnostic[]; }; } declare namespace ts { function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, targetSourceFile: SourceFile): Diagnostic[]; - function writeDeclarationFile(declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection): boolean; + function writeDeclarationFile(declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection, emitOnlyDtsFiles: boolean): boolean; +} +declare namespace ts { + type VisitResult = T | T[]; + /** + * Similar to `reduceLeft`, performs a reduction against each child of a node. + * NOTE: Unlike `forEachChild`, this does *not* visit every node. Only nodes added to the + * `nodeEdgeTraversalMap` above will be visited. + * + * @param node The node containing the children to reduce. + * @param f The callback function + * @param initial The initial value to supply to the reduction. + */ + function reduceEachChild(node: Node, f: (memo: T, node: Node) => T, initial: T): T; + /** + * Visits a Node using the supplied visitor, possibly returning a new Node in its place. + * + * @param node The Node to visit. + * @param visitor The callback used to visit the Node. + * @param test A callback to execute to verify the Node is valid. + * @param optional An optional value indicating whether the Node is itself optional. + * @param lift An optional callback to execute to lift a NodeArrayNode into a valid Node. + */ + function visitNode(node: T, visitor: (node: Node) => VisitResult, test: (node: Node) => boolean, optional?: boolean, lift?: (node: NodeArray) => T): T; + function visitNode(node: T, visitor: (node: Node) => VisitResult, test: (node: Node) => boolean, optional: boolean, lift: (node: NodeArray) => T, parenthesize: (node: Node, parentNode: Node) => Node, parentNode: Node): T; + /** + * Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place. + * + * @param nodes The NodeArray to visit. + * @param visitor The callback used to visit a Node. + * @param test A node test to execute for each node. + * @param start An optional value indicating the starting offset at which to start visiting. + * @param count An optional value indicating the maximum number of nodes to visit. + */ + function visitNodes(nodes: NodeArray, visitor: (node: Node) => VisitResult, test: (node: Node) => boolean, start?: number, count?: number): NodeArray; + function visitNodes(nodes: NodeArray, visitor: (node: Node) => VisitResult, test: (node: Node) => boolean, start: number, count: number, parenthesize: (node: Node, parentNode: Node) => Node, parentNode: Node): NodeArray; + /** + * Visits each child of a Node using the supplied visitor, possibly returning a new Node of the same kind in its place. + * + * @param node The Node whose children will be visited. + * @param visitor The callback used to visit each child. + * @param context A lexical environment context for the visitor. + */ + function visitEachChild(node: T, visitor: (node: Node) => VisitResult, context: LexicalEnvironment): T; + /** + * Merges generated lexical declarations into the FunctionBody of a non-arrow function-like declaration. + * + * @param node The ConciseBody of an arrow function. + * @param declarations The lexical declarations to merge. + */ + function mergeFunctionBodyLexicalEnvironment(body: FunctionBody, declarations: Statement[]): FunctionBody; + /** + * Merges generated lexical declarations into the ConciseBody of an ArrowFunction. + * + * @param node The ConciseBody of an arrow function. + * @param declarations The lexical declarations to merge. + */ + function mergeFunctionBodyLexicalEnvironment(body: ConciseBody, declarations: Statement[]): ConciseBody; + /** + * Lifts a NodeArray containing only Statement nodes to a block. + * + * @param nodes The NodeArray. + */ + function liftToBlock(nodes: Node[]): Statement; + /** + * Aggregates the TransformFlags for a Node and its subtree. + */ + function aggregateTransformFlags(node: T): T; + namespace Debug { + const failNotOptional: (message?: string) => void; + const failBadSyntaxKind: (node: Node, message?: string) => void; + const assertNode: (node: Node, test: (node: Node) => boolean, message?: string) => void; + } +} +declare namespace ts { + /** + * Flattens a destructuring assignment expression. + * + * @param root The destructuring assignment expression. + * @param needsValue Indicates whether the value from the right-hand-side of the + * destructuring assignment is needed as part of a larger expression. + * @param recordTempVariable A callback used to record new temporary variables. + * @param visitor An optional visitor to use to visit expressions. + */ + function flattenDestructuringAssignment(context: TransformationContext, node: BinaryExpression, needsValue: boolean, recordTempVariable: (node: Identifier) => void, visitor?: (node: Node) => VisitResult): Expression; + /** + * Flattens binding patterns in a parameter declaration. + * + * @param node The ParameterDeclaration to flatten. + * @param value The rhs value for the binding pattern. + * @param visitor An optional visitor to use to visit expressions. + */ + function flattenParameterDestructuring(context: TransformationContext, node: ParameterDeclaration, value: Expression, visitor?: (node: Node) => VisitResult): VariableDeclaration[]; + /** + * Flattens binding patterns in a variable declaration. + * + * @param node The VariableDeclaration to flatten. + * @param value An optional rhs value for the binding pattern. + * @param visitor An optional visitor to use to visit expressions. + */ + function flattenVariableDestructuring(context: TransformationContext, node: VariableDeclaration, value?: Expression, visitor?: (node: Node) => VisitResult, recordTempVariable?: (node: Identifier) => void): VariableDeclaration[]; + /** + * Flattens binding patterns in a variable declaration and transforms them into an expression. + * + * @param node The VariableDeclaration to flatten. + * @param recordTempVariable A callback used to record new temporary variables. + * @param nameSubstitution An optional callback used to substitute binding names. + * @param visitor An optional visitor to use to visit expressions. + */ + function flattenVariableDestructuringToExpression(context: TransformationContext, node: VariableDeclaration, recordTempVariable: (name: Identifier) => void, nameSubstitution?: (name: Identifier) => Expression, visitor?: (node: Node) => VisitResult): Expression; +} +declare namespace ts { + function transformTypeScript(context: TransformationContext): (node: SourceFile) => SourceFile; +} +declare namespace ts { + function transformJsx(context: TransformationContext): (node: SourceFile) => SourceFile; +} +declare namespace ts { + function transformES7(context: TransformationContext): (node: SourceFile) => SourceFile; +} +declare namespace ts { + function transformES6(context: TransformationContext): (node: SourceFile) => SourceFile; +} +declare namespace ts { + function transformGenerators(context: TransformationContext): (node: SourceFile) => SourceFile; +} +declare namespace ts { + function transformModule(context: TransformationContext): (node: SourceFile) => SourceFile; +} +declare namespace ts { + function transformSystemModule(context: TransformationContext): (node: SourceFile) => SourceFile; +} +declare namespace ts { + function transformES6Module(context: TransformationContext): (node: SourceFile) => SourceFile; +} +declare namespace ts { + interface TransformationResult { + /** + * Gets the transformed source files. + */ + transformed: SourceFile[]; + /** + * Emits the substitute for a node, if one is available; otherwise, emits the node. + * + * @param emitContext The current emit context. + * @param node The node to substitute. + * @param emitCallback A callback used to emit the node or its substitute. + */ + emitNodeWithSubstitution(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void; + /** + * Emits a node with possible notification. + * + * @param emitContext The current emit context. + * @param node The node to emit. + * @param emitCallback A callback used to emit the node. + */ + emitNodeWithNotification(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void; + } + interface TransformationContext extends LexicalEnvironment { + getCompilerOptions(): CompilerOptions; + getEmitResolver(): EmitResolver; + getEmitHost(): EmitHost; + /** + * Hoists a function declaration to the containing scope. + */ + hoistFunctionDeclaration(node: FunctionDeclaration): void; + /** + * Hoists a variable declaration to the containing scope. + */ + hoistVariableDeclaration(node: Identifier): void; + /** + * Enables expression substitutions in the pretty printer for the provided SyntaxKind. + */ + enableSubstitution(kind: SyntaxKind): void; + /** + * Determines whether expression substitutions are enabled for the provided node. + */ + isSubstitutionEnabled(node: Node): boolean; + /** + * Hook used by transformers to substitute expressions just before they + * are emitted by the pretty printer. + */ + onSubstituteNode?: (emitContext: EmitContext, node: Node) => Node; + /** + * Enables before/after emit notifications in the pretty printer for the provided + * SyntaxKind. + */ + enableEmitNotification(kind: SyntaxKind): void; + /** + * Determines whether before/after emit notifications should be raised in the pretty + * printer when it emits a node. + */ + isEmitNotificationEnabled(node: Node): boolean; + /** + * Hook used to allow transformers to capture state before or after + * the printer emits a node. + */ + onEmitNode?: (emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) => void; + } + type Transformer = (context: TransformationContext) => (node: SourceFile) => SourceFile; + function getTransformers(compilerOptions: CompilerOptions): Transformer[]; + /** + * Transforms an array of SourceFiles by passing them through each transformer. + * + * @param resolver The emit resolver provided by the checker. + * @param host The emit host. + * @param sourceFiles An array of source files + * @param transforms An array of Transformers. + */ + function transformFiles(resolver: EmitResolver, host: EmitHost, sourceFiles: SourceFile[], transformers: Transformer[]): TransformationResult; } declare namespace ts { interface SourceMapWriter { - getSourceMapData(): SourceMapData; + /** + * Initialize the SourceMapWriter for a new output file. + * + * @param filePath The path to the generated output file. + * @param sourceMapFilePath The path to the output source map file. + * @param sourceFiles The input source files for the program. + * @param isBundledEmit A value indicating whether the generated output file is a bundle. + */ + initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean): void; + /** + * Reset the SourceMapWriter to an empty state. + */ + reset(): void; + /** + * Set the current source file. + * + * @param sourceFile The source file. + */ setSourceFile(sourceFile: SourceFile): void; + /** + * Emits a mapping. + * + * If the position is synthetic (undefined or a negative value), no mapping will be + * created. + * + * @param pos The position. + */ emitPos(pos: number): void; - emitStart(range: TextRange): void; - emitEnd(range: TextRange, stopOverridingSpan?: boolean): void; - changeEmitSourcePos(): void; + /** + * Emits a node with possible leading and trailing source maps. + * + * @param emitContext The current emit context + * @param node The node to emit. + * @param emitCallback The callback used to emit the node. + */ + emitNodeWithSourceMap(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void; + /** + * Emits a token of a node node with possible leading and trailing source maps. + * + * @param node The node containing the token. + * @param token The token to emit. + * @param tokenStartPos The start pos of the token. + * @param emitCallback The callback used to emit the token. + */ + emitTokenWithSourceMap(node: Node, token: SyntaxKind, tokenStartPos: number, emitCallback: (token: SyntaxKind, tokenStartPos: number) => number): number; + /** + * Gets the text for the source map. + */ getText(): string; + /** + * Gets the SourceMappingURL for the source map. + */ getSourceMappingURL(): string; - initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean): void; - reset(): void; + /** + * Gets test data for source maps. + */ + getSourceMapData(): SourceMapData; } - function getNullSourceMapWriter(): SourceMapWriter; function createSourceMapWriter(host: EmitHost, writer: EmitTextWriter): SourceMapWriter; } declare namespace ts { - function getResolvedExternalModuleName(host: EmitHost, file: SourceFile): string; - function getExternalModuleNameFromDeclaration(host: EmitHost, resolver: EmitResolver, declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration): string; - function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile): EmitResult; + interface CommentWriter { + reset(): void; + setSourceFile(sourceFile: SourceFile): void; + emitNodeWithComments(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void; + emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void): void; + emitTrailingCommentsOfPosition(pos: number): void; + } + function createCommentWriter(host: EmitHost, writer: EmitTextWriter, sourceMap: SourceMapWriter): CommentWriter; +} +declare namespace ts { + function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile, emitOnlyDtsFiles?: boolean): EmitResult; } declare namespace ts { /** The version of the TypeScript compiler release */ - const version: string; - function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean): string; + const version = "2.1.0"; + function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean, configName?: string): string; function resolveTripleslashReference(moduleName: string, containingFile: string): string; function computeCommonSourceDirectoryOfFilenames(fileNames: string[], currentDirectory: string, getCanonicalFileName: (fileName: string) => string): string; - function hasZeroOrOneAsteriskCharacter(str: string): boolean; - /** - * @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. - * This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups - * is assumed to be the same as root directory of the project. - */ - function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string, options: CompilerOptions, host: ModuleResolutionHost): ResolvedTypeReferenceDirectiveWithFailedLookupLocations; - function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations; - /** Return the object corresponding to the best pattern to match `candidate`. */ - function findBestPatternMatch(values: T[], getPattern: (value: T) => Pattern, candidate: string): T | undefined; - function tryParsePattern(pattern: string): Pattern | undefined; - function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations; - function directoryProbablyExists(directoryName: string, host: { - directoryExists?: (directoryName: string) => boolean; - }): boolean; - function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations; function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost; function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[]; interface FormatDiagnosticsHost { @@ -7695,15 +8927,6 @@ declare namespace ts { } function formatDiagnostics(diagnostics: Diagnostic[], host: FormatDiagnosticsHost): string; function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain, newLine: string): string; - /** - * Given a set of options, returns the set of type directive names - * that should be included for this program automatically. - * This list could either come from the config file, - * or from enumerating the types root + initial secondary types lookup location. - * More type directives might appear in the program later as a result of loading actual source files; - * this list is only the set of defaults that are implicitly included. - */ - function getAutomaticTypeDirectiveNames(options: CompilerOptions, host: ModuleResolutionHost): string[]; function createProgram(rootNames: string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program): Program; } declare namespace ts { @@ -7712,53 +8935,6 @@ declare namespace ts { } function executeCommandLine(args: string[]): void; } -declare namespace ts.OutliningElementsCollector { - function collectElements(sourceFile: SourceFile): OutliningSpan[]; -} -declare namespace ts.NavigateTo { - function getNavigateToItems(program: Program, checker: TypeChecker, cancellationToken: CancellationToken, searchValue: string, maxResultCount: number): NavigateToItem[]; -} -declare namespace ts.NavigationBar { - function getNavigationBarItems(sourceFile: SourceFile): NavigationBarItem[]; -} -declare namespace ts { - enum PatternMatchKind { - exact = 0, - prefix = 1, - substring = 2, - camelCase = 3, - } - interface PatternMatch { - kind: PatternMatchKind; - camelCaseWeight?: number; - isCaseSensitive: boolean; - punctuationStripped: boolean; - } - interface PatternMatcher { - getMatchesForLastSegmentOfPattern(candidate: string): PatternMatch[]; - getMatches(candidateContainers: string[], candidate: string): PatternMatch[]; - patternContainsDots: boolean; - } - function createPatternMatcher(pattern: string): PatternMatcher; - function breakIntoCharacterSpans(identifier: string): TextSpan[]; - function breakIntoWordSpans(identifier: string): TextSpan[]; -} -declare namespace ts.SignatureHelp { - enum ArgumentListKind { - TypeArguments = 0, - CallArguments = 1, - TaggedTemplateArguments = 2, - } - interface ArgumentListInfo { - kind: ArgumentListKind; - invocation: CallLikeExpression; - argumentsSpan: TextSpan; - argumentIndex?: number; - argumentCount: number; - } - function getSignatureHelpItems(program: Program, sourceFile: SourceFile, position: number, cancellationToken: CancellationToken): SignatureHelpItems; - function getContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile): ArgumentListInfo; -} declare namespace ts { interface Node { getSourceFile(): SourceFile; @@ -7862,6 +9038,10 @@ declare namespace ts { trace?(s: string): void; error?(s: string): void; useCaseSensitiveFileNames?(): boolean; + readDirectory?(path: string, extensions?: string[], exclude?: string[], include?: string[]): string[]; + readFile?(path: string, encoding?: string): string; + fileExists?(path: string): boolean; + getTypeRootsVersion?(): number; resolveModuleNames?(moduleNames: string[], containingFile: string): ResolvedModule[]; resolveTypeReferenceDirectives?(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; directoryExists?(directoryName: string): boolean; @@ -7884,6 +9064,7 @@ declare namespace ts { getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications; getCompletionsAtPosition(fileName: string, position: number): CompletionInfo; getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails; + getCompletionEntrySymbol(fileName: string, position: number, entryName: string): Symbol; getQuickInfoAtPosition(fileName: string, position: number): QuickInfo; getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan; getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan; @@ -7892,25 +9073,31 @@ declare namespace ts { findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[]; getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[]; getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[]; + getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[]; getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[]; findReferences(fileName: string, position: number): ReferencedSymbol[]; getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[]; /** @deprecated */ getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[]; - getNavigateToItems(searchValue: string, maxResultCount?: number): NavigateToItem[]; + getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles?: boolean): NavigateToItem[]; getNavigationBarItems(fileName: string): NavigationBarItem[]; getOutliningSpans(fileName: string): OutliningSpan[]; getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[]; getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[]; - getIndentationAtPosition(fileName: string, position: number, options: EditorOptions): number; - getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions): TextChange[]; - getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[]; - getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[]; + getIndentationAtPosition(fileName: string, position: number, options: EditorOptions | EditorSettings): number; + getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; + getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; + getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion; isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean; - getEmitOutput(fileName: string): EmitOutput; + getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput; getProgram(): Program; getNonBoundSourceFile(fileName: string): SourceFile; + /** + * @internal + * @deprecated Use ts.createSourceFile instead. + */ + getSourceFile(fileName: string): SourceFile; dispose(): void; } interface Classifications { @@ -7959,15 +9146,19 @@ declare namespace ts { isWriteAccess: boolean; isDefinition: boolean; } + interface ImplementationLocation { + textSpan: TextSpan; + fileName: string; + } interface DocumentHighlights { fileName: string; highlightSpans: HighlightSpan[]; } namespace HighlightSpanKind { - const none: string; - const definition: string; - const reference: string; - const writtenReference: string; + const none = "none"; + const definition = "definition"; + const reference = "reference"; + const writtenReference = "writtenReference"; } interface HighlightSpan { fileName?: string; @@ -7985,6 +9176,11 @@ declare namespace ts { containerName: string; containerKind: string; } + enum IndentStyle { + None = 0, + Block = 1, + Smart = 2, + } interface EditorOptions { BaseIndentSize?: number; IndentSize: number; @@ -7993,10 +9189,13 @@ declare namespace ts { ConvertTabsToSpaces: boolean; IndentStyle: IndentStyle; } - enum IndentStyle { - None = 0, - Block = 1, - Smart = 2, + interface EditorSettings { + baseIndentSize?: number; + indentSize: number; + tabSize: number; + newLineCharacter: string; + convertTabsToSpaces: boolean; + indentStyle: IndentStyle; } interface FormatCodeOptions extends EditorOptions { InsertSpaceAfterCommaDelimiter: boolean; @@ -8006,11 +9205,27 @@ declare namespace ts { InsertSpaceAfterFunctionKeywordForAnonymousFunctions: boolean; InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean; InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean; + InsertSpaceAfterOpeningAndBeforeClosingNonemptyBraces?: boolean; InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: boolean; InsertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces?: boolean; + InsertSpaceAfterTypeAssertion?: boolean; PlaceOpenBraceOnNewLineForFunctions: boolean; PlaceOpenBraceOnNewLineForControlBlocks: boolean; - [s: string]: boolean | number | string | undefined; + } + interface FormatCodeSettings extends EditorSettings { + insertSpaceAfterCommaDelimiter: boolean; + insertSpaceAfterSemicolonInForStatements: boolean; + insertSpaceBeforeAndAfterBinaryOperators: boolean; + insertSpaceAfterKeywordsInControlFlowStatements: boolean; + insertSpaceAfterFunctionKeywordForAnonymousFunctions: boolean; + insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean; + insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean; + insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces?: boolean; + insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: boolean; + insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: boolean; + insertSpaceAfterTypeAssertion?: boolean; + placeOpenBraceOnNewLineForFunctions: boolean; + placeOpenBraceOnNewLineForControlBlocks: boolean; } interface DefinitionInfo { fileName: string; @@ -8112,6 +9327,12 @@ declare namespace ts { kind: string; kindModifiers: string; sortText: string; + /** + * An optional span that indicates the text to be replaced by this completion item. It will be + * set if the required span differs from the one generated by the default replacement behavior and should + * be used in that case + */ + replacementSpan?: TextSpan; } interface CompletionEntryDetails { name: string; @@ -8199,139 +9420,78 @@ declare namespace ts { getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): ClassificationResult; getEncodedLexicalClassifications(text: string, endOfLineState: EndOfLineState, syntacticClassifierAbsent: boolean): Classifications; } - /** - * The document registry represents a store of SourceFile objects that can be shared between - * multiple LanguageService instances. A LanguageService instance holds on the SourceFile (AST) - * of files in the context. - * SourceFile objects account for most of the memory usage by the language service. Sharing - * the same DocumentRegistry instance between different instances of LanguageService allow - * for more efficient memory utilization since all projects will share at least the library - * file (lib.d.ts). - * - * A more advanced use of the document registry is to serialize sourceFile objects to disk - * and re-hydrate them when needed. - * - * To create a default DocumentRegistry, use createDocumentRegistry to create one, and pass it - * to all subsequent createLanguageService calls. - */ - interface DocumentRegistry { - /** - * Request a stored SourceFile with a given fileName and compilationSettings. - * The first call to acquire will call createLanguageServiceSourceFile to generate - * the SourceFile if was not found in the registry. - * - * @param fileName The name of the file requested - * @param compilationSettings Some compilation settings like target affects the - * shape of a the resulting SourceFile. This allows the DocumentRegistry to store - * multiple copies of the same file for different compilation settings. - * @parm scriptSnapshot Text of the file. Only used if the file was not found - * in the registry and a new one was created. - * @parm version Current version of the file. Only used if the file was not found - * in the registry and a new one was created. - */ - acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; - acquireDocumentWithKey(fileName: string, path: Path, compilationSettings: CompilerOptions, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; - /** - * Request an updated version of an already existing SourceFile with a given fileName - * and compilationSettings. The update will in-turn call updateLanguageServiceSourceFile - * to get an updated SourceFile. - * - * @param fileName The name of the file requested - * @param compilationSettings Some compilation settings like target affects the - * shape of a the resulting SourceFile. This allows the DocumentRegistry to store - * multiple copies of the same file for different compilation settings. - * @param scriptSnapshot Text of the file. - * @param version Current version of the file. - */ - updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; - updateDocumentWithKey(fileName: string, path: Path, compilationSettings: CompilerOptions, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; - getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey; - /** - * Informs the DocumentRegistry that a file is not needed any longer. - * - * Note: It is not allowed to call release on a SourceFile that was not acquired from - * this registry originally. - * - * @param fileName The name of the file to be released - * @param compilationSettings The compilation settings used to acquire the file - */ - releaseDocument(fileName: string, compilationSettings: CompilerOptions): void; - releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey): void; - reportStats(): string; - } - type DocumentRegistryBucketKey = string & { - __bucketKey: any; - }; namespace ScriptElementKind { - const unknown: string; - const warning: string; + const unknown = ""; + const warning = "warning"; /** predefined type (void) or keyword (class) */ - const keyword: string; + const keyword = "keyword"; /** top level script node */ - const scriptElement: string; + const scriptElement = "script"; /** module foo {} */ - const moduleElement: string; + const moduleElement = "module"; /** class X {} */ - const classElement: string; + const classElement = "class"; /** var x = class X {} */ - const localClassElement: string; + const localClassElement = "local class"; /** interface Y {} */ - const interfaceElement: string; + const interfaceElement = "interface"; /** type T = ... */ - const typeElement: string; + const typeElement = "type"; /** enum E */ - const enumElement: string; - const enumMemberElement: string; + const enumElement = "enum"; + const enumMemberElement = "const"; /** * Inside module and script only * const v = .. */ - const variableElement: string; + const variableElement = "var"; /** Inside function */ - const localVariableElement: string; + const localVariableElement = "local var"; /** * Inside module and script only * function f() { } */ - const functionElement: string; + const functionElement = "function"; /** Inside function */ - const localFunctionElement: string; + const localFunctionElement = "local function"; /** class X { [public|private]* foo() {} } */ - const memberFunctionElement: string; + const memberFunctionElement = "method"; /** class X { [public|private]* [get|set] foo:number; } */ - const memberGetAccessorElement: string; - const memberSetAccessorElement: string; + const memberGetAccessorElement = "getter"; + const memberSetAccessorElement = "setter"; /** * class X { [public|private]* foo:number; } * interface Y { foo:number; } */ - const memberVariableElement: string; + const memberVariableElement = "property"; /** class X { constructor() { } } */ - const constructorImplementationElement: string; + const constructorImplementationElement = "constructor"; /** interface Y { ():number; } */ - const callSignatureElement: string; + const callSignatureElement = "call"; /** interface Y { []:number; } */ - const indexSignatureElement: string; + const indexSignatureElement = "index"; /** interface Y { new():Y; } */ - const constructSignatureElement: string; + const constructSignatureElement = "construct"; /** function foo(*Y*: string) */ - const parameterElement: string; - const typeParameterElement: string; - const primitiveType: string; - const label: string; - const alias: string; - const constElement: string; - const letElement: string; + const parameterElement = "parameter"; + const typeParameterElement = "type parameter"; + const primitiveType = "primitive type"; + const label = "label"; + const alias = "alias"; + const constElement = "const"; + const letElement = "let"; + const directory = "directory"; + const externalModuleName = "external module name"; } namespace ScriptElementKindModifier { - const none: string; - const publicMemberModifier: string; - const privateMemberModifier: string; - const protectedMemberModifier: string; - const exportedModifier: string; - const ambientModifier: string; - const staticModifier: string; - const abstractModifier: string; + const none = ""; + const publicMemberModifier = "public"; + const privateMemberModifier = "private"; + const protectedMemberModifier = "protected"; + const exportedModifier = "export"; + const ambientModifier = "declare"; + const staticModifier = "static"; + const abstractModifier = "abstract"; } class ClassificationTypeNames { static comment: string; @@ -8386,6 +9546,35 @@ declare namespace ts { } } declare namespace ts { + const scanner: Scanner; + const emptyArray: any[]; + enum SemanticMeaning { + None = 0, + Value = 1, + Type = 2, + Namespace = 4, + All = 7, + } + function getMeaningFromDeclaration(node: Node): SemanticMeaning; + function getMeaningFromLocation(node: Node): SemanticMeaning; + function isCallExpressionTarget(node: Node): boolean; + function isNewExpressionTarget(node: Node): boolean; + function climbPastPropertyAccess(node: Node): Node; + function getTargetLabel(referenceNode: Node, labelName: string): Identifier; + function isJumpStatementTarget(node: Node): boolean; + function isLabelName(node: Node): boolean; + function isRightSideOfQualifiedName(node: Node): boolean; + function isRightSideOfPropertyAccess(node: Node): boolean; + function isNameOfModuleDeclaration(node: Node): boolean; + function isNameOfFunctionDeclaration(node: Node): boolean; + function isLiteralNameOfPropertyDeclarationOrIndexAccess(node: Node): boolean; + function isExpressionOfExternalModuleImportEqualsDeclaration(node: Node): boolean; + /** Returns true if the position is within a comment */ + function isInsideComment(sourceFile: SourceFile, token: Node, position: number): boolean; + function getContainerNode(node: Node): Declaration; + function getNodeKind(node: Node): string; + function getStringLiteralTypeForNode(node: StringLiteral | LiteralTypeNode, typeChecker: TypeChecker): LiteralType; + function isThis(node: Node): boolean; interface ListItemInfo { listItemIndex: number; list: Node; @@ -8447,6 +9636,9 @@ declare namespace ts { function isAccessibilityModifier(kind: SyntaxKind): boolean; function compareDataObjects(dst: any, src: any): boolean; function isArrayLiteralOrObjectLiteralDestructuringPattern(node: Node): boolean; + function hasTrailingDirectorySeparator(path: string): boolean; + function isInReferenceComment(sourceFile: SourceFile, position: number): boolean; + function isInNonReferenceComment(sourceFile: SourceFile, position: number): boolean; } declare namespace ts { function isFirstDeclarationOfSymbolParameter(symbol: Symbol): boolean; @@ -8477,11 +9669,131 @@ declare namespace ts { function stripQuotes(name: string): string; function scriptKindIs(fileName: string, host: LanguageServiceHost, ...scriptKinds: ScriptKind[]): boolean; function getScriptKind(fileName: string, host?: LanguageServiceHost): ScriptKind; - function parseAndReEmitConfigJSONFile(content: string): { + function sanitizeConfigFile(configFileName: string, content: string): { configJsonObject: any; diagnostics: Diagnostic[]; }; } +declare namespace ts { + function createClassifier(): Classifier; + function getSemanticClassifications(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, classifiableNames: Map, span: TextSpan): ClassifiedSpan[]; + function getEncodedSemanticClassifications(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, classifiableNames: Map, span: TextSpan): Classifications; + function getSyntacticClassifications(cancellationToken: CancellationToken, sourceFile: SourceFile, span: TextSpan): ClassifiedSpan[]; + function getEncodedSyntacticClassifications(cancellationToken: CancellationToken, sourceFile: SourceFile, span: TextSpan): Classifications; +} +declare namespace ts.Completions { + function getCompletionsAtPosition(host: LanguageServiceHost, typeChecker: TypeChecker, log: (message: string) => void, compilerOptions: CompilerOptions, sourceFile: SourceFile, position: number): CompletionInfo; + function getCompletionEntryDetails(typeChecker: TypeChecker, log: (message: string) => void, compilerOptions: CompilerOptions, sourceFile: SourceFile, position: number, entryName: string): CompletionEntryDetails; + function getCompletionEntrySymbol(typeChecker: TypeChecker, log: (message: string) => void, compilerOptions: CompilerOptions, sourceFile: SourceFile, position: number, entryName: string): Symbol; +} +declare namespace ts.DocumentHighlights { + function getDocumentHighlights(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, position: number, sourceFilesToSearch: SourceFile[]): DocumentHighlights[]; +} +declare namespace ts { + /** + * The document registry represents a store of SourceFile objects that can be shared between + * multiple LanguageService instances. A LanguageService instance holds on the SourceFile (AST) + * of files in the context. + * SourceFile objects account for most of the memory usage by the language service. Sharing + * the same DocumentRegistry instance between different instances of LanguageService allow + * for more efficient memory utilization since all projects will share at least the library + * file (lib.d.ts). + * + * A more advanced use of the document registry is to serialize sourceFile objects to disk + * and re-hydrate them when needed. + * + * To create a default DocumentRegistry, use createDocumentRegistry to create one, and pass it + * to all subsequent createLanguageService calls. + */ + interface DocumentRegistry { + /** + * Request a stored SourceFile with a given fileName and compilationSettings. + * The first call to acquire will call createLanguageServiceSourceFile to generate + * the SourceFile if was not found in the registry. + * + * @param fileName The name of the file requested + * @param compilationSettings Some compilation settings like target affects the + * shape of a the resulting SourceFile. This allows the DocumentRegistry to store + * multiple copies of the same file for different compilation settings. + * @parm scriptSnapshot Text of the file. Only used if the file was not found + * in the registry and a new one was created. + * @parm version Current version of the file. Only used if the file was not found + * in the registry and a new one was created. + */ + acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; + acquireDocumentWithKey(fileName: string, path: Path, compilationSettings: CompilerOptions, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; + /** + * Request an updated version of an already existing SourceFile with a given fileName + * and compilationSettings. The update will in-turn call updateLanguageServiceSourceFile + * to get an updated SourceFile. + * + * @param fileName The name of the file requested + * @param compilationSettings Some compilation settings like target affects the + * shape of a the resulting SourceFile. This allows the DocumentRegistry to store + * multiple copies of the same file for different compilation settings. + * @param scriptSnapshot Text of the file. + * @param version Current version of the file. + */ + updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; + updateDocumentWithKey(fileName: string, path: Path, compilationSettings: CompilerOptions, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; + getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey; + /** + * Informs the DocumentRegistry that a file is not needed any longer. + * + * Note: It is not allowed to call release on a SourceFile that was not acquired from + * this registry originally. + * + * @param fileName The name of the file to be released + * @param compilationSettings The compilation settings used to acquire the file + */ + releaseDocument(fileName: string, compilationSettings: CompilerOptions): void; + releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey): void; + reportStats(): string; + } + type DocumentRegistryBucketKey = string & { + __bucketKey: any; + }; + function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory?: string): DocumentRegistry; +} +declare namespace ts.FindAllReferences { + function findReferencedSymbols(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFiles: SourceFile[], sourceFile: SourceFile, position: number, findInStrings: boolean, findInComments: boolean): ReferencedSymbol[]; + function getReferencedSymbolsForNode(typeChecker: TypeChecker, cancellationToken: CancellationToken, node: Node, sourceFiles: SourceFile[], findInStrings: boolean, findInComments: boolean, implementations: boolean): ReferencedSymbol[]; + function convertReferences(referenceSymbols: ReferencedSymbol[]): ReferenceEntry[]; + function getReferenceEntriesForShorthandPropertyAssignment(node: Node, typeChecker: TypeChecker, result: ReferenceEntry[]): void; + function getReferenceEntryFromNode(node: Node): ReferenceEntry; +} +declare namespace ts.GoToDefinition { + function getDefinitionAtPosition(program: Program, sourceFile: SourceFile, position: number): DefinitionInfo[]; + function getTypeDefinitionAtPosition(typeChecker: TypeChecker, sourceFile: SourceFile, position: number): DefinitionInfo[]; +} +declare namespace ts.GoToImplementation { + function getImplementationAtPosition(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFiles: SourceFile[], node: Node): ImplementationLocation[]; +} +declare namespace ts.JsDoc { + function getJsDocCommentsFromDeclarations(declarations: Declaration[], name: string, canUseParsedParamTagComments: boolean): SymbolDisplayPart[]; + function getAllJsDocCompletionEntries(): CompletionEntry[]; + /** + * Checks if position points to a valid position to add JSDoc comments, and if so, + * returns the appropriate template. Otherwise returns an empty string. + * Valid positions are + * - outside of comments, statements, and expressions, and + * - preceding a: + * - function/constructor/method declaration + * - class declarations + * - variable statements + * - namespace declarations + * + * Hosts should ideally check that: + * - The line is all whitespace up to 'position' before performing the insertion. + * - If the keystroke sequence "/\*\*" induced the call, we also check that the next + * non-whitespace character is '*', which (approximately) indicates whether we added + * the second '*' to complete an existing (JSDoc) comment. + * @param fileName The file in which to perform the check. + * @param position The (character-indexed) position in the file where the check should + * be performed. + */ + function getDocCommentTemplateAtPosition(newLine: string, sourceFile: SourceFile, position: number): TextInsertion; +} declare namespace ts.JsTyping { interface TypingResolutionHost { directoryExists: (path: string) => boolean; @@ -8504,6 +9816,84 @@ declare namespace ts.JsTyping { filesToWatch: string[]; }; } +declare namespace ts.NavigateTo { + function getNavigateToItems(sourceFiles: SourceFile[], checker: TypeChecker, cancellationToken: CancellationToken, searchValue: string, maxResultCount: number, excludeDtsFiles: boolean): NavigateToItem[]; +} +declare namespace ts.NavigationBar { + function getNavigationBarItems(sourceFile: SourceFile): NavigationBarItem[]; +} +declare namespace ts.OutliningElementsCollector { + function collectElements(sourceFile: SourceFile): OutliningSpan[]; +} +declare namespace ts { + enum PatternMatchKind { + exact = 0, + prefix = 1, + substring = 2, + camelCase = 3, + } + interface PatternMatch { + kind: PatternMatchKind; + camelCaseWeight?: number; + isCaseSensitive: boolean; + punctuationStripped: boolean; + } + interface PatternMatcher { + getMatchesForLastSegmentOfPattern(candidate: string): PatternMatch[]; + getMatches(candidateContainers: string[], candidate: string): PatternMatch[]; + patternContainsDots: boolean; + } + function createPatternMatcher(pattern: string): PatternMatcher; + function breakIntoCharacterSpans(identifier: string): TextSpan[]; + function breakIntoWordSpans(identifier: string): TextSpan[]; +} +declare namespace ts { + function preProcessFile(sourceText: string, readImportFiles?: boolean, detectJavaScriptImports?: boolean): PreProcessedFileInfo; +} +declare namespace ts.Rename { + function getRenameInfo(typeChecker: TypeChecker, defaultLibFileName: string, getCanonicalFileName: (fileName: string) => string, sourceFile: SourceFile, position: number): RenameInfo; +} +declare namespace ts.SignatureHelp { + enum ArgumentListKind { + TypeArguments = 0, + CallArguments = 1, + TaggedTemplateArguments = 2, + } + interface ArgumentListInfo { + kind: ArgumentListKind; + invocation: CallLikeExpression; + argumentsSpan: TextSpan; + argumentIndex?: number; + argumentCount: number; + } + function getSignatureHelpItems(program: Program, sourceFile: SourceFile, position: number, cancellationToken: CancellationToken): SignatureHelpItems; + function getContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile): ArgumentListInfo; +} +declare namespace ts.SymbolDisplay { + function getSymbolKind(typeChecker: TypeChecker, symbol: Symbol, location: Node): string; + function getSymbolModifiers(symbol: Symbol): string; + function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: TypeChecker, symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node, location: Node, semanticMeaning?: SemanticMeaning): { + displayParts: SymbolDisplayPart[]; + documentation: SymbolDisplayPart[]; + symbolKind: string; + }; +} +declare namespace ts { + interface TranspileOptions { + compilerOptions?: CompilerOptions; + fileName?: string; + reportDiagnostics?: boolean; + moduleName?: string; + renamedDependencies?: MapLike; + } + interface TranspileOutput { + outputText: string; + diagnostics?: Diagnostic[]; + sourceMapText?: string; + } + function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput; + function transpile(input: string, compilerOptions?: CompilerOptions, fileName?: string, diagnostics?: Diagnostic[], moduleName?: string): string; +} declare namespace ts.formatting { interface FormattingScanner { advance(): void; @@ -8629,6 +10019,8 @@ declare namespace ts.formatting { NoSpaceAfterCloseBracket: Rule; SpaceAfterOpenBrace: Rule; SpaceBeforeCloseBrace: Rule; + NoSpaceAfterOpenBrace: Rule; + NoSpaceBeforeCloseBrace: Rule; NoSpaceBetweenEmptyBraceBrackets: Rule; NewLineAfterOpenBraceInBlockContext: Rule; NewLineBeforeCloseBraceInBlockContext: Rule; @@ -8670,7 +10062,6 @@ declare namespace ts.formatting { NoSpaceAfterOpenAngularBracket: Rule; NoSpaceBeforeCloseAngularBracket: Rule; NoSpaceAfterCloseAngularBracket: Rule; - NoSpaceAfterTypeAssertion: Rule; NoSpaceBetweenEmptyInterfaceBraceBrackets: Rule; HighPriorityCommonRules: Rule[]; LowPriorityCommonRules: Rule[]; @@ -8728,6 +10119,8 @@ declare namespace ts.formatting { NoSpaceBeforeGreaterThanTokenInJsxOpeningElement: Rule; NoSpaceBeforeEqualInJsxAttribute: Rule; NoSpaceAfterEqualInJsxAttribute: Rule; + NoSpaceAfterTypeAssertion: Rule; + SpaceAfterTypeAssertion: Rule; constructor(); static IsForContext(context: FormattingContext): boolean; static IsNotForContext(context: FormattingContext): boolean; @@ -8872,7 +10265,7 @@ declare namespace ts.formatting { getRuleName(rule: Rule): string; getRuleByName(name: string): Rule; getRulesMap(): RulesMap; - ensureUpToDate(options: ts.FormatCodeOptions): void; + ensureUpToDate(options: ts.FormatCodeSettings): void; private createActiveRules(options); } } @@ -8885,60 +10278,43 @@ declare namespace ts.formatting { token: TextRangeWithKind; trailingTrivia: TextRangeWithKind[]; } - function formatOnEnter(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[]; - function formatOnSemicolon(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[]; - function formatOnClosingCurly(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[]; - function formatDocument(sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[]; - function formatSelection(start: number, end: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[]; - function getIndentationString(indentation: number, options: FormatCodeOptions): string; + function formatOnEnter(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[]; + function formatOnSemicolon(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[]; + function formatOnClosingCurly(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[]; + function formatDocument(sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[]; + function formatSelection(start: number, end: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[]; + function getIndentationString(indentation: number, options: EditorSettings): string; } declare namespace ts.formatting { namespace SmartIndenter { - function getIndentation(position: number, sourceFile: SourceFile, options: EditorOptions): number; - function getBaseIndentation(options: EditorOptions): number; - function getIndentationForNode(n: Node, ignoreActualIndentationRange: TextRange, sourceFile: SourceFile, options: FormatCodeOptions): number; + function getIndentation(position: number, sourceFile: SourceFile, options: EditorSettings): number; + function getIndentationForNode(n: Node, ignoreActualIndentationRange: TextRange, sourceFile: SourceFile, options: EditorSettings): number; + function getBaseIndentation(options: EditorSettings): number; function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFile): boolean; - function findFirstNonWhitespaceCharacterAndColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorOptions): { + function findFirstNonWhitespaceCharacterAndColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorSettings): { column: number; character: number; }; - function findFirstNonWhitespaceColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorOptions): number; + function findFirstNonWhitespaceColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorSettings): number; function nodeWillIndentChild(parent: TextRangeWithKind, child: TextRangeWithKind, indentByDefault: boolean): boolean; function shouldIndentChildNode(parent: TextRangeWithKind, child?: TextRangeWithKind): boolean; } } declare namespace ts { /** The version of the language service API */ - const servicesVersion: string; + const servicesVersion = "0.5"; interface DisplayPartsSymbolWriter extends SymbolWriter { displayParts(): SymbolDisplayPart[]; } + function toEditorSettings(options: FormatCodeOptions | FormatCodeSettings): FormatCodeSettings; + function toEditorSettings(options: EditorOptions | EditorSettings): EditorSettings; function displayPartsToString(displayParts: SymbolDisplayPart[]): string; function getDefaultCompilerOptions(): CompilerOptions; - interface TranspileOptions { - compilerOptions?: CompilerOptions; - fileName?: string; - reportDiagnostics?: boolean; - moduleName?: string; - renamedDependencies?: MapLike; - } - interface TranspileOutput { - outputText: string; - diagnostics?: Diagnostic[]; - sourceMapText?: string; - } - function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput; - function transpile(input: string, compilerOptions?: CompilerOptions, fileName?: string, diagnostics?: Diagnostic[], moduleName?: string): string; function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, setNodeParents: boolean, scriptKind?: ScriptKind): SourceFile; let disableIncrementalParsing: boolean; function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile; - function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory?: string): DocumentRegistry; - function preProcessFile(sourceText: string, readImportFiles?: boolean, detectJavaScriptImports?: boolean): PreProcessedFileInfo; - function getContainerNode(node: Node): Declaration; - function getNodeKind(node: Node): string; function createLanguageService(host: LanguageServiceHost, documentRegistry?: DocumentRegistry): LanguageService; function getNameTable(sourceFile: SourceFile): Map; - function createClassifier(): Classifier; /** * Get the path of the default library files (lib.d.ts) as distributed with the typescript * node package. @@ -8990,6 +10366,10 @@ declare namespace ts { getNewLine?(): string; getProjectVersion?(): string; useCaseSensitiveFileNames?(): boolean; + getTypeRootsVersion?(): number; + readDirectory(rootDir: string, extension: string, basePaths?: string, excludeEx?: string, includeFileEx?: string, includeDirEx?: string, depth?: number): string; + readFile(path: string, encoding?: string): string; + fileExists(path: string): boolean; getModuleResolutionsForFile?(fileName: string): string; getTypeReferenceDirectiveResolutionsForFile?(fileName: string): string; directoryExists(directoryName: string): boolean; @@ -9070,6 +10450,11 @@ declare namespace ts { * Or undefined value if no definition can be found. */ getTypeDefinitionAtPosition(fileName: string, position: number): string; + /** + * Returns a JSON-encoded value of the type: + * { fileName: string; textSpan: { start: number; length: number}; }[] + */ + getImplementationAtPosition(fileName: string, position: number): string; /** * Returns a JSON-encoded value of the type: * { fileName: string; textSpan: { start: number; length: number}; isWriteAccess: boolean, isDefinition?: boolean }[] @@ -9098,7 +10483,7 @@ declare namespace ts { * Returns a JSON-encoded value of the type: * { name: string; kind: string; kindModifiers: string; containerName: string; containerKind: string; matchKind: string; fileName: string; textSpan: { start: number; length: number}; } [] = []; */ - getNavigateToItems(searchValue: string, maxResultCount?: number): string; + getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string): string; /** * Returns a JSON-encoded value of the type: * { text: string; kind: string; kindModifiers: string; bolded: boolean; grayed: boolean; indent: number; spans: { start: number; length: number; }[]; childItems: [] } [] = []; @@ -9152,6 +10537,7 @@ declare namespace ts { trace(s: string): void; error(s: string): void; getProjectVersion(): string; + getTypeRootsVersion(): number; useCaseSensitiveFileNames(): boolean; getCompilationSettings(): CompilerOptions; getScriptFileNames(): string[]; @@ -9163,6 +10549,9 @@ declare namespace ts { getCurrentDirectory(): string; getDirectories(path: string): string[]; getDefaultLibFileName(options: CompilerOptions): string; + readDirectory(path: string, extensions?: string[], exclude?: string[], include?: string[], depth?: number): string[]; + readFile(path: string, encoding?: string): string; + fileExists(path: string): boolean; } class CoreServicesShimHostAdapter implements ParseConfigHost, ModuleResolutionHost { private shimHost; @@ -9198,7 +10587,7 @@ declare namespace ts { declare namespace TypeScript.Services { const TypeScriptServicesFactory: typeof ts.TypeScriptServicesFactory; } -declare const toolsVersion: string; +declare const toolsVersion = "2.1"; /** * Sample: add a new utility function */ diff --git a/bin/ntypescript.js b/bin/ntypescript.js index 0b6fd54..d1faf83 100644 --- a/bin/ntypescript.js +++ b/bin/ntypescript.js @@ -325,11 +325,16 @@ var ts; SyntaxKind[SyntaxKind["JSDocNeverKeyword"] = 285] = "JSDocNeverKeyword"; // Synthesized list SyntaxKind[SyntaxKind["SyntaxList"] = 286] = "SyntaxList"; + // Transformation nodes + SyntaxKind[SyntaxKind["NotEmittedStatement"] = 287] = "NotEmittedStatement"; + SyntaxKind[SyntaxKind["PartiallyEmittedExpression"] = 288] = "PartiallyEmittedExpression"; // Enum value count - SyntaxKind[SyntaxKind["Count"] = 287] = "Count"; + SyntaxKind[SyntaxKind["Count"] = 289] = "Count"; // Markers SyntaxKind[SyntaxKind["FirstAssignment"] = 56] = "FirstAssignment"; SyntaxKind[SyntaxKind["LastAssignment"] = 68] = "LastAssignment"; + SyntaxKind[SyntaxKind["FirstCompoundAssignment"] = 57] = "FirstCompoundAssignment"; + SyntaxKind[SyntaxKind["LastCompoundAssignment"] = 68] = "LastCompoundAssignment"; SyntaxKind[SyntaxKind["FirstReservedWord"] = 70] = "FirstReservedWord"; SyntaxKind[SyntaxKind["LastReservedWord"] = 105] = "LastReservedWord"; SyntaxKind[SyntaxKind["FirstKeyword"] = 70] = "FirstKeyword"; @@ -359,51 +364,59 @@ var ts; var SyntaxKind = ts.SyntaxKind; (function (NodeFlags) { NodeFlags[NodeFlags["None"] = 0] = "None"; - NodeFlags[NodeFlags["Export"] = 1] = "Export"; - NodeFlags[NodeFlags["Ambient"] = 2] = "Ambient"; - NodeFlags[NodeFlags["Public"] = 4] = "Public"; - NodeFlags[NodeFlags["Private"] = 8] = "Private"; - NodeFlags[NodeFlags["Protected"] = 16] = "Protected"; - NodeFlags[NodeFlags["Static"] = 32] = "Static"; - NodeFlags[NodeFlags["Readonly"] = 64] = "Readonly"; - NodeFlags[NodeFlags["Abstract"] = 128] = "Abstract"; - NodeFlags[NodeFlags["Async"] = 256] = "Async"; - NodeFlags[NodeFlags["Default"] = 512] = "Default"; - NodeFlags[NodeFlags["Let"] = 1024] = "Let"; - NodeFlags[NodeFlags["Const"] = 2048] = "Const"; - NodeFlags[NodeFlags["Namespace"] = 4096] = "Namespace"; - NodeFlags[NodeFlags["ExportContext"] = 8192] = "ExportContext"; - NodeFlags[NodeFlags["ContainsThis"] = 16384] = "ContainsThis"; - NodeFlags[NodeFlags["HasImplicitReturn"] = 32768] = "HasImplicitReturn"; - NodeFlags[NodeFlags["HasExplicitReturn"] = 65536] = "HasExplicitReturn"; - NodeFlags[NodeFlags["GlobalAugmentation"] = 131072] = "GlobalAugmentation"; - NodeFlags[NodeFlags["HasClassExtends"] = 262144] = "HasClassExtends"; - NodeFlags[NodeFlags["HasDecorators"] = 524288] = "HasDecorators"; - NodeFlags[NodeFlags["HasParamDecorators"] = 1048576] = "HasParamDecorators"; - NodeFlags[NodeFlags["HasAsyncFunctions"] = 2097152] = "HasAsyncFunctions"; - NodeFlags[NodeFlags["DisallowInContext"] = 4194304] = "DisallowInContext"; - NodeFlags[NodeFlags["YieldContext"] = 8388608] = "YieldContext"; - NodeFlags[NodeFlags["DecoratorContext"] = 16777216] = "DecoratorContext"; - NodeFlags[NodeFlags["AwaitContext"] = 33554432] = "AwaitContext"; - NodeFlags[NodeFlags["ThisNodeHasError"] = 67108864] = "ThisNodeHasError"; - NodeFlags[NodeFlags["JavaScriptFile"] = 134217728] = "JavaScriptFile"; - NodeFlags[NodeFlags["ThisNodeOrAnySubNodesHasError"] = 268435456] = "ThisNodeOrAnySubNodesHasError"; - NodeFlags[NodeFlags["HasAggregatedChildData"] = 536870912] = "HasAggregatedChildData"; - NodeFlags[NodeFlags["HasJsxSpreadAttribute"] = 1073741824] = "HasJsxSpreadAttribute"; - NodeFlags[NodeFlags["Modifier"] = 1023] = "Modifier"; - NodeFlags[NodeFlags["AccessibilityModifier"] = 28] = "AccessibilityModifier"; - // Accessibility modifiers and 'readonly' can be attached to a parameter in a constructor to make it a property. - NodeFlags[NodeFlags["ParameterPropertyModifier"] = 92] = "ParameterPropertyModifier"; - NodeFlags[NodeFlags["BlockScoped"] = 3072] = "BlockScoped"; - NodeFlags[NodeFlags["ReachabilityCheckFlags"] = 98304] = "ReachabilityCheckFlags"; - NodeFlags[NodeFlags["EmitHelperFlags"] = 3932160] = "EmitHelperFlags"; - NodeFlags[NodeFlags["ReachabilityAndEmitFlags"] = 4030464] = "ReachabilityAndEmitFlags"; + NodeFlags[NodeFlags["Let"] = 1] = "Let"; + NodeFlags[NodeFlags["Const"] = 2] = "Const"; + NodeFlags[NodeFlags["NestedNamespace"] = 4] = "NestedNamespace"; + NodeFlags[NodeFlags["Synthesized"] = 8] = "Synthesized"; + NodeFlags[NodeFlags["Namespace"] = 16] = "Namespace"; + NodeFlags[NodeFlags["ExportContext"] = 32] = "ExportContext"; + NodeFlags[NodeFlags["ContainsThis"] = 64] = "ContainsThis"; + NodeFlags[NodeFlags["HasImplicitReturn"] = 128] = "HasImplicitReturn"; + NodeFlags[NodeFlags["HasExplicitReturn"] = 256] = "HasExplicitReturn"; + NodeFlags[NodeFlags["GlobalAugmentation"] = 512] = "GlobalAugmentation"; + NodeFlags[NodeFlags["HasClassExtends"] = 1024] = "HasClassExtends"; + NodeFlags[NodeFlags["HasDecorators"] = 2048] = "HasDecorators"; + NodeFlags[NodeFlags["HasParamDecorators"] = 4096] = "HasParamDecorators"; + NodeFlags[NodeFlags["HasAsyncFunctions"] = 8192] = "HasAsyncFunctions"; + NodeFlags[NodeFlags["HasJsxSpreadAttributes"] = 16384] = "HasJsxSpreadAttributes"; + NodeFlags[NodeFlags["DisallowInContext"] = 32768] = "DisallowInContext"; + NodeFlags[NodeFlags["YieldContext"] = 65536] = "YieldContext"; + NodeFlags[NodeFlags["DecoratorContext"] = 131072] = "DecoratorContext"; + NodeFlags[NodeFlags["AwaitContext"] = 262144] = "AwaitContext"; + NodeFlags[NodeFlags["ThisNodeHasError"] = 524288] = "ThisNodeHasError"; + NodeFlags[NodeFlags["JavaScriptFile"] = 1048576] = "JavaScriptFile"; + NodeFlags[NodeFlags["ThisNodeOrAnySubNodesHasError"] = 2097152] = "ThisNodeOrAnySubNodesHasError"; + NodeFlags[NodeFlags["HasAggregatedChildData"] = 4194304] = "HasAggregatedChildData"; + NodeFlags[NodeFlags["BlockScoped"] = 3] = "BlockScoped"; + NodeFlags[NodeFlags["ReachabilityCheckFlags"] = 384] = "ReachabilityCheckFlags"; + NodeFlags[NodeFlags["EmitHelperFlags"] = 31744] = "EmitHelperFlags"; + NodeFlags[NodeFlags["ReachabilityAndEmitFlags"] = 32128] = "ReachabilityAndEmitFlags"; // Parsing context flags - NodeFlags[NodeFlags["ContextFlags"] = 197132288] = "ContextFlags"; + NodeFlags[NodeFlags["ContextFlags"] = 1540096] = "ContextFlags"; // Exclude these flags when parsing a Type - NodeFlags[NodeFlags["TypeExcludesFlags"] = 41943040] = "TypeExcludesFlags"; + NodeFlags[NodeFlags["TypeExcludesFlags"] = 327680] = "TypeExcludesFlags"; })(ts.NodeFlags || (ts.NodeFlags = {})); var NodeFlags = ts.NodeFlags; + (function (ModifierFlags) { + ModifierFlags[ModifierFlags["None"] = 0] = "None"; + ModifierFlags[ModifierFlags["Export"] = 1] = "Export"; + ModifierFlags[ModifierFlags["Ambient"] = 2] = "Ambient"; + ModifierFlags[ModifierFlags["Public"] = 4] = "Public"; + ModifierFlags[ModifierFlags["Private"] = 8] = "Private"; + ModifierFlags[ModifierFlags["Protected"] = 16] = "Protected"; + ModifierFlags[ModifierFlags["Static"] = 32] = "Static"; + ModifierFlags[ModifierFlags["Readonly"] = 64] = "Readonly"; + ModifierFlags[ModifierFlags["Abstract"] = 128] = "Abstract"; + ModifierFlags[ModifierFlags["Async"] = 256] = "Async"; + ModifierFlags[ModifierFlags["Default"] = 512] = "Default"; + ModifierFlags[ModifierFlags["Const"] = 2048] = "Const"; + ModifierFlags[ModifierFlags["HasComputedFlags"] = 536870912] = "HasComputedFlags"; + ModifierFlags[ModifierFlags["AccessibilityModifier"] = 28] = "AccessibilityModifier"; + // Accessibility modifiers and 'readonly' can be attached to a parameter in a constructor to make it a property. + ModifierFlags[ModifierFlags["ParameterPropertyModifier"] = 92] = "ParameterPropertyModifier"; + ModifierFlags[ModifierFlags["NonPublicAccessibilityModifier"] = 24] = "NonPublicAccessibilityModifier"; + })(ts.ModifierFlags || (ts.ModifierFlags = {})); + var ModifierFlags = ts.ModifierFlags; (function (JsxFlags) { JsxFlags[JsxFlags["None"] = 0] = "None"; /** An element from a named property of the JSX.IntrinsicElements interface */ @@ -420,6 +433,15 @@ var ts; RelationComparisonResult[RelationComparisonResult["FailedAndReported"] = 3] = "FailedAndReported"; })(ts.RelationComparisonResult || (ts.RelationComparisonResult = {})); var RelationComparisonResult = ts.RelationComparisonResult; + /*@internal*/ + (function (GeneratedIdentifierKind) { + GeneratedIdentifierKind[GeneratedIdentifierKind["None"] = 0] = "None"; + GeneratedIdentifierKind[GeneratedIdentifierKind["Auto"] = 1] = "Auto"; + GeneratedIdentifierKind[GeneratedIdentifierKind["Loop"] = 2] = "Loop"; + GeneratedIdentifierKind[GeneratedIdentifierKind["Unique"] = 3] = "Unique"; + GeneratedIdentifierKind[GeneratedIdentifierKind["Node"] = 4] = "Node"; + })(ts.GeneratedIdentifierKind || (ts.GeneratedIdentifierKind = {})); + var GeneratedIdentifierKind = ts.GeneratedIdentifierKind; (function (FlowFlags) { FlowFlags[FlowFlags["Unreachable"] = 1] = "Unreachable"; FlowFlags[FlowFlags["Start"] = 2] = "Start"; @@ -465,6 +487,7 @@ var ts; TypeFormatFlags[TypeFormatFlags["UseFullyQualifiedType"] = 128] = "UseFullyQualifiedType"; TypeFormatFlags[TypeFormatFlags["InFirstTypeArgument"] = 256] = "InFirstTypeArgument"; TypeFormatFlags[TypeFormatFlags["InTypeAlias"] = 512] = "InTypeAlias"; + TypeFormatFlags[TypeFormatFlags["UseTypeAliasValue"] = 1024] = "UseTypeAliasValue"; })(ts.TypeFormatFlags || (ts.TypeFormatFlags = {})); var TypeFormatFlags = ts.TypeFormatFlags; (function (SymbolFormatFlags) { @@ -502,15 +525,16 @@ var ts; // function that can be reached at runtime (e.g. a `class` // declaration or a `var` declaration for the static side // of a type, such as the global `Promise` type in lib.d.ts). - TypeReferenceSerializationKind[TypeReferenceSerializationKind["VoidType"] = 2] = "VoidType"; + TypeReferenceSerializationKind[TypeReferenceSerializationKind["VoidNullableOrNeverType"] = 2] = "VoidNullableOrNeverType"; TypeReferenceSerializationKind[TypeReferenceSerializationKind["NumberLikeType"] = 3] = "NumberLikeType"; TypeReferenceSerializationKind[TypeReferenceSerializationKind["StringLikeType"] = 4] = "StringLikeType"; TypeReferenceSerializationKind[TypeReferenceSerializationKind["BooleanType"] = 5] = "BooleanType"; TypeReferenceSerializationKind[TypeReferenceSerializationKind["ArrayLikeType"] = 6] = "ArrayLikeType"; TypeReferenceSerializationKind[TypeReferenceSerializationKind["ESSymbolType"] = 7] = "ESSymbolType"; - TypeReferenceSerializationKind[TypeReferenceSerializationKind["TypeWithCallSignature"] = 8] = "TypeWithCallSignature"; + TypeReferenceSerializationKind[TypeReferenceSerializationKind["Promise"] = 8] = "Promise"; + TypeReferenceSerializationKind[TypeReferenceSerializationKind["TypeWithCallSignature"] = 9] = "TypeWithCallSignature"; // with call signatures. - TypeReferenceSerializationKind[TypeReferenceSerializationKind["ObjectType"] = 9] = "ObjectType"; + TypeReferenceSerializationKind[TypeReferenceSerializationKind["ObjectType"] = 10] = "ObjectType"; })(ts.TypeReferenceSerializationKind || (ts.TypeReferenceSerializationKind = {})); var TypeReferenceSerializationKind = ts.TypeReferenceSerializationKind; (function (SymbolFlags) { @@ -609,6 +633,8 @@ var ts; NodeCheckFlags[NodeCheckFlags["BodyScopedClassBinding"] = 1048576] = "BodyScopedClassBinding"; NodeCheckFlags[NodeCheckFlags["NeedsLoopOutParameter"] = 2097152] = "NeedsLoopOutParameter"; NodeCheckFlags[NodeCheckFlags["AssignmentsMarked"] = 4194304] = "AssignmentsMarked"; + NodeCheckFlags[NodeCheckFlags["ClassWithConstructorReference"] = 8388608] = "ClassWithConstructorReference"; + NodeCheckFlags[NodeCheckFlags["ConstructorReferenceInClass"] = 16777216] = "ConstructorReferenceInClass"; })(ts.NodeCheckFlags || (ts.NodeCheckFlags = {})); var NodeCheckFlags = ts.NodeCheckFlags; (function (TypeFlags) { @@ -638,7 +664,7 @@ var ts; /* @internal */ TypeFlags[TypeFlags["ObjectLiteral"] = 8388608] = "ObjectLiteral"; /* @internal */ - TypeFlags[TypeFlags["FreshObjectLiteral"] = 16777216] = "FreshObjectLiteral"; + TypeFlags[TypeFlags["FreshLiteral"] = 16777216] = "FreshLiteral"; /* @internal */ TypeFlags[TypeFlags["ContainsWideningType"] = 33554432] = "ContainsWideningType"; /* @internal */ @@ -650,6 +676,7 @@ var ts; /* @internal */ TypeFlags[TypeFlags["Nullable"] = 6144] = "Nullable"; TypeFlags[TypeFlags["Literal"] = 480] = "Literal"; + TypeFlags[TypeFlags["StringOrNumberLiteral"] = 96] = "StringOrNumberLiteral"; /* @internal */ TypeFlags[TypeFlags["DefinitelyFalsy"] = 7392] = "DefinitelyFalsy"; TypeFlags[TypeFlags["PossiblyFalsy"] = 7406] = "PossiblyFalsy"; @@ -891,6 +918,105 @@ var ts; CharacterCodes[CharacterCodes["verticalTab"] = 11] = "verticalTab"; })(ts.CharacterCodes || (ts.CharacterCodes = {})); var CharacterCodes = ts.CharacterCodes; + /* @internal */ + (function (TransformFlags) { + TransformFlags[TransformFlags["None"] = 0] = "None"; + // Facts + // - Flags used to indicate that a node or subtree contains syntax that requires transformation. + TransformFlags[TransformFlags["TypeScript"] = 1] = "TypeScript"; + TransformFlags[TransformFlags["ContainsTypeScript"] = 2] = "ContainsTypeScript"; + TransformFlags[TransformFlags["Jsx"] = 4] = "Jsx"; + TransformFlags[TransformFlags["ContainsJsx"] = 8] = "ContainsJsx"; + TransformFlags[TransformFlags["ES7"] = 16] = "ES7"; + TransformFlags[TransformFlags["ContainsES7"] = 32] = "ContainsES7"; + TransformFlags[TransformFlags["ES6"] = 64] = "ES6"; + TransformFlags[TransformFlags["ContainsES6"] = 128] = "ContainsES6"; + TransformFlags[TransformFlags["DestructuringAssignment"] = 256] = "DestructuringAssignment"; + TransformFlags[TransformFlags["Generator"] = 512] = "Generator"; + TransformFlags[TransformFlags["ContainsGenerator"] = 1024] = "ContainsGenerator"; + // Markers + // - Flags used to indicate that a subtree contains a specific transformation. + TransformFlags[TransformFlags["ContainsDecorators"] = 2048] = "ContainsDecorators"; + TransformFlags[TransformFlags["ContainsPropertyInitializer"] = 4096] = "ContainsPropertyInitializer"; + TransformFlags[TransformFlags["ContainsLexicalThis"] = 8192] = "ContainsLexicalThis"; + TransformFlags[TransformFlags["ContainsCapturedLexicalThis"] = 16384] = "ContainsCapturedLexicalThis"; + TransformFlags[TransformFlags["ContainsLexicalThisInComputedPropertyName"] = 32768] = "ContainsLexicalThisInComputedPropertyName"; + TransformFlags[TransformFlags["ContainsDefaultValueAssignments"] = 65536] = "ContainsDefaultValueAssignments"; + TransformFlags[TransformFlags["ContainsParameterPropertyAssignments"] = 131072] = "ContainsParameterPropertyAssignments"; + TransformFlags[TransformFlags["ContainsSpreadElementExpression"] = 262144] = "ContainsSpreadElementExpression"; + TransformFlags[TransformFlags["ContainsComputedPropertyName"] = 524288] = "ContainsComputedPropertyName"; + TransformFlags[TransformFlags["ContainsBlockScopedBinding"] = 1048576] = "ContainsBlockScopedBinding"; + TransformFlags[TransformFlags["ContainsBindingPattern"] = 2097152] = "ContainsBindingPattern"; + TransformFlags[TransformFlags["ContainsYield"] = 4194304] = "ContainsYield"; + TransformFlags[TransformFlags["ContainsHoistedDeclarationOrCompletion"] = 8388608] = "ContainsHoistedDeclarationOrCompletion"; + TransformFlags[TransformFlags["HasComputedFlags"] = 536870912] = "HasComputedFlags"; + // Assertions + // - Bitmasks that are used to assert facts about the syntax of a node and its subtree. + TransformFlags[TransformFlags["AssertTypeScript"] = 3] = "AssertTypeScript"; + TransformFlags[TransformFlags["AssertJsx"] = 12] = "AssertJsx"; + TransformFlags[TransformFlags["AssertES7"] = 48] = "AssertES7"; + TransformFlags[TransformFlags["AssertES6"] = 192] = "AssertES6"; + TransformFlags[TransformFlags["AssertGenerator"] = 1536] = "AssertGenerator"; + // Scope Exclusions + // - Bitmasks that exclude flags from propagating out of a specific context + // into the subtree flags of their container. + TransformFlags[TransformFlags["NodeExcludes"] = 536871765] = "NodeExcludes"; + TransformFlags[TransformFlags["ArrowFunctionExcludes"] = 550710101] = "ArrowFunctionExcludes"; + TransformFlags[TransformFlags["FunctionExcludes"] = 550726485] = "FunctionExcludes"; + TransformFlags[TransformFlags["ConstructorExcludes"] = 550593365] = "ConstructorExcludes"; + TransformFlags[TransformFlags["MethodOrAccessorExcludes"] = 550593365] = "MethodOrAccessorExcludes"; + TransformFlags[TransformFlags["ClassExcludes"] = 537590613] = "ClassExcludes"; + TransformFlags[TransformFlags["ModuleExcludes"] = 546335573] = "ModuleExcludes"; + TransformFlags[TransformFlags["TypeExcludes"] = -3] = "TypeExcludes"; + TransformFlags[TransformFlags["ObjectLiteralExcludes"] = 537430869] = "ObjectLiteralExcludes"; + TransformFlags[TransformFlags["ArrayLiteralOrCallOrNewExcludes"] = 537133909] = "ArrayLiteralOrCallOrNewExcludes"; + TransformFlags[TransformFlags["VariableDeclarationListExcludes"] = 538968917] = "VariableDeclarationListExcludes"; + TransformFlags[TransformFlags["ParameterExcludes"] = 538968917] = "ParameterExcludes"; + // Masks + // - Additional bitmasks + TransformFlags[TransformFlags["TypeScriptClassSyntaxMask"] = 137216] = "TypeScriptClassSyntaxMask"; + TransformFlags[TransformFlags["ES6FunctionSyntaxMask"] = 81920] = "ES6FunctionSyntaxMask"; + })(ts.TransformFlags || (ts.TransformFlags = {})); + var TransformFlags = ts.TransformFlags; + /* @internal */ + (function (EmitFlags) { + EmitFlags[EmitFlags["EmitEmitHelpers"] = 1] = "EmitEmitHelpers"; + EmitFlags[EmitFlags["EmitExportStar"] = 2] = "EmitExportStar"; + EmitFlags[EmitFlags["EmitSuperHelper"] = 4] = "EmitSuperHelper"; + EmitFlags[EmitFlags["EmitAdvancedSuperHelper"] = 8] = "EmitAdvancedSuperHelper"; + EmitFlags[EmitFlags["UMDDefine"] = 16] = "UMDDefine"; + EmitFlags[EmitFlags["SingleLine"] = 32] = "SingleLine"; + EmitFlags[EmitFlags["AdviseOnEmitNode"] = 64] = "AdviseOnEmitNode"; + EmitFlags[EmitFlags["NoSubstitution"] = 128] = "NoSubstitution"; + EmitFlags[EmitFlags["CapturesThis"] = 256] = "CapturesThis"; + EmitFlags[EmitFlags["NoLeadingSourceMap"] = 512] = "NoLeadingSourceMap"; + EmitFlags[EmitFlags["NoTrailingSourceMap"] = 1024] = "NoTrailingSourceMap"; + EmitFlags[EmitFlags["NoSourceMap"] = 1536] = "NoSourceMap"; + EmitFlags[EmitFlags["NoNestedSourceMaps"] = 2048] = "NoNestedSourceMaps"; + EmitFlags[EmitFlags["NoTokenLeadingSourceMaps"] = 4096] = "NoTokenLeadingSourceMaps"; + EmitFlags[EmitFlags["NoTokenTrailingSourceMaps"] = 8192] = "NoTokenTrailingSourceMaps"; + EmitFlags[EmitFlags["NoTokenSourceMaps"] = 12288] = "NoTokenSourceMaps"; + EmitFlags[EmitFlags["NoLeadingComments"] = 16384] = "NoLeadingComments"; + EmitFlags[EmitFlags["NoTrailingComments"] = 32768] = "NoTrailingComments"; + EmitFlags[EmitFlags["NoComments"] = 49152] = "NoComments"; + EmitFlags[EmitFlags["NoNestedComments"] = 65536] = "NoNestedComments"; + EmitFlags[EmitFlags["ExportName"] = 131072] = "ExportName"; + EmitFlags[EmitFlags["LocalName"] = 262144] = "LocalName"; + EmitFlags[EmitFlags["Indented"] = 524288] = "Indented"; + EmitFlags[EmitFlags["NoIndentation"] = 1048576] = "NoIndentation"; + EmitFlags[EmitFlags["AsyncFunctionBody"] = 2097152] = "AsyncFunctionBody"; + EmitFlags[EmitFlags["ReuseTempVariableScope"] = 4194304] = "ReuseTempVariableScope"; + EmitFlags[EmitFlags["CustomPrologue"] = 8388608] = "CustomPrologue"; + })(ts.EmitFlags || (ts.EmitFlags = {})); + var EmitFlags = ts.EmitFlags; + /* @internal */ + (function (EmitContext) { + EmitContext[EmitContext["SourceFile"] = 0] = "SourceFile"; + EmitContext[EmitContext["Expression"] = 1] = "Expression"; + EmitContext[EmitContext["IdentifierName"] = 2] = "IdentifierName"; + EmitContext[EmitContext["Unspecified"] = 3] = "Unspecified"; + })(ts.EmitContext || (ts.EmitContext = {})); + var EmitContext = ts.EmitContext; })(ts || (ts = {})); /*@internal*/ var ts; @@ -1032,6 +1158,7 @@ var ts; contains: contains, remove: remove, forEachValue: forEachValueInMap, + getKeys: getKeys, clear: clear, }; function forEachValueInMap(f) { @@ -1039,6 +1166,13 @@ var ts; f(key, files[key]); } } + function getKeys() { + var keys = []; + for (var key in files) { + keys.push(key); + } + return keys; + } // path should already be well-formed so it does not need to be normalized function get(path) { return files[toKey(path)]; @@ -1091,6 +1225,22 @@ var ts; return undefined; } ts.forEach = forEach; + /** + * Iterates through `array` by index and performs the callback on each element of array until the callback + * returns a falsey value, then returns false. + * If no such value is found, the callback is applied to each element of array and `true` is returned. + */ + function every(array, callback) { + if (array) { + for (var i = 0, len = array.length; i < len; i++) { + if (!callback(array[i], i)) { + return false; + } + } + } + return true; + } + ts.every = every; /** Works like Array.prototype.find, returning `undefined` if no element satisfying the predicate is found. */ function find(array, predicate) { for (var i = 0, len = array.length; i < len; i++) { @@ -1151,9 +1301,9 @@ var ts; function countWhere(array, predicate) { var count = 0; if (array) { - for (var _i = 0, array_2 = array; _i < array_2.length; _i++) { - var v = array_2[_i]; - if (predicate(v)) { + for (var i = 0; i < array.length; i++) { + var v = array[i]; + if (predicate(v, i)) { count++; } } @@ -1161,10 +1311,6 @@ var ts; return count; } ts.countWhere = countWhere; - /** - * Filters an array by a predicate function. Returns the same array instance if the predicate is - * true for all elements, otherwise returns a new array instance containing the filtered subset. - */ function filter(array, f) { if (array) { var len = array.length; @@ -1189,8 +1335,8 @@ var ts; ts.filter = filter; function removeWhere(array, f) { var outIndex = 0; - for (var _i = 0, array_3 = array; _i < array_3.length; _i++) { - var item = array_3[_i]; + for (var _i = 0, array_2 = array; _i < array_2.length; _i++) { + var item = array_2[_i]; if (!f(item)) { array[outIndex] = item; outIndex++; @@ -1205,8 +1351,8 @@ var ts; ts.removeWhere = removeWhere; function filterMutate(array, f) { var outIndex = 0; - for (var _i = 0, array_4 = array; _i < array_4.length; _i++) { - var item = array_4[_i]; + for (var _i = 0, array_3 = array; _i < array_3.length; _i++) { + var item = array_3[_i]; if (f(item)) { array[outIndex] = item; outIndex++; @@ -1219,14 +1365,136 @@ var ts; var result; if (array) { result = []; - for (var _i = 0, array_5 = array; _i < array_5.length; _i++) { - var v = array_5[_i]; - result.push(f(v)); + for (var i = 0; i < array.length; i++) { + var v = array[i]; + result.push(f(v, i)); } } return result; } ts.map = map; + /** + * Flattens an array containing a mix of array or non-array elements. + * + * @param array The array to flatten. + */ + function flatten(array) { + var result; + if (array) { + result = []; + for (var _i = 0, array_4 = array; _i < array_4.length; _i++) { + var v = array_4[_i]; + if (v) { + if (isArray(v)) { + addRange(result, v); + } + else { + result.push(v); + } + } + } + } + return result; + } + ts.flatten = flatten; + /** + * Maps an array. If the mapped value is an array, it is spread into the result. + * + * @param array The array to map. + * @param mapfn The callback used to map the result into one or more values. + */ + function flatMap(array, mapfn) { + var result; + if (array) { + result = []; + for (var i = 0; i < array.length; i++) { + var v = mapfn(array[i], i); + if (v) { + if (isArray(v)) { + addRange(result, v); + } + else { + result.push(v); + } + } + } + } + return result; + } + ts.flatMap = flatMap; + /** + * Computes the first matching span of elements and returns a tuple of the first span + * and the remaining elements. + */ + function span(array, f) { + if (array) { + for (var i = 0; i < array.length; i++) { + if (!f(array[i], i)) { + return [array.slice(0, i), array.slice(i)]; + } + } + return [array.slice(0), []]; + } + return undefined; + } + ts.span = span; + /** + * Maps contiguous spans of values with the same key. + * + * @param array The array to map. + * @param keyfn A callback used to select the key for an element. + * @param mapfn A callback used to map a contiguous chunk of values to a single value. + */ + function spanMap(array, keyfn, mapfn) { + var result; + if (array) { + result = []; + var len = array.length; + var previousKey = void 0; + var key = void 0; + var start = 0; + var pos = 0; + while (start < len) { + while (pos < len) { + var value = array[pos]; + key = keyfn(value, pos); + if (pos === 0) { + previousKey = key; + } + else if (key !== previousKey) { + break; + } + pos++; + } + if (start < pos) { + var v = mapfn(array.slice(start, pos), previousKey, start, pos); + if (v) { + result.push(v); + } + start = pos; + } + previousKey = key; + pos++; + } + } + return result; + } + ts.spanMap = spanMap; + function mapObject(object, f) { + var result; + if (object) { + result = {}; + for (var _i = 0, _a = getOwnKeys(object); _i < _a.length; _i++) { + var v = _a[_i]; + var _b = f(v, object[v]) || [undefined, undefined], key = _b[0], value = _b[1]; + if (key !== undefined) { + result[key] = value; + } + } + } + return result; + } + ts.mapObject = mapObject; function concatenate(array1, array2) { if (!array2 || !array2.length) return array1; @@ -1235,12 +1503,13 @@ var ts; return array1.concat(array2); } ts.concatenate = concatenate; + // TODO: fixme (N^2) - add optional comparer so collection can be sorted before deduplication. function deduplicate(array, areEqual) { var result; if (array) { result = []; - loop: for (var _i = 0, array_6 = array; _i < array_6.length; _i++) { - var item = array_6[_i]; + loop: for (var _i = 0, array_5 = array; _i < array_5.length; _i++) { + var item = array_5[_i]; for (var _a = 0, result_1 = result; _a < result_1.length; _a++) { var res = result_1[_a]; if (areEqual ? areEqual(res, item) : res === item) { @@ -1253,10 +1522,31 @@ var ts; return result; } ts.deduplicate = deduplicate; + /** + * Compacts an array, removing any falsey elements. + */ + function compact(array) { + var result; + if (array) { + for (var i = 0; i < array.length; i++) { + var v = array[i]; + if (result || !v) { + if (!result) { + result = array.slice(0, i); + } + if (v) { + result.push(v); + } + } + } + } + return result || array; + } + ts.compact = compact; function sum(array, prop) { var result = 0; - for (var _i = 0, array_7 = array; _i < array_7.length; _i++) { - var v = array_7[_i]; + for (var _i = 0, array_6 = array; _i < array_6.length; _i++) { + var v = array_6[_i]; result += v[prop]; } return result; @@ -1266,7 +1556,9 @@ var ts; if (to && from) { for (var _i = 0, from_1 = from; _i < from_1.length; _i++) { var v = from_1[_i]; - to.push(v); + if (v !== undefined) { + to.push(v); + } } } } @@ -1281,14 +1573,31 @@ var ts; return true; } ts.rangeEquals = rangeEquals; + function firstOrUndefined(array) { + return array && array.length > 0 + ? array[0] + : undefined; + } + ts.firstOrUndefined = firstOrUndefined; + function singleOrUndefined(array) { + return array && array.length === 1 + ? array[0] + : undefined; + } + ts.singleOrUndefined = singleOrUndefined; + function singleOrMany(array) { + return array && array.length === 1 + ? array[0] + : array; + } + ts.singleOrMany = singleOrMany; /** * Returns the last element of an array if non-empty, undefined otherwise. */ function lastOrUndefined(array) { - if (array.length === 0) { - return undefined; - } - return array[array.length - 1]; + return array && array.length > 0 + ? array[array.length - 1] + : undefined; } ts.lastOrUndefined = lastOrUndefined; /** @@ -1298,16 +1607,22 @@ var ts; * @param array A sorted array whose first element must be no larger than number * @param number The value to be searched for in the array. */ - function binarySearch(array, value) { + function binarySearch(array, value, comparer) { + if (!array || array.length === 0) { + return -1; + } var low = 0; var high = array.length - 1; + comparer = comparer !== undefined + ? comparer + : function (v1, v2) { return (v1 < v2 ? -1 : (v1 > v2 ? 1 : 0)); }; while (low <= high) { var middle = low + ((high - low) >> 1); var midValue = array[middle]; - if (midValue === value) { + if (comparer(midValue, value) === 0) { return middle; } - else if (midValue > value) { + else if (comparer(midValue, value) > 0) { high = middle - 1; } else { @@ -1317,11 +1632,12 @@ var ts; return ~low; } ts.binarySearch = binarySearch; - function reduceLeft(array, f, initial) { - if (array) { - var count = array.length; - if (count > 0) { - var pos = 0; + function reduceLeft(array, f, initial, start, count) { + if (array && array.length > 0) { + var size = array.length; + if (size > 0) { + var pos = start === undefined || start < 0 ? 0 : start; + var end = count === undefined || pos + count > size - 1 ? size - 1 : pos + count; var result = void 0; if (arguments.length <= 2) { result = array[pos]; @@ -1330,8 +1646,8 @@ var ts; else { result = initial; } - while (pos < count) { - result = f(result, array[pos]); + while (pos <= end) { + result = f(result, array[pos], pos); pos++; } return result; @@ -1340,10 +1656,12 @@ var ts; return initial; } ts.reduceLeft = reduceLeft; - function reduceRight(array, f, initial) { + function reduceRight(array, f, initial, start, count) { if (array) { - var pos = array.length - 1; - if (pos >= 0) { + var size = array.length; + if (size > 0) { + var pos = start === undefined || start > size - 1 ? size - 1 : start; + var end = count === undefined || pos - count < 0 ? 0 : pos - count; var result = void 0; if (arguments.length <= 2) { result = array[pos]; @@ -1352,8 +1670,8 @@ var ts; else { result = initial; } - while (pos >= 0) { - result = f(result, array[pos]); + while (pos >= end) { + result = f(result, array[pos], pos); pos--; } return result; @@ -1447,6 +1765,21 @@ var ts; } } ts.copyProperties = copyProperties; + function assign(t) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + for (var _a = 0, args_1 = args; _a < args_1.length; _a++) { + var arg = args_1[_a]; + for (var _b = 0, _c = getOwnKeys(arg); _b < _c.length; _b++) { + var p = _c[_b]; + t[p] = arg[p]; + } + } + return t; + } + ts.assign = assign; /** * Reduce the properties of a map. * @@ -1512,13 +1845,22 @@ var ts; ts.equalOwnProperties = equalOwnProperties; function arrayToMap(array, makeKey, makeValue) { var result = createMap(); - for (var _i = 0, array_8 = array; _i < array_8.length; _i++) { - var value = array_8[_i]; + for (var _i = 0, array_7 = array; _i < array_7.length; _i++) { + var value = array_7[_i]; result[makeKey(value)] = makeValue ? makeValue(value) : value; } return result; } ts.arrayToMap = arrayToMap; + function isEmpty(map) { + for (var id in map) { + if (hasProperty(map, id)) { + return false; + } + } + return true; + } + ts.isEmpty = isEmpty; function cloneMap(map) { var clone = createMap(); copyProperties(map, clone); @@ -1563,6 +1905,21 @@ var ts; } } ts.multiMapAdd = multiMapAdd; + /** + * Removes a value from an array of values associated with the key. + * Does not preserve the order of those values. + * Does nothing if `key` is not in `map`, or `value` is not in `map[key]`. + */ + function multiMapRemove(map, key, value) { + var values = map[key]; + if (values) { + unorderedRemoveItem(values, value); + if (!values.length) { + delete map[key]; + } + } + } + ts.multiMapRemove = multiMapRemove; /** * Tests whether a value is an array. */ @@ -1581,6 +1938,56 @@ var ts; }; } ts.memoize = memoize; + function chain(a, b, c, d, e) { + if (e) { + var args_2 = []; + for (var i = 0; i < arguments.length; i++) { + args_2[i] = arguments[i]; + } + return function (t) { return compose.apply(void 0, map(args_2, function (f) { return f(t); })); }; + } + else if (d) { + return function (t) { return compose(a(t), b(t), c(t), d(t)); }; + } + else if (c) { + return function (t) { return compose(a(t), b(t), c(t)); }; + } + else if (b) { + return function (t) { return compose(a(t), b(t)); }; + } + else if (a) { + return function (t) { return compose(a(t)); }; + } + else { + return function (t) { return function (u) { return u; }; }; + } + } + ts.chain = chain; + function compose(a, b, c, d, e) { + if (e) { + var args_3 = []; + for (var i = 0; i < arguments.length; i++) { + args_3[i] = arguments[i]; + } + return function (t) { return reduceLeft(args_3, function (u, f) { return f(u); }, t); }; + } + else if (d) { + return function (t) { return d(c(b(a(t)))); }; + } + else if (c) { + return function (t) { return c(b(a(t))); }; + } + else if (b) { + return function (t) { return b(a(t)); }; + } + else if (a) { + return function (t) { return a(t); }; + } + else { + return function (t) { return t; }; + } + } + ts.compose = compose; function formatStringFromArgs(text, args, baseIndex) { baseIndex = baseIndex || 0; return text.replace(/{(\d+)}/g, function (match, index) { return args[+index + baseIndex]; }); @@ -1782,6 +2189,7 @@ var ts; } ts.getRootLength = getRootLength; ts.directorySeparator = "/"; + var directorySeparatorCharCode = 47 /* slash */; function getNormalizedParts(normalizedSlashedPath, rootLength) { var parts = normalizedSlashedPath.substr(rootLength).split(ts.directorySeparator); var normalized = []; @@ -1805,10 +2213,22 @@ var ts; function normalizePath(path) { path = normalizeSlashes(path); var rootLength = getRootLength(path); + var root = path.substr(0, rootLength); var normalized = getNormalizedParts(path, rootLength); - return path.substr(0, rootLength) + normalized.join(ts.directorySeparator); + if (normalized.length) { + var joinedParts = root + normalized.join(ts.directorySeparator); + return pathEndsWithDirectorySeparator(path) ? joinedParts + ts.directorySeparator : joinedParts; + } + else { + return root; + } } ts.normalizePath = normalizePath; + /** A path ending with '/' refers to a directory only, never a file. */ + function pathEndsWithDirectorySeparator(path) { + return path.charCodeAt(path.length - 1) === directorySeparatorCharCode; + } + ts.pathEndsWithDirectorySeparator = pathEndsWithDirectorySeparator; function getDirectoryPath(path) { return path.substr(0, Math.max(getRootLength(path), path.lastIndexOf(ts.directorySeparator))); } @@ -1817,10 +2237,49 @@ var ts; return path && !isRootedDiskPath(path) && path.indexOf("://") !== -1; } ts.isUrl = isUrl; + function isExternalModuleNameRelative(moduleName) { + // TypeScript 1.0 spec (April 2014): 11.2.1 + // An external module name is "relative" if the first term is "." or "..". + return /^\.\.?($|[\\/])/.test(moduleName); + } + ts.isExternalModuleNameRelative = isExternalModuleNameRelative; + function getEmitScriptTarget(compilerOptions) { + return compilerOptions.target || 0 /* ES3 */; + } + ts.getEmitScriptTarget = getEmitScriptTarget; + function getEmitModuleKind(compilerOptions) { + return typeof compilerOptions.module === "number" ? + compilerOptions.module : + getEmitScriptTarget(compilerOptions) === 2 /* ES6 */ ? ts.ModuleKind.ES6 : ts.ModuleKind.CommonJS; + } + ts.getEmitModuleKind = getEmitModuleKind; + /* @internal */ + function hasZeroOrOneAsteriskCharacter(str) { + var seenAsterisk = false; + for (var i = 0; i < str.length; i++) { + if (str.charCodeAt(i) === 42 /* asterisk */) { + if (!seenAsterisk) { + seenAsterisk = true; + } + else { + // have already seen asterisk + return false; + } + } + } + return true; + } + ts.hasZeroOrOneAsteriskCharacter = hasZeroOrOneAsteriskCharacter; function isRootedDiskPath(path) { return getRootLength(path) !== 0; } ts.isRootedDiskPath = isRootedDiskPath; + function convertToRelativePath(absoluteOrRelativePath, basePath, getCanonicalFileName) { + return !isRootedDiskPath(absoluteOrRelativePath) + ? absoluteOrRelativePath + : getRelativePathToDirectoryOrUrl(basePath, absoluteOrRelativePath, basePath, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false); + } + ts.convertToRelativePath = convertToRelativePath; function normalizedPathComponents(path, rootLength) { var normalizedParts = getNormalizedParts(path, rootLength); return [path.substr(0, rootLength)].concat(normalizedParts); @@ -2264,6 +2723,14 @@ var ts; return options && options.allowJs ? allSupportedExtensions : ts.supportedTypeScriptExtensions; } ts.getSupportedExtensions = getSupportedExtensions; + function hasJavaScriptFileExtension(fileName) { + return forEach(ts.supportedJavascriptExtensions, function (extension) { return fileExtensionIs(fileName, extension); }); + } + ts.hasJavaScriptFileExtension = hasJavaScriptFileExtension; + function hasTypeScriptFileExtension(fileName) { + return forEach(ts.supportedTypeScriptExtensions, function (extension) { return fileExtensionIs(fileName, extension); }); + } + ts.hasTypeScriptFileExtension = hasTypeScriptFileExtension; function isSupportedSourceFileName(fileName, compilerOptions) { if (!fileName) { return false; @@ -2367,11 +2834,15 @@ var ts; function Signature(checker) { } function Node(kind, pos, end) { + this.id = 0; this.kind = kind; this.pos = pos; this.end = end; this.flags = 0 /* None */; + this.modifierFlagsCache = 0 /* None */; + this.transformFlags = 0 /* None */; this.parent = undefined; + this.original = undefined; } ts.objectAllocator = { getNodeConstructor: function () { return Node; }, @@ -2391,9 +2862,9 @@ var ts; var AssertionLevel = ts.AssertionLevel; var Debug; (function (Debug) { - var currentAssertionLevel = 0 /* None */; + var currentAssertionLevel; function shouldAssert(level) { - return currentAssertionLevel >= level; + return getCurrentAssertionLevel() >= level; } Debug.shouldAssert = shouldAssert; function assert(expression, message, verboseDebugInfo) { @@ -2411,7 +2882,30 @@ var ts; Debug.assert(/*expression*/ false, message); } Debug.fail = fail; + function getCurrentAssertionLevel() { + if (currentAssertionLevel !== undefined) { + return currentAssertionLevel; + } + if (ts.sys === undefined) { + return 0 /* None */; + } + var developmentMode = /^development$/i.test(getEnvironmentVariable("NODE_ENV")); + currentAssertionLevel = developmentMode + ? 1 /* Normal */ + : 0 /* None */; + return currentAssertionLevel; + } })(Debug = ts.Debug || (ts.Debug = {})); + function getEnvironmentVariable(name, host) { + if (host && host.getEnvironmentVariable) { + return host.getEnvironmentVariable(name); + } + if (ts.sys && ts.sys.getEnvironmentVariable) { + return ts.sys.getEnvironmentVariable(name); + } + return ""; + } + ts.getEnvironmentVariable = getEnvironmentVariable; /** Remove an item from an array, moving everything to its right one space left. */ function orderedRemoveItemAt(array, index) { // This seems to be faster than either `array.splice(i, 1)` or `array.copyWithin(i, i+ 1)`. @@ -2447,6 +2941,84 @@ var ts; : (function (fileName) { return fileName.toLowerCase(); }); } ts.createGetCanonicalFileName = createGetCanonicalFileName; + /** + * patternStrings contains both pattern strings (containing "*") and regular strings. + * Return an exact match if possible, or a pattern match, or undefined. + * (These are verified by verifyCompilerOptions to have 0 or 1 "*" characters.) + */ + /* @internal */ + function matchPatternOrExact(patternStrings, candidate) { + var patterns = []; + for (var _i = 0, patternStrings_1 = patternStrings; _i < patternStrings_1.length; _i++) { + var patternString = patternStrings_1[_i]; + var pattern = tryParsePattern(patternString); + if (pattern) { + patterns.push(pattern); + } + else if (patternString === candidate) { + // pattern was matched as is - no need to search further + return patternString; + } + } + return findBestPatternMatch(patterns, function (_) { return _; }, candidate); + } + ts.matchPatternOrExact = matchPatternOrExact; + /* @internal */ + function patternText(_a) { + var prefix = _a.prefix, suffix = _a.suffix; + return prefix + "*" + suffix; + } + ts.patternText = patternText; + /** + * Given that candidate matches pattern, returns the text matching the '*'. + * E.g.: matchedText(tryParsePattern("foo*baz"), "foobarbaz") === "bar" + */ + /* @internal */ + function matchedText(pattern, candidate) { + Debug.assert(isPatternMatch(pattern, candidate)); + return candidate.substr(pattern.prefix.length, candidate.length - pattern.suffix.length); + } + ts.matchedText = matchedText; + /** Return the object corresponding to the best pattern to match `candidate`. */ + /* @internal */ + function findBestPatternMatch(values, getPattern, candidate) { + var matchedValue = undefined; + // use length of prefix as betterness criteria + var longestMatchPrefixLength = -1; + for (var _i = 0, values_1 = values; _i < values_1.length; _i++) { + var v = values_1[_i]; + var pattern = getPattern(v); + if (isPatternMatch(pattern, candidate) && pattern.prefix.length > longestMatchPrefixLength) { + longestMatchPrefixLength = pattern.prefix.length; + matchedValue = v; + } + } + return matchedValue; + } + ts.findBestPatternMatch = findBestPatternMatch; + function isPatternMatch(_a, candidate) { + var prefix = _a.prefix, suffix = _a.suffix; + return candidate.length >= prefix.length + suffix.length && + startsWith(candidate, prefix) && + endsWith(candidate, suffix); + } + /* @internal */ + function tryParsePattern(pattern) { + // This should be verified outside of here and a proper error thrown. + Debug.assert(hasZeroOrOneAsteriskCharacter(pattern)); + var indexOfStar = pattern.indexOf("*"); + return indexOfStar === -1 ? undefined : { + prefix: pattern.substr(0, indexOfStar), + suffix: pattern.substr(indexOfStar + 1) + }; + } + ts.tryParsePattern = tryParsePattern; + function positionIsSynthesized(pos) { + // This is a fast way of testing the following conditions: + // pos === undefined || pos === null || isNaN(pos) || pos < 0; + return !(pos >= 0); + } + ts.positionIsSynthesized = positionIsSynthesized; })(ts || (ts = {})); /// var ts; @@ -2571,6 +3143,9 @@ var ts; return shell.CurrentDirectory; }, getDirectories: getDirectories, + getEnvironmentVariable: function (name) { + return new ActiveXObject("WScript.Shell").ExpandEnvironmentStrings("%" + name + "%"); + }, readDirectory: readDirectory, exit: function (exitCode) { try { @@ -2628,13 +3203,7 @@ var ts; reduceDirWatcherRefCountForFile(watchedFile.fileName); } function removeFileWatcherCallback(filePath, callback) { - var callbacks = fileWatcherCallbacks[filePath]; - if (callbacks) { - ts.unorderedRemoveItem(callbacks, callback); - if (callbacks.length === 0) { - delete fileWatcherCallbacks[filePath]; - } - } + ts.multiMapRemove(fileWatcherCallbacks, filePath, callback); } function fileEventHandler(eventName, relativeFileName, baseDirPath) { // When files are deleted from disk, the triggered "rename" event would have a relativefileName of "undefined" @@ -2761,7 +3330,7 @@ var ts; return fileSystemEntryExists(path, 1 /* Directory */); } function getDirectories(path) { - return ts.filter(_fs.readdirSync(path), function (p) { return fileSystemEntryExists(ts.combinePaths(path, p), 1 /* Directory */); }); + return ts.filter(_fs.readdirSync(path), function (dir) { return fileSystemEntryExists(ts.combinePaths(path, dir), 1 /* Directory */); }); } var nodeSystem = { args: process.argv.slice(2), @@ -2830,6 +3399,9 @@ var ts; return process.cwd(); }, getDirectories: getDirectories, + getEnvironmentVariable: function (name) { + return process.env[name] || ""; + }, readDirectory: readDirectory, getModifiedTime: function (path) { try { @@ -2865,6 +3437,13 @@ var ts; }, realpath: function (path) { return _fs.realpathSync(path); + }, + tryEnableSourceMapsForHost: function () { + try { + require("source-map-support").install(); + } + catch (e) { + } } }; return nodeSystem; @@ -2894,6 +3473,7 @@ var ts; getExecutingFilePath: function () { return ChakraHost.executingFile; }, getCurrentDirectory: function () { return ChakraHost.currentDirectory; }, getDirectories: ChakraHost.getDirectories, + getEnvironmentVariable: ChakraHost.getEnvironmentVariable || (function (name) { return ""; }), readDirectory: function (path, extensions, excludes, includes) { var pattern = ts.getFileMatcherPatterns(path, extensions, excludes, includes, !!ChakraHost.useCaseSensitiveFileNames, ChakraHost.currentDirectory); return ChakraHost.readDirectory(path, extensions, pattern.basePaths, pattern.excludePattern, pattern.includeFilePattern, pattern.includeDirectoryPattern); @@ -2902,26 +3482,47 @@ var ts; realpath: realpath }; } + function recursiveCreateDirectory(directoryPath, sys) { + var basePath = ts.getDirectoryPath(directoryPath); + var shouldCreateParent = directoryPath !== basePath && !sys.directoryExists(basePath); + if (shouldCreateParent) { + recursiveCreateDirectory(basePath, sys); + } + if (shouldCreateParent || !sys.directoryExists(directoryPath)) { + sys.createDirectory(directoryPath); + } + } + var sys; if (typeof ChakraHost !== "undefined") { - return getChakraSystem(); + sys = getChakraSystem(); } else if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") { - return getWScriptSystem(); + sys = getWScriptSystem(); } else if (typeof process !== "undefined" && process.nextTick && !process.browser && typeof require !== "undefined") { // process and process.nextTick checks if current environment is node-like // process.browser check excludes webpack and browserify - return getNodeSystem(); + sys = getNodeSystem(); } - else { - return undefined; // Unsupported host + if (sys) { + // patch writefile to create folder before writing the file + var originalWriteFile_1 = sys.writeFile; + sys.writeFile = function (path, data, writeBom) { + var directoryPath = ts.getDirectoryPath(ts.normalizeSlashes(path)); + if (directoryPath && !sys.directoryExists(directoryPath)) { + recursiveCreateDirectory(directoryPath, sys); + } + originalWriteFile_1.call(sys, path, data, writeBom); + }; } + return sys; })(); })(ts || (ts = {})); /// /* @internal */ var ts; (function (ts) { + ts.externalHelpersModuleNameText = "tslib"; function getDeclarationOfKind(symbol, kind) { var declarations = symbol.declarations; if (declarations) { @@ -2989,7 +3590,7 @@ var ts; } ts.arrayIsEqualTo = arrayIsEqualTo; function hasResolvedModule(sourceFile, moduleNameText) { - return !!(sourceFile.resolvedModules && sourceFile.resolvedModules[moduleNameText]); + return !!(sourceFile && sourceFile.resolvedModules && sourceFile.resolvedModules[moduleNameText]); } ts.hasResolvedModule = hasResolvedModule; function getResolvedModule(sourceFile, moduleNameText) { @@ -3041,24 +3642,24 @@ var ts; // Returns true if this node contains a parse error anywhere underneath it. function containsParseError(node) { aggregateChildData(node); - return (node.flags & 268435456 /* ThisNodeOrAnySubNodesHasError */) !== 0; + return (node.flags & 2097152 /* ThisNodeOrAnySubNodesHasError */) !== 0; } ts.containsParseError = containsParseError; function aggregateChildData(node) { - if (!(node.flags & 536870912 /* HasAggregatedChildData */)) { + if (!(node.flags & 4194304 /* HasAggregatedChildData */)) { // A node is considered to contain a parse error if: // a) the parser explicitly marked that it had an error // b) any of it's children reported that it had an error. - var thisNodeOrAnySubNodesHasError = ((node.flags & 67108864 /* ThisNodeHasError */) !== 0) || + var thisNodeOrAnySubNodesHasError = ((node.flags & 524288 /* ThisNodeHasError */) !== 0) || ts.forEachChild(node, containsParseError); // If so, mark ourselves accordingly. if (thisNodeOrAnySubNodesHasError) { - node.flags |= 268435456 /* ThisNodeOrAnySubNodesHasError */; + node.flags |= 2097152 /* ThisNodeOrAnySubNodesHasError */; } // Also mark that we've propagated the child information to this node. This way we can // always consult the bit directly on this node without needing to check its children // again. - node.flags |= 536870912 /* HasAggregatedChildData */; + node.flags |= 4194304 /* HasAggregatedChildData */; } } function getSourceFileOfNode(node) { @@ -3096,6 +3697,10 @@ var ts; return node.pos; } ts.getStartPosOfNode = getStartPosOfNode; + function isDefined(value) { + return value !== undefined; + } + ts.isDefined = isDefined; function getEndLinePosition(line, sourceFile) { ts.Debug.assert(line >= 0); var lineStarts = ts.getLineStarts(sourceFile); @@ -3135,7 +3740,7 @@ var ts; // However, this node will be 'missing' in the sense that no actual source-code/tokens are // contained within it. function nodeIsMissing(node) { - if (!node) { + if (node === undefined) { return true; } return node.pos === node.end && node.pos >= 0 && node.kind !== 1 /* EndOfFileToken */; @@ -3203,6 +3808,56 @@ var ts; return getSourceTextOfNodeFromSourceFile(getSourceFileOfNode(node), node, includeTrivia); } ts.getTextOfNode = getTextOfNode; + function getLiteralText(node, sourceFile, languageVersion) { + // Any template literal or string literal with an extended escape + // (e.g. "\u{0067}") will need to be downleveled as a escaped string literal. + if (languageVersion < 2 /* ES6 */ && (isTemplateLiteralKind(node.kind) || node.hasExtendedUnicodeEscape)) { + return getQuotedEscapedLiteralText('"', node.text, '"'); + } + // If we don't need to downlevel and we can reach the original source text using + // the node's parent reference, then simply get the text as it was originally written. + if (!nodeIsSynthesized(node) && node.parent) { + var text = getSourceTextOfNodeFromSourceFile(sourceFile, node); + if (languageVersion < 2 /* ES6 */ && isBinaryOrOctalIntegerLiteral(node, text)) { + return node.text; + } + return text; + } + // If we can't reach the original source text, use the canonical form if it's a number, + // or an escaped quoted form of the original text if it's string-like. + switch (node.kind) { + case 9 /* StringLiteral */: + return getQuotedEscapedLiteralText('"', node.text, '"'); + case 11 /* NoSubstitutionTemplateLiteral */: + return getQuotedEscapedLiteralText("`", node.text, "`"); + case 12 /* TemplateHead */: + return getQuotedEscapedLiteralText("`", node.text, "${"); + case 13 /* TemplateMiddle */: + return getQuotedEscapedLiteralText("}", node.text, "${"); + case 14 /* TemplateTail */: + return getQuotedEscapedLiteralText("}", node.text, "`"); + case 8 /* NumericLiteral */: + return node.text; + } + ts.Debug.fail("Literal kind '" + node.kind + "' not accounted for."); + } + ts.getLiteralText = getLiteralText; + function isBinaryOrOctalIntegerLiteral(node, text) { + if (node.kind === 8 /* NumericLiteral */ && text.length > 1) { + switch (text.charCodeAt(1)) { + case 98 /* b */: + case 66 /* B */: + case 111 /* o */: + case 79 /* O */: + return true; + } + } + return false; + } + ts.isBinaryOrOctalIntegerLiteral = isBinaryOrOctalIntegerLiteral; + function getQuotedEscapedLiteralText(leftQuote, text, rightQuote) { + return leftQuote + escapeNonAsciiCharacters(escapeString(text)) + rightQuote; + } // Add an extra underscore to identifiers that start with two underscores to avoid issues with magic names like '__proto__' function escapeIdentifier(identifier) { return identifier.length >= 2 && identifier.charCodeAt(0) === 95 /* _ */ && identifier.charCodeAt(1) === 95 /* _ */ ? "_" + identifier : identifier; @@ -3220,7 +3875,7 @@ var ts; } ts.makeIdentifierFromModuleName = makeIdentifierFromModuleName; function isBlockOrCatchScoped(declaration) { - return (getCombinedNodeFlags(declaration) & 3072 /* BlockScoped */) !== 0 || + return (ts.getCombinedNodeFlags(declaration) & 3 /* BlockScoped */) !== 0 || isCatchClauseVariableDeclaration(declaration); } ts.isBlockOrCatchScoped = isBlockOrCatchScoped; @@ -3229,20 +3884,22 @@ var ts; (node.name.kind === 9 /* StringLiteral */ || isGlobalScopeAugmentation(node)); } ts.isAmbientModule = isAmbientModule; + function isShorthandAmbientModuleSymbol(moduleSymbol) { + return isShorthandAmbientModule(moduleSymbol.valueDeclaration); + } + ts.isShorthandAmbientModuleSymbol = isShorthandAmbientModuleSymbol; function isShorthandAmbientModule(node) { // The only kind of module that can be missing a body is a shorthand ambient module. return node.kind === 225 /* ModuleDeclaration */ && (!node.body); } - ts.isShorthandAmbientModule = isShorthandAmbientModule; function isBlockScopedContainerTopLevel(node) { return node.kind === 256 /* SourceFile */ || node.kind === 225 /* ModuleDeclaration */ || - isFunctionLike(node) || - isFunctionBlock(node); + isFunctionLike(node); } ts.isBlockScopedContainerTopLevel = isBlockScopedContainerTopLevel; function isGlobalScopeAugmentation(module) { - return !!(module.flags & 131072 /* GlobalAugmentation */); + return !!(module.flags & 512 /* GlobalAugmentation */); } ts.isGlobalScopeAugmentation = isGlobalScopeAugmentation; function isExternalModuleAugmentation(node) { @@ -3261,30 +3918,39 @@ var ts; return false; } ts.isExternalModuleAugmentation = isExternalModuleAugmentation; + function isBlockScope(node, parentNode) { + switch (node.kind) { + case 256 /* SourceFile */: + case 227 /* CaseBlock */: + case 252 /* CatchClause */: + case 225 /* ModuleDeclaration */: + case 206 /* ForStatement */: + case 207 /* ForInStatement */: + case 208 /* ForOfStatement */: + case 148 /* Constructor */: + case 147 /* MethodDeclaration */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + case 180 /* ArrowFunction */: + return true; + case 199 /* Block */: + // function block is not considered block-scope container + // see comment in binder.ts: bind(...), case for SyntaxKind.Block + return parentNode && !isFunctionLike(parentNode); + } + return false; + } + ts.isBlockScope = isBlockScope; // Gets the nearest enclosing block scope container that has the provided node // as a descendant, that is not the provided node. function getEnclosingBlockScopeContainer(node) { var current = node.parent; while (current) { - if (isFunctionLike(current)) { + if (isBlockScope(current, current.parent)) { return current; } - switch (current.kind) { - case 256 /* SourceFile */: - case 227 /* CaseBlock */: - case 252 /* CatchClause */: - case 225 /* ModuleDeclaration */: - case 206 /* ForStatement */: - case 207 /* ForInStatement */: - case 208 /* ForOfStatement */: - return current; - case 199 /* Block */: - // function block is not considered block-scope container - // see comment in binder.ts: bind(...), case for SyntaxKind.Block - if (!isFunctionLike(current.parent)) { - return current; - } - } current = current.parent; } } @@ -3396,41 +4062,13 @@ var ts; return node.kind === 224 /* EnumDeclaration */ && isConst(node); } ts.isConstEnumDeclaration = isConstEnumDeclaration; - function walkUpBindingElementsAndPatterns(node) { - while (node && (node.kind === 169 /* BindingElement */ || isBindingPattern(node))) { - node = node.parent; - } - return node; - } - // Returns the node flags for this node and all relevant parent nodes. This is done so that - // nodes like variable declarations and binding elements can returned a view of their flags - // that includes the modifiers from their container. i.e. flags like export/declare aren't - // stored on the variable declaration directly, but on the containing variable statement - // (if it has one). Similarly, flags for let/const are store on the variable declaration - // list. By calling this function, all those flags are combined so that the client can treat - // the node as if it actually had those flags. - function getCombinedNodeFlags(node) { - node = walkUpBindingElementsAndPatterns(node); - var flags = node.flags; - if (node.kind === 218 /* VariableDeclaration */) { - node = node.parent; - } - if (node && node.kind === 219 /* VariableDeclarationList */) { - flags |= node.flags; - node = node.parent; - } - if (node && node.kind === 200 /* VariableStatement */) { - flags |= node.flags; - } - return flags; - } - ts.getCombinedNodeFlags = getCombinedNodeFlags; function isConst(node) { - return !!(getCombinedNodeFlags(node) & 2048 /* Const */); + return !!(ts.getCombinedNodeFlags(node) & 2 /* Const */) + || !!(ts.getCombinedModifierFlags(node) & 2048 /* Const */); } ts.isConst = isConst; function isLet(node) { - return !!(getCombinedNodeFlags(node) & 1024 /* Let */); + return !!(ts.getCombinedNodeFlags(node) & 1 /* Let */); } ts.isLet = isLet; function isSuperCallExpression(n) { @@ -3472,7 +4110,7 @@ var ts; ts.fullTripleSlashReferencePathRegEx = /^(\/\/\/\s*/; ts.fullTripleSlashReferenceTypeReferenceDirectiveRegEx = /^(\/\/\/\s*/; ts.fullTripleSlashAMDReferencePathRegEx = /^(\/\/\/\s*/; - function isTypeNode(node) { + function isPartOfTypeNode(node) { if (154 /* FirstTypeNode */ <= node.kind && node.kind <= 166 /* LastTypeNode */) { return true; } @@ -3500,7 +4138,7 @@ var ts; node = node.parent; } // At this point, node is either a qualified name or an identifier - ts.Debug.assert(node.kind === 69 /* Identifier */ || node.kind === 139 /* QualifiedName */ || node.kind === 172 /* PropertyAccessExpression */, "'node' was expected to be a qualified name, identifier or property access in 'isTypeNode'."); + ts.Debug.assert(node.kind === 69 /* Identifier */ || node.kind === 139 /* QualifiedName */ || node.kind === 172 /* PropertyAccessExpression */, "'node' was expected to be a qualified name, identifier or property access in 'isPartOfTypeNode'."); case 139 /* QualifiedName */: case 172 /* PropertyAccessExpression */: case 97 /* ThisKeyword */: @@ -3508,11 +4146,11 @@ var ts; if (parent_1.kind === 158 /* TypeQuery */) { return false; } - // Do not recursively call isTypeNode on the parent. In the example: + // Do not recursively call isPartOfTypeNode on the parent. In the example: // // let a: A.B.C; // - // Calling isTypeNode would consider the qualified name A.B a type node. Only C or + // Calling isPartOfTypeNode would consider the qualified name A.B a type node. Only C or // A.B.C is a type node. if (154 /* FirstTypeNode */ <= parent_1.kind && parent_1.kind <= 166 /* LastTypeNode */) { return true; @@ -3552,7 +4190,7 @@ var ts; } return false; } - ts.isTypeNode = isTypeNode; + ts.isPartOfTypeNode = isPartOfTypeNode; // Warning: This has the same semantics as the forEach family of functions, // in that traversal terminates in the event that 'visitor' supplies a truthy value. function forEachReturnStatement(body, visitor) { @@ -3611,7 +4249,7 @@ var ts; return; } } - else if (!isTypeNode(node)) { + else if (!isPartOfTypeNode(node)) { // This is the general case, which should include mostly expressions and statements. // Also includes NodeArrays. ts.forEachChild(node, traverse); @@ -3792,11 +4430,11 @@ var ts; } ts.getThisContainer = getThisContainer; /** - * Given an super call\property node returns a closest node where either - * - super call\property is legal in the node and not legal in the parent node the node. + * Given an super call/property node, returns the closest node where + * - a super call/property access is legal in the node and not legal in the parent node the node. * i.e. super call is legal in constructor but not legal in the class body. - * - node is arrow function (so caller might need to call getSuperContainer in case it needs to climb higher) - * - super call\property is definitely illegal in the node (but might be legal in some subnode) + * - the container is an arrow function (so caller might need to call getSuperContainer again in case it needs to climb higher) + * - a super call/property is definitely illegal in the container (but might be legal in some subnode) * i.e. super property access is illegal in function declaration but can be legal in the statement list */ function getSuperContainer(node, stopOnFunctions) { @@ -3857,12 +4495,12 @@ var ts; /** * Determines whether a node is a property or element access expression for super. */ - function isSuperPropertyOrElementAccess(node) { - return (node.kind === 172 /* PropertyAccessExpression */ - || node.kind === 173 /* ElementAccessExpression */) + function isSuperProperty(node) { + var kind = node.kind; + return (kind === 172 /* PropertyAccessExpression */ || kind === 173 /* ElementAccessExpression */) && node.expression.kind === 95 /* SuperKeyword */; } - ts.isSuperPropertyOrElementAccess = isSuperPropertyOrElementAccess; + ts.isSuperProperty = isSuperProperty; function getEntityNameFromTypeNode(node) { if (node) { switch (node.kind) { @@ -3929,14 +4567,20 @@ var ts; && nodeCanBeDecorated(node); } ts.nodeIsDecorated = nodeIsDecorated; - function isPropertyAccessExpression(node) { - return node.kind === 172 /* PropertyAccessExpression */; + function nodeOrChildIsDecorated(node) { + return nodeIsDecorated(node) || childIsDecorated(node); } - ts.isPropertyAccessExpression = isPropertyAccessExpression; - function isElementAccessExpression(node) { - return node.kind === 173 /* ElementAccessExpression */; + ts.nodeOrChildIsDecorated = nodeOrChildIsDecorated; + function childIsDecorated(node) { + switch (node.kind) { + case 221 /* ClassDeclaration */: + return ts.forEach(node.members, nodeOrChildIsDecorated); + case 147 /* MethodDeclaration */: + case 150 /* SetAccessor */: + return ts.forEach(node.parameters, nodeIsDecorated); + } } - ts.isElementAccessExpression = isElementAccessExpression; + ts.childIsDecorated = childIsDecorated; function isJSXTagName(node) { var parent = node.parent; if (parent.kind === 243 /* JsxOpeningElement */ || @@ -3947,7 +4591,7 @@ var ts; return false; } ts.isJSXTagName = isJSXTagName; - function isExpression(node) { + function isPartOfExpression(node) { switch (node.kind) { case 97 /* ThisKeyword */: case 95 /* SuperKeyword */: @@ -4043,20 +4687,14 @@ var ts; case 194 /* ExpressionWithTypeArguments */: return parent_3.expression === node && isExpressionWithTypeArgumentsInClassExtendsClause(parent_3); default: - if (isExpression(parent_3)) { + if (isPartOfExpression(parent_3)) { return true; } } } return false; } - ts.isExpression = isExpression; - function isExternalModuleNameRelative(moduleName) { - // TypeScript 1.0 spec (April 2014): 11.2.1 - // An external module name is "relative" if the first term is "." or "..". - return /^\.\.?($|[\\/])/.test(moduleName); - } - ts.isExternalModuleNameRelative = isExternalModuleNameRelative; + ts.isPartOfExpression = isPartOfExpression; function isInstantiatedModule(node, preserveConstEnums) { var moduleState = ts.getModuleInstanceState(node); return moduleState === 1 /* Instantiated */ || @@ -4081,7 +4719,7 @@ var ts; } ts.isSourceFileJavaScript = isSourceFileJavaScript; function isInJavaScriptFile(node) { - return node && !!(node.flags & 134217728 /* JavaScriptFile */); + return node && !!(node.flags & 1048576 /* JavaScriptFile */); } ts.isInJavaScriptFile = isInJavaScriptFile; /** @@ -4177,6 +4815,22 @@ var ts; } } ts.getExternalModuleName = getExternalModuleName; + function getNamespaceDeclarationNode(node) { + if (node.kind === 229 /* ImportEqualsDeclaration */) { + return node; + } + var importClause = node.importClause; + if (importClause && importClause.namedBindings && importClause.namedBindings.kind === 232 /* NamespaceImport */) { + return importClause.namedBindings; + } + } + ts.getNamespaceDeclarationNode = getNamespaceDeclarationNode; + function isDefaultImport(node) { + return node.kind === 230 /* ImportDeclaration */ + && node.importClause + && !!node.importClause.name; + } + ts.isDefaultImport = isDefaultImport; function hasQuestionToken(node) { if (node) { switch (node.kind) { @@ -4203,37 +4857,71 @@ var ts; if (!node) { return undefined; } - var jsDocComments = getJSDocComments(node, checkParentVariableStatement); - if (!jsDocComments) { + var jsDocTags = getJSDocTags(node, checkParentVariableStatement); + if (!jsDocTags) { return undefined; } - for (var _i = 0, jsDocComments_1 = jsDocComments; _i < jsDocComments_1.length; _i++) { - var jsDocComment = jsDocComments_1[_i]; - for (var _a = 0, _b = jsDocComment.tags; _a < _b.length; _a++) { - var tag = _b[_a]; - if (tag.kind === kind) { - return tag; - } + for (var _i = 0, jsDocTags_1 = jsDocTags; _i < jsDocTags_1.length; _i++) { + var tag = jsDocTags_1[_i]; + if (tag.kind === kind) { + return tag; } } } + function append(previous, additional) { + if (additional) { + if (!previous) { + previous = []; + } + for (var _i = 0, additional_1 = additional; _i < additional_1.length; _i++) { + var x = additional_1[_i]; + previous.push(x); + } + } + return previous; + } function getJSDocComments(node, checkParentVariableStatement) { - if (node.jsDocComments) { - return node.jsDocComments; - } - // Try to recognize this pattern when node is initializer of variable declaration and JSDoc comments are on containing variable statement. - // /** - // * @param {number} name - // * @returns {number} - // */ - // var x = function(name) { return name.length; } + return getJSDocs(node, checkParentVariableStatement, function (docs) { return ts.map(docs, function (doc) { return doc.comment; }); }, function (tags) { return ts.map(tags, function (tag) { return tag.comment; }); }); + } + ts.getJSDocComments = getJSDocComments; + function getJSDocTags(node, checkParentVariableStatement) { + return getJSDocs(node, checkParentVariableStatement, function (docs) { + var result = []; + for (var _i = 0, docs_1 = docs; _i < docs_1.length; _i++) { + var doc = docs_1[_i]; + if (doc.tags) { + result.push.apply(result, doc.tags); + } + } + return result; + }, function (tags) { return tags; }); + } + function getJSDocs(node, checkParentVariableStatement, getDocs, getTags) { + // TODO: Get rid of getJsDocComments and friends (note the lowercase 's' in Js) + // TODO: A lot of this work should be cached, maybe. I guess it's only used in services right now... + var result = undefined; + // prepend documentation from parent sources if (checkParentVariableStatement) { - var isInitializerOfVariableDeclarationInStatement = node.parent.kind === 218 /* VariableDeclaration */ && - node.parent.initializer === node && + // Try to recognize this pattern when node is initializer of variable declaration and JSDoc comments are on containing variable statement. + // /** + // * @param {number} name + // * @returns {number} + // */ + // var x = function(name) { return name.length; } + var isInitializerOfVariableDeclarationInStatement = isVariableLike(node.parent) && + (node.parent).initializer === node && node.parent.parent.parent.kind === 200 /* VariableStatement */; - var variableStatementNode = isInitializerOfVariableDeclarationInStatement ? node.parent.parent.parent : undefined; + var isVariableOfVariableDeclarationStatement = isVariableLike(node) && + node.parent.parent.kind === 200 /* VariableStatement */; + var variableStatementNode = isInitializerOfVariableDeclarationInStatement ? node.parent.parent.parent : + isVariableOfVariableDeclarationStatement ? node.parent.parent : + undefined; if (variableStatementNode) { - return variableStatementNode.jsDocComments; + result = append(result, getJSDocs(variableStatementNode, checkParentVariableStatement, getDocs, getTags)); + } + if (node.kind === 225 /* ModuleDeclaration */ && + node.parent && node.parent.kind === 225 /* ModuleDeclaration */) { + result = append(result, getJSDocs(node.parent, checkParentVariableStatement, getDocs, getTags)); } // Also recognize when the node is the RHS of an assignment expression var parent_4 = node.parent; @@ -4242,14 +4930,56 @@ var ts; parent_4.operatorToken.kind === 56 /* EqualsToken */ && parent_4.parent.kind === 202 /* ExpressionStatement */; if (isSourceOfAssignmentExpressionStatement) { - return parent_4.parent.jsDocComments; + result = append(result, getJSDocs(parent_4.parent, checkParentVariableStatement, getDocs, getTags)); } var isPropertyAssignmentExpression = parent_4 && parent_4.kind === 253 /* PropertyAssignment */; if (isPropertyAssignmentExpression) { - return parent_4.jsDocComments; + result = append(result, getJSDocs(parent_4, checkParentVariableStatement, getDocs, getTags)); + } + // Pull parameter comments from declaring function as well + if (node.kind === 142 /* Parameter */) { + var paramTags = getJSDocParameterTag(node, checkParentVariableStatement); + if (paramTags) { + result = append(result, getTags(paramTags)); + } } } - return undefined; + if (isVariableLike(node) && node.initializer) { + result = append(result, getJSDocs(node.initializer, /*checkParentVariableStatement*/ false, getDocs, getTags)); + } + if (node.jsDocComments) { + if (result) { + result = append(result, getDocs(node.jsDocComments)); + } + else { + return getDocs(node.jsDocComments); + } + } + return result; + } + function getJSDocParameterTag(param, checkParentVariableStatement) { + var func = param.parent; + var tags = getJSDocTags(func, checkParentVariableStatement); + if (!param.name) { + // this is an anonymous jsdoc param from a `function(type1, type2): type3` specification + var i = func.parameters.indexOf(param); + var paramTags = ts.filter(tags, function (tag) { return tag.kind === 275 /* JSDocParameterTag */; }); + if (paramTags && 0 <= i && i < paramTags.length) { + return [paramTags[i]]; + } + } + else if (param.name.kind === 69 /* Identifier */) { + var name_5 = param.name.text; + var paramTags = ts.filter(tags, function (tag) { return tag.kind === 275 /* JSDocParameterTag */ && tag.parameterName.text === name_5; }); + if (paramTags) { + return paramTags; + } + } + else { + // TODO: it's a destructured parameter, so it should look up an "object type" series of multiple lines + // But multi-line object types aren't supported yet either + return undefined; + } } function getJSDocTypeTag(node) { return getJSDocTag(node, 277 /* JSDocTypeTag */, /*checkParentVariableStatement*/ false); @@ -4268,19 +4998,16 @@ var ts; // If it's a parameter, see if the parent has a jsdoc comment with an @param // annotation. var parameterName = parameter.name.text; - var jsDocComments = getJSDocComments(parameter.parent, /*checkParentVariableStatement*/ true); - if (jsDocComments) { - for (var _i = 0, jsDocComments_2 = jsDocComments; _i < jsDocComments_2.length; _i++) { - var jsDocComment = jsDocComments_2[_i]; - for (var _a = 0, _b = jsDocComment.tags; _a < _b.length; _a++) { - var tag = _b[_a]; - if (tag.kind === 275 /* JSDocParameterTag */) { - var parameterTag = tag; - var name_5 = parameterTag.preParameterName || parameterTag.postParameterName; - if (name_5.text === parameterName) { - return parameterTag; - } - } + var jsDocTags = getJSDocTags(parameter.parent, /*checkParentVariableStatement*/ true); + if (!jsDocTags) { + return undefined; + } + for (var _i = 0, jsDocTags_2 = jsDocTags; _i < jsDocTags_2.length; _i++) { + var tag = jsDocTags_2[_i]; + if (tag.kind === 275 /* JSDocParameterTag */) { + var parameterTag = tag; + if (parameterTag.parameterName.text === parameterName) { + return parameterTag; } } } @@ -4297,7 +5024,7 @@ var ts; } ts.hasDeclaredRestParameter = hasDeclaredRestParameter; function isRestParameter(node) { - if (node && (node.flags & 134217728 /* JavaScriptFile */)) { + if (node && (node.flags & 1048576 /* JavaScriptFile */)) { if (node.type && node.type.kind === 270 /* JSDocVariadicType */) { return true; } @@ -4313,22 +5040,6 @@ var ts; return node && node.dotDotDotToken !== undefined; } ts.isDeclaredRestParam = isDeclaredRestParam; - function isLiteralKind(kind) { - return 8 /* FirstLiteralToken */ <= kind && kind <= 11 /* LastLiteralToken */; - } - ts.isLiteralKind = isLiteralKind; - function isTextualLiteralKind(kind) { - return kind === 9 /* StringLiteral */ || kind === 11 /* NoSubstitutionTemplateLiteral */; - } - ts.isTextualLiteralKind = isTextualLiteralKind; - function isTemplateLiteralKind(kind) { - return 11 /* FirstTemplateToken */ <= kind && kind <= 14 /* LastTemplateToken */; - } - ts.isTemplateLiteralKind = isTemplateLiteralKind; - function isBindingPattern(node) { - return !!node && (node.kind === 168 /* ArrayBindingPattern */ || node.kind === 167 /* ObjectBindingPattern */); - } - ts.isBindingPattern = isBindingPattern; // A node is an assignment target if it is on the left hand side of an '=' token, if it is parented by a property // assignment in an object literal that is an assignment target, or if it is parented by an array literal that is // an assignment target. Examples include 'a = xxx', '{ p: a } = xxx', '[{ p: a}] = xxx'. @@ -4354,7 +5065,7 @@ var ts; } } ts.isAssignmentTarget = isAssignmentTarget; - function isNodeDescendentOf(node, ancestor) { + function isNodeDescendantOf(node, ancestor) { while (node) { if (node === ancestor) return true; @@ -4362,10 +5073,10 @@ var ts; } return false; } - ts.isNodeDescendentOf = isNodeDescendentOf; + ts.isNodeDescendantOf = isNodeDescendantOf; function isInAmbientContext(node) { while (node) { - if (node.flags & 2 /* Ambient */ || (node.kind === 256 /* SourceFile */ && node.isDeclarationFile)) { + if (hasModifier(node, 2 /* Ambient */) || (node.kind === 256 /* SourceFile */ && node.isDeclarationFile)) { return true; } node = node.parent; @@ -4373,85 +5084,6 @@ var ts; return false; } ts.isInAmbientContext = isInAmbientContext; - function isDeclaration(node) { - switch (node.kind) { - case 180 /* ArrowFunction */: - case 169 /* BindingElement */: - case 221 /* ClassDeclaration */: - case 192 /* ClassExpression */: - case 148 /* Constructor */: - case 224 /* EnumDeclaration */: - case 255 /* EnumMember */: - case 238 /* ExportSpecifier */: - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - case 149 /* GetAccessor */: - case 231 /* ImportClause */: - case 229 /* ImportEqualsDeclaration */: - case 234 /* ImportSpecifier */: - case 222 /* InterfaceDeclaration */: - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - case 225 /* ModuleDeclaration */: - case 232 /* NamespaceImport */: - case 228 /* NamespaceExportDeclaration */: - case 142 /* Parameter */: - case 253 /* PropertyAssignment */: - case 145 /* PropertyDeclaration */: - case 144 /* PropertySignature */: - case 150 /* SetAccessor */: - case 254 /* ShorthandPropertyAssignment */: - case 223 /* TypeAliasDeclaration */: - case 141 /* TypeParameter */: - case 218 /* VariableDeclaration */: - case 279 /* JSDocTypedefTag */: - return true; - } - return false; - } - ts.isDeclaration = isDeclaration; - function isStatement(n) { - switch (n.kind) { - case 210 /* BreakStatement */: - case 209 /* ContinueStatement */: - case 217 /* DebuggerStatement */: - case 204 /* DoStatement */: - case 202 /* ExpressionStatement */: - case 201 /* EmptyStatement */: - case 207 /* ForInStatement */: - case 208 /* ForOfStatement */: - case 206 /* ForStatement */: - case 203 /* IfStatement */: - case 214 /* LabeledStatement */: - case 211 /* ReturnStatement */: - case 213 /* SwitchStatement */: - case 215 /* ThrowStatement */: - case 216 /* TryStatement */: - case 200 /* VariableStatement */: - case 205 /* WhileStatement */: - case 212 /* WithStatement */: - case 235 /* ExportAssignment */: - return true; - default: - return false; - } - } - ts.isStatement = isStatement; - function isClassElement(n) { - switch (n.kind) { - case 148 /* Constructor */: - case 145 /* PropertyDeclaration */: - case 147 /* MethodDeclaration */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 146 /* MethodSignature */: - case 153 /* IndexSignature */: - return true; - default: - return false; - } - } - ts.isClassElement = isClassElement; // True if the given identifier, string literal, or number literal is the name of a declaration node function isDeclarationName(name) { if (name.kind !== 69 /* Identifier */ && name.kind !== 9 /* StringLiteral */ && name.kind !== 8 /* NumericLiteral */) { @@ -4619,7 +5251,7 @@ var ts; } ts.isTrivia = isTrivia; function isAsyncFunctionLike(node) { - return isFunctionLike(node) && (node.flags & 256 /* Async */) !== 0 && !isAccessor(node); + return isFunctionLike(node) && hasModifier(node, 256 /* Async */) && !isAccessor(node); } ts.isAsyncFunctionLike = isAsyncFunctionLike; function isStringOrNumericLiteral(kind) { @@ -4710,77 +5342,241 @@ var ts; return node; } ts.getRootDeclaration = getRootDeclaration; - function nodeStartsNewLexicalEnvironment(n) { - return isFunctionLike(n) || n.kind === 225 /* ModuleDeclaration */ || n.kind === 256 /* SourceFile */; + function nodeStartsNewLexicalEnvironment(node) { + var kind = node.kind; + return kind === 148 /* Constructor */ + || kind === 179 /* FunctionExpression */ + || kind === 220 /* FunctionDeclaration */ + || kind === 180 /* ArrowFunction */ + || kind === 147 /* MethodDeclaration */ + || kind === 149 /* GetAccessor */ + || kind === 150 /* SetAccessor */ + || kind === 225 /* ModuleDeclaration */ + || kind === 256 /* SourceFile */; } ts.nodeStartsNewLexicalEnvironment = nodeStartsNewLexicalEnvironment; - /** - * Creates a shallow, memberwise clone of a node. The "kind", "pos", "end", "flags", and "parent" - * properties are excluded by default, and can be provided via the "location", "flags", and - * "parent" parameters. - * @param node The node to clone. - * @param location An optional TextRange to use to supply the new position. - * @param flags The NodeFlags to use for the cloned node. - * @param parent The parent for the new node. - */ - function cloneNode(node, location, flags, parent) { - // We don't use "clone" from core.ts here, as we need to preserve the prototype chain of - // the original node. We also need to exclude specific properties and only include own- - // properties (to skip members already defined on the shared prototype). - var clone = location !== undefined - ? ts.createNode(node.kind, location.pos, location.end) - : createSynthesizedNode(node.kind); - for (var key in node) { - if (clone.hasOwnProperty(key) || !node.hasOwnProperty(key)) { - continue; + function nodeIsSynthesized(node) { + return ts.positionIsSynthesized(node.pos) + || ts.positionIsSynthesized(node.end); + } + ts.nodeIsSynthesized = nodeIsSynthesized; + function getOriginalNode(node) { + if (node) { + while (node.original !== undefined) { + node = node.original; } - clone[key] = node[key]; - } - if (flags !== undefined) { - clone.flags = flags; - } - if (parent !== undefined) { - clone.parent = parent; } - return clone; + return node; } - ts.cloneNode = cloneNode; + ts.getOriginalNode = getOriginalNode; /** - * Creates a deep clone of an EntityName, with new parent pointers. - * @param node The EntityName to clone. - * @param parent The parent for the cloned node. + * Gets a value indicating whether a node originated in the parse tree. + * + * @param node The node to test. */ - function cloneEntityName(node, parent) { - var clone = cloneNode(node, node, node.flags, parent); - if (isQualifiedName(clone)) { - var left = clone.left, right = clone.right; - clone.left = cloneEntityName(left, clone); - clone.right = cloneNode(right, right, right.flags, parent); + function isParseTreeNode(node) { + return (node.flags & 8 /* Synthesized */) === 0; + } + ts.isParseTreeNode = isParseTreeNode; + function getParseTreeNode(node, nodeTest) { + if (isParseTreeNode(node)) { + return node; } - return clone; + node = getOriginalNode(node); + if (isParseTreeNode(node) && (!nodeTest || nodeTest(node))) { + return node; + } + return undefined; } - ts.cloneEntityName = cloneEntityName; - function isQualifiedName(node) { - return node.kind === 139 /* QualifiedName */; + ts.getParseTreeNode = getParseTreeNode; + function getOriginalSourceFiles(sourceFiles) { + var originalSourceFiles = []; + for (var _i = 0, sourceFiles_1 = sourceFiles; _i < sourceFiles_1.length; _i++) { + var sourceFile = sourceFiles_1[_i]; + var originalSourceFile = getParseTreeNode(sourceFile, isSourceFile); + if (originalSourceFile) { + originalSourceFiles.push(originalSourceFile); + } + } + return originalSourceFiles; + } + ts.getOriginalSourceFiles = getOriginalSourceFiles; + function getOriginalNodeId(node) { + node = getOriginalNode(node); + return node ? ts.getNodeId(node) : 0; + } + ts.getOriginalNodeId = getOriginalNodeId; + (function (Associativity) { + Associativity[Associativity["Left"] = 0] = "Left"; + Associativity[Associativity["Right"] = 1] = "Right"; + })(ts.Associativity || (ts.Associativity = {})); + var Associativity = ts.Associativity; + function getExpressionAssociativity(expression) { + var operator = getOperator(expression); + var hasArguments = expression.kind === 175 /* NewExpression */ && expression.arguments !== undefined; + return getOperatorAssociativity(expression.kind, operator, hasArguments); + } + ts.getExpressionAssociativity = getExpressionAssociativity; + function getOperatorAssociativity(kind, operator, hasArguments) { + switch (kind) { + case 175 /* NewExpression */: + return hasArguments ? 0 /* Left */ : 1 /* Right */; + case 185 /* PrefixUnaryExpression */: + case 182 /* TypeOfExpression */: + case 183 /* VoidExpression */: + case 181 /* DeleteExpression */: + case 184 /* AwaitExpression */: + case 188 /* ConditionalExpression */: + case 190 /* YieldExpression */: + return 1 /* Right */; + case 187 /* BinaryExpression */: + switch (operator) { + case 38 /* AsteriskAsteriskToken */: + case 56 /* EqualsToken */: + case 57 /* PlusEqualsToken */: + case 58 /* MinusEqualsToken */: + case 60 /* AsteriskAsteriskEqualsToken */: + case 59 /* AsteriskEqualsToken */: + case 61 /* SlashEqualsToken */: + case 62 /* PercentEqualsToken */: + case 63 /* LessThanLessThanEqualsToken */: + case 64 /* GreaterThanGreaterThanEqualsToken */: + case 65 /* GreaterThanGreaterThanGreaterThanEqualsToken */: + case 66 /* AmpersandEqualsToken */: + case 68 /* CaretEqualsToken */: + case 67 /* BarEqualsToken */: + return 1 /* Right */; + } + } + return 0 /* Left */; } - ts.isQualifiedName = isQualifiedName; - function nodeIsSynthesized(node) { - return node.pos === -1; + ts.getOperatorAssociativity = getOperatorAssociativity; + function getExpressionPrecedence(expression) { + var operator = getOperator(expression); + var hasArguments = expression.kind === 175 /* NewExpression */ && expression.arguments !== undefined; + return getOperatorPrecedence(expression.kind, operator, hasArguments); } - ts.nodeIsSynthesized = nodeIsSynthesized; - function createSynthesizedNode(kind, startsOnNewLine) { - var node = ts.createNode(kind, /* pos */ -1, /* end */ -1); - node.startsOnNewLine = startsOnNewLine; - return node; + ts.getExpressionPrecedence = getExpressionPrecedence; + function getOperator(expression) { + if (expression.kind === 187 /* BinaryExpression */) { + return expression.operatorToken.kind; + } + else if (expression.kind === 185 /* PrefixUnaryExpression */ || expression.kind === 186 /* PostfixUnaryExpression */) { + return expression.operator; + } + else { + return expression.kind; + } } - ts.createSynthesizedNode = createSynthesizedNode; - function createSynthesizedNodeArray() { - var array = []; - array.pos = -1; - array.end = -1; - return array; + ts.getOperator = getOperator; + function getOperatorPrecedence(nodeKind, operatorKind, hasArguments) { + switch (nodeKind) { + case 97 /* ThisKeyword */: + case 95 /* SuperKeyword */: + case 69 /* Identifier */: + case 93 /* NullKeyword */: + case 99 /* TrueKeyword */: + case 84 /* FalseKeyword */: + case 8 /* NumericLiteral */: + case 9 /* StringLiteral */: + case 170 /* ArrayLiteralExpression */: + case 171 /* ObjectLiteralExpression */: + case 179 /* FunctionExpression */: + case 180 /* ArrowFunction */: + case 192 /* ClassExpression */: + case 241 /* JsxElement */: + case 242 /* JsxSelfClosingElement */: + case 10 /* RegularExpressionLiteral */: + case 11 /* NoSubstitutionTemplateLiteral */: + case 189 /* TemplateExpression */: + case 178 /* ParenthesizedExpression */: + case 193 /* OmittedExpression */: + return 19; + case 176 /* TaggedTemplateExpression */: + case 172 /* PropertyAccessExpression */: + case 173 /* ElementAccessExpression */: + return 18; + case 175 /* NewExpression */: + return hasArguments ? 18 : 17; + case 174 /* CallExpression */: + return 17; + case 186 /* PostfixUnaryExpression */: + return 16; + case 185 /* PrefixUnaryExpression */: + case 182 /* TypeOfExpression */: + case 183 /* VoidExpression */: + case 181 /* DeleteExpression */: + case 184 /* AwaitExpression */: + return 15; + case 187 /* BinaryExpression */: + switch (operatorKind) { + case 49 /* ExclamationToken */: + case 50 /* TildeToken */: + return 15; + case 38 /* AsteriskAsteriskToken */: + case 37 /* AsteriskToken */: + case 39 /* SlashToken */: + case 40 /* PercentToken */: + return 14; + case 35 /* PlusToken */: + case 36 /* MinusToken */: + return 13; + case 43 /* LessThanLessThanToken */: + case 44 /* GreaterThanGreaterThanToken */: + case 45 /* GreaterThanGreaterThanGreaterThanToken */: + return 12; + case 25 /* LessThanToken */: + case 28 /* LessThanEqualsToken */: + case 27 /* GreaterThanToken */: + case 29 /* GreaterThanEqualsToken */: + case 90 /* InKeyword */: + case 91 /* InstanceOfKeyword */: + return 11; + case 30 /* EqualsEqualsToken */: + case 32 /* EqualsEqualsEqualsToken */: + case 31 /* ExclamationEqualsToken */: + case 33 /* ExclamationEqualsEqualsToken */: + return 10; + case 46 /* AmpersandToken */: + return 9; + case 48 /* CaretToken */: + return 8; + case 47 /* BarToken */: + return 7; + case 51 /* AmpersandAmpersandToken */: + return 6; + case 52 /* BarBarToken */: + return 5; + case 56 /* EqualsToken */: + case 57 /* PlusEqualsToken */: + case 58 /* MinusEqualsToken */: + case 60 /* AsteriskAsteriskEqualsToken */: + case 59 /* AsteriskEqualsToken */: + case 61 /* SlashEqualsToken */: + case 62 /* PercentEqualsToken */: + case 63 /* LessThanLessThanEqualsToken */: + case 64 /* GreaterThanGreaterThanEqualsToken */: + case 65 /* GreaterThanGreaterThanGreaterThanEqualsToken */: + case 66 /* AmpersandEqualsToken */: + case 68 /* CaretEqualsToken */: + case 67 /* BarEqualsToken */: + return 3; + case 24 /* CommaToken */: + return 0; + default: + return -1; + } + case 188 /* ConditionalExpression */: + return 4; + case 190 /* YieldExpression */: + return 2; + case 191 /* SpreadElementExpression */: + return 1; + default: + return -1; + } } - ts.createSynthesizedNodeArray = createSynthesizedNodeArray; + ts.getOperatorPrecedence = getOperatorPrecedence; function createDiagnosticCollection() { var nonFileDiagnostics = []; var fileDiagnostics = ts.createMap(); @@ -4797,12 +5593,12 @@ var ts; return modificationCount; } function reattachFileDiagnostics(newFile) { - var diagnostics = fileDiagnostics[newFile.fileName]; - if (diagnostics) { - for (var _i = 0, diagnostics_1 = diagnostics; _i < diagnostics_1.length; _i++) { - var diagnostic = diagnostics_1[_i]; - diagnostic.file = newFile; - } + if (!ts.hasProperty(fileDiagnostics, newFile.fileName)) { + return; + } + for (var _i = 0, _a = fileDiagnostics[newFile.fileName]; _i < _a.length; _i++) { + var diagnostic = _a[_i]; + diagnostic.file = newFile; } } function add(diagnostic) { @@ -4981,10 +5777,23 @@ var ts; getLine: function () { return lineCount + 1; }, getColumn: function () { return lineStart ? indent * getIndentSize() + 1 : output.length - linePos + 1; }, getText: function () { return output; }, + isAtStartOfLine: function () { return lineStart; }, reset: reset }; } ts.createTextWriter = createTextWriter; + function getResolvedExternalModuleName(host, file) { + return file.moduleName || getExternalModuleNameFromPath(host, file.fileName); + } + ts.getResolvedExternalModuleName = getResolvedExternalModuleName; + function getExternalModuleNameFromDeclaration(host, resolver, declaration) { + var file = resolver.getExternalModuleFileFromDeclaration(declaration); + if (!file || isDeclarationFile(file)) { + return undefined; + } + return getResolvedExternalModuleName(host, file); + } + ts.getExternalModuleNameFromDeclaration = getExternalModuleNameFromDeclaration; /** * Resolves a local path to a path which is absolute to the base of the emit */ @@ -5011,25 +5820,112 @@ var ts; function getDeclarationEmitOutputFilePath(sourceFile, host) { var options = host.getCompilerOptions(); var outputDir = options.declarationDir || options.outDir; // Prefer declaration folder if specified - if (options.declaration) { - var path = outputDir - ? getSourceFilePathInNewDir(sourceFile, host, outputDir) - : sourceFile.fileName; - return ts.removeFileExtension(path) + ".d.ts"; - } + var path = outputDir + ? getSourceFilePathInNewDir(sourceFile, host, outputDir) + : sourceFile.fileName; + return ts.removeFileExtension(path) + ".d.ts"; } ts.getDeclarationEmitOutputFilePath = getDeclarationEmitOutputFilePath; - function getEmitScriptTarget(compilerOptions) { - return compilerOptions.target || 0 /* ES3 */; + /** + * Gets the source files that are expected to have an emit output. + * + * Originally part of `forEachExpectedEmitFile`, this functionality was extracted to support + * transformations. + * + * @param host An EmitHost. + * @param targetSourceFile An optional target source file to emit. + */ + function getSourceFilesToEmit(host, targetSourceFile) { + var options = host.getCompilerOptions(); + if (options.outFile || options.out) { + var moduleKind = ts.getEmitModuleKind(options); + var moduleEmitEnabled = moduleKind === ts.ModuleKind.AMD || moduleKind === ts.ModuleKind.System; + var sourceFiles = host.getSourceFiles(); + // Can emit only sources that are not declaration file and are either non module code or module with --module or --target es6 specified + return ts.filter(sourceFiles, moduleEmitEnabled ? isNonDeclarationFile : isBundleEmitNonExternalModule); + } + else { + var sourceFiles = targetSourceFile === undefined ? host.getSourceFiles() : [targetSourceFile]; + return ts.filter(sourceFiles, isNonDeclarationFile); + } } - ts.getEmitScriptTarget = getEmitScriptTarget; - function getEmitModuleKind(compilerOptions) { - return typeof compilerOptions.module === "number" ? - compilerOptions.module : - getEmitScriptTarget(compilerOptions) === 2 /* ES6 */ ? ts.ModuleKind.ES6 : ts.ModuleKind.CommonJS; + ts.getSourceFilesToEmit = getSourceFilesToEmit; + function isNonDeclarationFile(sourceFile) { + return !isDeclarationFile(sourceFile); } - ts.getEmitModuleKind = getEmitModuleKind; - function forEachExpectedEmitFile(host, action, targetSourceFile) { + function isBundleEmitNonExternalModule(sourceFile) { + return !isDeclarationFile(sourceFile) && !ts.isExternalModule(sourceFile); + } + /** + * Iterates over each source file to emit. The source files are expected to have been + * transformed for use by the pretty printer. + * + * Originally part of `forEachExpectedEmitFile`, this functionality was extracted to support + * transformations. + * + * @param host An EmitHost. + * @param sourceFiles The transformed source files to emit. + * @param action The action to execute. + */ + function forEachTransformedEmitFile(host, sourceFiles, action, emitOnlyDtsFiles) { + var options = host.getCompilerOptions(); + // Emit on each source file + if (options.outFile || options.out) { + onBundledEmit(host, sourceFiles); + } + else { + for (var _i = 0, sourceFiles_2 = sourceFiles; _i < sourceFiles_2.length; _i++) { + var sourceFile = sourceFiles_2[_i]; + // Don't emit if source file is a declaration file, or was located under node_modules + if (!isDeclarationFile(sourceFile) && !host.isSourceFileFromExternalLibrary(sourceFile)) { + onSingleFileEmit(host, sourceFile); + } + } + } + function onSingleFileEmit(host, sourceFile) { + // JavaScript files are always LanguageVariant.JSX, as JSX syntax is allowed in .js files also. + // So for JavaScript files, '.jsx' is only emitted if the input was '.jsx', and JsxEmit.Preserve. + // For TypeScript, the only time to emit with a '.jsx' extension, is on JSX input, and JsxEmit.Preserve + var extension = ".js"; + if (options.jsx === 1 /* Preserve */) { + if (isSourceFileJavaScript(sourceFile)) { + if (ts.fileExtensionIs(sourceFile.fileName, ".jsx")) { + extension = ".jsx"; + } + } + else if (sourceFile.languageVariant === 1 /* JSX */) { + // TypeScript source file preserving JSX syntax + extension = ".jsx"; + } + } + var jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, extension); + var sourceMapFilePath = getSourceMapFilePath(jsFilePath, options); + var declarationFilePath = !isSourceFileJavaScript(sourceFile) && (options.declaration || emitOnlyDtsFiles) ? getDeclarationEmitOutputFilePath(sourceFile, host) : undefined; + action(jsFilePath, sourceMapFilePath, declarationFilePath, [sourceFile], /*isBundledEmit*/ false); + } + function onBundledEmit(host, sourceFiles) { + if (sourceFiles.length) { + var jsFilePath = options.outFile || options.out; + var sourceMapFilePath = getSourceMapFilePath(jsFilePath, options); + var declarationFilePath = options.declaration ? ts.removeFileExtension(jsFilePath) + ".d.ts" : undefined; + action(jsFilePath, sourceMapFilePath, declarationFilePath, sourceFiles, /*isBundledEmit*/ true); + } + } + } + ts.forEachTransformedEmitFile = forEachTransformedEmitFile; + function getSourceMapFilePath(jsFilePath, options) { + return options.sourceMap ? jsFilePath + ".map" : undefined; + } + /** + * Iterates over the source files that are expected to have an emit output. This function + * is used by the legacy emitter and the declaration emitter and should not be used by + * the tree transforming emitter. + * + * @param host An EmitHost. + * @param action The action to execute. + * @param targetSourceFile An optional target source file to emit. + */ + function forEachExpectedEmitFile(host, action, targetSourceFile, emitOnlyDtsFiles) { var options = host.getCompilerOptions(); // Emit on each source file if (options.outFile || options.out) { @@ -5037,8 +5933,8 @@ var ts; } else { var sourceFiles = targetSourceFile === undefined ? host.getSourceFiles() : [targetSourceFile]; - for (var _i = 0, sourceFiles_1 = sourceFiles; _i < sourceFiles_1.length; _i++) { - var sourceFile = sourceFiles_1[_i]; + for (var _i = 0, sourceFiles_3 = sourceFiles; _i < sourceFiles_3.length; _i++) { + var sourceFile = sourceFiles_3[_i]; // Don't emit if source file is a declaration file, or was located under node_modules if (!isDeclarationFile(sourceFile) && !host.isSourceFileFromExternalLibrary(sourceFile)) { onSingleFileEmit(host, sourceFile); @@ -5062,12 +5958,13 @@ var ts; } } var jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, extension); + var declarationFilePath = !isSourceFileJavaScript(sourceFile) && (emitOnlyDtsFiles || options.declaration) ? getDeclarationEmitOutputFilePath(sourceFile, host) : undefined; var emitFileNames = { jsFilePath: jsFilePath, sourceMapFilePath: getSourceMapFilePath(jsFilePath, options), - declarationFilePath: !isSourceFileJavaScript(sourceFile) ? getDeclarationEmitOutputFilePath(sourceFile, host) : undefined + declarationFilePath: declarationFilePath }; - action(emitFileNames, [sourceFile], /*isBundledEmit*/ false); + action(emitFileNames, [sourceFile], /*isBundledEmit*/ false, emitOnlyDtsFiles); } function onBundledEmit(host) { // Can emit only sources that are not declaration file and are either non module code or module with @@ -5075,7 +5972,7 @@ var ts; var bundledSources = ts.filter(host.getSourceFiles(), function (sourceFile) { return !isDeclarationFile(sourceFile) && !host.isSourceFileFromExternalLibrary(sourceFile) && (!ts.isExternalModule(sourceFile) || - !!getEmitModuleKind(options)); }); + !!ts.getEmitModuleKind(options)); }); if (bundledSources.length) { var jsFilePath = options.outFile || options.out; var emitFileNames = { @@ -5083,12 +5980,9 @@ var ts; sourceMapFilePath: getSourceMapFilePath(jsFilePath, options), declarationFilePath: options.declaration ? ts.removeFileExtension(jsFilePath) + ".d.ts" : undefined }; - action(emitFileNames, bundledSources, /*isBundledEmit*/ true); + action(emitFileNames, bundledSources, /*isBundledEmit*/ true, emitOnlyDtsFiles); } } - function getSourceMapFilePath(jsFilePath, options) { - return options.sourceMap ? jsFilePath + ".map" : undefined; - } } ts.forEachExpectedEmitFile = forEachExpectedEmitFile; function getSourceFilePathInNewDir(sourceFile, host, newDirPath) { @@ -5150,7 +6044,7 @@ var ts; else { ts.forEach(declarations, function (member) { if ((member.kind === 149 /* GetAccessor */ || member.kind === 150 /* SetAccessor */) - && (member.flags & 32 /* Static */) === (accessor.flags & 32 /* Static */)) { + && hasModifier(member, 32 /* Static */) === hasModifier(accessor, 32 /* Static */)) { var memberName = getPropertyNameForPropertyNameNode(member.name); var accessorName = getPropertyNameForPropertyNameNode(accessor.name); if (memberName === accessorName) { @@ -5179,32 +6073,49 @@ var ts; } ts.getAllAccessorDeclarations = getAllAccessorDeclarations; function emitNewLineBeforeLeadingComments(lineMap, writer, node, leadingComments) { + emitNewLineBeforeLeadingCommentsOfPosition(lineMap, writer, node.pos, leadingComments); + } + ts.emitNewLineBeforeLeadingComments = emitNewLineBeforeLeadingComments; + function emitNewLineBeforeLeadingCommentsOfPosition(lineMap, writer, pos, leadingComments) { // If the leading comments start on different line than the start of node, write new line - if (leadingComments && leadingComments.length && node.pos !== leadingComments[0].pos && - getLineOfLocalPositionFromLineMap(lineMap, node.pos) !== getLineOfLocalPositionFromLineMap(lineMap, leadingComments[0].pos)) { + if (leadingComments && leadingComments.length && pos !== leadingComments[0].pos && + getLineOfLocalPositionFromLineMap(lineMap, pos) !== getLineOfLocalPositionFromLineMap(lineMap, leadingComments[0].pos)) { writer.writeLine(); } } - ts.emitNewLineBeforeLeadingComments = emitNewLineBeforeLeadingComments; - function emitComments(text, lineMap, writer, comments, trailingSeparator, newLine, writeComment) { - var emitLeadingSpace = !trailingSeparator; - ts.forEach(comments, function (comment) { - if (emitLeadingSpace) { + ts.emitNewLineBeforeLeadingCommentsOfPosition = emitNewLineBeforeLeadingCommentsOfPosition; + function emitNewLineBeforeLeadingCommentOfPosition(lineMap, writer, pos, commentPos) { + // If the leading comments start on different line than the start of node, write new line + if (pos !== commentPos && + getLineOfLocalPositionFromLineMap(lineMap, pos) !== getLineOfLocalPositionFromLineMap(lineMap, commentPos)) { + writer.writeLine(); + } + } + ts.emitNewLineBeforeLeadingCommentOfPosition = emitNewLineBeforeLeadingCommentOfPosition; + function emitComments(text, lineMap, writer, comments, leadingSeparator, trailingSeparator, newLine, writeComment) { + if (comments && comments.length > 0) { + if (leadingSeparator) { writer.write(" "); - emitLeadingSpace = false; } - writeComment(text, lineMap, writer, comment, newLine); - if (comment.hasTrailingNewLine) { - writer.writeLine(); + var emitInterveningSeparator = false; + for (var _i = 0, comments_1 = comments; _i < comments_1.length; _i++) { + var comment = comments_1[_i]; + if (emitInterveningSeparator) { + writer.write(" "); + emitInterveningSeparator = false; + } + writeComment(text, lineMap, writer, comment.pos, comment.end, newLine); + if (comment.hasTrailingNewLine) { + writer.writeLine(); + } + else { + emitInterveningSeparator = true; + } } - else if (trailingSeparator) { + if (emitInterveningSeparator && trailingSeparator) { writer.write(" "); } - else { - // Emit leading space to separate comment during next comment emit - emitLeadingSpace = true; - } - }); + } } ts.emitComments = emitComments; /** @@ -5255,7 +6166,7 @@ var ts; if (nodeLine >= lastCommentLine + 2) { // Valid detachedComments emitNewLineBeforeLeadingComments(lineMap, writer, node, leadingComments); - emitComments(text, lineMap, writer, detachedComments, /*trailingSeparator*/ true, newLine, writeComment); + emitComments(text, lineMap, writer, detachedComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeComment); currentDetachedCommentInfo = { nodePos: node.pos, detachedCommentEndPos: ts.lastOrUndefined(detachedComments).end }; } } @@ -5267,19 +6178,19 @@ var ts; } } ts.emitDetachedComments = emitDetachedComments; - function writeCommentRange(text, lineMap, writer, comment, newLine) { - if (text.charCodeAt(comment.pos + 1) === 42 /* asterisk */) { - var firstCommentLineAndCharacter = ts.computeLineAndCharacterOfPosition(lineMap, comment.pos); + function writeCommentRange(text, lineMap, writer, commentPos, commentEnd, newLine) { + if (text.charCodeAt(commentPos + 1) === 42 /* asterisk */) { + var firstCommentLineAndCharacter = ts.computeLineAndCharacterOfPosition(lineMap, commentPos); var lineCount = lineMap.length; var firstCommentLineIndent = void 0; - for (var pos = comment.pos, currentLine = firstCommentLineAndCharacter.line; pos < comment.end; currentLine++) { + for (var pos = commentPos, currentLine = firstCommentLineAndCharacter.line; pos < commentEnd; currentLine++) { var nextLineStart = (currentLine + 1) === lineCount ? text.length + 1 : lineMap[currentLine + 1]; - if (pos !== comment.pos) { + if (pos !== commentPos) { // If we are not emitting first line, we need to write the spaces to adjust the alignment if (firstCommentLineIndent === undefined) { - firstCommentLineIndent = calculateIndent(text, lineMap[firstCommentLineAndCharacter.line], comment.pos); + firstCommentLineIndent = calculateIndent(text, lineMap[firstCommentLineAndCharacter.line], commentPos); } // These are number of spaces writer is going to write at current indent var currentWriterIndentSpacing = writer.getIndent() * getIndentSize(); @@ -5315,23 +6226,23 @@ var ts; } } // Write the comment line text - writeTrimmedCurrentLine(text, comment, writer, newLine, pos, nextLineStart); + writeTrimmedCurrentLine(text, commentEnd, writer, newLine, pos, nextLineStart); pos = nextLineStart; } } else { // Single line comment of style //.... - writer.write(text.substring(comment.pos, comment.end)); + writer.write(text.substring(commentPos, commentEnd)); } } ts.writeCommentRange = writeCommentRange; - function writeTrimmedCurrentLine(text, comment, writer, newLine, pos, nextLineStart) { - var end = Math.min(comment.end, nextLineStart - 1); + function writeTrimmedCurrentLine(text, commentEnd, writer, newLine, pos, nextLineStart) { + var end = Math.min(commentEnd, nextLineStart - 1); var currentLineText = text.substring(pos, end).replace(/^\s+|\s+$/g, ""); if (currentLineText) { // trimmed forward and ending spaces text writer.write(currentLineText); - if (end !== comment.end) { + if (end !== commentEnd) { writer.writeLine(); } } @@ -5354,6 +6265,32 @@ var ts; } return currentLineIndent; } + function hasModifiers(node) { + return getModifierFlags(node) !== 0 /* None */; + } + ts.hasModifiers = hasModifiers; + function hasModifier(node, flags) { + return (getModifierFlags(node) & flags) !== 0; + } + ts.hasModifier = hasModifier; + function getModifierFlags(node) { + if (node.modifierFlagsCache & 536870912 /* HasComputedFlags */) { + return node.modifierFlagsCache & ~536870912 /* HasComputedFlags */; + } + var flags = 0 /* None */; + if (node.modifiers) { + for (var _i = 0, _a = node.modifiers; _i < _a.length; _i++) { + var modifier = _a[_i]; + flags |= modifierToFlag(modifier.kind); + } + } + if (node.flags & 4 /* NestedNamespace */) { + flags |= 1 /* Export */; + } + node.modifierFlagsCache = flags | 536870912 /* HasComputedFlags */; + return flags; + } + ts.getModifierFlags = getModifierFlags; function modifierToFlag(token) { switch (token) { case 113 /* StaticKeyword */: return 32 /* Static */; @@ -5368,42 +6305,15 @@ var ts; case 118 /* AsyncKeyword */: return 256 /* Async */; case 128 /* ReadonlyKeyword */: return 64 /* Readonly */; } - return 0; + return 0 /* None */; } ts.modifierToFlag = modifierToFlag; - function isLeftHandSideExpression(expr) { - if (expr) { - switch (expr.kind) { - case 172 /* PropertyAccessExpression */: - case 173 /* ElementAccessExpression */: - case 175 /* NewExpression */: - case 174 /* CallExpression */: - case 196 /* NonNullExpression */: - case 241 /* JsxElement */: - case 242 /* JsxSelfClosingElement */: - case 176 /* TaggedTemplateExpression */: - case 170 /* ArrayLiteralExpression */: - case 178 /* ParenthesizedExpression */: - case 171 /* ObjectLiteralExpression */: - case 192 /* ClassExpression */: - case 179 /* FunctionExpression */: - case 69 /* Identifier */: - case 10 /* RegularExpressionLiteral */: - case 8 /* NumericLiteral */: - case 9 /* StringLiteral */: - case 11 /* NoSubstitutionTemplateLiteral */: - case 189 /* TemplateExpression */: - case 84 /* FalseKeyword */: - case 93 /* NullKeyword */: - case 97 /* ThisKeyword */: - case 99 /* TrueKeyword */: - case 95 /* SuperKeyword */: - return true; - } - } - return false; + function isLogicalOperator(token) { + return token === 52 /* BarBarToken */ + || token === 51 /* AmpersandAmpersandToken */ + || token === 49 /* ExclamationToken */; } - ts.isLeftHandSideExpression = isLeftHandSideExpression; + ts.isLogicalOperator = isLogicalOperator; function isAssignmentOperator(token) { return token >= 56 /* FirstAssignment */ && token <= 68 /* LastAssignment */; } @@ -5417,6 +6327,34 @@ var ts; } } ts.tryGetClassExtendingExpressionWithTypeArguments = tryGetClassExtendingExpressionWithTypeArguments; + function isDestructuringAssignment(node) { + if (isBinaryExpression(node)) { + if (node.operatorToken.kind === 56 /* EqualsToken */) { + var kind = node.left.kind; + return kind === 171 /* ObjectLiteralExpression */ + || kind === 170 /* ArrayLiteralExpression */; + } + } + return false; + } + ts.isDestructuringAssignment = isDestructuringAssignment; + // Returns false if this heritage clause element's expression contains something unsupported + // (i.e. not a name or dotted name). + function isSupportedExpressionWithTypeArguments(node) { + return isSupportedExpressionWithTypeArgumentsRest(node.expression); + } + ts.isSupportedExpressionWithTypeArguments = isSupportedExpressionWithTypeArguments; + function isSupportedExpressionWithTypeArgumentsRest(node) { + if (node.kind === 69 /* Identifier */) { + return true; + } + else if (isPropertyAccessExpression(node)) { + return isSupportedExpressionWithTypeArgumentsRest(node.expression); + } + else { + return false; + } + } function isExpressionWithTypeArgumentsInClassExtendsClause(node) { return tryGetClassExtendingExpressionWithTypeArguments(node) !== undefined; } @@ -5443,17 +6381,9 @@ var ts; } ts.isEmptyObjectLiteralOrArrayLiteral = isEmptyObjectLiteralOrArrayLiteral; function getLocalSymbolForExportDefault(symbol) { - return symbol && symbol.valueDeclaration && (symbol.valueDeclaration.flags & 512 /* Default */) ? symbol.valueDeclaration.localSymbol : undefined; + return symbol && symbol.valueDeclaration && hasModifier(symbol.valueDeclaration, 512 /* Default */) ? symbol.valueDeclaration.localSymbol : undefined; } ts.getLocalSymbolForExportDefault = getLocalSymbolForExportDefault; - function hasJavaScriptFileExtension(fileName) { - return ts.forEach(ts.supportedJavascriptExtensions, function (extension) { return ts.fileExtensionIs(fileName, extension); }); - } - ts.hasJavaScriptFileExtension = hasJavaScriptFileExtension; - function hasTypeScriptFileExtension(fileName) { - return ts.forEach(ts.supportedTypeScriptExtensions, function (extension) { return ts.fileExtensionIs(fileName, extension); }); - } - ts.hasTypeScriptFileExtension = hasTypeScriptFileExtension; /** Return ".ts", ".d.ts", or ".tsx", if that is the extension. */ function tryExtractTypeScriptExtension(fileName) { return ts.find(ts.supportedTypescriptExtensionsForExtractExtension, function (extension) { return ts.fileExtensionIs(fileName, extension); }); @@ -5566,12 +6496,6 @@ var ts; return result; } ts.convertToBase64 = convertToBase64; - function convertToRelativePath(absoluteOrRelativePath, basePath, getCanonicalFileName) { - return !ts.isRootedDiskPath(absoluteOrRelativePath) - ? absoluteOrRelativePath - : ts.getRelativePathToDirectoryOrUrl(basePath, absoluteOrRelativePath, basePath, getCanonicalFileName, /* isAbsolutePathAnUrl */ false); - } - ts.convertToRelativePath = convertToRelativePath; var carriageReturnLineFeed = "\r\n"; var lineFeed = "\n"; function getNewLineCharacter(options) { @@ -5587,6 +6511,847 @@ var ts; return carriageReturnLineFeed; } ts.getNewLineCharacter = getNewLineCharacter; + /** + * Tests whether a node and its subtree is simple enough to have its position + * information ignored when emitting source maps in a destructuring assignment. + * + * @param node The expression to test. + */ + function isSimpleExpression(node) { + return isSimpleExpressionWorker(node, 0); + } + ts.isSimpleExpression = isSimpleExpression; + function isSimpleExpressionWorker(node, depth) { + if (depth <= 5) { + var kind = node.kind; + if (kind === 9 /* StringLiteral */ + || kind === 8 /* NumericLiteral */ + || kind === 10 /* RegularExpressionLiteral */ + || kind === 11 /* NoSubstitutionTemplateLiteral */ + || kind === 69 /* Identifier */ + || kind === 97 /* ThisKeyword */ + || kind === 95 /* SuperKeyword */ + || kind === 99 /* TrueKeyword */ + || kind === 84 /* FalseKeyword */ + || kind === 93 /* NullKeyword */) { + return true; + } + else if (kind === 172 /* PropertyAccessExpression */) { + return isSimpleExpressionWorker(node.expression, depth + 1); + } + else if (kind === 173 /* ElementAccessExpression */) { + return isSimpleExpressionWorker(node.expression, depth + 1) + && isSimpleExpressionWorker(node.argumentExpression, depth + 1); + } + else if (kind === 185 /* PrefixUnaryExpression */ + || kind === 186 /* PostfixUnaryExpression */) { + return isSimpleExpressionWorker(node.operand, depth + 1); + } + else if (kind === 187 /* BinaryExpression */) { + return node.operatorToken.kind !== 38 /* AsteriskAsteriskToken */ + && isSimpleExpressionWorker(node.left, depth + 1) + && isSimpleExpressionWorker(node.right, depth + 1); + } + else if (kind === 188 /* ConditionalExpression */) { + return isSimpleExpressionWorker(node.condition, depth + 1) + && isSimpleExpressionWorker(node.whenTrue, depth + 1) + && isSimpleExpressionWorker(node.whenFalse, depth + 1); + } + else if (kind === 183 /* VoidExpression */ + || kind === 182 /* TypeOfExpression */ + || kind === 181 /* DeleteExpression */) { + return isSimpleExpressionWorker(node.expression, depth + 1); + } + else if (kind === 170 /* ArrayLiteralExpression */) { + return node.elements.length === 0; + } + else if (kind === 171 /* ObjectLiteralExpression */) { + return node.properties.length === 0; + } + else if (kind === 174 /* CallExpression */) { + if (!isSimpleExpressionWorker(node.expression, depth + 1)) { + return false; + } + for (var _i = 0, _a = node.arguments; _i < _a.length; _i++) { + var argument = _a[_i]; + if (!isSimpleExpressionWorker(argument, depth + 1)) { + return false; + } + } + return true; + } + } + return false; + } + var syntaxKindCache = ts.createMap(); + function formatSyntaxKind(kind) { + var syntaxKindEnum = ts.SyntaxKind; + if (syntaxKindEnum) { + if (syntaxKindCache[kind]) { + return syntaxKindCache[kind]; + } + for (var name_6 in syntaxKindEnum) { + if (syntaxKindEnum[name_6] === kind) { + return syntaxKindCache[kind] = kind.toString() + " (" + name_6 + ")"; + } + } + } + else { + return kind.toString(); + } + } + ts.formatSyntaxKind = formatSyntaxKind; + /** + * Increases (or decreases) a position by the provided amount. + * + * @param pos The position. + * @param value The delta. + */ + function movePos(pos, value) { + return ts.positionIsSynthesized(pos) ? -1 : pos + value; + } + ts.movePos = movePos; + /** + * Creates a new TextRange from the provided pos and end. + * + * @param pos The start position. + * @param end The end position. + */ + function createRange(pos, end) { + return { pos: pos, end: end }; + } + ts.createRange = createRange; + /** + * Creates a new TextRange from a provided range with a new end position. + * + * @param range A TextRange. + * @param end The new end position. + */ + function moveRangeEnd(range, end) { + return createRange(range.pos, end); + } + ts.moveRangeEnd = moveRangeEnd; + /** + * Creates a new TextRange from a provided range with a new start position. + * + * @param range A TextRange. + * @param pos The new Start position. + */ + function moveRangePos(range, pos) { + return createRange(pos, range.end); + } + ts.moveRangePos = moveRangePos; + /** + * Moves the start position of a range past any decorators. + */ + function moveRangePastDecorators(node) { + return node.decorators && node.decorators.length > 0 + ? moveRangePos(node, node.decorators.end) + : node; + } + ts.moveRangePastDecorators = moveRangePastDecorators; + /** + * Moves the start position of a range past any decorators or modifiers. + */ + function moveRangePastModifiers(node) { + return node.modifiers && node.modifiers.length > 0 + ? moveRangePos(node, node.modifiers.end) + : moveRangePastDecorators(node); + } + ts.moveRangePastModifiers = moveRangePastModifiers; + /** + * Determines whether a TextRange has the same start and end positions. + * + * @param range A TextRange. + */ + function isCollapsedRange(range) { + return range.pos === range.end; + } + ts.isCollapsedRange = isCollapsedRange; + /** + * Creates a new TextRange from a provided range with its end position collapsed to its + * start position. + * + * @param range A TextRange. + */ + function collapseRangeToStart(range) { + return isCollapsedRange(range) ? range : moveRangeEnd(range, range.pos); + } + ts.collapseRangeToStart = collapseRangeToStart; + /** + * Creates a new TextRange from a provided range with its start position collapsed to its + * end position. + * + * @param range A TextRange. + */ + function collapseRangeToEnd(range) { + return isCollapsedRange(range) ? range : moveRangePos(range, range.end); + } + ts.collapseRangeToEnd = collapseRangeToEnd; + /** + * Creates a new TextRange for a token at the provides start position. + * + * @param pos The start position. + * @param token The token. + */ + function createTokenRange(pos, token) { + return createRange(pos, pos + ts.tokenToString(token).length); + } + ts.createTokenRange = createTokenRange; + function rangeIsOnSingleLine(range, sourceFile) { + return rangeStartIsOnSameLineAsRangeEnd(range, range, sourceFile); + } + ts.rangeIsOnSingleLine = rangeIsOnSingleLine; + function rangeStartPositionsAreOnSameLine(range1, range2, sourceFile) { + return positionsAreOnSameLine(getStartPositionOfRange(range1, sourceFile), getStartPositionOfRange(range2, sourceFile), sourceFile); + } + ts.rangeStartPositionsAreOnSameLine = rangeStartPositionsAreOnSameLine; + function rangeEndPositionsAreOnSameLine(range1, range2, sourceFile) { + return positionsAreOnSameLine(range1.end, range2.end, sourceFile); + } + ts.rangeEndPositionsAreOnSameLine = rangeEndPositionsAreOnSameLine; + function rangeStartIsOnSameLineAsRangeEnd(range1, range2, sourceFile) { + return positionsAreOnSameLine(getStartPositionOfRange(range1, sourceFile), range2.end, sourceFile); + } + ts.rangeStartIsOnSameLineAsRangeEnd = rangeStartIsOnSameLineAsRangeEnd; + function rangeEndIsOnSameLineAsRangeStart(range1, range2, sourceFile) { + return positionsAreOnSameLine(range1.end, getStartPositionOfRange(range2, sourceFile), sourceFile); + } + ts.rangeEndIsOnSameLineAsRangeStart = rangeEndIsOnSameLineAsRangeStart; + function positionsAreOnSameLine(pos1, pos2, sourceFile) { + return pos1 === pos2 || + getLineOfLocalPosition(sourceFile, pos1) === getLineOfLocalPosition(sourceFile, pos2); + } + ts.positionsAreOnSameLine = positionsAreOnSameLine; + function getStartPositionOfRange(range, sourceFile) { + return ts.positionIsSynthesized(range.pos) ? -1 : ts.skipTrivia(sourceFile.text, range.pos); + } + ts.getStartPositionOfRange = getStartPositionOfRange; + function collectExternalModuleInfo(sourceFile, resolver) { + var externalImports = []; + var exportSpecifiers = ts.createMap(); + var exportEquals = undefined; + var hasExportStarsToExportValues = false; + for (var _i = 0, _a = sourceFile.statements; _i < _a.length; _i++) { + var node = _a[_i]; + switch (node.kind) { + case 230 /* ImportDeclaration */: + if (!node.importClause || + resolver.isReferencedAliasDeclaration(node.importClause, /*checkChildren*/ true)) { + // import "mod" + // import x from "mod" where x is referenced + // import * as x from "mod" where x is referenced + // import { x, y } from "mod" where at least one import is referenced + externalImports.push(node); + } + break; + case 229 /* ImportEqualsDeclaration */: + if (node.moduleReference.kind === 240 /* ExternalModuleReference */ && resolver.isReferencedAliasDeclaration(node)) { + // import x = require("mod") where x is referenced + externalImports.push(node); + } + break; + case 236 /* ExportDeclaration */: + if (node.moduleSpecifier) { + if (!node.exportClause) { + // export * from "mod" + if (resolver.moduleExportsSomeValue(node.moduleSpecifier)) { + externalImports.push(node); + hasExportStarsToExportValues = true; + } + } + else if (resolver.isValueAliasDeclaration(node)) { + // export { x, y } from "mod" where at least one export is a value symbol + externalImports.push(node); + } + } + else { + // export { x, y } + for (var _b = 0, _c = node.exportClause.elements; _b < _c.length; _b++) { + var specifier = _c[_b]; + var name_7 = (specifier.propertyName || specifier.name).text; + (exportSpecifiers[name_7] || (exportSpecifiers[name_7] = [])).push(specifier); + } + } + break; + case 235 /* ExportAssignment */: + if (node.isExportEquals && !exportEquals) { + // export = x + exportEquals = node; + } + break; + } + } + return { externalImports: externalImports, exportSpecifiers: exportSpecifiers, exportEquals: exportEquals, hasExportStarsToExportValues: hasExportStarsToExportValues }; + } + ts.collectExternalModuleInfo = collectExternalModuleInfo; + function getInitializedVariables(node) { + return ts.filter(node.declarations, isInitializedVariable); + } + ts.getInitializedVariables = getInitializedVariables; + function isInitializedVariable(node) { + return node.initializer !== undefined; + } + /** + * Gets a value indicating whether a node is merged with a class declaration in the same scope. + */ + function isMergedWithClass(node) { + if (node.symbol) { + for (var _i = 0, _a = node.symbol.declarations; _i < _a.length; _i++) { + var declaration = _a[_i]; + if (declaration.kind === 221 /* ClassDeclaration */ && declaration !== node) { + return true; + } + } + } + return false; + } + ts.isMergedWithClass = isMergedWithClass; + /** + * Gets a value indicating whether a node is the first declaration of its kind. + * + * @param node A Declaration node. + * @param kind The SyntaxKind to find among related declarations. + */ + function isFirstDeclarationOfKind(node, kind) { + return node.symbol && getDeclarationOfKind(node.symbol, kind) === node; + } + ts.isFirstDeclarationOfKind = isFirstDeclarationOfKind; + // Node tests + // + // All node tests in the following list should *not* reference parent pointers so that + // they may be used with transformations. + // Node Arrays + function isNodeArray(array) { + return array.hasOwnProperty("pos") + && array.hasOwnProperty("end"); + } + ts.isNodeArray = isNodeArray; + // Literals + function isNoSubstitutionTemplateLiteral(node) { + return node.kind === 11 /* NoSubstitutionTemplateLiteral */; + } + ts.isNoSubstitutionTemplateLiteral = isNoSubstitutionTemplateLiteral; + function isLiteralKind(kind) { + return 8 /* FirstLiteralToken */ <= kind && kind <= 11 /* LastLiteralToken */; + } + ts.isLiteralKind = isLiteralKind; + function isTextualLiteralKind(kind) { + return kind === 9 /* StringLiteral */ || kind === 11 /* NoSubstitutionTemplateLiteral */; + } + ts.isTextualLiteralKind = isTextualLiteralKind; + function isLiteralExpression(node) { + return isLiteralKind(node.kind); + } + ts.isLiteralExpression = isLiteralExpression; + // Pseudo-literals + function isTemplateLiteralKind(kind) { + return 11 /* FirstTemplateToken */ <= kind && kind <= 14 /* LastTemplateToken */; + } + ts.isTemplateLiteralKind = isTemplateLiteralKind; + function isTemplateLiteralFragmentKind(kind) { + return kind === 12 /* TemplateHead */ + || kind === 13 /* TemplateMiddle */ + || kind === 14 /* TemplateTail */; + } + function isTemplateLiteralFragment(node) { + return isTemplateLiteralFragmentKind(node.kind); + } + ts.isTemplateLiteralFragment = isTemplateLiteralFragment; + // Identifiers + function isIdentifier(node) { + return node.kind === 69 /* Identifier */; + } + ts.isIdentifier = isIdentifier; + function isGeneratedIdentifier(node) { + // Using `>` here catches both `GeneratedIdentifierKind.None` and `undefined`. + return isIdentifier(node) && node.autoGenerateKind > 0 /* None */; + } + ts.isGeneratedIdentifier = isGeneratedIdentifier; + // Keywords + function isModifier(node) { + return isModifierKind(node.kind); + } + ts.isModifier = isModifier; + // Names + function isQualifiedName(node) { + return node.kind === 139 /* QualifiedName */; + } + ts.isQualifiedName = isQualifiedName; + function isComputedPropertyName(node) { + return node.kind === 140 /* ComputedPropertyName */; + } + ts.isComputedPropertyName = isComputedPropertyName; + function isEntityName(node) { + var kind = node.kind; + return kind === 139 /* QualifiedName */ + || kind === 69 /* Identifier */; + } + ts.isEntityName = isEntityName; + function isPropertyName(node) { + var kind = node.kind; + return kind === 69 /* Identifier */ + || kind === 9 /* StringLiteral */ + || kind === 8 /* NumericLiteral */ + || kind === 140 /* ComputedPropertyName */; + } + ts.isPropertyName = isPropertyName; + function isModuleName(node) { + var kind = node.kind; + return kind === 69 /* Identifier */ + || kind === 9 /* StringLiteral */; + } + ts.isModuleName = isModuleName; + function isBindingName(node) { + var kind = node.kind; + return kind === 69 /* Identifier */ + || kind === 167 /* ObjectBindingPattern */ + || kind === 168 /* ArrayBindingPattern */; + } + ts.isBindingName = isBindingName; + // Signature elements + function isTypeParameter(node) { + return node.kind === 141 /* TypeParameter */; + } + ts.isTypeParameter = isTypeParameter; + function isParameter(node) { + return node.kind === 142 /* Parameter */; + } + ts.isParameter = isParameter; + function isDecorator(node) { + return node.kind === 143 /* Decorator */; + } + ts.isDecorator = isDecorator; + // Type members + function isMethodDeclaration(node) { + return node.kind === 147 /* MethodDeclaration */; + } + ts.isMethodDeclaration = isMethodDeclaration; + function isClassElement(node) { + var kind = node.kind; + return kind === 148 /* Constructor */ + || kind === 145 /* PropertyDeclaration */ + || kind === 147 /* MethodDeclaration */ + || kind === 149 /* GetAccessor */ + || kind === 150 /* SetAccessor */ + || kind === 153 /* IndexSignature */ + || kind === 198 /* SemicolonClassElement */; + } + ts.isClassElement = isClassElement; + function isObjectLiteralElementLike(node) { + var kind = node.kind; + return kind === 253 /* PropertyAssignment */ + || kind === 254 /* ShorthandPropertyAssignment */ + || kind === 147 /* MethodDeclaration */ + || kind === 149 /* GetAccessor */ + || kind === 150 /* SetAccessor */ + || kind === 239 /* MissingDeclaration */; + } + ts.isObjectLiteralElementLike = isObjectLiteralElementLike; + // Type + function isTypeNodeKind(kind) { + return (kind >= 154 /* FirstTypeNode */ && kind <= 166 /* LastTypeNode */) + || kind === 117 /* AnyKeyword */ + || kind === 130 /* NumberKeyword */ + || kind === 120 /* BooleanKeyword */ + || kind === 132 /* StringKeyword */ + || kind === 133 /* SymbolKeyword */ + || kind === 103 /* VoidKeyword */ + || kind === 127 /* NeverKeyword */ + || kind === 194 /* ExpressionWithTypeArguments */; + } + /** + * Node test that determines whether a node is a valid type node. + * This differs from the `isPartOfTypeNode` function which determines whether a node is *part* + * of a TypeNode. + */ + function isTypeNode(node) { + return isTypeNodeKind(node.kind); + } + ts.isTypeNode = isTypeNode; + // Binding patterns + function isBindingPattern(node) { + if (node) { + var kind = node.kind; + return kind === 168 /* ArrayBindingPattern */ + || kind === 167 /* ObjectBindingPattern */; + } + return false; + } + ts.isBindingPattern = isBindingPattern; + function isBindingElement(node) { + return node.kind === 169 /* BindingElement */; + } + ts.isBindingElement = isBindingElement; + function isArrayBindingElement(node) { + var kind = node.kind; + return kind === 169 /* BindingElement */ + || kind === 193 /* OmittedExpression */; + } + ts.isArrayBindingElement = isArrayBindingElement; + // Expression + function isPropertyAccessExpression(node) { + return node.kind === 172 /* PropertyAccessExpression */; + } + ts.isPropertyAccessExpression = isPropertyAccessExpression; + function isElementAccessExpression(node) { + return node.kind === 173 /* ElementAccessExpression */; + } + ts.isElementAccessExpression = isElementAccessExpression; + function isBinaryExpression(node) { + return node.kind === 187 /* BinaryExpression */; + } + ts.isBinaryExpression = isBinaryExpression; + function isConditionalExpression(node) { + return node.kind === 188 /* ConditionalExpression */; + } + ts.isConditionalExpression = isConditionalExpression; + function isCallExpression(node) { + return node.kind === 174 /* CallExpression */; + } + ts.isCallExpression = isCallExpression; + function isTemplate(node) { + var kind = node.kind; + return kind === 189 /* TemplateExpression */ + || kind === 11 /* NoSubstitutionTemplateLiteral */; + } + ts.isTemplate = isTemplate; + function isSpreadElementExpression(node) { + return node.kind === 191 /* SpreadElementExpression */; + } + ts.isSpreadElementExpression = isSpreadElementExpression; + function isExpressionWithTypeArguments(node) { + return node.kind === 194 /* ExpressionWithTypeArguments */; + } + ts.isExpressionWithTypeArguments = isExpressionWithTypeArguments; + function isLeftHandSideExpressionKind(kind) { + return kind === 172 /* PropertyAccessExpression */ + || kind === 173 /* ElementAccessExpression */ + || kind === 175 /* NewExpression */ + || kind === 174 /* CallExpression */ + || kind === 241 /* JsxElement */ + || kind === 242 /* JsxSelfClosingElement */ + || kind === 176 /* TaggedTemplateExpression */ + || kind === 170 /* ArrayLiteralExpression */ + || kind === 178 /* ParenthesizedExpression */ + || kind === 171 /* ObjectLiteralExpression */ + || kind === 192 /* ClassExpression */ + || kind === 179 /* FunctionExpression */ + || kind === 69 /* Identifier */ + || kind === 10 /* RegularExpressionLiteral */ + || kind === 8 /* NumericLiteral */ + || kind === 9 /* StringLiteral */ + || kind === 11 /* NoSubstitutionTemplateLiteral */ + || kind === 189 /* TemplateExpression */ + || kind === 84 /* FalseKeyword */ + || kind === 93 /* NullKeyword */ + || kind === 97 /* ThisKeyword */ + || kind === 99 /* TrueKeyword */ + || kind === 95 /* SuperKeyword */ + || kind === 196 /* NonNullExpression */; + } + function isLeftHandSideExpression(node) { + return isLeftHandSideExpressionKind(ts.skipPartiallyEmittedExpressions(node).kind); + } + ts.isLeftHandSideExpression = isLeftHandSideExpression; + function isUnaryExpressionKind(kind) { + return kind === 185 /* PrefixUnaryExpression */ + || kind === 186 /* PostfixUnaryExpression */ + || kind === 181 /* DeleteExpression */ + || kind === 182 /* TypeOfExpression */ + || kind === 183 /* VoidExpression */ + || kind === 184 /* AwaitExpression */ + || kind === 177 /* TypeAssertionExpression */ + || isLeftHandSideExpressionKind(kind); + } + function isUnaryExpression(node) { + return isUnaryExpressionKind(ts.skipPartiallyEmittedExpressions(node).kind); + } + ts.isUnaryExpression = isUnaryExpression; + function isExpressionKind(kind) { + return kind === 188 /* ConditionalExpression */ + || kind === 190 /* YieldExpression */ + || kind === 180 /* ArrowFunction */ + || kind === 187 /* BinaryExpression */ + || kind === 191 /* SpreadElementExpression */ + || kind === 195 /* AsExpression */ + || kind === 193 /* OmittedExpression */ + || isUnaryExpressionKind(kind); + } + function isExpression(node) { + return isExpressionKind(ts.skipPartiallyEmittedExpressions(node).kind); + } + ts.isExpression = isExpression; + function isAssertionExpression(node) { + var kind = node.kind; + return kind === 177 /* TypeAssertionExpression */ + || kind === 195 /* AsExpression */; + } + ts.isAssertionExpression = isAssertionExpression; + function isPartiallyEmittedExpression(node) { + return node.kind === 288 /* PartiallyEmittedExpression */; + } + ts.isPartiallyEmittedExpression = isPartiallyEmittedExpression; + function isNotEmittedStatement(node) { + return node.kind === 287 /* NotEmittedStatement */; + } + ts.isNotEmittedStatement = isNotEmittedStatement; + function isNotEmittedOrPartiallyEmittedNode(node) { + return isNotEmittedStatement(node) + || isPartiallyEmittedExpression(node); + } + ts.isNotEmittedOrPartiallyEmittedNode = isNotEmittedOrPartiallyEmittedNode; + function isOmittedExpression(node) { + return node.kind === 193 /* OmittedExpression */; + } + ts.isOmittedExpression = isOmittedExpression; + // Misc + function isTemplateSpan(node) { + return node.kind === 197 /* TemplateSpan */; + } + ts.isTemplateSpan = isTemplateSpan; + // Element + function isBlock(node) { + return node.kind === 199 /* Block */; + } + ts.isBlock = isBlock; + function isConciseBody(node) { + return isBlock(node) + || isExpression(node); + } + ts.isConciseBody = isConciseBody; + function isFunctionBody(node) { + return isBlock(node); + } + ts.isFunctionBody = isFunctionBody; + function isForInitializer(node) { + return isVariableDeclarationList(node) + || isExpression(node); + } + ts.isForInitializer = isForInitializer; + function isVariableDeclaration(node) { + return node.kind === 218 /* VariableDeclaration */; + } + ts.isVariableDeclaration = isVariableDeclaration; + function isVariableDeclarationList(node) { + return node.kind === 219 /* VariableDeclarationList */; + } + ts.isVariableDeclarationList = isVariableDeclarationList; + function isCaseBlock(node) { + return node.kind === 227 /* CaseBlock */; + } + ts.isCaseBlock = isCaseBlock; + function isModuleBody(node) { + var kind = node.kind; + return kind === 226 /* ModuleBlock */ + || kind === 225 /* ModuleDeclaration */; + } + ts.isModuleBody = isModuleBody; + function isImportEqualsDeclaration(node) { + return node.kind === 229 /* ImportEqualsDeclaration */; + } + ts.isImportEqualsDeclaration = isImportEqualsDeclaration; + function isImportClause(node) { + return node.kind === 231 /* ImportClause */; + } + ts.isImportClause = isImportClause; + function isNamedImportBindings(node) { + var kind = node.kind; + return kind === 233 /* NamedImports */ + || kind === 232 /* NamespaceImport */; + } + ts.isNamedImportBindings = isNamedImportBindings; + function isImportSpecifier(node) { + return node.kind === 234 /* ImportSpecifier */; + } + ts.isImportSpecifier = isImportSpecifier; + function isNamedExports(node) { + return node.kind === 237 /* NamedExports */; + } + ts.isNamedExports = isNamedExports; + function isExportSpecifier(node) { + return node.kind === 238 /* ExportSpecifier */; + } + ts.isExportSpecifier = isExportSpecifier; + function isModuleOrEnumDeclaration(node) { + return node.kind === 225 /* ModuleDeclaration */ || node.kind === 224 /* EnumDeclaration */; + } + ts.isModuleOrEnumDeclaration = isModuleOrEnumDeclaration; + function isDeclarationKind(kind) { + return kind === 180 /* ArrowFunction */ + || kind === 169 /* BindingElement */ + || kind === 221 /* ClassDeclaration */ + || kind === 192 /* ClassExpression */ + || kind === 148 /* Constructor */ + || kind === 224 /* EnumDeclaration */ + || kind === 255 /* EnumMember */ + || kind === 238 /* ExportSpecifier */ + || kind === 220 /* FunctionDeclaration */ + || kind === 179 /* FunctionExpression */ + || kind === 149 /* GetAccessor */ + || kind === 231 /* ImportClause */ + || kind === 229 /* ImportEqualsDeclaration */ + || kind === 234 /* ImportSpecifier */ + || kind === 222 /* InterfaceDeclaration */ + || kind === 147 /* MethodDeclaration */ + || kind === 146 /* MethodSignature */ + || kind === 225 /* ModuleDeclaration */ + || kind === 228 /* NamespaceExportDeclaration */ + || kind === 232 /* NamespaceImport */ + || kind === 142 /* Parameter */ + || kind === 253 /* PropertyAssignment */ + || kind === 145 /* PropertyDeclaration */ + || kind === 144 /* PropertySignature */ + || kind === 150 /* SetAccessor */ + || kind === 254 /* ShorthandPropertyAssignment */ + || kind === 223 /* TypeAliasDeclaration */ + || kind === 141 /* TypeParameter */ + || kind === 218 /* VariableDeclaration */ + || kind === 279 /* JSDocTypedefTag */; + } + function isDeclarationStatementKind(kind) { + return kind === 220 /* FunctionDeclaration */ + || kind === 239 /* MissingDeclaration */ + || kind === 221 /* ClassDeclaration */ + || kind === 222 /* InterfaceDeclaration */ + || kind === 223 /* TypeAliasDeclaration */ + || kind === 224 /* EnumDeclaration */ + || kind === 225 /* ModuleDeclaration */ + || kind === 230 /* ImportDeclaration */ + || kind === 229 /* ImportEqualsDeclaration */ + || kind === 236 /* ExportDeclaration */ + || kind === 235 /* ExportAssignment */ + || kind === 228 /* NamespaceExportDeclaration */; + } + function isStatementKindButNotDeclarationKind(kind) { + return kind === 210 /* BreakStatement */ + || kind === 209 /* ContinueStatement */ + || kind === 217 /* DebuggerStatement */ + || kind === 204 /* DoStatement */ + || kind === 202 /* ExpressionStatement */ + || kind === 201 /* EmptyStatement */ + || kind === 207 /* ForInStatement */ + || kind === 208 /* ForOfStatement */ + || kind === 206 /* ForStatement */ + || kind === 203 /* IfStatement */ + || kind === 214 /* LabeledStatement */ + || kind === 211 /* ReturnStatement */ + || kind === 213 /* SwitchStatement */ + || kind === 215 /* ThrowStatement */ + || kind === 216 /* TryStatement */ + || kind === 200 /* VariableStatement */ + || kind === 205 /* WhileStatement */ + || kind === 212 /* WithStatement */ + || kind === 287 /* NotEmittedStatement */; + } + function isDeclaration(node) { + return isDeclarationKind(node.kind); + } + ts.isDeclaration = isDeclaration; + function isDeclarationStatement(node) { + return isDeclarationStatementKind(node.kind); + } + ts.isDeclarationStatement = isDeclarationStatement; + /** + * Determines whether the node is a statement that is not also a declaration + */ + function isStatementButNotDeclaration(node) { + return isStatementKindButNotDeclarationKind(node.kind); + } + ts.isStatementButNotDeclaration = isStatementButNotDeclaration; + function isStatement(node) { + var kind = node.kind; + return isStatementKindButNotDeclarationKind(kind) + || isDeclarationStatementKind(kind) + || kind === 199 /* Block */; + } + ts.isStatement = isStatement; + // Module references + function isModuleReference(node) { + var kind = node.kind; + return kind === 240 /* ExternalModuleReference */ + || kind === 139 /* QualifiedName */ + || kind === 69 /* Identifier */; + } + ts.isModuleReference = isModuleReference; + // JSX + function isJsxOpeningElement(node) { + return node.kind === 243 /* JsxOpeningElement */; + } + ts.isJsxOpeningElement = isJsxOpeningElement; + function isJsxClosingElement(node) { + return node.kind === 245 /* JsxClosingElement */; + } + ts.isJsxClosingElement = isJsxClosingElement; + function isJsxTagNameExpression(node) { + var kind = node.kind; + return kind === 97 /* ThisKeyword */ + || kind === 69 /* Identifier */ + || kind === 172 /* PropertyAccessExpression */; + } + ts.isJsxTagNameExpression = isJsxTagNameExpression; + function isJsxChild(node) { + var kind = node.kind; + return kind === 241 /* JsxElement */ + || kind === 248 /* JsxExpression */ + || kind === 242 /* JsxSelfClosingElement */ + || kind === 244 /* JsxText */; + } + ts.isJsxChild = isJsxChild; + function isJsxAttributeLike(node) { + var kind = node.kind; + return kind === 246 /* JsxAttribute */ + || kind === 247 /* JsxSpreadAttribute */; + } + ts.isJsxAttributeLike = isJsxAttributeLike; + function isJsxSpreadAttribute(node) { + return node.kind === 247 /* JsxSpreadAttribute */; + } + ts.isJsxSpreadAttribute = isJsxSpreadAttribute; + function isJsxAttribute(node) { + return node.kind === 246 /* JsxAttribute */; + } + ts.isJsxAttribute = isJsxAttribute; + function isStringLiteralOrJsxExpression(node) { + var kind = node.kind; + return kind === 9 /* StringLiteral */ + || kind === 248 /* JsxExpression */; + } + ts.isStringLiteralOrJsxExpression = isStringLiteralOrJsxExpression; + // Clauses + function isCaseOrDefaultClause(node) { + var kind = node.kind; + return kind === 249 /* CaseClause */ + || kind === 250 /* DefaultClause */; + } + ts.isCaseOrDefaultClause = isCaseOrDefaultClause; + function isHeritageClause(node) { + return node.kind === 251 /* HeritageClause */; + } + ts.isHeritageClause = isHeritageClause; + function isCatchClause(node) { + return node.kind === 252 /* CatchClause */; + } + ts.isCatchClause = isCatchClause; + // Property assignments + function isPropertyAssignment(node) { + return node.kind === 253 /* PropertyAssignment */; + } + ts.isPropertyAssignment = isPropertyAssignment; + function isShorthandPropertyAssignment(node) { + return node.kind === 254 /* ShorthandPropertyAssignment */; + } + ts.isShorthandPropertyAssignment = isShorthandPropertyAssignment; + // Enum + function isEnumMember(node) { + return node.kind === 255 /* EnumMember */; + } + ts.isEnumMember = isEnumMember; + // Top-level nodes + function isSourceFile(node) { + return node.kind === 256 /* SourceFile */; + } + ts.isSourceFile = isSourceFile; function isWatchSet(options) { // Firefox has Object.prototype.watch return options.watch && options.hasOwnProperty("watch"); @@ -5815,9 +7580,54 @@ var ts; } ts.getTypeParameterOwner = getTypeParameterOwner; function isParameterPropertyDeclaration(node) { - return node.flags & 92 /* ParameterPropertyModifier */ && node.parent.kind === 148 /* Constructor */ && ts.isClassLike(node.parent.parent); + return ts.hasModifier(node, 92 /* ParameterPropertyModifier */) && node.parent.kind === 148 /* Constructor */ && ts.isClassLike(node.parent.parent); } ts.isParameterPropertyDeclaration = isParameterPropertyDeclaration; + function walkUpBindingElementsAndPatterns(node) { + while (node && (node.kind === 169 /* BindingElement */ || ts.isBindingPattern(node))) { + node = node.parent; + } + return node; + } + function getCombinedModifierFlags(node) { + node = walkUpBindingElementsAndPatterns(node); + var flags = ts.getModifierFlags(node); + if (node.kind === 218 /* VariableDeclaration */) { + node = node.parent; + } + if (node && node.kind === 219 /* VariableDeclarationList */) { + flags |= ts.getModifierFlags(node); + node = node.parent; + } + if (node && node.kind === 200 /* VariableStatement */) { + flags |= ts.getModifierFlags(node); + } + return flags; + } + ts.getCombinedModifierFlags = getCombinedModifierFlags; + // Returns the node flags for this node and all relevant parent nodes. This is done so that + // nodes like variable declarations and binding elements can returned a view of their flags + // that includes the modifiers from their container. i.e. flags like export/declare aren't + // stored on the variable declaration directly, but on the containing variable statement + // (if it has one). Similarly, flags for let/const are store on the variable declaration + // list. By calling this function, all those flags are combined so that the client can treat + // the node as if it actually had those flags. + function getCombinedNodeFlags(node) { + node = walkUpBindingElementsAndPatterns(node); + var flags = node.flags; + if (node.kind === 218 /* VariableDeclaration */) { + node = node.parent; + } + if (node && node.kind === 219 /* VariableDeclarationList */) { + flags |= node.flags; + node = node.parent; + } + if (node && node.kind === 200 /* VariableStatement */) { + flags |= node.flags; + } + return flags; + } + ts.getCombinedNodeFlags = getCombinedNodeFlags; })(ts || (ts = {})); // /// @@ -6030,9 +7840,9 @@ var ts; Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Class_definitions_are_automatically_in_strict_mode: { code: 1251, category: ts.DiagnosticCategory.Error, key: "Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Class_d_1251", message: "Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Class definitions are automatically in strict mode." }, Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Modules_are_automatically_in_strict_mode: { code: 1252, category: ts.DiagnosticCategory.Error, key: "Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Modules_1252", message: "Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Modules are automatically in strict mode." }, _0_tag_cannot_be_used_independently_as_a_top_level_JSDoc_tag: { code: 1253, category: ts.DiagnosticCategory.Error, key: "_0_tag_cannot_be_used_independently_as_a_top_level_JSDoc_tag_1253", message: "'{0}' tag cannot be used independently as a top level JSDoc tag." }, + A_const_initializer_in_an_ambient_context_must_be_a_string_or_numeric_literal: { code: 1254, category: ts.DiagnosticCategory.Error, key: "A_const_initializer_in_an_ambient_context_must_be_a_string_or_numeric_literal_1254", message: "A 'const' initializer in an ambient context must be a string or numeric literal." }, with_statements_are_not_allowed_in_an_async_function_block: { code: 1300, category: ts.DiagnosticCategory.Error, key: "with_statements_are_not_allowed_in_an_async_function_block_1300", message: "'with' statements are not allowed in an async function block." }, await_expression_is_only_allowed_within_an_async_function: { code: 1308, category: ts.DiagnosticCategory.Error, key: "await_expression_is_only_allowed_within_an_async_function_1308", message: "'await' expression is only allowed within an async function." }, - Async_functions_are_only_available_when_targeting_ECMAScript_2015_or_higher: { code: 1311, category: ts.DiagnosticCategory.Error, key: "Async_functions_are_only_available_when_targeting_ECMAScript_2015_or_higher_1311", message: "Async functions are only available when targeting ECMAScript 2015 or higher." }, can_only_be_used_in_an_object_literal_property_inside_a_destructuring_assignment: { code: 1312, category: ts.DiagnosticCategory.Error, key: "can_only_be_used_in_an_object_literal_property_inside_a_destructuring_assignment_1312", message: "'=' can only be used in an object literal property inside a destructuring assignment." }, The_body_of_an_if_statement_cannot_be_the_empty_statement: { code: 1313, category: ts.DiagnosticCategory.Error, key: "The_body_of_an_if_statement_cannot_be_the_empty_statement_1313", message: "The body of an 'if' statement cannot be the empty statement." }, Global_module_exports_may_only_appear_in_module_files: { code: 1314, category: ts.DiagnosticCategory.Error, key: "Global_module_exports_may_only_appear_in_module_files_1314", message: "Global module exports may only appear in module files." }, @@ -6087,12 +7897,11 @@ var ts; Supplied_parameters_do_not_match_any_signature_of_call_target: { code: 2346, category: ts.DiagnosticCategory.Error, key: "Supplied_parameters_do_not_match_any_signature_of_call_target_2346", message: "Supplied parameters do not match any signature of call target." }, Untyped_function_calls_may_not_accept_type_arguments: { code: 2347, category: ts.DiagnosticCategory.Error, key: "Untyped_function_calls_may_not_accept_type_arguments_2347", message: "Untyped function calls may not accept type arguments." }, Value_of_type_0_is_not_callable_Did_you_mean_to_include_new: { code: 2348, category: ts.DiagnosticCategory.Error, key: "Value_of_type_0_is_not_callable_Did_you_mean_to_include_new_2348", message: "Value of type '{0}' is not callable. Did you mean to include 'new'?" }, - Cannot_invoke_an_expression_whose_type_lacks_a_call_signature: { code: 2349, category: ts.DiagnosticCategory.Error, key: "Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_2349", message: "Cannot invoke an expression whose type lacks a call signature." }, + Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures: { code: 2349, category: ts.DiagnosticCategory.Error, key: "Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatur_2349", message: "Cannot invoke an expression whose type lacks a call signature. Type '{0}' has no compatible call signatures." }, Only_a_void_function_can_be_called_with_the_new_keyword: { code: 2350, category: ts.DiagnosticCategory.Error, key: "Only_a_void_function_can_be_called_with_the_new_keyword_2350", message: "Only a void function can be called with the 'new' keyword." }, Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature: { code: 2351, category: ts.DiagnosticCategory.Error, key: "Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature_2351", message: "Cannot use 'new' with an expression whose type lacks a call or construct signature." }, Type_0_cannot_be_converted_to_type_1: { code: 2352, category: ts.DiagnosticCategory.Error, key: "Type_0_cannot_be_converted_to_type_1_2352", message: "Type '{0}' cannot be converted to type '{1}'." }, Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1: { code: 2353, category: ts.DiagnosticCategory.Error, key: "Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1_2353", message: "Object literal may only specify known properties, and '{0}' does not exist in type '{1}'." }, - No_best_common_type_exists_among_return_expressions: { code: 2354, category: ts.DiagnosticCategory.Error, key: "No_best_common_type_exists_among_return_expressions_2354", message: "No best common type exists among return expressions." }, A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value: { code: 2355, category: ts.DiagnosticCategory.Error, key: "A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value_2355", message: "A function whose declared type is neither 'void' nor 'any' must return a value." }, An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type: { code: 2356, category: ts.DiagnosticCategory.Error, key: "An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type_2356", message: "An arithmetic operand must be of type 'any', 'number' or an enum type." }, The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer: { code: 2357, category: ts.DiagnosticCategory.Error, key: "The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer_2357", message: "The operand of an increment or decrement operator must be a variable, property or indexer." }, @@ -6146,7 +7955,7 @@ var ts; The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter: { code: 2407, category: ts.DiagnosticCategory.Error, key: "The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter_2407", message: "The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter." }, Setters_cannot_return_a_value: { code: 2408, category: ts.DiagnosticCategory.Error, key: "Setters_cannot_return_a_value_2408", message: "Setters cannot return a value." }, Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class: { code: 2409, category: ts.DiagnosticCategory.Error, key: "Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class_2409", message: "Return type of constructor signature must be assignable to the instance type of the class" }, - All_symbols_within_a_with_block_will_be_resolved_to_any: { code: 2410, category: ts.DiagnosticCategory.Error, key: "All_symbols_within_a_with_block_will_be_resolved_to_any_2410", message: "All symbols within a 'with' block will be resolved to 'any'." }, + The_with_statement_is_not_supported_All_symbols_in_a_with_block_will_have_type_any: { code: 2410, category: ts.DiagnosticCategory.Error, key: "The_with_statement_is_not_supported_All_symbols_in_a_with_block_will_have_type_any_2410", message: "The 'with' statement is not supported. All symbols in a 'with' block will have type 'any'." }, Property_0_of_type_1_is_not_assignable_to_string_index_type_2: { code: 2411, category: ts.DiagnosticCategory.Error, key: "Property_0_of_type_1_is_not_assignable_to_string_index_type_2_2411", message: "Property '{0}' of type '{1}' is not assignable to string index type '{2}'." }, Property_0_of_type_1_is_not_assignable_to_numeric_index_type_2: { code: 2412, category: ts.DiagnosticCategory.Error, key: "Property_0_of_type_1_is_not_assignable_to_numeric_index_type_2_2412", message: "Property '{0}' of type '{1}' is not assignable to numeric index type '{2}'." }, Numeric_index_type_0_is_not_assignable_to_string_index_type_1: { code: 2413, category: ts.DiagnosticCategory.Error, key: "Numeric_index_type_0_is_not_assignable_to_string_index_type_1_2413", message: "Numeric index type '{0}' is not assignable to string index type '{1}'." }, @@ -6234,7 +8043,6 @@ var ts; A_rest_element_cannot_contain_a_binding_pattern: { code: 2501, category: ts.DiagnosticCategory.Error, key: "A_rest_element_cannot_contain_a_binding_pattern_2501", message: "A rest element cannot contain a binding pattern." }, _0_is_referenced_directly_or_indirectly_in_its_own_type_annotation: { code: 2502, category: ts.DiagnosticCategory.Error, key: "_0_is_referenced_directly_or_indirectly_in_its_own_type_annotation_2502", message: "'{0}' is referenced directly or indirectly in its own type annotation." }, Cannot_find_namespace_0: { code: 2503, category: ts.DiagnosticCategory.Error, key: "Cannot_find_namespace_0_2503", message: "Cannot find namespace '{0}'." }, - No_best_common_type_exists_among_yield_expressions: { code: 2504, category: ts.DiagnosticCategory.Error, key: "No_best_common_type_exists_among_yield_expressions_2504", message: "No best common type exists among yield expressions." }, A_generator_cannot_have_a_void_type_annotation: { code: 2505, category: ts.DiagnosticCategory.Error, key: "A_generator_cannot_have_a_void_type_annotation_2505", message: "A generator cannot have a 'void' type annotation." }, _0_is_referenced_directly_or_indirectly_in_its_own_base_expression: { code: 2506, category: ts.DiagnosticCategory.Error, key: "_0_is_referenced_directly_or_indirectly_in_its_own_base_expression_2506", message: "'{0}' is referenced directly or indirectly in its own base expression." }, Type_0_is_not_a_constructor_function_type: { code: 2507, category: ts.DiagnosticCategory.Error, key: "Type_0_is_not_a_constructor_function_type_2507", message: "Type '{0}' is not a constructor function type." }, @@ -6251,7 +8059,7 @@ var ts; A_this_based_type_guard_is_not_compatible_with_a_parameter_based_type_guard: { code: 2518, category: ts.DiagnosticCategory.Error, key: "A_this_based_type_guard_is_not_compatible_with_a_parameter_based_type_guard_2518", message: "A 'this'-based type guard is not compatible with a parameter-based type guard." }, Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions: { code: 2520, category: ts.DiagnosticCategory.Error, key: "Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions_2520", message: "Duplicate identifier '{0}'. Compiler uses declaration '{1}' to support async functions." }, Expression_resolves_to_variable_declaration_0_that_compiler_uses_to_support_async_functions: { code: 2521, category: ts.DiagnosticCategory.Error, key: "Expression_resolves_to_variable_declaration_0_that_compiler_uses_to_support_async_functions_2521", message: "Expression resolves to variable declaration '{0}' that compiler uses to support async functions." }, - The_arguments_object_cannot_be_referenced_in_an_async_arrow_function_Consider_using_a_standard_async_function_expression: { code: 2522, category: ts.DiagnosticCategory.Error, key: "The_arguments_object_cannot_be_referenced_in_an_async_arrow_function_Consider_using_a_standard_async_2522", message: "The 'arguments' object cannot be referenced in an async arrow function. Consider using a standard async function expression." }, + The_arguments_object_cannot_be_referenced_in_an_async_function_or_method_in_ES3_and_ES5_Consider_using_a_standard_function_or_method: { code: 2522, category: ts.DiagnosticCategory.Error, key: "The_arguments_object_cannot_be_referenced_in_an_async_function_or_method_in_ES3_and_ES5_Consider_usi_2522", message: "The 'arguments' object cannot be referenced in an async function or method in ES3 and ES5. Consider using a standard function or method." }, yield_expressions_cannot_be_used_in_a_parameter_initializer: { code: 2523, category: ts.DiagnosticCategory.Error, key: "yield_expressions_cannot_be_used_in_a_parameter_initializer_2523", message: "'yield' expressions cannot be used in a parameter initializer." }, await_expressions_cannot_be_used_in_a_parameter_initializer: { code: 2524, category: ts.DiagnosticCategory.Error, key: "await_expressions_cannot_be_used_in_a_parameter_initializer_2524", message: "'await' expressions cannot be used in a parameter initializer." }, Initializer_provides_no_value_for_this_binding_element_and_the_binding_element_has_no_default_value: { code: 2525, category: ts.DiagnosticCategory.Error, key: "Initializer_provides_no_value_for_this_binding_element_and_the_binding_element_has_no_default_value_2525", message: "Initializer provides no value for this binding element and the binding element has no default value." }, @@ -6315,6 +8123,10 @@ var ts; A_class_must_be_declared_after_its_base_class: { code: 2690, category: ts.DiagnosticCategory.Error, key: "A_class_must_be_declared_after_its_base_class_2690", message: "A class must be declared after its base class." }, An_import_path_cannot_end_with_a_0_extension_Consider_importing_1_instead: { code: 2691, category: ts.DiagnosticCategory.Error, key: "An_import_path_cannot_end_with_a_0_extension_Consider_importing_1_instead_2691", message: "An import path cannot end with a '{0}' extension. Consider importing '{1}' instead." }, _0_is_a_primitive_but_1_is_a_wrapper_object_Prefer_using_0_when_possible: { code: 2692, category: ts.DiagnosticCategory.Error, key: "_0_is_a_primitive_but_1_is_a_wrapper_object_Prefer_using_0_when_possible_2692", message: "'{0}' is a primitive, but '{1}' is a wrapper object. Prefer using '{0}' when possible." }, + _0_only_refers_to_a_type_but_is_being_used_as_a_value_here: { code: 2693, category: ts.DiagnosticCategory.Error, key: "_0_only_refers_to_a_type_but_is_being_used_as_a_value_here_2693", message: "'{0}' only refers to a type, but is being used as a value here." }, + Namespace_0_has_no_exported_member_1: { code: 2694, category: ts.DiagnosticCategory.Error, key: "Namespace_0_has_no_exported_member_1_2694", message: "Namespace '{0}' has no exported member '{1}'." }, + Left_side_of_comma_operator_is_unused_and_has_no_side_effects: { code: 2695, category: ts.DiagnosticCategory.Error, key: "Left_side_of_comma_operator_is_unused_and_has_no_side_effects_2695", message: "Left side of comma operator is unused and has no side effects." }, + The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead: { code: 2696, category: ts.DiagnosticCategory.Error, key: "The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead_2696", message: "The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead?" }, Import_declaration_0_is_using_private_name_1: { code: 4000, category: ts.DiagnosticCategory.Error, key: "Import_declaration_0_is_using_private_name_1_4000", message: "Import declaration '{0}' is using private name '{1}'." }, Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: ts.DiagnosticCategory.Error, key: "Type_parameter_0_of_exported_class_has_or_is_using_private_name_1_4002", message: "Type parameter '{0}' of exported class has or is using private name '{1}'." }, Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4004, category: ts.DiagnosticCategory.Error, key: "Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1_4004", message: "Type parameter '{0}' of exported interface has or is using private name '{1}'." }, @@ -6444,6 +8256,7 @@ var ts; VERSION: { code: 6036, category: ts.DiagnosticCategory.Message, key: "VERSION_6036", message: "VERSION" }, LOCATION: { code: 6037, category: ts.DiagnosticCategory.Message, key: "LOCATION_6037", message: "LOCATION" }, DIRECTORY: { code: 6038, category: ts.DiagnosticCategory.Message, key: "DIRECTORY_6038", message: "DIRECTORY" }, + STRATEGY: { code: 6039, category: ts.DiagnosticCategory.Message, key: "STRATEGY_6039", message: "STRATEGY" }, Compilation_complete_Watching_for_file_changes: { code: 6042, category: ts.DiagnosticCategory.Message, key: "Compilation_complete_Watching_for_file_changes_6042", message: "Compilation complete. Watching for file changes." }, Generates_corresponding_map_file: { code: 6043, category: ts.DiagnosticCategory.Message, key: "Generates_corresponding_map_file_6043", message: "Generates corresponding '.map' file." }, Compiler_option_0_expects_an_argument: { code: 6044, category: ts.DiagnosticCategory.Error, key: "Compiler_option_0_expects_an_argument_6044", message: "Compiler option '{0}' expects an argument." }, @@ -6535,6 +8348,8 @@ var ts; The_maximum_dependency_depth_to_search_under_node_modules_and_load_JavaScript_files: { code: 6136, category: ts.DiagnosticCategory.Message, key: "The_maximum_dependency_depth_to_search_under_node_modules_and_load_JavaScript_files_6136", message: "The maximum dependency depth to search under node_modules and load JavaScript files" }, No_types_specified_in_package_json_but_allowJs_is_set_so_returning_main_value_of_0: { code: 6137, category: ts.DiagnosticCategory.Message, key: "No_types_specified_in_package_json_but_allowJs_is_set_so_returning_main_value_of_0_6137", message: "No types specified in 'package.json' but 'allowJs' is set, so returning 'main' value of '{0}'" }, Property_0_is_declared_but_never_used: { code: 6138, category: ts.DiagnosticCategory.Error, key: "Property_0_is_declared_but_never_used_6138", message: "Property '{0}' is declared but never used." }, + Import_emit_helpers_from_tslib: { code: 6139, category: ts.DiagnosticCategory.Message, key: "Import_emit_helpers_from_tslib_6139", message: "Import emit helpers from 'tslib'." }, + Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using_cache_location_2: { code: 6140, category: ts.DiagnosticCategory.Error, key: "Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using__6140", message: "Auto discovery for typings is enabled in project '{0}'. Running extra resolution pass for module '{1}' using cache location '{2}'." }, Variable_0_implicitly_has_an_1_type: { code: 7005, category: ts.DiagnosticCategory.Error, key: "Variable_0_implicitly_has_an_1_type_7005", message: "Variable '{0}' implicitly has an '{1}' type." }, Parameter_0_implicitly_has_an_1_type: { code: 7006, category: ts.DiagnosticCategory.Error, key: "Parameter_0_implicitly_has_an_1_type_7006", message: "Parameter '{0}' implicitly has an '{1}' type." }, Member_0_implicitly_has_an_1_type: { code: 7008, category: ts.DiagnosticCategory.Error, key: "Member_0_implicitly_has_an_1_type_7008", message: "Member '{0}' implicitly has an '{1}' type." }, @@ -6587,6 +8402,8 @@ var ts; JSX_element_0_has_no_corresponding_closing_tag: { code: 17008, category: ts.DiagnosticCategory.Error, key: "JSX_element_0_has_no_corresponding_closing_tag_17008", message: "JSX element '{0}' has no corresponding closing tag." }, super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class: { code: 17009, category: ts.DiagnosticCategory.Error, key: "super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class_17009", message: "'super' must be called before accessing 'this' in the constructor of a derived class." }, Unknown_typing_option_0: { code: 17010, category: ts.DiagnosticCategory.Error, key: "Unknown_typing_option_0_17010", message: "Unknown typing option '{0}'." }, + Circularity_detected_while_resolving_configuration_Colon_0: { code: 18000, category: ts.DiagnosticCategory.Error, key: "Circularity_detected_while_resolving_configuration_Colon_0_18000", message: "Circularity detected while resolving configuration: {0}" }, + The_path_in_an_extends_options_must_be_relative_or_rooted: { code: 18001, category: ts.DiagnosticCategory.Error, key: "The_path_in_an_extends_options_must_be_relative_or_rooted_18001", message: "The path in an 'extends' options must be relative or rooted." }, }; })(ts || (ts = {})); /// @@ -6807,8 +8624,8 @@ var ts; } function makeReverseMap(source) { var result = []; - for (var name_6 in source) { - result[source[name_6]] = name_6; + for (var name_8 in source) { + result[source[name_8]] = name_8; } return result; } @@ -6969,9 +8786,7 @@ var ts; /* @internal */ function skipTrivia(text, pos, stopAfterLineBreak, stopAtComments) { if (stopAtComments === void 0) { stopAtComments = false; } - // Using ! with a greater than test is a fast way of testing the following conditions: - // pos === undefined || pos === null || isNaN(pos) || pos < 0; - if (!(pos >= 0)) { + if (ts.positionIsSynthesized(pos)) { return pos; } // Keep in sync with couldStartTrivia @@ -7102,20 +8917,34 @@ var ts; return pos; } /** - * Extract comments from text prefixing the token closest following `pos`. - * The return value is an array containing a TextRange for each comment. - * Single-line comment ranges include the beginning '//' characters but not the ending line break. - * Multi - line comment ranges include the beginning '/* and ending '/' characters. - * The return value is undefined if no comments were found. - * @param trailing - * If false, whitespace is skipped until the first line break and comments between that location - * and the next token are returned. - * If true, comments occurring between the given position and the next line break are returned. + * Invokes a callback for each comment range following the provided position. + * + * Single-line comment ranges include the leading double-slash characters but not the ending + * line break. Multi-line comment ranges include the leading slash-asterisk and trailing + * asterisk-slash characters. + * + * @param reduce If true, accumulates the result of calling the callback in a fashion similar + * to reduceLeft. If false, iteration stops when the callback returns a truthy value. + * @param text The source text to scan. + * @param pos The position at which to start scanning. + * @param trailing If false, whitespace is skipped until the first line break and comments + * between that location and the next token are returned. If true, comments occurring + * between the given position and the next line break are returned. + * @param cb The callback to execute as each comment range is encountered. + * @param state A state value to pass to each iteration of the callback. + * @param initial An initial value to pass when accumulating results (when "reduce" is true). + * @returns If "reduce" is true, the accumulated value. If "reduce" is false, the first truthy + * return value of the callback. */ - function getCommentRanges(text, pos, trailing) { - var result; + function iterateCommentRanges(reduce, text, pos, trailing, cb, state, initial) { + var pendingPos; + var pendingEnd; + var pendingKind; + var pendingHasTrailingNewLine; + var hasPendingCommentRange = false; var collecting = trailing || pos === 0; - while (pos < text.length) { + var accumulator = initial; + scan: while (pos >= 0 && pos < text.length) { var ch = text.charCodeAt(pos); switch (ch) { case 13 /* carriageReturn */: @@ -7125,11 +8954,11 @@ var ts; case 10 /* lineFeed */: pos++; if (trailing) { - return result; + break scan; } collecting = true; - if (result && result.length) { - ts.lastOrUndefined(result).hasTrailingNewLine = true; + if (hasPendingCommentRange) { + pendingHasTrailingNewLine = true; } continue; case 9 /* tab */: @@ -7164,34 +8993,68 @@ var ts; } } if (collecting) { - if (!result) { - result = []; + if (hasPendingCommentRange) { + accumulator = cb(pendingPos, pendingEnd, pendingKind, pendingHasTrailingNewLine, state, accumulator); + if (!reduce && accumulator) { + // If we are not reducing and we have a truthy result, return it. + return accumulator; + } + hasPendingCommentRange = false; } - result.push({ pos: startPos, end: pos, hasTrailingNewLine: hasTrailingNewLine, kind: kind }); + pendingPos = startPos; + pendingEnd = pos; + pendingKind = kind; + pendingHasTrailingNewLine = hasTrailingNewLine; + hasPendingCommentRange = true; } continue; } - break; + break scan; default: if (ch > 127 /* maxAsciiCharacter */ && (isWhiteSpace(ch))) { - if (result && result.length && isLineBreak(ch)) { - ts.lastOrUndefined(result).hasTrailingNewLine = true; + if (hasPendingCommentRange && isLineBreak(ch)) { + pendingHasTrailingNewLine = true; } pos++; continue; } - break; + break scan; } - return result; } - return result; + if (hasPendingCommentRange) { + accumulator = cb(pendingPos, pendingEnd, pendingKind, pendingHasTrailingNewLine, state, accumulator); + } + return accumulator; + } + function forEachLeadingCommentRange(text, pos, cb, state) { + return iterateCommentRanges(/*reduce*/ false, text, pos, /*trailing*/ false, cb, state); + } + ts.forEachLeadingCommentRange = forEachLeadingCommentRange; + function forEachTrailingCommentRange(text, pos, cb, state) { + return iterateCommentRanges(/*reduce*/ false, text, pos, /*trailing*/ true, cb, state); + } + ts.forEachTrailingCommentRange = forEachTrailingCommentRange; + function reduceEachLeadingCommentRange(text, pos, cb, state, initial) { + return iterateCommentRanges(/*reduce*/ true, text, pos, /*trailing*/ false, cb, state, initial); + } + ts.reduceEachLeadingCommentRange = reduceEachLeadingCommentRange; + function reduceEachTrailingCommentRange(text, pos, cb, state, initial) { + return iterateCommentRanges(/*reduce*/ true, text, pos, /*trailing*/ true, cb, state, initial); + } + ts.reduceEachTrailingCommentRange = reduceEachTrailingCommentRange; + function appendCommentRange(pos, end, kind, hasTrailingNewLine, state, comments) { + if (!comments) { + comments = []; + } + comments.push({ pos: pos, end: end, hasTrailingNewLine: hasTrailingNewLine, kind: kind }); + return comments; } function getLeadingCommentRanges(text, pos) { - return getCommentRanges(text, pos, /*trailing*/ false); + return reduceEachLeadingCommentRange(text, pos, appendCommentRange, undefined, undefined); } ts.getLeadingCommentRanges = getLeadingCommentRanges; function getTrailingCommentRanges(text, pos) { - return getCommentRanges(text, pos, /*trailing*/ true); + return reduceEachTrailingCommentRange(text, pos, appendCommentRange, undefined, undefined); } ts.getTrailingCommentRanges = getTrailingCommentRanges; /** Optionally, get the shebang */ @@ -7214,7 +9077,7 @@ var ts; } ts.isIdentifierPart = isIdentifierPart; /* @internal */ - function isIdentifier(name, languageVersion) { + function isIdentifierText(name, languageVersion) { if (!isIdentifierStart(name.charCodeAt(0), languageVersion)) { return false; } @@ -7225,7 +9088,7 @@ var ts; } return true; } - ts.isIdentifier = isIdentifier; + ts.isIdentifierText = isIdentifierText; // Creates a scanner over a (possibly unspecified) range of a piece of text. function createScanner(languageVersion, skipTrivia, languageVariant, text, onError, start, length) { if (languageVariant === void 0) { languageVariant = 0 /* Standard */; } @@ -7259,6 +9122,7 @@ var ts; reScanSlashToken: reScanSlashToken, reScanTemplateToken: reScanTemplateToken, scanJsxIdentifier: scanJsxIdentifier, + scanJsxAttributeValue: scanJsxAttributeValue, reScanJsxToken: reScanJsxToken, scanJsxToken: scanJsxToken, scanJSDocToken: scanJSDocToken, @@ -7350,7 +9214,8 @@ var ts; } return value; } - function scanString() { + function scanString(allowEscapes) { + if (allowEscapes === void 0) { allowEscapes = true; } var quote = text.charCodeAt(pos); pos++; var result = ""; @@ -7368,7 +9233,7 @@ var ts; pos++; break; } - if (ch === 92 /* backslash */) { + if (ch === 92 /* backslash */ && allowEscapes) { result += text.substring(start, pos); result += scanEscapeSequence(); start = pos; @@ -8113,43 +9978,62 @@ var ts; } return token; } + function scanJsxAttributeValue() { + startPos = pos; + switch (text.charCodeAt(pos)) { + case 34 /* doubleQuote */: + case 39 /* singleQuote */: + tokenValue = scanString(/*allowEscapes*/ false); + return token = 9 /* StringLiteral */; + default: + // If this scans anything other than `{`, it's a parse error. + return scan(); + } + } function scanJSDocToken() { if (pos >= end) { return token = 1 /* EndOfFileToken */; } startPos = pos; - // Eat leading whitespace - var ch = text.charCodeAt(pos); - while (pos < end) { - ch = text.charCodeAt(pos); - if (isWhiteSpaceSingleLine(ch)) { - pos++; - } - else { - break; - } - } tokenPos = pos; + var ch = text.charCodeAt(pos); switch (ch) { + case 9 /* tab */: + case 11 /* verticalTab */: + case 12 /* formFeed */: + case 32 /* space */: + while (pos < end && isWhiteSpaceSingleLine(text.charCodeAt(pos))) { + pos++; + } + return token = 5 /* WhitespaceTrivia */; case 64 /* at */: - return pos += 1, token = 55 /* AtToken */; + pos++; + return token = 55 /* AtToken */; case 10 /* lineFeed */: case 13 /* carriageReturn */: - return pos += 1, token = 4 /* NewLineTrivia */; + pos++; + return token = 4 /* NewLineTrivia */; case 42 /* asterisk */: - return pos += 1, token = 37 /* AsteriskToken */; + pos++; + return token = 37 /* AsteriskToken */; case 123 /* openBrace */: - return pos += 1, token = 15 /* OpenBraceToken */; + pos++; + return token = 15 /* OpenBraceToken */; case 125 /* closeBrace */: - return pos += 1, token = 16 /* CloseBraceToken */; + pos++; + return token = 16 /* CloseBraceToken */; case 91 /* openBracket */: - return pos += 1, token = 19 /* OpenBracketToken */; + pos++; + return token = 19 /* OpenBracketToken */; case 93 /* closeBracket */: - return pos += 1, token = 20 /* CloseBracketToken */; + pos++; + return token = 20 /* CloseBracketToken */; case 61 /* equals */: - return pos += 1, token = 56 /* EqualsToken */; + pos++; + return token = 56 /* EqualsToken */; case 44 /* comma */: - return pos += 1, token = 24 /* CommaToken */; + pos++; + return token = 24 /* CommaToken */; } if (isIdentifierStart(ch, 2 /* Latest */)) { pos++; @@ -8242,2025 +10126,4656 @@ var ts; } ts.createScanner = createScanner; })(ts || (ts = {})); +/// /// -/// +/* @internal */ var ts; (function (ts) { var NodeConstructor; - var TokenConstructor; - var IdentifierConstructor; var SourceFileConstructor; - function createNode(kind, pos, end) { - if (kind === 256 /* SourceFile */) { - return new (SourceFileConstructor || (SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor()))(kind, pos, end); + function createNode(kind, location, flags) { + var ConstructorForKind = kind === 256 /* SourceFile */ + ? (SourceFileConstructor || (SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor())) + : (NodeConstructor || (NodeConstructor = ts.objectAllocator.getNodeConstructor())); + var node = location + ? new ConstructorForKind(kind, location.pos, location.end) + : new ConstructorForKind(kind, /*pos*/ -1, /*end*/ -1); + node.flags = flags | 8 /* Synthesized */; + return node; + } + function updateNode(updated, original) { + if (updated !== original) { + setOriginalNode(updated, original); + if (original.startsOnNewLine) { + updated.startsOnNewLine = true; + } + ts.aggregateTransformFlags(updated); } - else if (kind === 69 /* Identifier */) { - return new (IdentifierConstructor || (IdentifierConstructor = ts.objectAllocator.getIdentifierConstructor()))(kind, pos, end); + return updated; + } + ts.updateNode = updateNode; + function createNodeArray(elements, location, hasTrailingComma) { + if (elements) { + if (ts.isNodeArray(elements)) { + return elements; + } } - else if (kind < 139 /* FirstNode */) { - return new (TokenConstructor || (TokenConstructor = ts.objectAllocator.getTokenConstructor()))(kind, pos, end); + else { + elements = []; + } + var array = elements; + if (location) { + array.pos = location.pos; + array.end = location.end; } else { - return new (NodeConstructor || (NodeConstructor = ts.objectAllocator.getNodeConstructor()))(kind, pos, end); + array.pos = -1; + array.end = -1; } + if (hasTrailingComma) { + array.hasTrailingComma = true; + } + return array; } - ts.createNode = createNode; - function visitNode(cbNode, node) { - if (node) { - return cbNode(node); + ts.createNodeArray = createNodeArray; + function createSynthesizedNode(kind, startsOnNewLine) { + var node = createNode(kind, /*location*/ undefined); + node.startsOnNewLine = startsOnNewLine; + return node; + } + ts.createSynthesizedNode = createSynthesizedNode; + function createSynthesizedNodeArray(elements) { + return createNodeArray(elements, /*location*/ undefined); + } + ts.createSynthesizedNodeArray = createSynthesizedNodeArray; + /** + * Creates a shallow, memberwise clone of a node with no source map location. + */ + function getSynthesizedClone(node) { + // We don't use "clone" from core.ts here, as we need to preserve the prototype chain of + // the original node. We also need to exclude specific properties and only include own- + // properties (to skip members already defined on the shared prototype). + var clone = createNode(node.kind, /*location*/ undefined, node.flags); + setOriginalNode(clone, node); + for (var key in node) { + if (clone.hasOwnProperty(key) || !node.hasOwnProperty(key)) { + continue; + } + clone[key] = node[key]; } + return clone; } - function visitNodeArray(cbNodes, nodes) { - if (nodes) { - return cbNodes(nodes); + ts.getSynthesizedClone = getSynthesizedClone; + /** + * Creates a shallow, memberwise clone of a node for mutation. + */ + function getMutableClone(node) { + var clone = getSynthesizedClone(node); + clone.pos = node.pos; + clone.end = node.end; + clone.parent = node.parent; + return clone; + } + ts.getMutableClone = getMutableClone; + function createLiteral(value, location) { + if (typeof value === "number") { + var node = createNode(8 /* NumericLiteral */, location, /*flags*/ undefined); + node.text = value.toString(); + return node; + } + else if (typeof value === "boolean") { + return createNode(value ? 99 /* TrueKeyword */ : 84 /* FalseKeyword */, location, /*flags*/ undefined); + } + else if (typeof value === "string") { + var node = createNode(9 /* StringLiteral */, location, /*flags*/ undefined); + node.text = value; + return node; + } + else { + var node = createNode(9 /* StringLiteral */, location, /*flags*/ undefined); + node.textSourceNode = value; + node.text = value.text; + return node; } } - function visitEachNode(cbNode, nodes) { - if (nodes) { - for (var _i = 0, nodes_1 = nodes; _i < nodes_1.length; _i++) { - var node = nodes_1[_i]; - var result = cbNode(node); - if (result) { - return result; - } - } + ts.createLiteral = createLiteral; + // Identifiers + var nextAutoGenerateId = 0; + function createIdentifier(text, location) { + var node = createNode(69 /* Identifier */, location); + node.text = ts.escapeIdentifier(text); + node.originalKeywordKind = ts.stringToToken(text); + node.autoGenerateKind = 0 /* None */; + node.autoGenerateId = 0; + return node; + } + ts.createIdentifier = createIdentifier; + function createTempVariable(recordTempVariable, location) { + var name = createNode(69 /* Identifier */, location); + name.text = ""; + name.originalKeywordKind = 0 /* Unknown */; + name.autoGenerateKind = 1 /* Auto */; + name.autoGenerateId = nextAutoGenerateId; + nextAutoGenerateId++; + if (recordTempVariable) { + recordTempVariable(name); } + return name; } - // Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes - // stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise, - // embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns - // a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned. - function forEachChild(node, cbNode, cbNodeArray) { - if (!node) { - return; - } - // The visitXXX functions could be written as local functions that close over the cbNode and cbNodeArray - // callback parameters, but that causes a closure allocation for each invocation with noticeable effects - // on performance. - var visitNodes = cbNodeArray ? visitNodeArray : visitEachNode; - var cbNodes = cbNodeArray || cbNode; - switch (node.kind) { - case 139 /* QualifiedName */: - return visitNode(cbNode, node.left) || - visitNode(cbNode, node.right); - case 141 /* TypeParameter */: - return visitNode(cbNode, node.name) || - visitNode(cbNode, node.constraint) || - visitNode(cbNode, node.expression); - case 254 /* ShorthandPropertyAssignment */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.questionToken) || - visitNode(cbNode, node.equalsToken) || - visitNode(cbNode, node.objectAssignmentInitializer); - case 142 /* Parameter */: - case 145 /* PropertyDeclaration */: - case 144 /* PropertySignature */: - case 253 /* PropertyAssignment */: - case 218 /* VariableDeclaration */: - case 169 /* BindingElement */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.propertyName) || - visitNode(cbNode, node.dotDotDotToken) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.questionToken) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.initializer); - case 156 /* FunctionType */: - case 157 /* ConstructorType */: - case 151 /* CallSignature */: - case 152 /* ConstructSignature */: - case 153 /* IndexSignature */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNodes(cbNodes, node.typeParameters) || - visitNodes(cbNodes, node.parameters) || - visitNode(cbNode, node.type); - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - case 148 /* Constructor */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 179 /* FunctionExpression */: - case 220 /* FunctionDeclaration */: - case 180 /* ArrowFunction */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.asteriskToken) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.questionToken) || - visitNodes(cbNodes, node.typeParameters) || - visitNodes(cbNodes, node.parameters) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.equalsGreaterThanToken) || - visitNode(cbNode, node.body); - case 155 /* TypeReference */: - return visitNode(cbNode, node.typeName) || - visitNodes(cbNodes, node.typeArguments); - case 154 /* TypePredicate */: - return visitNode(cbNode, node.parameterName) || - visitNode(cbNode, node.type); - case 158 /* TypeQuery */: - return visitNode(cbNode, node.exprName); - case 159 /* TypeLiteral */: - return visitNodes(cbNodes, node.members); - case 160 /* ArrayType */: - return visitNode(cbNode, node.elementType); - case 161 /* TupleType */: - return visitNodes(cbNodes, node.elementTypes); - case 162 /* UnionType */: - case 163 /* IntersectionType */: - return visitNodes(cbNodes, node.types); - case 164 /* ParenthesizedType */: - return visitNode(cbNode, node.type); - case 166 /* LiteralType */: - return visitNode(cbNode, node.literal); - case 167 /* ObjectBindingPattern */: - case 168 /* ArrayBindingPattern */: - return visitNodes(cbNodes, node.elements); - case 170 /* ArrayLiteralExpression */: - return visitNodes(cbNodes, node.elements); - case 171 /* ObjectLiteralExpression */: - return visitNodes(cbNodes, node.properties); - case 172 /* PropertyAccessExpression */: - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.name); - case 173 /* ElementAccessExpression */: - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.argumentExpression); - case 174 /* CallExpression */: - case 175 /* NewExpression */: - return visitNode(cbNode, node.expression) || - visitNodes(cbNodes, node.typeArguments) || - visitNodes(cbNodes, node.arguments); - case 176 /* TaggedTemplateExpression */: - return visitNode(cbNode, node.tag) || - visitNode(cbNode, node.template); - case 177 /* TypeAssertionExpression */: - return visitNode(cbNode, node.type) || - visitNode(cbNode, node.expression); - case 178 /* ParenthesizedExpression */: - return visitNode(cbNode, node.expression); - case 181 /* DeleteExpression */: - return visitNode(cbNode, node.expression); - case 182 /* TypeOfExpression */: - return visitNode(cbNode, node.expression); - case 183 /* VoidExpression */: - return visitNode(cbNode, node.expression); - case 185 /* PrefixUnaryExpression */: - return visitNode(cbNode, node.operand); - case 190 /* YieldExpression */: - return visitNode(cbNode, node.asteriskToken) || - visitNode(cbNode, node.expression); - case 184 /* AwaitExpression */: - return visitNode(cbNode, node.expression); - case 186 /* PostfixUnaryExpression */: - return visitNode(cbNode, node.operand); - case 187 /* BinaryExpression */: - return visitNode(cbNode, node.left) || - visitNode(cbNode, node.operatorToken) || - visitNode(cbNode, node.right); - case 195 /* AsExpression */: - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.type); - case 196 /* NonNullExpression */: - return visitNode(cbNode, node.expression); - case 188 /* ConditionalExpression */: - return visitNode(cbNode, node.condition) || - visitNode(cbNode, node.questionToken) || - visitNode(cbNode, node.whenTrue) || - visitNode(cbNode, node.colonToken) || - visitNode(cbNode, node.whenFalse); - case 191 /* SpreadElementExpression */: - return visitNode(cbNode, node.expression); - case 199 /* Block */: - case 226 /* ModuleBlock */: - return visitNodes(cbNodes, node.statements); - case 256 /* SourceFile */: - return visitNodes(cbNodes, node.statements) || - visitNode(cbNode, node.endOfFileToken); - case 200 /* VariableStatement */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.declarationList); - case 219 /* VariableDeclarationList */: - return visitNodes(cbNodes, node.declarations); - case 202 /* ExpressionStatement */: - return visitNode(cbNode, node.expression); - case 203 /* IfStatement */: - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.thenStatement) || - visitNode(cbNode, node.elseStatement); - case 204 /* DoStatement */: - return visitNode(cbNode, node.statement) || - visitNode(cbNode, node.expression); - case 205 /* WhileStatement */: - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.statement); - case 206 /* ForStatement */: - return visitNode(cbNode, node.initializer) || - visitNode(cbNode, node.condition) || - visitNode(cbNode, node.incrementor) || - visitNode(cbNode, node.statement); - case 207 /* ForInStatement */: - return visitNode(cbNode, node.initializer) || - visitNode(cbNode, node.expression) || - visitNode(cbNode, node.statement); - case 208 /* ForOfStatement */: - return visitNode(cbNode, node.initializer) || - visitNode(cbNode, node.expression) || - visitNode(cbNode, node.statement); - case 209 /* ContinueStatement */: - case 210 /* BreakStatement */: - return visitNode(cbNode, node.label); - case 211 /* ReturnStatement */: - return visitNode(cbNode, node.expression); - case 212 /* WithStatement */: - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.statement); - case 213 /* SwitchStatement */: - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.caseBlock); - case 227 /* CaseBlock */: - return visitNodes(cbNodes, node.clauses); - case 249 /* CaseClause */: - return visitNode(cbNode, node.expression) || - visitNodes(cbNodes, node.statements); - case 250 /* DefaultClause */: - return visitNodes(cbNodes, node.statements); - case 214 /* LabeledStatement */: - return visitNode(cbNode, node.label) || - visitNode(cbNode, node.statement); - case 215 /* ThrowStatement */: - return visitNode(cbNode, node.expression); - case 216 /* TryStatement */: - return visitNode(cbNode, node.tryBlock) || - visitNode(cbNode, node.catchClause) || - visitNode(cbNode, node.finallyBlock); - case 252 /* CatchClause */: - return visitNode(cbNode, node.variableDeclaration) || - visitNode(cbNode, node.block); - case 143 /* Decorator */: - return visitNode(cbNode, node.expression); - case 221 /* ClassDeclaration */: - case 192 /* ClassExpression */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNodes(cbNodes, node.typeParameters) || - visitNodes(cbNodes, node.heritageClauses) || - visitNodes(cbNodes, node.members); - case 222 /* InterfaceDeclaration */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNodes(cbNodes, node.typeParameters) || - visitNodes(cbNodes, node.heritageClauses) || - visitNodes(cbNodes, node.members); - case 223 /* TypeAliasDeclaration */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNodes(cbNodes, node.typeParameters) || - visitNode(cbNode, node.type); - case 224 /* EnumDeclaration */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNodes(cbNodes, node.members); - case 255 /* EnumMember */: - return visitNode(cbNode, node.name) || - visitNode(cbNode, node.initializer); - case 225 /* ModuleDeclaration */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.body); - case 229 /* ImportEqualsDeclaration */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.moduleReference); - case 230 /* ImportDeclaration */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.importClause) || - visitNode(cbNode, node.moduleSpecifier); - case 231 /* ImportClause */: - return visitNode(cbNode, node.name) || - visitNode(cbNode, node.namedBindings); - case 228 /* NamespaceExportDeclaration */: - return visitNode(cbNode, node.name); - case 232 /* NamespaceImport */: - return visitNode(cbNode, node.name); - case 233 /* NamedImports */: - case 237 /* NamedExports */: - return visitNodes(cbNodes, node.elements); - case 236 /* ExportDeclaration */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.exportClause) || - visitNode(cbNode, node.moduleSpecifier); - case 234 /* ImportSpecifier */: - case 238 /* ExportSpecifier */: - return visitNode(cbNode, node.propertyName) || - visitNode(cbNode, node.name); - case 235 /* ExportAssignment */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.expression); - case 189 /* TemplateExpression */: - return visitNode(cbNode, node.head) || visitNodes(cbNodes, node.templateSpans); - case 197 /* TemplateSpan */: - return visitNode(cbNode, node.expression) || visitNode(cbNode, node.literal); - case 140 /* ComputedPropertyName */: - return visitNode(cbNode, node.expression); - case 251 /* HeritageClause */: - return visitNodes(cbNodes, node.types); - case 194 /* ExpressionWithTypeArguments */: - return visitNode(cbNode, node.expression) || - visitNodes(cbNodes, node.typeArguments); - case 240 /* ExternalModuleReference */: - return visitNode(cbNode, node.expression); - case 239 /* MissingDeclaration */: - return visitNodes(cbNodes, node.decorators); - case 241 /* JsxElement */: - return visitNode(cbNode, node.openingElement) || - visitNodes(cbNodes, node.children) || - visitNode(cbNode, node.closingElement); - case 242 /* JsxSelfClosingElement */: - case 243 /* JsxOpeningElement */: - return visitNode(cbNode, node.tagName) || - visitNodes(cbNodes, node.attributes); - case 246 /* JsxAttribute */: - return visitNode(cbNode, node.name) || - visitNode(cbNode, node.initializer); - case 247 /* JsxSpreadAttribute */: - return visitNode(cbNode, node.expression); - case 248 /* JsxExpression */: - return visitNode(cbNode, node.expression); - case 245 /* JsxClosingElement */: - return visitNode(cbNode, node.tagName); - case 257 /* JSDocTypeExpression */: - return visitNode(cbNode, node.type); - case 261 /* JSDocUnionType */: - return visitNodes(cbNodes, node.types); - case 262 /* JSDocTupleType */: - return visitNodes(cbNodes, node.types); - case 260 /* JSDocArrayType */: - return visitNode(cbNode, node.elementType); - case 264 /* JSDocNonNullableType */: - return visitNode(cbNode, node.type); - case 263 /* JSDocNullableType */: - return visitNode(cbNode, node.type); - case 265 /* JSDocRecordType */: - return visitNodes(cbNodes, node.members); - case 267 /* JSDocTypeReference */: - return visitNode(cbNode, node.name) || - visitNodes(cbNodes, node.typeArguments); - case 268 /* JSDocOptionalType */: - return visitNode(cbNode, node.type); - case 269 /* JSDocFunctionType */: - return visitNodes(cbNodes, node.parameters) || - visitNode(cbNode, node.type); - case 270 /* JSDocVariadicType */: - return visitNode(cbNode, node.type); - case 271 /* JSDocConstructorType */: - return visitNode(cbNode, node.type); - case 272 /* JSDocThisType */: - return visitNode(cbNode, node.type); - case 266 /* JSDocRecordMember */: - return visitNode(cbNode, node.name) || - visitNode(cbNode, node.type); - case 273 /* JSDocComment */: - return visitNodes(cbNodes, node.tags); - case 275 /* JSDocParameterTag */: - return visitNode(cbNode, node.preParameterName) || - visitNode(cbNode, node.typeExpression) || - visitNode(cbNode, node.postParameterName); - case 276 /* JSDocReturnTag */: - return visitNode(cbNode, node.typeExpression); - case 277 /* JSDocTypeTag */: - return visitNode(cbNode, node.typeExpression); - case 278 /* JSDocTemplateTag */: - return visitNodes(cbNodes, node.typeParameters); - case 279 /* JSDocTypedefTag */: - return visitNode(cbNode, node.typeExpression) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.jsDocTypeLiteral); - case 281 /* JSDocTypeLiteral */: - return visitNodes(cbNodes, node.jsDocPropertyTags); - case 280 /* JSDocPropertyTag */: - return visitNode(cbNode, node.typeExpression) || - visitNode(cbNode, node.name); - case 282 /* JSDocLiteralType */: - return visitNode(cbNode, node.literal); + ts.createTempVariable = createTempVariable; + function createLoopVariable(location) { + var name = createNode(69 /* Identifier */, location); + name.text = ""; + name.originalKeywordKind = 0 /* Unknown */; + name.autoGenerateKind = 2 /* Loop */; + name.autoGenerateId = nextAutoGenerateId; + nextAutoGenerateId++; + return name; + } + ts.createLoopVariable = createLoopVariable; + function createUniqueName(text, location) { + var name = createNode(69 /* Identifier */, location); + name.text = text; + name.originalKeywordKind = 0 /* Unknown */; + name.autoGenerateKind = 3 /* Unique */; + name.autoGenerateId = nextAutoGenerateId; + nextAutoGenerateId++; + return name; + } + ts.createUniqueName = createUniqueName; + function getGeneratedNameForNode(node, location) { + var name = createNode(69 /* Identifier */, location); + name.original = node; + name.text = ""; + name.originalKeywordKind = 0 /* Unknown */; + name.autoGenerateKind = 4 /* Node */; + name.autoGenerateId = nextAutoGenerateId; + nextAutoGenerateId++; + return name; + } + ts.getGeneratedNameForNode = getGeneratedNameForNode; + // Punctuation + function createToken(token) { + return createNode(token); + } + ts.createToken = createToken; + // Reserved words + function createSuper() { + var node = createNode(95 /* SuperKeyword */); + return node; + } + ts.createSuper = createSuper; + function createThis(location) { + var node = createNode(97 /* ThisKeyword */, location); + return node; + } + ts.createThis = createThis; + function createNull() { + var node = createNode(93 /* NullKeyword */); + return node; + } + ts.createNull = createNull; + // Names + function createComputedPropertyName(expression, location) { + var node = createNode(140 /* ComputedPropertyName */, location); + node.expression = expression; + return node; + } + ts.createComputedPropertyName = createComputedPropertyName; + function updateComputedPropertyName(node, expression) { + if (node.expression !== expression) { + return updateNode(createComputedPropertyName(expression, node), node); } + return node; } - ts.forEachChild = forEachChild; - function createSourceFile(fileName, sourceText, languageVersion, setParentNodes, scriptKind) { - if (setParentNodes === void 0) { setParentNodes = false; } - ts.performance.mark("beforeParse"); - var result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind); - ts.performance.mark("afterParse"); - ts.performance.measure("Parse", "beforeParse", "afterParse"); - return result; + ts.updateComputedPropertyName = updateComputedPropertyName; + // Signature elements + function createParameter(name, initializer, location) { + return createParameterDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, name, + /*questionToken*/ undefined, + /*type*/ undefined, initializer, location); + } + ts.createParameter = createParameter; + function createParameterDeclaration(decorators, modifiers, dotDotDotToken, name, questionToken, type, initializer, location, flags) { + var node = createNode(142 /* Parameter */, location, flags); + node.decorators = decorators ? createNodeArray(decorators) : undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.dotDotDotToken = dotDotDotToken; + node.name = typeof name === "string" ? createIdentifier(name) : name; + node.questionToken = questionToken; + node.type = type; + node.initializer = initializer ? parenthesizeExpressionForList(initializer) : undefined; + return node; } - ts.createSourceFile = createSourceFile; - function isExternalModule(file) { - return file.externalModuleIndicator !== undefined; + ts.createParameterDeclaration = createParameterDeclaration; + function updateParameterDeclaration(node, decorators, modifiers, name, type, initializer) { + if (node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name || node.type !== type || node.initializer !== initializer) { + return updateNode(createParameterDeclaration(decorators, modifiers, node.dotDotDotToken, name, node.questionToken, type, initializer, /*location*/ node, /*flags*/ node.flags), node); + } + return node; } - ts.isExternalModule = isExternalModule; - // Produces a new SourceFile for the 'newText' provided. The 'textChangeRange' parameter - // indicates what changed between the 'text' that this SourceFile has and the 'newText'. - // The SourceFile will be created with the compiler attempting to reuse as many nodes from - // this file as possible. - // - // Note: this function mutates nodes from this SourceFile. That means any existing nodes - // from this SourceFile that are being held onto may change as a result (including - // becoming detached from any SourceFile). It is recommended that this SourceFile not - // be used once 'update' is called on it. - function updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks) { - return IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); + ts.updateParameterDeclaration = updateParameterDeclaration; + // Type members + function createProperty(decorators, modifiers, name, questionToken, type, initializer, location) { + var node = createNode(145 /* PropertyDeclaration */, location); + node.decorators = decorators ? createNodeArray(decorators) : undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.name = typeof name === "string" ? createIdentifier(name) : name; + node.questionToken = questionToken; + node.type = type; + node.initializer = initializer; + return node; } - ts.updateSourceFile = updateSourceFile; - /* @internal */ - function parseIsolatedJSDocComment(content, start, length) { - var result = Parser.JSDocParser.parseIsolatedJSDocComment(content, start, length); - if (result && result.jsDocComment) { - // because the jsDocComment was parsed out of the source file, it might - // not be covered by the fixupParentReferences. - Parser.fixupParentReferences(result.jsDocComment); + ts.createProperty = createProperty; + function updateProperty(node, decorators, modifiers, name, type, initializer) { + if (node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name || node.type !== type || node.initializer !== initializer) { + return updateNode(createProperty(decorators, modifiers, name, node.questionToken, type, initializer, node), node); } - return result; + return node; } - ts.parseIsolatedJSDocComment = parseIsolatedJSDocComment; - /* @internal */ - // Exposed only for testing. - function parseJSDocTypeExpressionForTests(content, start, length) { - return Parser.JSDocParser.parseJSDocTypeExpressionForTests(content, start, length); + ts.updateProperty = updateProperty; + function createMethod(decorators, modifiers, asteriskToken, name, typeParameters, parameters, type, body, location, flags) { + var node = createNode(147 /* MethodDeclaration */, location, flags); + node.decorators = decorators ? createNodeArray(decorators) : undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.asteriskToken = asteriskToken; + node.name = typeof name === "string" ? createIdentifier(name) : name; + node.typeParameters = typeParameters ? createNodeArray(typeParameters) : undefined; + node.parameters = createNodeArray(parameters); + node.type = type; + node.body = body; + return node; } - ts.parseJSDocTypeExpressionForTests = parseJSDocTypeExpressionForTests; - // Implement the parser as a singleton module. We do this for perf reasons because creating - // parser instances can actually be expensive enough to impact us on projects with many source - // files. - var Parser; - (function (Parser) { - // Share a single scanner across all calls to parse a source file. This helps speed things - // up by avoiding the cost of creating/compiling scanners over and over again. - var scanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ true); - var disallowInAndDecoratorContext = 4194304 /* DisallowInContext */ | 16777216 /* DecoratorContext */; - // capture constructors in 'initializeState' to avoid null checks - var NodeConstructor; - var TokenConstructor; - var IdentifierConstructor; - var SourceFileConstructor; - var sourceFile; - var parseDiagnostics; - var syntaxCursor; - var currentToken; - var sourceText; - var nodeCount; - var identifiers; - var identifierCount; - var parsingContext; - // Flags that dictate what parsing context we're in. For example: - // Whether or not we are in strict parsing mode. All that changes in strict parsing mode is - // that some tokens that would be considered identifiers may be considered keywords. - // - // When adding more parser context flags, consider which is the more common case that the - // flag will be in. This should be the 'false' state for that flag. The reason for this is - // that we don't store data in our nodes unless the value is in the *non-default* state. So, - // for example, more often than code 'allows-in' (or doesn't 'disallow-in'). We opt for - // 'disallow-in' set to 'false'. Otherwise, if we had 'allowsIn' set to 'true', then almost - // all nodes would need extra state on them to store this info. - // - // Note: 'allowIn' and 'allowYield' track 1:1 with the [in] and [yield] concepts in the ES6 - // grammar specification. - // - // An important thing about these context concepts. By default they are effectively inherited - // while parsing through every grammar production. i.e. if you don't change them, then when - // you parse a sub-production, it will have the same context values as the parent production. - // This is great most of the time. After all, consider all the 'expression' grammar productions - // and how nearly all of them pass along the 'in' and 'yield' context values: - // - // EqualityExpression[In, Yield] : - // RelationalExpression[?In, ?Yield] - // EqualityExpression[?In, ?Yield] == RelationalExpression[?In, ?Yield] - // EqualityExpression[?In, ?Yield] != RelationalExpression[?In, ?Yield] - // EqualityExpression[?In, ?Yield] === RelationalExpression[?In, ?Yield] - // EqualityExpression[?In, ?Yield] !== RelationalExpression[?In, ?Yield] - // - // Where you have to be careful is then understanding what the points are in the grammar - // where the values are *not* passed along. For example: - // - // SingleNameBinding[Yield,GeneratorParameter] - // [+GeneratorParameter]BindingIdentifier[Yield] Initializer[In]opt - // [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt - // - // Here this is saying that if the GeneratorParameter context flag is set, that we should - // explicitly set the 'yield' context flag to false before calling into the BindingIdentifier - // and we should explicitly unset the 'yield' context flag before calling into the Initializer. - // production. Conversely, if the GeneratorParameter context flag is not set, then we - // should leave the 'yield' context flag alone. - // - // Getting this all correct is tricky and requires careful reading of the grammar to - // understand when these values should be changed versus when they should be inherited. - // - // Note: it should not be necessary to save/restore these flags during speculative/lookahead - // parsing. These context flags are naturally stored and restored through normal recursive - // descent parsing and unwinding. - var contextFlags; - // Whether or not we've had a parse error since creating the last AST node. If we have - // encountered an error, it will be stored on the next AST node we create. Parse errors - // can be broken down into three categories: - // - // 1) An error that occurred during scanning. For example, an unterminated literal, or a - // character that was completely not understood. - // - // 2) A token was expected, but was not present. This type of error is commonly produced - // by the 'parseExpected' function. - // - // 3) A token was present that no parsing function was able to consume. This type of error - // only occurs in the 'abortParsingListOrMoveToNextToken' function when the parser - // decides to skip the token. - // - // In all of these cases, we want to mark the next node as having had an error before it. - // With this mark, we can know in incremental settings if this node can be reused, or if - // we have to reparse it. If we don't keep this information around, we may just reuse the - // node. in that event we would then not produce the same errors as we did before, causing - // significant confusion problems. - // - // Note: it is necessary that this value be saved/restored during speculative/lookahead - // parsing. During lookahead parsing, we will often create a node. That node will have - // this value attached, and then this value will be set back to 'false'. If we decide to - // rewind, we must get back to the same value we had prior to the lookahead. - // - // Note: any errors at the end of the file that do not precede a regular node, should get - // attached to the EOF token. - var parseErrorBeforeNextFinishedNode = false; - function parseSourceFile(fileName, _sourceText, languageVersion, _syntaxCursor, setParentNodes, scriptKind) { - scriptKind = ts.ensureScriptKind(fileName, scriptKind); - initializeState(fileName, _sourceText, languageVersion, _syntaxCursor, scriptKind); - var result = parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind); - clearState(); - return result; + ts.createMethod = createMethod; + function updateMethod(node, decorators, modifiers, name, typeParameters, parameters, type, body) { + if (node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name || node.typeParameters !== typeParameters || node.parameters !== parameters || node.type !== type || node.body !== body) { + return updateNode(createMethod(decorators, modifiers, node.asteriskToken, name, typeParameters, parameters, type, body, /*location*/ node, node.flags), node); } - Parser.parseSourceFile = parseSourceFile; - function getLanguageVariant(scriptKind) { - // .tsx and .jsx files are treated as jsx language variant. - return scriptKind === 4 /* TSX */ || scriptKind === 2 /* JSX */ || scriptKind === 1 /* JS */ ? 1 /* JSX */ : 0 /* Standard */; + return node; + } + ts.updateMethod = updateMethod; + function createConstructor(decorators, modifiers, parameters, body, location, flags) { + var node = createNode(148 /* Constructor */, location, flags); + node.decorators = decorators ? createNodeArray(decorators) : undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.typeParameters = undefined; + node.parameters = createNodeArray(parameters); + node.type = undefined; + node.body = body; + return node; + } + ts.createConstructor = createConstructor; + function updateConstructor(node, decorators, modifiers, parameters, body) { + if (node.decorators !== decorators || node.modifiers !== modifiers || node.parameters !== parameters || node.body !== body) { + return updateNode(createConstructor(decorators, modifiers, parameters, body, /*location*/ node, node.flags), node); } - function initializeState(fileName, _sourceText, languageVersion, _syntaxCursor, scriptKind) { - NodeConstructor = ts.objectAllocator.getNodeConstructor(); - TokenConstructor = ts.objectAllocator.getTokenConstructor(); - IdentifierConstructor = ts.objectAllocator.getIdentifierConstructor(); - SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor(); - sourceText = _sourceText; - syntaxCursor = _syntaxCursor; - parseDiagnostics = []; - parsingContext = 0; - identifiers = ts.createMap(); - identifierCount = 0; - nodeCount = 0; - contextFlags = scriptKind === 1 /* JS */ || scriptKind === 2 /* JSX */ ? 134217728 /* JavaScriptFile */ : 0 /* None */; - parseErrorBeforeNextFinishedNode = false; - // Initialize and prime the scanner before parsing the source elements. - scanner.setText(sourceText); - scanner.setOnError(scanError); - scanner.setScriptTarget(languageVersion); - scanner.setLanguageVariant(getLanguageVariant(scriptKind)); + return node; + } + ts.updateConstructor = updateConstructor; + function createGetAccessor(decorators, modifiers, name, parameters, type, body, location, flags) { + var node = createNode(149 /* GetAccessor */, location, flags); + node.decorators = decorators ? createNodeArray(decorators) : undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.name = typeof name === "string" ? createIdentifier(name) : name; + node.typeParameters = undefined; + node.parameters = createNodeArray(parameters); + node.type = type; + node.body = body; + return node; + } + ts.createGetAccessor = createGetAccessor; + function updateGetAccessor(node, decorators, modifiers, name, parameters, type, body) { + if (node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name || node.parameters !== parameters || node.type !== type || node.body !== body) { + return updateNode(createGetAccessor(decorators, modifiers, name, parameters, type, body, /*location*/ node, node.flags), node); } - function clearState() { - // Clear out the text the scanner is pointing at, so it doesn't keep anything alive unnecessarily. - scanner.setText(""); - scanner.setOnError(undefined); - // Clear any data. We don't want to accidentally hold onto it for too long. - parseDiagnostics = undefined; - sourceFile = undefined; - identifiers = undefined; - syntaxCursor = undefined; - sourceText = undefined; + return node; + } + ts.updateGetAccessor = updateGetAccessor; + function createSetAccessor(decorators, modifiers, name, parameters, body, location, flags) { + var node = createNode(150 /* SetAccessor */, location, flags); + node.decorators = decorators ? createNodeArray(decorators) : undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.name = typeof name === "string" ? createIdentifier(name) : name; + node.typeParameters = undefined; + node.parameters = createNodeArray(parameters); + node.body = body; + return node; + } + ts.createSetAccessor = createSetAccessor; + function updateSetAccessor(node, decorators, modifiers, name, parameters, body) { + if (node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name || node.parameters !== parameters || node.body !== body) { + return updateNode(createSetAccessor(decorators, modifiers, name, parameters, body, /*location*/ node, node.flags), node); } - function parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind) { - sourceFile = createSourceFile(fileName, languageVersion, scriptKind); - sourceFile.flags = contextFlags; - // Prime the scanner. - nextToken(); - processReferenceComments(sourceFile); - sourceFile.statements = parseList(0 /* SourceElements */, parseStatement); - ts.Debug.assert(token() === 1 /* EndOfFileToken */); - sourceFile.endOfFileToken = parseTokenNode(); - setExternalModuleIndicator(sourceFile); - sourceFile.nodeCount = nodeCount; - sourceFile.identifierCount = identifierCount; - sourceFile.identifiers = identifiers; - sourceFile.parseDiagnostics = parseDiagnostics; - if (setParentNodes) { - fixupParentReferences(sourceFile); - } - return sourceFile; + return node; + } + ts.updateSetAccessor = updateSetAccessor; + // Binding Patterns + function createObjectBindingPattern(elements, location) { + var node = createNode(167 /* ObjectBindingPattern */, location); + node.elements = createNodeArray(elements); + return node; + } + ts.createObjectBindingPattern = createObjectBindingPattern; + function updateObjectBindingPattern(node, elements) { + if (node.elements !== elements) { + return updateNode(createObjectBindingPattern(elements, node), node); } - function addJSDocComment(node) { - if (contextFlags & 134217728 /* JavaScriptFile */) { - var comments = ts.getLeadingCommentRangesOfNode(node, sourceFile); - if (comments) { - for (var _i = 0, comments_1 = comments; _i < comments_1.length; _i++) { - var comment = comments_1[_i]; - var jsDocComment = JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos); - if (!jsDocComment) { - continue; - } - if (!node.jsDocComments) { - node.jsDocComments = []; - } - node.jsDocComments.push(jsDocComment); - } - } - } - return node; + return node; + } + ts.updateObjectBindingPattern = updateObjectBindingPattern; + function createArrayBindingPattern(elements, location) { + var node = createNode(168 /* ArrayBindingPattern */, location); + node.elements = createNodeArray(elements); + return node; + } + ts.createArrayBindingPattern = createArrayBindingPattern; + function updateArrayBindingPattern(node, elements) { + if (node.elements !== elements) { + return updateNode(createArrayBindingPattern(elements, node), node); } - function fixupParentReferences(rootNode) { - // normally parent references are set during binding. However, for clients that only need - // a syntax tree, and no semantic features, then the binding process is an unnecessary - // overhead. This functions allows us to set all the parents, without all the expense of - // binding. - var parent = rootNode; - forEachChild(rootNode, visitNode); - return; - function visitNode(n) { - // walk down setting parents that differ from the parent we think it should be. This - // allows us to quickly bail out of setting parents for subtrees during incremental - // parsing - if (n.parent !== parent) { - n.parent = parent; - var saveParent = parent; - parent = n; - forEachChild(n, visitNode); - if (n.jsDocComments) { - for (var _i = 0, _a = n.jsDocComments; _i < _a.length; _i++) { - var jsDocComment = _a[_i]; - jsDocComment.parent = n; - parent = jsDocComment; - forEachChild(jsDocComment, visitNode); - } - } - parent = saveParent; - } - } + return node; + } + ts.updateArrayBindingPattern = updateArrayBindingPattern; + function createBindingElement(propertyName, dotDotDotToken, name, initializer, location) { + var node = createNode(169 /* BindingElement */, location); + node.propertyName = typeof propertyName === "string" ? createIdentifier(propertyName) : propertyName; + node.dotDotDotToken = dotDotDotToken; + node.name = typeof name === "string" ? createIdentifier(name) : name; + node.initializer = initializer; + return node; + } + ts.createBindingElement = createBindingElement; + function updateBindingElement(node, propertyName, name, initializer) { + if (node.propertyName !== propertyName || node.name !== name || node.initializer !== initializer) { + return updateNode(createBindingElement(propertyName, node.dotDotDotToken, name, initializer, node), node); } - Parser.fixupParentReferences = fixupParentReferences; - function createSourceFile(fileName, languageVersion, scriptKind) { - // code from createNode is inlined here so createNode won't have to deal with special case of creating source files - // this is quite rare comparing to other nodes and createNode should be as fast as possible - var sourceFile = new SourceFileConstructor(256 /* SourceFile */, /*pos*/ 0, /* end */ sourceText.length); - nodeCount++; - sourceFile.text = sourceText; - sourceFile.bindDiagnostics = []; - sourceFile.languageVersion = languageVersion; - sourceFile.fileName = ts.normalizePath(fileName); - sourceFile.languageVariant = getLanguageVariant(scriptKind); - sourceFile.isDeclarationFile = ts.fileExtensionIs(sourceFile.fileName, ".d.ts"); - sourceFile.scriptKind = scriptKind; - return sourceFile; + return node; + } + ts.updateBindingElement = updateBindingElement; + // Expression + function createArrayLiteral(elements, location, multiLine) { + var node = createNode(170 /* ArrayLiteralExpression */, location); + node.elements = parenthesizeListElements(createNodeArray(elements)); + if (multiLine) { + node.multiLine = true; } - function setContextFlag(val, flag) { - if (val) { - contextFlags |= flag; - } - else { - contextFlags &= ~flag; - } + return node; + } + ts.createArrayLiteral = createArrayLiteral; + function updateArrayLiteral(node, elements) { + if (node.elements !== elements) { + return updateNode(createArrayLiteral(elements, node, node.multiLine), node); } - function setDisallowInContext(val) { - setContextFlag(val, 4194304 /* DisallowInContext */); + return node; + } + ts.updateArrayLiteral = updateArrayLiteral; + function createObjectLiteral(properties, location, multiLine) { + var node = createNode(171 /* ObjectLiteralExpression */, location); + node.properties = createNodeArray(properties); + if (multiLine) { + node.multiLine = true; } - function setYieldContext(val) { - setContextFlag(val, 8388608 /* YieldContext */); + return node; + } + ts.createObjectLiteral = createObjectLiteral; + function updateObjectLiteral(node, properties) { + if (node.properties !== properties) { + return updateNode(createObjectLiteral(properties, node, node.multiLine), node); } - function setDecoratorContext(val) { - setContextFlag(val, 16777216 /* DecoratorContext */); + return node; + } + ts.updateObjectLiteral = updateObjectLiteral; + function createPropertyAccess(expression, name, location, flags) { + var node = createNode(172 /* PropertyAccessExpression */, location, flags); + node.expression = parenthesizeForAccess(expression); + (node.emitNode || (node.emitNode = {})).flags |= 1048576 /* NoIndentation */; + node.name = typeof name === "string" ? createIdentifier(name) : name; + return node; + } + ts.createPropertyAccess = createPropertyAccess; + function updatePropertyAccess(node, expression, name) { + if (node.expression !== expression || node.name !== name) { + var propertyAccess = createPropertyAccess(expression, name, /*location*/ node, node.flags); + // Because we are updating existed propertyAccess we want to inherit its emitFlags instead of using default from createPropertyAccess + (propertyAccess.emitNode || (propertyAccess.emitNode = {})).flags = getEmitFlags(node); + return updateNode(propertyAccess, node); } - function setAwaitContext(val) { - setContextFlag(val, 33554432 /* AwaitContext */); + return node; + } + ts.updatePropertyAccess = updatePropertyAccess; + function createElementAccess(expression, index, location) { + var node = createNode(173 /* ElementAccessExpression */, location); + node.expression = parenthesizeForAccess(expression); + node.argumentExpression = typeof index === "number" ? createLiteral(index) : index; + return node; + } + ts.createElementAccess = createElementAccess; + function updateElementAccess(node, expression, argumentExpression) { + if (node.expression !== expression || node.argumentExpression !== argumentExpression) { + return updateNode(createElementAccess(expression, argumentExpression, node), node); } - function doOutsideOfContext(context, func) { - // contextFlagsToClear will contain only the context flags that are - // currently set that we need to temporarily clear - // We don't just blindly reset to the previous flags to ensure - // that we do not mutate cached flags for the incremental - // parser (ThisNodeHasError, ThisNodeOrAnySubNodesHasError, and - // HasAggregatedChildData). - var contextFlagsToClear = context & contextFlags; - if (contextFlagsToClear) { - // clear the requested context flags - setContextFlag(/*val*/ false, contextFlagsToClear); - var result = func(); - // restore the context flags we just cleared - setContextFlag(/*val*/ true, contextFlagsToClear); - return result; - } - // no need to do anything special as we are not in any of the requested contexts - return func(); + return node; + } + ts.updateElementAccess = updateElementAccess; + function createCall(expression, typeArguments, argumentsArray, location, flags) { + var node = createNode(174 /* CallExpression */, location, flags); + node.expression = parenthesizeForAccess(expression); + if (typeArguments) { + node.typeArguments = createNodeArray(typeArguments); } - function doInsideOfContext(context, func) { - // contextFlagsToSet will contain only the context flags that - // are not currently set that we need to temporarily enable. - // We don't just blindly reset to the previous flags to ensure - // that we do not mutate cached flags for the incremental - // parser (ThisNodeHasError, ThisNodeOrAnySubNodesHasError, and - // HasAggregatedChildData). - var contextFlagsToSet = context & ~contextFlags; - if (contextFlagsToSet) { - // set the requested context flags - setContextFlag(/*val*/ true, contextFlagsToSet); - var result = func(); - // reset the context flags we just set - setContextFlag(/*val*/ false, contextFlagsToSet); - return result; - } - // no need to do anything special as we are already in all of the requested contexts - return func(); + node.arguments = parenthesizeListElements(createNodeArray(argumentsArray)); + return node; + } + ts.createCall = createCall; + function updateCall(node, expression, typeArguments, argumentsArray) { + if (expression !== node.expression || typeArguments !== node.typeArguments || argumentsArray !== node.arguments) { + return updateNode(createCall(expression, typeArguments, argumentsArray, /*location*/ node, node.flags), node); } - function allowInAnd(func) { - return doOutsideOfContext(4194304 /* DisallowInContext */, func); + return node; + } + ts.updateCall = updateCall; + function createNew(expression, typeArguments, argumentsArray, location, flags) { + var node = createNode(175 /* NewExpression */, location, flags); + node.expression = parenthesizeForNew(expression); + node.typeArguments = typeArguments ? createNodeArray(typeArguments) : undefined; + node.arguments = argumentsArray ? parenthesizeListElements(createNodeArray(argumentsArray)) : undefined; + return node; + } + ts.createNew = createNew; + function updateNew(node, expression, typeArguments, argumentsArray) { + if (node.expression !== expression || node.typeArguments !== typeArguments || node.arguments !== argumentsArray) { + return updateNode(createNew(expression, typeArguments, argumentsArray, /*location*/ node, node.flags), node); } - function disallowInAnd(func) { - return doInsideOfContext(4194304 /* DisallowInContext */, func); + return node; + } + ts.updateNew = updateNew; + function createTaggedTemplate(tag, template, location) { + var node = createNode(176 /* TaggedTemplateExpression */, location); + node.tag = parenthesizeForAccess(tag); + node.template = template; + return node; + } + ts.createTaggedTemplate = createTaggedTemplate; + function updateTaggedTemplate(node, tag, template) { + if (node.tag !== tag || node.template !== template) { + return updateNode(createTaggedTemplate(tag, template, node), node); } - function doInYieldContext(func) { - return doInsideOfContext(8388608 /* YieldContext */, func); + return node; + } + ts.updateTaggedTemplate = updateTaggedTemplate; + function createParen(expression, location) { + var node = createNode(178 /* ParenthesizedExpression */, location); + node.expression = expression; + return node; + } + ts.createParen = createParen; + function updateParen(node, expression) { + if (node.expression !== expression) { + return updateNode(createParen(expression, node), node); } - function doInDecoratorContext(func) { - return doInsideOfContext(16777216 /* DecoratorContext */, func); + return node; + } + ts.updateParen = updateParen; + function createFunctionExpression(asteriskToken, name, typeParameters, parameters, type, body, location, flags) { + var node = createNode(179 /* FunctionExpression */, location, flags); + node.modifiers = undefined; + node.asteriskToken = asteriskToken; + node.name = typeof name === "string" ? createIdentifier(name) : name; + node.typeParameters = typeParameters ? createNodeArray(typeParameters) : undefined; + node.parameters = createNodeArray(parameters); + node.type = type; + node.body = body; + return node; + } + ts.createFunctionExpression = createFunctionExpression; + function updateFunctionExpression(node, name, typeParameters, parameters, type, body) { + if (node.name !== name || node.typeParameters !== typeParameters || node.parameters !== parameters || node.type !== type || node.body !== body) { + return updateNode(createFunctionExpression(node.asteriskToken, name, typeParameters, parameters, type, body, /*location*/ node, node.flags), node); } - function doInAwaitContext(func) { - return doInsideOfContext(33554432 /* AwaitContext */, func); + return node; + } + ts.updateFunctionExpression = updateFunctionExpression; + function createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanToken, body, location, flags) { + var node = createNode(180 /* ArrowFunction */, location, flags); + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.typeParameters = typeParameters ? createNodeArray(typeParameters) : undefined; + node.parameters = createNodeArray(parameters); + node.type = type; + node.equalsGreaterThanToken = equalsGreaterThanToken || createNode(34 /* EqualsGreaterThanToken */); + node.body = parenthesizeConciseBody(body); + return node; + } + ts.createArrowFunction = createArrowFunction; + function updateArrowFunction(node, modifiers, typeParameters, parameters, type, body) { + if (node.modifiers !== modifiers || node.typeParameters !== typeParameters || node.parameters !== parameters || node.type !== type || node.body !== body) { + return updateNode(createArrowFunction(modifiers, typeParameters, parameters, type, node.equalsGreaterThanToken, body, /*location*/ node, node.flags), node); } - function doOutsideOfAwaitContext(func) { - return doOutsideOfContext(33554432 /* AwaitContext */, func); + return node; + } + ts.updateArrowFunction = updateArrowFunction; + function createDelete(expression, location) { + var node = createNode(181 /* DeleteExpression */, location); + node.expression = parenthesizePrefixOperand(expression); + return node; + } + ts.createDelete = createDelete; + function updateDelete(node, expression) { + if (node.expression !== expression) { + return updateNode(createDelete(expression, node), expression); } - function doInYieldAndAwaitContext(func) { - return doInsideOfContext(8388608 /* YieldContext */ | 33554432 /* AwaitContext */, func); + return node; + } + ts.updateDelete = updateDelete; + function createTypeOf(expression, location) { + var node = createNode(182 /* TypeOfExpression */, location); + node.expression = parenthesizePrefixOperand(expression); + return node; + } + ts.createTypeOf = createTypeOf; + function updateTypeOf(node, expression) { + if (node.expression !== expression) { + return updateNode(createTypeOf(expression, node), expression); } - function inContext(flags) { - return (contextFlags & flags) !== 0; + return node; + } + ts.updateTypeOf = updateTypeOf; + function createVoid(expression, location) { + var node = createNode(183 /* VoidExpression */, location); + node.expression = parenthesizePrefixOperand(expression); + return node; + } + ts.createVoid = createVoid; + function updateVoid(node, expression) { + if (node.expression !== expression) { + return updateNode(createVoid(expression, node), node); } - function inYieldContext() { - return inContext(8388608 /* YieldContext */); + return node; + } + ts.updateVoid = updateVoid; + function createAwait(expression, location) { + var node = createNode(184 /* AwaitExpression */, location); + node.expression = parenthesizePrefixOperand(expression); + return node; + } + ts.createAwait = createAwait; + function updateAwait(node, expression) { + if (node.expression !== expression) { + return updateNode(createAwait(expression, node), node); } - function inDisallowInContext() { - return inContext(4194304 /* DisallowInContext */); + return node; + } + ts.updateAwait = updateAwait; + function createPrefix(operator, operand, location) { + var node = createNode(185 /* PrefixUnaryExpression */, location); + node.operator = operator; + node.operand = parenthesizePrefixOperand(operand); + return node; + } + ts.createPrefix = createPrefix; + function updatePrefix(node, operand) { + if (node.operand !== operand) { + return updateNode(createPrefix(node.operator, operand, node), node); } - function inDecoratorContext() { - return inContext(16777216 /* DecoratorContext */); + return node; + } + ts.updatePrefix = updatePrefix; + function createPostfix(operand, operator, location) { + var node = createNode(186 /* PostfixUnaryExpression */, location); + node.operand = parenthesizePostfixOperand(operand); + node.operator = operator; + return node; + } + ts.createPostfix = createPostfix; + function updatePostfix(node, operand) { + if (node.operand !== operand) { + return updateNode(createPostfix(operand, node.operator, node), node); } - function inAwaitContext() { - return inContext(33554432 /* AwaitContext */); + return node; + } + ts.updatePostfix = updatePostfix; + function createBinary(left, operator, right, location) { + var operatorToken = typeof operator === "number" ? createSynthesizedNode(operator) : operator; + var operatorKind = operatorToken.kind; + var node = createNode(187 /* BinaryExpression */, location); + node.left = parenthesizeBinaryOperand(operatorKind, left, /*isLeftSideOfBinary*/ true, /*leftOperand*/ undefined); + node.operatorToken = operatorToken; + node.right = parenthesizeBinaryOperand(operatorKind, right, /*isLeftSideOfBinary*/ false, node.left); + return node; + } + ts.createBinary = createBinary; + function updateBinary(node, left, right) { + if (node.left !== left || node.right !== right) { + return updateNode(createBinary(left, node.operatorToken, right, /*location*/ node), node); } - function parseErrorAtCurrentToken(message, arg0) { - var start = scanner.getTokenPos(); - var length = scanner.getTextPos() - start; - parseErrorAtPosition(start, length, message, arg0); + return node; + } + ts.updateBinary = updateBinary; + function createConditional(condition, questionToken, whenTrue, colonToken, whenFalse, location) { + var node = createNode(188 /* ConditionalExpression */, location); + node.condition = condition; + node.questionToken = questionToken; + node.whenTrue = whenTrue; + node.colonToken = colonToken; + node.whenFalse = whenFalse; + return node; + } + ts.createConditional = createConditional; + function updateConditional(node, condition, whenTrue, whenFalse) { + if (node.condition !== condition || node.whenTrue !== whenTrue || node.whenFalse !== whenFalse) { + return updateNode(createConditional(condition, node.questionToken, whenTrue, node.colonToken, whenFalse, node), node); } - function parseErrorAtPosition(start, length, message, arg0) { - // Don't report another error if it would just be at the same position as the last error. - var lastError = ts.lastOrUndefined(parseDiagnostics); - if (!lastError || start !== lastError.start) { - parseDiagnostics.push(ts.createFileDiagnostic(sourceFile, start, length, message, arg0)); - } - // Mark that we've encountered an error. We'll set an appropriate bit on the next - // node we finish so that it can't be reused incrementally. - parseErrorBeforeNextFinishedNode = true; + return node; + } + ts.updateConditional = updateConditional; + function createTemplateExpression(head, templateSpans, location) { + var node = createNode(189 /* TemplateExpression */, location); + node.head = head; + node.templateSpans = createNodeArray(templateSpans); + return node; + } + ts.createTemplateExpression = createTemplateExpression; + function updateTemplateExpression(node, head, templateSpans) { + if (node.head !== head || node.templateSpans !== templateSpans) { + return updateNode(createTemplateExpression(head, templateSpans, node), node); } - function scanError(message, length) { - var pos = scanner.getTextPos(); - parseErrorAtPosition(pos, length || 0, message); + return node; + } + ts.updateTemplateExpression = updateTemplateExpression; + function createYield(asteriskToken, expression, location) { + var node = createNode(190 /* YieldExpression */, location); + node.asteriskToken = asteriskToken; + node.expression = expression; + return node; + } + ts.createYield = createYield; + function updateYield(node, expression) { + if (node.expression !== expression) { + return updateNode(createYield(node.asteriskToken, expression, node), node); } - function getNodePos() { - return scanner.getStartPos(); + return node; + } + ts.updateYield = updateYield; + function createSpread(expression, location) { + var node = createNode(191 /* SpreadElementExpression */, location); + node.expression = parenthesizeExpressionForList(expression); + return node; + } + ts.createSpread = createSpread; + function updateSpread(node, expression) { + if (node.expression !== expression) { + return updateNode(createSpread(expression, node), node); } - function getNodeEnd() { - return scanner.getStartPos(); + return node; + } + ts.updateSpread = updateSpread; + function createClassExpression(modifiers, name, typeParameters, heritageClauses, members, location) { + var node = createNode(192 /* ClassExpression */, location); + node.decorators = undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.name = name; + node.typeParameters = typeParameters ? createNodeArray(typeParameters) : undefined; + node.heritageClauses = createNodeArray(heritageClauses); + node.members = createNodeArray(members); + return node; + } + ts.createClassExpression = createClassExpression; + function updateClassExpression(node, modifiers, name, typeParameters, heritageClauses, members) { + if (node.modifiers !== modifiers || node.name !== name || node.typeParameters !== typeParameters || node.heritageClauses !== heritageClauses || node.members !== members) { + return updateNode(createClassExpression(modifiers, name, typeParameters, heritageClauses, members, node), node); } - // Use this function to access the current token instead of reading the currentToken - // variable. Since function results aren't narrowed in control flow analysis, this ensures - // that the type checker doesn't make wrong assumptions about the type of the current - // token (e.g. a call to nextToken() changes the current token but the checker doesn't - // reason about this side effect). Mainstream VMs inline simple functions like this, so - // there is no performance penalty. - function token() { - return currentToken; + return node; + } + ts.updateClassExpression = updateClassExpression; + function createOmittedExpression(location) { + var node = createNode(193 /* OmittedExpression */, location); + return node; + } + ts.createOmittedExpression = createOmittedExpression; + function createExpressionWithTypeArguments(typeArguments, expression, location) { + var node = createNode(194 /* ExpressionWithTypeArguments */, location); + node.typeArguments = typeArguments ? createNodeArray(typeArguments) : undefined; + node.expression = parenthesizeForAccess(expression); + return node; + } + ts.createExpressionWithTypeArguments = createExpressionWithTypeArguments; + function updateExpressionWithTypeArguments(node, typeArguments, expression) { + if (node.typeArguments !== typeArguments || node.expression !== expression) { + return updateNode(createExpressionWithTypeArguments(typeArguments, expression, node), node); } - function nextToken() { - return currentToken = scanner.scan(); + return node; + } + ts.updateExpressionWithTypeArguments = updateExpressionWithTypeArguments; + // Misc + function createTemplateSpan(expression, literal, location) { + var node = createNode(197 /* TemplateSpan */, location); + node.expression = expression; + node.literal = literal; + return node; + } + ts.createTemplateSpan = createTemplateSpan; + function updateTemplateSpan(node, expression, literal) { + if (node.expression !== expression || node.literal !== literal) { + return updateNode(createTemplateSpan(expression, literal, node), node); } - function reScanGreaterToken() { - return currentToken = scanner.reScanGreaterToken(); + return node; + } + ts.updateTemplateSpan = updateTemplateSpan; + // Element + function createBlock(statements, location, multiLine, flags) { + var block = createNode(199 /* Block */, location, flags); + block.statements = createNodeArray(statements); + if (multiLine) { + block.multiLine = true; } - function reScanSlashToken() { - return currentToken = scanner.reScanSlashToken(); + return block; + } + ts.createBlock = createBlock; + function updateBlock(node, statements) { + if (statements !== node.statements) { + return updateNode(createBlock(statements, /*location*/ node, node.multiLine, node.flags), node); } - function reScanTemplateToken() { - return currentToken = scanner.reScanTemplateToken(); + return node; + } + ts.updateBlock = updateBlock; + function createVariableStatement(modifiers, declarationList, location, flags) { + var node = createNode(200 /* VariableStatement */, location, flags); + node.decorators = undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.declarationList = ts.isArray(declarationList) ? createVariableDeclarationList(declarationList) : declarationList; + return node; + } + ts.createVariableStatement = createVariableStatement; + function updateVariableStatement(node, modifiers, declarationList) { + if (node.modifiers !== modifiers || node.declarationList !== declarationList) { + return updateNode(createVariableStatement(modifiers, declarationList, /*location*/ node, node.flags), node); } - function scanJsxIdentifier() { - return currentToken = scanner.scanJsxIdentifier(); + return node; + } + ts.updateVariableStatement = updateVariableStatement; + function createVariableDeclarationList(declarations, location, flags) { + var node = createNode(219 /* VariableDeclarationList */, location, flags); + node.declarations = createNodeArray(declarations); + return node; + } + ts.createVariableDeclarationList = createVariableDeclarationList; + function updateVariableDeclarationList(node, declarations) { + if (node.declarations !== declarations) { + return updateNode(createVariableDeclarationList(declarations, /*location*/ node, node.flags), node); } - function scanJsxText() { - return currentToken = scanner.scanJsxToken(); + return node; + } + ts.updateVariableDeclarationList = updateVariableDeclarationList; + function createVariableDeclaration(name, type, initializer, location, flags) { + var node = createNode(218 /* VariableDeclaration */, location, flags); + node.name = typeof name === "string" ? createIdentifier(name) : name; + node.type = type; + node.initializer = initializer !== undefined ? parenthesizeExpressionForList(initializer) : undefined; + return node; + } + ts.createVariableDeclaration = createVariableDeclaration; + function updateVariableDeclaration(node, name, type, initializer) { + if (node.name !== name || node.type !== type || node.initializer !== initializer) { + return updateNode(createVariableDeclaration(name, type, initializer, /*location*/ node, node.flags), node); } - function speculationHelper(callback, isLookAhead) { - // Keep track of the state we'll need to rollback to if lookahead fails (or if the - // caller asked us to always reset our state). - var saveToken = currentToken; - var saveParseDiagnosticsLength = parseDiagnostics.length; - var saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode; - // Note: it is not actually necessary to save/restore the context flags here. That's - // because the saving/restoring of these flags happens naturally through the recursive - // descent nature of our parser. However, we still store this here just so we can - // assert that invariant holds. - var saveContextFlags = contextFlags; - // If we're only looking ahead, then tell the scanner to only lookahead as well. - // Otherwise, if we're actually speculatively parsing, then tell the scanner to do the - // same. - var result = isLookAhead - ? scanner.lookAhead(callback) - : scanner.tryScan(callback); - ts.Debug.assert(saveContextFlags === contextFlags); - // If our callback returned something 'falsy' or we're just looking ahead, - // then unconditionally restore us to where we were. - if (!result || isLookAhead) { - currentToken = saveToken; - parseDiagnostics.length = saveParseDiagnosticsLength; - parseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode; - } - return result; + return node; + } + ts.updateVariableDeclaration = updateVariableDeclaration; + function createEmptyStatement(location) { + return createNode(201 /* EmptyStatement */, location); + } + ts.createEmptyStatement = createEmptyStatement; + function createStatement(expression, location, flags) { + var node = createNode(202 /* ExpressionStatement */, location, flags); + node.expression = parenthesizeExpressionForExpressionStatement(expression); + return node; + } + ts.createStatement = createStatement; + function updateStatement(node, expression) { + if (node.expression !== expression) { + return updateNode(createStatement(expression, /*location*/ node, node.flags), node); } - /** Invokes the provided callback then unconditionally restores the parser to the state it - * was in immediately prior to invoking the callback. The result of invoking the callback - * is returned from this function. - */ - function lookAhead(callback) { - return speculationHelper(callback, /*isLookAhead*/ true); + return node; + } + ts.updateStatement = updateStatement; + function createIf(expression, thenStatement, elseStatement, location) { + var node = createNode(203 /* IfStatement */, location); + node.expression = expression; + node.thenStatement = thenStatement; + node.elseStatement = elseStatement; + return node; + } + ts.createIf = createIf; + function updateIf(node, expression, thenStatement, elseStatement) { + if (node.expression !== expression || node.thenStatement !== thenStatement || node.elseStatement !== elseStatement) { + return updateNode(createIf(expression, thenStatement, elseStatement, /*location*/ node), node); } - /** Invokes the provided callback. If the callback returns something falsy, then it restores - * the parser to the state it was in immediately prior to invoking the callback. If the - * callback returns something truthy, then the parser state is not rolled back. The result - * of invoking the callback is returned from this function. - */ - function tryParse(callback) { - return speculationHelper(callback, /*isLookAhead*/ false); + return node; + } + ts.updateIf = updateIf; + function createDo(statement, expression, location) { + var node = createNode(204 /* DoStatement */, location); + node.statement = statement; + node.expression = expression; + return node; + } + ts.createDo = createDo; + function updateDo(node, statement, expression) { + if (node.statement !== statement || node.expression !== expression) { + return updateNode(createDo(statement, expression, node), node); } - // Ignore strict mode flag because we will report an error in type checker instead. - function isIdentifier() { - if (token() === 69 /* Identifier */) { - return true; - } - // If we have a 'yield' keyword, and we're in the [yield] context, then 'yield' is - // considered a keyword and is not an identifier. - if (token() === 114 /* YieldKeyword */ && inYieldContext()) { - return false; - } - // If we have a 'await' keyword, and we're in the [Await] context, then 'await' is - // considered a keyword and is not an identifier. - if (token() === 119 /* AwaitKeyword */ && inAwaitContext()) { - return false; - } - return token() > 105 /* LastReservedWord */; + return node; + } + ts.updateDo = updateDo; + function createWhile(expression, statement, location) { + var node = createNode(205 /* WhileStatement */, location); + node.expression = expression; + node.statement = statement; + return node; + } + ts.createWhile = createWhile; + function updateWhile(node, expression, statement) { + if (node.expression !== expression || node.statement !== statement) { + return updateNode(createWhile(expression, statement, node), node); } - function parseExpected(kind, diagnosticMessage, shouldAdvance) { - if (shouldAdvance === void 0) { shouldAdvance = true; } - if (token() === kind) { - if (shouldAdvance) { - nextToken(); - } - return true; - } - // Report specific message if provided with one. Otherwise, report generic fallback message. - if (diagnosticMessage) { - parseErrorAtCurrentToken(diagnosticMessage); - } - else { - parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(kind)); - } - return false; + return node; + } + ts.updateWhile = updateWhile; + function createFor(initializer, condition, incrementor, statement, location) { + var node = createNode(206 /* ForStatement */, location, /*flags*/ undefined); + node.initializer = initializer; + node.condition = condition; + node.incrementor = incrementor; + node.statement = statement; + return node; + } + ts.createFor = createFor; + function updateFor(node, initializer, condition, incrementor, statement) { + if (node.initializer !== initializer || node.condition !== condition || node.incrementor !== incrementor || node.statement !== statement) { + return updateNode(createFor(initializer, condition, incrementor, statement, node), node); } - function parseOptional(t) { - if (token() === t) { - nextToken(); - return true; - } - return false; + return node; + } + ts.updateFor = updateFor; + function createForIn(initializer, expression, statement, location) { + var node = createNode(207 /* ForInStatement */, location); + node.initializer = initializer; + node.expression = expression; + node.statement = statement; + return node; + } + ts.createForIn = createForIn; + function updateForIn(node, initializer, expression, statement) { + if (node.initializer !== initializer || node.expression !== expression || node.statement !== statement) { + return updateNode(createForIn(initializer, expression, statement, node), node); } - function parseOptionalToken(t) { - if (token() === t) { - return parseTokenNode(); - } - return undefined; + return node; + } + ts.updateForIn = updateForIn; + function createForOf(initializer, expression, statement, location) { + var node = createNode(208 /* ForOfStatement */, location); + node.initializer = initializer; + node.expression = expression; + node.statement = statement; + return node; + } + ts.createForOf = createForOf; + function updateForOf(node, initializer, expression, statement) { + if (node.initializer !== initializer || node.expression !== expression || node.statement !== statement) { + return updateNode(createForOf(initializer, expression, statement, node), node); } - function parseExpectedToken(t, reportAtCurrentPosition, diagnosticMessage, arg0) { - return parseOptionalToken(t) || - createMissingNode(t, reportAtCurrentPosition, diagnosticMessage, arg0); + return node; + } + ts.updateForOf = updateForOf; + function createContinue(label, location) { + var node = createNode(209 /* ContinueStatement */, location); + if (label) { + node.label = label; } - function parseTokenNode() { - var node = createNode(token()); - nextToken(); - return finishNode(node); + return node; + } + ts.createContinue = createContinue; + function updateContinue(node, label) { + if (node.label !== label) { + return updateNode(createContinue(label, node), node); } - function canParseSemicolon() { - // If there's a real semicolon, then we can always parse it out. - if (token() === 23 /* SemicolonToken */) { - return true; - } - // We can parse out an optional semicolon in ASI cases in the following cases. - return token() === 16 /* CloseBraceToken */ || token() === 1 /* EndOfFileToken */ || scanner.hasPrecedingLineBreak(); + return node; + } + ts.updateContinue = updateContinue; + function createBreak(label, location) { + var node = createNode(210 /* BreakStatement */, location); + if (label) { + node.label = label; } - function parseSemicolon() { - if (canParseSemicolon()) { - if (token() === 23 /* SemicolonToken */) { - // consume the semicolon if it was explicitly provided. - nextToken(); - } - return true; - } - else { - return parseExpected(23 /* SemicolonToken */); - } + return node; + } + ts.createBreak = createBreak; + function updateBreak(node, label) { + if (node.label !== label) { + return updateNode(createBreak(label, node), node); } - // note: this function creates only node - function createNode(kind, pos) { - nodeCount++; - if (!(pos >= 0)) { - pos = scanner.getStartPos(); - } - return kind >= 139 /* FirstNode */ ? new NodeConstructor(kind, pos, pos) : - kind === 69 /* Identifier */ ? new IdentifierConstructor(kind, pos, pos) : - new TokenConstructor(kind, pos, pos); + return node; + } + ts.updateBreak = updateBreak; + function createReturn(expression, location) { + var node = createNode(211 /* ReturnStatement */, location); + node.expression = expression; + return node; + } + ts.createReturn = createReturn; + function updateReturn(node, expression) { + if (node.expression !== expression) { + return updateNode(createReturn(expression, /*location*/ node), node); } - function finishNode(node, end) { - node.end = end === undefined ? scanner.getStartPos() : end; - if (contextFlags) { - node.flags |= contextFlags; - } - // Keep track on the node if we encountered an error while parsing it. If we did, then - // we cannot reuse the node incrementally. Once we've marked this node, clear out the - // flag so that we don't mark any subsequent nodes. - if (parseErrorBeforeNextFinishedNode) { - parseErrorBeforeNextFinishedNode = false; - node.flags |= 67108864 /* ThisNodeHasError */; - } - return node; + return node; + } + ts.updateReturn = updateReturn; + function createWith(expression, statement, location) { + var node = createNode(212 /* WithStatement */, location); + node.expression = expression; + node.statement = statement; + return node; + } + ts.createWith = createWith; + function updateWith(node, expression, statement) { + if (node.expression !== expression || node.statement !== statement) { + return updateNode(createWith(expression, statement, node), node); } - function createMissingNode(kind, reportAtCurrentPosition, diagnosticMessage, arg0) { - if (reportAtCurrentPosition) { - parseErrorAtPosition(scanner.getStartPos(), 0, diagnosticMessage, arg0); - } - else { - parseErrorAtCurrentToken(diagnosticMessage, arg0); - } - var result = createNode(kind, scanner.getStartPos()); - result.text = ""; - return finishNode(result); + return node; + } + ts.updateWith = updateWith; + function createSwitch(expression, caseBlock, location) { + var node = createNode(213 /* SwitchStatement */, location); + node.expression = parenthesizeExpressionForList(expression); + node.caseBlock = caseBlock; + return node; + } + ts.createSwitch = createSwitch; + function updateSwitch(node, expression, caseBlock) { + if (node.expression !== expression || node.caseBlock !== caseBlock) { + return updateNode(createSwitch(expression, caseBlock, node), node); } - function internIdentifier(text) { - text = ts.escapeIdentifier(text); - return identifiers[text] || (identifiers[text] = text); + return node; + } + ts.updateSwitch = updateSwitch; + function createLabel(label, statement, location) { + var node = createNode(214 /* LabeledStatement */, location); + node.label = typeof label === "string" ? createIdentifier(label) : label; + node.statement = statement; + return node; + } + ts.createLabel = createLabel; + function updateLabel(node, label, statement) { + if (node.label !== label || node.statement !== statement) { + return updateNode(createLabel(label, statement, node), node); } - // An identifier that starts with two underscores has an extra underscore character prepended to it to avoid issues - // with magic property names like '__proto__'. The 'identifiers' object is used to share a single string instance for - // each identifier in order to reduce memory consumption. - function createIdentifier(isIdentifier, diagnosticMessage) { - identifierCount++; - if (isIdentifier) { - var node = createNode(69 /* Identifier */); - // Store original token kind if it is not just an Identifier so we can report appropriate error later in type checker - if (token() !== 69 /* Identifier */) { - node.originalKeywordKind = token(); - } - node.text = internIdentifier(scanner.getTokenValue()); - nextToken(); - return finishNode(node); - } - return createMissingNode(69 /* Identifier */, /*reportAtCurrentPosition*/ false, diagnosticMessage || ts.Diagnostics.Identifier_expected); + return node; + } + ts.updateLabel = updateLabel; + function createThrow(expression, location) { + var node = createNode(215 /* ThrowStatement */, location); + node.expression = expression; + return node; + } + ts.createThrow = createThrow; + function updateThrow(node, expression) { + if (node.expression !== expression) { + return updateNode(createThrow(expression, node), node); } - function parseIdentifier(diagnosticMessage) { - return createIdentifier(isIdentifier(), diagnosticMessage); + return node; + } + ts.updateThrow = updateThrow; + function createTry(tryBlock, catchClause, finallyBlock, location) { + var node = createNode(216 /* TryStatement */, location); + node.tryBlock = tryBlock; + node.catchClause = catchClause; + node.finallyBlock = finallyBlock; + return node; + } + ts.createTry = createTry; + function updateTry(node, tryBlock, catchClause, finallyBlock) { + if (node.tryBlock !== tryBlock || node.catchClause !== catchClause || node.finallyBlock !== finallyBlock) { + return updateNode(createTry(tryBlock, catchClause, finallyBlock, node), node); } - function parseIdentifierName() { - return createIdentifier(ts.tokenIsIdentifierOrKeyword(token())); + return node; + } + ts.updateTry = updateTry; + function createCaseBlock(clauses, location) { + var node = createNode(227 /* CaseBlock */, location); + node.clauses = createNodeArray(clauses); + return node; + } + ts.createCaseBlock = createCaseBlock; + function updateCaseBlock(node, clauses) { + if (node.clauses !== clauses) { + return updateNode(createCaseBlock(clauses, node), node); } - function isLiteralPropertyName() { - return ts.tokenIsIdentifierOrKeyword(token()) || - token() === 9 /* StringLiteral */ || - token() === 8 /* NumericLiteral */; + return node; + } + ts.updateCaseBlock = updateCaseBlock; + function createFunctionDeclaration(decorators, modifiers, asteriskToken, name, typeParameters, parameters, type, body, location, flags) { + var node = createNode(220 /* FunctionDeclaration */, location, flags); + node.decorators = decorators ? createNodeArray(decorators) : undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.asteriskToken = asteriskToken; + node.name = typeof name === "string" ? createIdentifier(name) : name; + node.typeParameters = typeParameters ? createNodeArray(typeParameters) : undefined; + node.parameters = createNodeArray(parameters); + node.type = type; + node.body = body; + return node; + } + ts.createFunctionDeclaration = createFunctionDeclaration; + function updateFunctionDeclaration(node, decorators, modifiers, name, typeParameters, parameters, type, body) { + if (node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name || node.typeParameters !== typeParameters || node.parameters !== parameters || node.type !== type || node.body !== body) { + return updateNode(createFunctionDeclaration(decorators, modifiers, node.asteriskToken, name, typeParameters, parameters, type, body, /*location*/ node, node.flags), node); } - function parsePropertyNameWorker(allowComputedPropertyNames) { - if (token() === 9 /* StringLiteral */ || token() === 8 /* NumericLiteral */) { - return parseLiteralNode(/*internName*/ true); - } - if (allowComputedPropertyNames && token() === 19 /* OpenBracketToken */) { - return parseComputedPropertyName(); - } - return parseIdentifierName(); + return node; + } + ts.updateFunctionDeclaration = updateFunctionDeclaration; + function createClassDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members, location) { + var node = createNode(221 /* ClassDeclaration */, location); + node.decorators = decorators ? createNodeArray(decorators) : undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.name = name; + node.typeParameters = typeParameters ? createNodeArray(typeParameters) : undefined; + node.heritageClauses = createNodeArray(heritageClauses); + node.members = createNodeArray(members); + return node; + } + ts.createClassDeclaration = createClassDeclaration; + function updateClassDeclaration(node, decorators, modifiers, name, typeParameters, heritageClauses, members) { + if (node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name || node.typeParameters !== typeParameters || node.heritageClauses !== heritageClauses || node.members !== members) { + return updateNode(createClassDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members, node), node); } - function parsePropertyName() { - return parsePropertyNameWorker(/*allowComputedPropertyNames*/ true); + return node; + } + ts.updateClassDeclaration = updateClassDeclaration; + function createImportDeclaration(decorators, modifiers, importClause, moduleSpecifier, location) { + var node = createNode(230 /* ImportDeclaration */, location); + node.decorators = decorators ? createNodeArray(decorators) : undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.importClause = importClause; + node.moduleSpecifier = moduleSpecifier; + return node; + } + ts.createImportDeclaration = createImportDeclaration; + function updateImportDeclaration(node, decorators, modifiers, importClause, moduleSpecifier) { + if (node.decorators !== decorators || node.modifiers !== modifiers || node.importClause !== importClause || node.moduleSpecifier !== moduleSpecifier) { + return updateNode(createImportDeclaration(decorators, modifiers, importClause, moduleSpecifier, node), node); } - function parseSimplePropertyName() { - return parsePropertyNameWorker(/*allowComputedPropertyNames*/ false); + return node; + } + ts.updateImportDeclaration = updateImportDeclaration; + function createImportClause(name, namedBindings, location) { + var node = createNode(231 /* ImportClause */, location); + node.name = name; + node.namedBindings = namedBindings; + return node; + } + ts.createImportClause = createImportClause; + function updateImportClause(node, name, namedBindings) { + if (node.name !== name || node.namedBindings !== namedBindings) { + return updateNode(createImportClause(name, namedBindings, node), node); } - function isSimplePropertyName() { - return token() === 9 /* StringLiteral */ || token() === 8 /* NumericLiteral */ || ts.tokenIsIdentifierOrKeyword(token()); + return node; + } + ts.updateImportClause = updateImportClause; + function createNamespaceImport(name, location) { + var node = createNode(232 /* NamespaceImport */, location); + node.name = name; + return node; + } + ts.createNamespaceImport = createNamespaceImport; + function updateNamespaceImport(node, name) { + if (node.name !== name) { + return updateNode(createNamespaceImport(name, node), node); } - function parseComputedPropertyName() { - // PropertyName [Yield]: - // LiteralPropertyName - // ComputedPropertyName[?Yield] - var node = createNode(140 /* ComputedPropertyName */); - parseExpected(19 /* OpenBracketToken */); - // We parse any expression (including a comma expression). But the grammar - // says that only an assignment expression is allowed, so the grammar checker - // will error if it sees a comma expression. - node.expression = allowInAnd(parseExpression); - parseExpected(20 /* CloseBracketToken */); - return finishNode(node); + return node; + } + ts.updateNamespaceImport = updateNamespaceImport; + function createNamedImports(elements, location) { + var node = createNode(233 /* NamedImports */, location); + node.elements = createNodeArray(elements); + return node; + } + ts.createNamedImports = createNamedImports; + function updateNamedImports(node, elements) { + if (node.elements !== elements) { + return updateNode(createNamedImports(elements, node), node); } - function parseContextualModifier(t) { - return token() === t && tryParse(nextTokenCanFollowModifier); + return node; + } + ts.updateNamedImports = updateNamedImports; + function createImportSpecifier(propertyName, name, location) { + var node = createNode(234 /* ImportSpecifier */, location); + node.propertyName = propertyName; + node.name = name; + return node; + } + ts.createImportSpecifier = createImportSpecifier; + function updateImportSpecifier(node, propertyName, name) { + if (node.propertyName !== propertyName || node.name !== name) { + return updateNode(createImportSpecifier(propertyName, name, node), node); } - function nextTokenIsOnSameLineAndCanFollowModifier() { - nextToken(); - if (scanner.hasPrecedingLineBreak()) { - return false; - } - return canFollowModifier(); + return node; + } + ts.updateImportSpecifier = updateImportSpecifier; + function createExportAssignment(decorators, modifiers, isExportEquals, expression, location) { + var node = createNode(235 /* ExportAssignment */, location); + node.decorators = decorators ? createNodeArray(decorators) : undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.isExportEquals = isExportEquals; + node.expression = expression; + return node; + } + ts.createExportAssignment = createExportAssignment; + function updateExportAssignment(node, decorators, modifiers, expression) { + if (node.decorators !== decorators || node.modifiers !== modifiers || node.expression !== expression) { + return updateNode(createExportAssignment(decorators, modifiers, node.isExportEquals, expression, node), node); } - function nextTokenCanFollowModifier() { - if (token() === 74 /* ConstKeyword */) { - // 'const' is only a modifier if followed by 'enum'. - return nextToken() === 81 /* EnumKeyword */; - } - if (token() === 82 /* ExportKeyword */) { - nextToken(); - if (token() === 77 /* DefaultKeyword */) { - return lookAhead(nextTokenIsClassOrFunctionOrAsync); - } - return token() !== 37 /* AsteriskToken */ && token() !== 116 /* AsKeyword */ && token() !== 15 /* OpenBraceToken */ && canFollowModifier(); - } - if (token() === 77 /* DefaultKeyword */) { - return nextTokenIsClassOrFunctionOrAsync(); - } - if (token() === 113 /* StaticKeyword */) { - nextToken(); - return canFollowModifier(); - } - return nextTokenIsOnSameLineAndCanFollowModifier(); + return node; + } + ts.updateExportAssignment = updateExportAssignment; + function createExportDeclaration(decorators, modifiers, exportClause, moduleSpecifier, location) { + var node = createNode(236 /* ExportDeclaration */, location); + node.decorators = decorators ? createNodeArray(decorators) : undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.exportClause = exportClause; + node.moduleSpecifier = moduleSpecifier; + return node; + } + ts.createExportDeclaration = createExportDeclaration; + function updateExportDeclaration(node, decorators, modifiers, exportClause, moduleSpecifier) { + if (node.decorators !== decorators || node.modifiers !== modifiers || node.exportClause !== exportClause || node.moduleSpecifier !== moduleSpecifier) { + return updateNode(createExportDeclaration(decorators, modifiers, exportClause, moduleSpecifier, node), node); } - function parseAnyContextualModifier() { - return ts.isModifierKind(token()) && tryParse(nextTokenCanFollowModifier); + return node; + } + ts.updateExportDeclaration = updateExportDeclaration; + function createNamedExports(elements, location) { + var node = createNode(237 /* NamedExports */, location); + node.elements = createNodeArray(elements); + return node; + } + ts.createNamedExports = createNamedExports; + function updateNamedExports(node, elements) { + if (node.elements !== elements) { + return updateNode(createNamedExports(elements, node), node); } - function canFollowModifier() { - return token() === 19 /* OpenBracketToken */ - || token() === 15 /* OpenBraceToken */ - || token() === 37 /* AsteriskToken */ - || token() === 22 /* DotDotDotToken */ - || isLiteralPropertyName(); + return node; + } + ts.updateNamedExports = updateNamedExports; + function createExportSpecifier(name, propertyName, location) { + var node = createNode(238 /* ExportSpecifier */, location); + node.name = typeof name === "string" ? createIdentifier(name) : name; + node.propertyName = typeof propertyName === "string" ? createIdentifier(propertyName) : propertyName; + return node; + } + ts.createExportSpecifier = createExportSpecifier; + function updateExportSpecifier(node, name, propertyName) { + if (node.name !== name || node.propertyName !== propertyName) { + return updateNode(createExportSpecifier(name, propertyName, node), node); } - function nextTokenIsClassOrFunctionOrAsync() { - nextToken(); - return token() === 73 /* ClassKeyword */ || token() === 87 /* FunctionKeyword */ || - (token() === 118 /* AsyncKeyword */ && lookAhead(nextTokenIsFunctionKeywordOnSameLine)); + return node; + } + ts.updateExportSpecifier = updateExportSpecifier; + // JSX + function createJsxElement(openingElement, children, closingElement, location) { + var node = createNode(241 /* JsxElement */, location); + node.openingElement = openingElement; + node.children = createNodeArray(children); + node.closingElement = closingElement; + return node; + } + ts.createJsxElement = createJsxElement; + function updateJsxElement(node, openingElement, children, closingElement) { + if (node.openingElement !== openingElement || node.children !== children || node.closingElement !== closingElement) { + return updateNode(createJsxElement(openingElement, children, closingElement, node), node); } - // True if positioned at the start of a list element - function isListElement(parsingContext, inErrorRecovery) { - var node = currentNode(parsingContext); - if (node) { - return true; - } - switch (parsingContext) { - case 0 /* SourceElements */: - case 1 /* BlockStatements */: - case 3 /* SwitchClauseStatements */: - // If we're in error recovery, then we don't want to treat ';' as an empty statement. - // The problem is that ';' can show up in far too many contexts, and if we see one - // and assume it's a statement, then we may bail out inappropriately from whatever - // we're parsing. For example, if we have a semicolon in the middle of a class, then - // we really don't want to assume the class is over and we're on a statement in the - // outer module. We just want to consume and move on. - return !(token() === 23 /* SemicolonToken */ && inErrorRecovery) && isStartOfStatement(); - case 2 /* SwitchClauses */: - return token() === 71 /* CaseKeyword */ || token() === 77 /* DefaultKeyword */; - case 4 /* TypeMembers */: - return lookAhead(isTypeMemberStart); - case 5 /* ClassMembers */: - // We allow semicolons as class elements (as specified by ES6) as long as we're - // not in error recovery. If we're in error recovery, we don't want an errant - // semicolon to be treated as a class member (since they're almost always used - // for statements. - return lookAhead(isClassMemberStart) || (token() === 23 /* SemicolonToken */ && !inErrorRecovery); - case 6 /* EnumMembers */: - // Include open bracket computed properties. This technically also lets in indexers, - // which would be a candidate for improved error reporting. - return token() === 19 /* OpenBracketToken */ || isLiteralPropertyName(); - case 12 /* ObjectLiteralMembers */: - return token() === 19 /* OpenBracketToken */ || token() === 37 /* AsteriskToken */ || isLiteralPropertyName(); - case 9 /* ObjectBindingElements */: - return token() === 19 /* OpenBracketToken */ || isLiteralPropertyName(); - case 7 /* HeritageClauseElement */: - // If we see { } then only consume it as an expression if it is followed by , or { - // That way we won't consume the body of a class in its heritage clause. - if (token() === 15 /* OpenBraceToken */) { - return lookAhead(isValidHeritageClauseObjectLiteral); - } - if (!inErrorRecovery) { - return isStartOfLeftHandSideExpression() && !isHeritageClauseExtendsOrImplementsKeyword(); - } - else { - // If we're in error recovery we tighten up what we're willing to match. - // That way we don't treat something like "this" as a valid heritage clause - // element during recovery. - return isIdentifier() && !isHeritageClauseExtendsOrImplementsKeyword(); - } - case 8 /* VariableDeclarations */: - return isIdentifierOrPattern(); - case 10 /* ArrayBindingElements */: - return token() === 24 /* CommaToken */ || token() === 22 /* DotDotDotToken */ || isIdentifierOrPattern(); - case 17 /* TypeParameters */: - return isIdentifier(); - case 11 /* ArgumentExpressions */: - case 15 /* ArrayLiteralMembers */: - return token() === 24 /* CommaToken */ || token() === 22 /* DotDotDotToken */ || isStartOfExpression(); - case 16 /* Parameters */: - return isStartOfParameter(); - case 18 /* TypeArguments */: - case 19 /* TupleElementTypes */: - return token() === 24 /* CommaToken */ || isStartOfType(); - case 20 /* HeritageClauses */: - return isHeritageClause(); - case 21 /* ImportOrExportSpecifiers */: - return ts.tokenIsIdentifierOrKeyword(token()); - case 13 /* JsxAttributes */: - return ts.tokenIsIdentifierOrKeyword(token()) || token() === 15 /* OpenBraceToken */; - case 14 /* JsxChildren */: - return true; - case 22 /* JSDocFunctionParameters */: - case 23 /* JSDocTypeArguments */: - case 25 /* JSDocTupleTypes */: - return JSDocParser.isJSDocType(); - case 24 /* JSDocRecordMembers */: - return isSimplePropertyName(); - } - ts.Debug.fail("Non-exhaustive case in 'isListElement'."); + return node; + } + ts.updateJsxElement = updateJsxElement; + function createJsxSelfClosingElement(tagName, attributes, location) { + var node = createNode(242 /* JsxSelfClosingElement */, location); + node.tagName = tagName; + node.attributes = createNodeArray(attributes); + return node; + } + ts.createJsxSelfClosingElement = createJsxSelfClosingElement; + function updateJsxSelfClosingElement(node, tagName, attributes) { + if (node.tagName !== tagName || node.attributes !== attributes) { + return updateNode(createJsxSelfClosingElement(tagName, attributes, node), node); } - function isValidHeritageClauseObjectLiteral() { - ts.Debug.assert(token() === 15 /* OpenBraceToken */); - if (nextToken() === 16 /* CloseBraceToken */) { - // if we see "extends {}" then only treat the {} as what we're extending (and not - // the class body) if we have: - // - // extends {} { - // extends {}, - // extends {} extends - // extends {} implements - var next = nextToken(); - return next === 24 /* CommaToken */ || next === 15 /* OpenBraceToken */ || next === 83 /* ExtendsKeyword */ || next === 106 /* ImplementsKeyword */; - } - return true; + return node; + } + ts.updateJsxSelfClosingElement = updateJsxSelfClosingElement; + function createJsxOpeningElement(tagName, attributes, location) { + var node = createNode(243 /* JsxOpeningElement */, location); + node.tagName = tagName; + node.attributes = createNodeArray(attributes); + return node; + } + ts.createJsxOpeningElement = createJsxOpeningElement; + function updateJsxOpeningElement(node, tagName, attributes) { + if (node.tagName !== tagName || node.attributes !== attributes) { + return updateNode(createJsxOpeningElement(tagName, attributes, node), node); } - function nextTokenIsIdentifier() { - nextToken(); - return isIdentifier(); + return node; + } + ts.updateJsxOpeningElement = updateJsxOpeningElement; + function createJsxClosingElement(tagName, location) { + var node = createNode(245 /* JsxClosingElement */, location); + node.tagName = tagName; + return node; + } + ts.createJsxClosingElement = createJsxClosingElement; + function updateJsxClosingElement(node, tagName) { + if (node.tagName !== tagName) { + return updateNode(createJsxClosingElement(tagName, node), node); } - function nextTokenIsIdentifierOrKeyword() { - nextToken(); - return ts.tokenIsIdentifierOrKeyword(token()); + return node; + } + ts.updateJsxClosingElement = updateJsxClosingElement; + function createJsxAttribute(name, initializer, location) { + var node = createNode(246 /* JsxAttribute */, location); + node.name = name; + node.initializer = initializer; + return node; + } + ts.createJsxAttribute = createJsxAttribute; + function updateJsxAttribute(node, name, initializer) { + if (node.name !== name || node.initializer !== initializer) { + return updateNode(createJsxAttribute(name, initializer, node), node); } - function isHeritageClauseExtendsOrImplementsKeyword() { - if (token() === 106 /* ImplementsKeyword */ || - token() === 83 /* ExtendsKeyword */) { - return lookAhead(nextTokenIsStartOfExpression); - } - return false; + return node; + } + ts.updateJsxAttribute = updateJsxAttribute; + function createJsxSpreadAttribute(expression, location) { + var node = createNode(247 /* JsxSpreadAttribute */, location); + node.expression = expression; + return node; + } + ts.createJsxSpreadAttribute = createJsxSpreadAttribute; + function updateJsxSpreadAttribute(node, expression) { + if (node.expression !== expression) { + return updateNode(createJsxSpreadAttribute(expression, node), node); } - function nextTokenIsStartOfExpression() { - nextToken(); - return isStartOfExpression(); + return node; + } + ts.updateJsxSpreadAttribute = updateJsxSpreadAttribute; + function createJsxExpression(expression, location) { + var node = createNode(248 /* JsxExpression */, location); + node.expression = expression; + return node; + } + ts.createJsxExpression = createJsxExpression; + function updateJsxExpression(node, expression) { + if (node.expression !== expression) { + return updateNode(createJsxExpression(expression, node), node); } - // True if positioned at a list terminator - function isListTerminator(kind) { - if (token() === 1 /* EndOfFileToken */) { - // Being at the end of the file ends all lists. - return true; - } - switch (kind) { - case 1 /* BlockStatements */: - case 2 /* SwitchClauses */: - case 4 /* TypeMembers */: - case 5 /* ClassMembers */: - case 6 /* EnumMembers */: - case 12 /* ObjectLiteralMembers */: - case 9 /* ObjectBindingElements */: - case 21 /* ImportOrExportSpecifiers */: - return token() === 16 /* CloseBraceToken */; - case 3 /* SwitchClauseStatements */: - return token() === 16 /* CloseBraceToken */ || token() === 71 /* CaseKeyword */ || token() === 77 /* DefaultKeyword */; - case 7 /* HeritageClauseElement */: - return token() === 15 /* OpenBraceToken */ || token() === 83 /* ExtendsKeyword */ || token() === 106 /* ImplementsKeyword */; - case 8 /* VariableDeclarations */: - return isVariableDeclaratorListTerminator(); - case 17 /* TypeParameters */: - // Tokens other than '>' are here for better error recovery - return token() === 27 /* GreaterThanToken */ || token() === 17 /* OpenParenToken */ || token() === 15 /* OpenBraceToken */ || token() === 83 /* ExtendsKeyword */ || token() === 106 /* ImplementsKeyword */; - case 11 /* ArgumentExpressions */: - // Tokens other than ')' are here for better error recovery - return token() === 18 /* CloseParenToken */ || token() === 23 /* SemicolonToken */; - case 15 /* ArrayLiteralMembers */: - case 19 /* TupleElementTypes */: - case 10 /* ArrayBindingElements */: - return token() === 20 /* CloseBracketToken */; - case 16 /* Parameters */: - // Tokens other than ')' and ']' (the latter for index signatures) are here for better error recovery - return token() === 18 /* CloseParenToken */ || token() === 20 /* CloseBracketToken */ /*|| token === SyntaxKind.OpenBraceToken*/; - case 18 /* TypeArguments */: - // Tokens other than '>' are here for better error recovery - return token() === 27 /* GreaterThanToken */ || token() === 17 /* OpenParenToken */; - case 20 /* HeritageClauses */: - return token() === 15 /* OpenBraceToken */ || token() === 16 /* CloseBraceToken */; - case 13 /* JsxAttributes */: - return token() === 27 /* GreaterThanToken */ || token() === 39 /* SlashToken */; - case 14 /* JsxChildren */: - return token() === 25 /* LessThanToken */ && lookAhead(nextTokenIsSlash); - case 22 /* JSDocFunctionParameters */: - return token() === 18 /* CloseParenToken */ || token() === 54 /* ColonToken */ || token() === 16 /* CloseBraceToken */; - case 23 /* JSDocTypeArguments */: - return token() === 27 /* GreaterThanToken */ || token() === 16 /* CloseBraceToken */; - case 25 /* JSDocTupleTypes */: - return token() === 20 /* CloseBracketToken */ || token() === 16 /* CloseBraceToken */; - case 24 /* JSDocRecordMembers */: - return token() === 16 /* CloseBraceToken */; - } + return node; + } + ts.updateJsxExpression = updateJsxExpression; + // Clauses + function createHeritageClause(token, types, location) { + var node = createNode(251 /* HeritageClause */, location); + node.token = token; + node.types = createNodeArray(types); + return node; + } + ts.createHeritageClause = createHeritageClause; + function updateHeritageClause(node, types) { + if (node.types !== types) { + return updateNode(createHeritageClause(node.token, types, node), node); } - function isVariableDeclaratorListTerminator() { - // If we can consume a semicolon (either explicitly, or with ASI), then consider us done - // with parsing the list of variable declarators. - if (canParseSemicolon()) { - return true; + return node; + } + ts.updateHeritageClause = updateHeritageClause; + function createCaseClause(expression, statements, location) { + var node = createNode(249 /* CaseClause */, location); + node.expression = parenthesizeExpressionForList(expression); + node.statements = createNodeArray(statements); + return node; + } + ts.createCaseClause = createCaseClause; + function updateCaseClause(node, expression, statements) { + if (node.expression !== expression || node.statements !== statements) { + return updateNode(createCaseClause(expression, statements, node), node); + } + return node; + } + ts.updateCaseClause = updateCaseClause; + function createDefaultClause(statements, location) { + var node = createNode(250 /* DefaultClause */, location); + node.statements = createNodeArray(statements); + return node; + } + ts.createDefaultClause = createDefaultClause; + function updateDefaultClause(node, statements) { + if (node.statements !== statements) { + return updateNode(createDefaultClause(statements, node), node); + } + return node; + } + ts.updateDefaultClause = updateDefaultClause; + function createCatchClause(variableDeclaration, block, location) { + var node = createNode(252 /* CatchClause */, location); + node.variableDeclaration = typeof variableDeclaration === "string" ? createVariableDeclaration(variableDeclaration) : variableDeclaration; + node.block = block; + return node; + } + ts.createCatchClause = createCatchClause; + function updateCatchClause(node, variableDeclaration, block) { + if (node.variableDeclaration !== variableDeclaration || node.block !== block) { + return updateNode(createCatchClause(variableDeclaration, block, node), node); + } + return node; + } + ts.updateCatchClause = updateCatchClause; + // Property assignments + function createPropertyAssignment(name, initializer, location) { + var node = createNode(253 /* PropertyAssignment */, location); + node.name = typeof name === "string" ? createIdentifier(name) : name; + node.questionToken = undefined; + node.initializer = initializer !== undefined ? parenthesizeExpressionForList(initializer) : undefined; + return node; + } + ts.createPropertyAssignment = createPropertyAssignment; + function updatePropertyAssignment(node, name, initializer) { + if (node.name !== name || node.initializer !== initializer) { + return updateNode(createPropertyAssignment(name, initializer, node), node); + } + return node; + } + ts.updatePropertyAssignment = updatePropertyAssignment; + function createShorthandPropertyAssignment(name, objectAssignmentInitializer, location) { + var node = createNode(254 /* ShorthandPropertyAssignment */, location); + node.name = typeof name === "string" ? createIdentifier(name) : name; + node.objectAssignmentInitializer = objectAssignmentInitializer !== undefined ? parenthesizeExpressionForList(objectAssignmentInitializer) : undefined; + return node; + } + ts.createShorthandPropertyAssignment = createShorthandPropertyAssignment; + function updateShorthandPropertyAssignment(node, name, objectAssignmentInitializer) { + if (node.name !== name || node.objectAssignmentInitializer !== objectAssignmentInitializer) { + return updateNode(createShorthandPropertyAssignment(name, objectAssignmentInitializer, node), node); + } + return node; + } + ts.updateShorthandPropertyAssignment = updateShorthandPropertyAssignment; + // Top-level nodes + function updateSourceFileNode(node, statements) { + if (node.statements !== statements) { + var updated = createNode(256 /* SourceFile */, /*location*/ node, node.flags); + updated.statements = createNodeArray(statements); + updated.endOfFileToken = node.endOfFileToken; + updated.fileName = node.fileName; + updated.path = node.path; + updated.text = node.text; + if (node.amdDependencies !== undefined) + updated.amdDependencies = node.amdDependencies; + if (node.moduleName !== undefined) + updated.moduleName = node.moduleName; + if (node.referencedFiles !== undefined) + updated.referencedFiles = node.referencedFiles; + if (node.typeReferenceDirectives !== undefined) + updated.typeReferenceDirectives = node.typeReferenceDirectives; + if (node.languageVariant !== undefined) + updated.languageVariant = node.languageVariant; + if (node.isDeclarationFile !== undefined) + updated.isDeclarationFile = node.isDeclarationFile; + if (node.renamedDependencies !== undefined) + updated.renamedDependencies = node.renamedDependencies; + if (node.hasNoDefaultLib !== undefined) + updated.hasNoDefaultLib = node.hasNoDefaultLib; + if (node.languageVersion !== undefined) + updated.languageVersion = node.languageVersion; + if (node.scriptKind !== undefined) + updated.scriptKind = node.scriptKind; + if (node.externalModuleIndicator !== undefined) + updated.externalModuleIndicator = node.externalModuleIndicator; + if (node.commonJsModuleIndicator !== undefined) + updated.commonJsModuleIndicator = node.commonJsModuleIndicator; + if (node.identifiers !== undefined) + updated.identifiers = node.identifiers; + if (node.nodeCount !== undefined) + updated.nodeCount = node.nodeCount; + if (node.identifierCount !== undefined) + updated.identifierCount = node.identifierCount; + if (node.symbolCount !== undefined) + updated.symbolCount = node.symbolCount; + if (node.parseDiagnostics !== undefined) + updated.parseDiagnostics = node.parseDiagnostics; + if (node.bindDiagnostics !== undefined) + updated.bindDiagnostics = node.bindDiagnostics; + if (node.lineMap !== undefined) + updated.lineMap = node.lineMap; + if (node.classifiableNames !== undefined) + updated.classifiableNames = node.classifiableNames; + if (node.resolvedModules !== undefined) + updated.resolvedModules = node.resolvedModules; + if (node.resolvedTypeReferenceDirectiveNames !== undefined) + updated.resolvedTypeReferenceDirectiveNames = node.resolvedTypeReferenceDirectiveNames; + if (node.imports !== undefined) + updated.imports = node.imports; + if (node.moduleAugmentations !== undefined) + updated.moduleAugmentations = node.moduleAugmentations; + if (node.externalHelpersModuleName !== undefined) + updated.externalHelpersModuleName = node.externalHelpersModuleName; + return updateNode(updated, node); + } + return node; + } + ts.updateSourceFileNode = updateSourceFileNode; + // Transformation nodes + /** + * Creates a synthetic statement to act as a placeholder for a not-emitted statement in + * order to preserve comments. + * + * @param original The original statement. + */ + function createNotEmittedStatement(original) { + var node = createNode(287 /* NotEmittedStatement */, /*location*/ original); + node.original = original; + return node; + } + ts.createNotEmittedStatement = createNotEmittedStatement; + /** + * Creates a synthetic expression to act as a placeholder for a not-emitted expression in + * order to preserve comments or sourcemap positions. + * + * @param expression The inner expression to emit. + * @param original The original outer expression. + * @param location The location for the expression. Defaults to the positions from "original" if provided. + */ + function createPartiallyEmittedExpression(expression, original, location) { + var node = createNode(288 /* PartiallyEmittedExpression */, /*location*/ location || original); + node.expression = expression; + node.original = original; + return node; + } + ts.createPartiallyEmittedExpression = createPartiallyEmittedExpression; + function updatePartiallyEmittedExpression(node, expression) { + if (node.expression !== expression) { + return updateNode(createPartiallyEmittedExpression(expression, node.original, node), node); + } + return node; + } + ts.updatePartiallyEmittedExpression = updatePartiallyEmittedExpression; + // Compound nodes + function createComma(left, right) { + return createBinary(left, 24 /* CommaToken */, right); + } + ts.createComma = createComma; + function createLessThan(left, right, location) { + return createBinary(left, 25 /* LessThanToken */, right, location); + } + ts.createLessThan = createLessThan; + function createAssignment(left, right, location) { + return createBinary(left, 56 /* EqualsToken */, right, location); + } + ts.createAssignment = createAssignment; + function createStrictEquality(left, right) { + return createBinary(left, 32 /* EqualsEqualsEqualsToken */, right); + } + ts.createStrictEquality = createStrictEquality; + function createStrictInequality(left, right) { + return createBinary(left, 33 /* ExclamationEqualsEqualsToken */, right); + } + ts.createStrictInequality = createStrictInequality; + function createAdd(left, right) { + return createBinary(left, 35 /* PlusToken */, right); + } + ts.createAdd = createAdd; + function createSubtract(left, right) { + return createBinary(left, 36 /* MinusToken */, right); + } + ts.createSubtract = createSubtract; + function createPostfixIncrement(operand, location) { + return createPostfix(operand, 41 /* PlusPlusToken */, location); + } + ts.createPostfixIncrement = createPostfixIncrement; + function createLogicalAnd(left, right) { + return createBinary(left, 51 /* AmpersandAmpersandToken */, right); + } + ts.createLogicalAnd = createLogicalAnd; + function createLogicalOr(left, right) { + return createBinary(left, 52 /* BarBarToken */, right); + } + ts.createLogicalOr = createLogicalOr; + function createLogicalNot(operand) { + return createPrefix(49 /* ExclamationToken */, operand); + } + ts.createLogicalNot = createLogicalNot; + function createVoidZero() { + return createVoid(createLiteral(0)); + } + ts.createVoidZero = createVoidZero; + function createMemberAccessForPropertyName(target, memberName, location) { + if (ts.isComputedPropertyName(memberName)) { + return createElementAccess(target, memberName.expression, location); + } + else { + var expression = ts.isIdentifier(memberName) ? createPropertyAccess(target, memberName, location) : createElementAccess(target, memberName, location); + (expression.emitNode || (expression.emitNode = {})).flags |= 2048 /* NoNestedSourceMaps */; + return expression; + } + } + ts.createMemberAccessForPropertyName = createMemberAccessForPropertyName; + function createRestParameter(name) { + return createParameterDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, createSynthesizedNode(22 /* DotDotDotToken */), name, + /*questionToken*/ undefined, + /*type*/ undefined, + /*initializer*/ undefined); + } + ts.createRestParameter = createRestParameter; + function createFunctionCall(func, thisArg, argumentsList, location) { + return createCall(createPropertyAccess(func, "call"), + /*typeArguments*/ undefined, [ + thisArg + ].concat(argumentsList), location); + } + ts.createFunctionCall = createFunctionCall; + function createFunctionApply(func, thisArg, argumentsExpression, location) { + return createCall(createPropertyAccess(func, "apply"), + /*typeArguments*/ undefined, [ + thisArg, + argumentsExpression + ], location); + } + ts.createFunctionApply = createFunctionApply; + function createArraySlice(array, start) { + var argumentsList = []; + if (start !== undefined) { + argumentsList.push(typeof start === "number" ? createLiteral(start) : start); + } + return createCall(createPropertyAccess(array, "slice"), /*typeArguments*/ undefined, argumentsList); + } + ts.createArraySlice = createArraySlice; + function createArrayConcat(array, values) { + return createCall(createPropertyAccess(array, "concat"), + /*typeArguments*/ undefined, values); + } + ts.createArrayConcat = createArrayConcat; + function createMathPow(left, right, location) { + return createCall(createPropertyAccess(createIdentifier("Math"), "pow"), + /*typeArguments*/ undefined, [left, right], location); + } + ts.createMathPow = createMathPow; + function createReactNamespace(reactNamespace, parent) { + // To ensure the emit resolver can properly resolve the namespace, we need to + // treat this identifier as if it were a source tree node by clearing the `Synthesized` + // flag and setting a parent node. + var react = createIdentifier(reactNamespace || "React"); + react.flags &= ~8 /* Synthesized */; + react.parent = parent; + return react; + } + function createReactCreateElement(reactNamespace, tagName, props, children, parentElement, location) { + var argumentsList = [tagName]; + if (props) { + argumentsList.push(props); + } + if (children && children.length > 0) { + if (!props) { + argumentsList.push(createNull()); } - // in the case where we're parsing the variable declarator of a 'for-in' statement, we - // are done if we see an 'in' keyword in front of us. Same with for-of - if (isInOrOfKeyword(token())) { - return true; + if (children.length > 1) { + for (var _i = 0, children_1 = children; _i < children_1.length; _i++) { + var child = children_1[_i]; + child.startsOnNewLine = true; + argumentsList.push(child); + } } - // ERROR RECOVERY TWEAK: - // For better error recovery, if we see an '=>' then we just stop immediately. We've got an - // arrow function here and it's going to be very unlikely that we'll resynchronize and get - // another variable declaration. - if (token() === 34 /* EqualsGreaterThanToken */) { + else { + argumentsList.push(children[0]); + } + } + return createCall(createPropertyAccess(createReactNamespace(reactNamespace, parentElement), "createElement"), + /*typeArguments*/ undefined, argumentsList, location); + } + ts.createReactCreateElement = createReactCreateElement; + function createLetDeclarationList(declarations, location) { + return createVariableDeclarationList(declarations, location, 1 /* Let */); + } + ts.createLetDeclarationList = createLetDeclarationList; + function createConstDeclarationList(declarations, location) { + return createVariableDeclarationList(declarations, location, 2 /* Const */); + } + ts.createConstDeclarationList = createConstDeclarationList; + // Helpers + function createHelperName(externalHelpersModuleName, name) { + return externalHelpersModuleName + ? createPropertyAccess(externalHelpersModuleName, name) + : createIdentifier(name); + } + ts.createHelperName = createHelperName; + function createExtendsHelper(externalHelpersModuleName, name) { + return createCall(createHelperName(externalHelpersModuleName, "__extends"), + /*typeArguments*/ undefined, [ + name, + createIdentifier("_super") + ]); + } + ts.createExtendsHelper = createExtendsHelper; + function createAssignHelper(externalHelpersModuleName, attributesSegments) { + return createCall(createHelperName(externalHelpersModuleName, "__assign"), + /*typeArguments*/ undefined, attributesSegments); + } + ts.createAssignHelper = createAssignHelper; + function createParamHelper(externalHelpersModuleName, expression, parameterOffset, location) { + return createCall(createHelperName(externalHelpersModuleName, "__param"), + /*typeArguments*/ undefined, [ + createLiteral(parameterOffset), + expression + ], location); + } + ts.createParamHelper = createParamHelper; + function createMetadataHelper(externalHelpersModuleName, metadataKey, metadataValue) { + return createCall(createHelperName(externalHelpersModuleName, "__metadata"), + /*typeArguments*/ undefined, [ + createLiteral(metadataKey), + metadataValue + ]); + } + ts.createMetadataHelper = createMetadataHelper; + function createDecorateHelper(externalHelpersModuleName, decoratorExpressions, target, memberName, descriptor, location) { + var argumentsArray = []; + argumentsArray.push(createArrayLiteral(decoratorExpressions, /*location*/ undefined, /*multiLine*/ true)); + argumentsArray.push(target); + if (memberName) { + argumentsArray.push(memberName); + if (descriptor) { + argumentsArray.push(descriptor); + } + } + return createCall(createHelperName(externalHelpersModuleName, "__decorate"), /*typeArguments*/ undefined, argumentsArray, location); + } + ts.createDecorateHelper = createDecorateHelper; + function createAwaiterHelper(externalHelpersModuleName, hasLexicalArguments, promiseConstructor, body) { + var generatorFunc = createFunctionExpression(createNode(37 /* AsteriskToken */), + /*name*/ undefined, + /*typeParameters*/ undefined, + /*parameters*/ [], + /*type*/ undefined, body); + // Mark this node as originally an async function + (generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= 2097152 /* AsyncFunctionBody */; + return createCall(createHelperName(externalHelpersModuleName, "__awaiter"), + /*typeArguments*/ undefined, [ + createThis(), + hasLexicalArguments ? createIdentifier("arguments") : createVoidZero(), + promiseConstructor ? createExpressionFromEntityName(promiseConstructor) : createVoidZero(), + generatorFunc + ]); + } + ts.createAwaiterHelper = createAwaiterHelper; + function createHasOwnProperty(target, propertyName) { + return createCall(createPropertyAccess(target, "hasOwnProperty"), + /*typeArguments*/ undefined, [propertyName]); + } + ts.createHasOwnProperty = createHasOwnProperty; + function createObjectCreate(prototype) { + return createCall(createPropertyAccess(createIdentifier("Object"), "create"), + /*typeArguments*/ undefined, [prototype]); + } + function createGeti(target) { + // name => super[name] + return createArrowFunction( + /*modifiers*/ undefined, + /*typeParameters*/ undefined, [createParameter("name")], + /*type*/ undefined, + /*equalsGreaterThanToken*/ undefined, createElementAccess(target, createIdentifier("name"))); + } + function createSeti(target) { + // (name, value) => super[name] = value + return createArrowFunction( + /*modifiers*/ undefined, + /*typeParameters*/ undefined, [ + createParameter("name"), + createParameter("value") + ], + /*type*/ undefined, + /*equalsGreaterThanToken*/ undefined, createAssignment(createElementAccess(target, createIdentifier("name")), createIdentifier("value"))); + } + function createAdvancedAsyncSuperHelper() { + // const _super = (function (geti, seti) { + // const cache = Object.create(null); + // return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } }); + // })(name => super[name], (name, value) => super[name] = value); + // const cache = Object.create(null); + var createCache = createVariableStatement( + /*modifiers*/ undefined, createConstDeclarationList([ + createVariableDeclaration("cache", + /*type*/ undefined, createObjectCreate(createNull())) + ])); + // get value() { return geti(name); } + var getter = createGetAccessor( + /*decorators*/ undefined, + /*modifiers*/ undefined, "value", + /*parameters*/ [], + /*type*/ undefined, createBlock([ + createReturn(createCall(createIdentifier("geti"), + /*typeArguments*/ undefined, [createIdentifier("name")])) + ])); + // set value(v) { seti(name, v); } + var setter = createSetAccessor( + /*decorators*/ undefined, + /*modifiers*/ undefined, "value", [createParameter("v")], createBlock([ + createStatement(createCall(createIdentifier("seti"), + /*typeArguments*/ undefined, [ + createIdentifier("name"), + createIdentifier("v") + ])) + ])); + // return name => cache[name] || ... + var getOrCreateAccessorsForName = createReturn(createArrowFunction( + /*modifiers*/ undefined, + /*typeParameters*/ undefined, [createParameter("name")], + /*type*/ undefined, + /*equalsGreaterThanToken*/ undefined, createLogicalOr(createElementAccess(createIdentifier("cache"), createIdentifier("name")), createParen(createAssignment(createElementAccess(createIdentifier("cache"), createIdentifier("name")), createObjectLiteral([ + getter, + setter + ])))))); + // const _super = (function (geti, seti) { + // const cache = Object.create(null); + // return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } }); + // })(name => super[name], (name, value) => super[name] = value); + return createVariableStatement( + /*modifiers*/ undefined, createConstDeclarationList([ + createVariableDeclaration("_super", + /*type*/ undefined, createCall(createParen(createFunctionExpression( + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ + createParameter("geti"), + createParameter("seti") + ], + /*type*/ undefined, createBlock([ + createCache, + getOrCreateAccessorsForName + ]))), + /*typeArguments*/ undefined, [ + createGeti(createSuper()), + createSeti(createSuper()) + ])) + ])); + } + ts.createAdvancedAsyncSuperHelper = createAdvancedAsyncSuperHelper; + function createSimpleAsyncSuperHelper() { + return createVariableStatement( + /*modifiers*/ undefined, createConstDeclarationList([ + createVariableDeclaration("_super", + /*type*/ undefined, createGeti(createSuper())) + ])); + } + ts.createSimpleAsyncSuperHelper = createSimpleAsyncSuperHelper; + function shouldBeCapturedInTempVariable(node, cacheIdentifiers) { + var target = skipParentheses(node); + switch (target.kind) { + case 69 /* Identifier */: + return cacheIdentifiers; + case 97 /* ThisKeyword */: + case 8 /* NumericLiteral */: + case 9 /* StringLiteral */: + return false; + case 170 /* ArrayLiteralExpression */: + var elements = target.elements; + if (elements.length === 0) { + return false; + } + return true; + case 171 /* ObjectLiteralExpression */: + return target.properties.length > 0; + default: return true; - } - // Keep trying to parse out variable declarators. - return false; } - // True if positioned at element or terminator of the current list or any enclosing list - function isInSomeParsingContext() { - for (var kind = 0; kind < 26 /* Count */; kind++) { - if (parsingContext & (1 << kind)) { - if (isListElement(kind, /*inErrorRecovery*/ true) || isListTerminator(kind)) { - return true; + } + function createCallBinding(expression, recordTempVariable, languageVersion, cacheIdentifiers) { + var callee = skipOuterExpressions(expression, 7 /* All */); + var thisArg; + var target; + if (ts.isSuperProperty(callee)) { + thisArg = createThis(); + target = callee; + } + else if (callee.kind === 95 /* SuperKeyword */) { + thisArg = createThis(); + target = languageVersion < 2 /* ES6 */ ? createIdentifier("_super", /*location*/ callee) : callee; + } + else { + switch (callee.kind) { + case 172 /* PropertyAccessExpression */: { + if (shouldBeCapturedInTempVariable(callee.expression, cacheIdentifiers)) { + // for `a.b()` target is `(_a = a).b` and thisArg is `_a` + thisArg = createTempVariable(recordTempVariable); + target = createPropertyAccess(createAssignment(thisArg, callee.expression, + /*location*/ callee.expression), callee.name, + /*location*/ callee); } + else { + thisArg = callee.expression; + target = callee; + } + break; } - } - return false; - } - // Parses a list of elements - function parseList(kind, parseElement) { - var saveParsingContext = parsingContext; - parsingContext |= 1 << kind; - var result = []; - result.pos = getNodePos(); - while (!isListTerminator(kind)) { - if (isListElement(kind, /*inErrorRecovery*/ false)) { - var element = parseListElement(kind, parseElement); - result.push(element); - continue; + case 173 /* ElementAccessExpression */: { + if (shouldBeCapturedInTempVariable(callee.expression, cacheIdentifiers)) { + // for `a[b]()` target is `(_a = a)[b]` and thisArg is `_a` + thisArg = createTempVariable(recordTempVariable); + target = createElementAccess(createAssignment(thisArg, callee.expression, + /*location*/ callee.expression), callee.argumentExpression, + /*location*/ callee); + } + else { + thisArg = callee.expression; + target = callee; + } + break; } - if (abortParsingListOrMoveToNextToken(kind)) { + default: { + // for `a()` target is `a` and thisArg is `void 0` + thisArg = createVoidZero(); + target = parenthesizeForAccess(expression); break; } } - result.end = getNodeEnd(); - parsingContext = saveParsingContext; - return result; } - function parseListElement(parsingContext, parseElement) { - var node = currentNode(parsingContext); - if (node) { - return consumeNode(node); - } - return parseElement(); + return { target: target, thisArg: thisArg }; + } + ts.createCallBinding = createCallBinding; + function inlineExpressions(expressions) { + return ts.reduceLeft(expressions, createComma); + } + ts.inlineExpressions = inlineExpressions; + function createExpressionFromEntityName(node) { + if (ts.isQualifiedName(node)) { + var left = createExpressionFromEntityName(node.left); + var right = getMutableClone(node.right); + return createPropertyAccess(left, right, /*location*/ node); } - function currentNode(parsingContext) { - // If there is an outstanding parse error that we've encountered, but not attached to - // some node, then we cannot get a node from the old source tree. This is because we - // want to mark the next node we encounter as being unusable. - // - // Note: This may be too conservative. Perhaps we could reuse the node and set the bit - // on it (or its leftmost child) as having the error. For now though, being conservative - // is nice and likely won't ever affect perf. - if (parseErrorBeforeNextFinishedNode) { - return undefined; - } - if (!syntaxCursor) { - // if we don't have a cursor, we could never return a node from the old tree. - return undefined; - } - var node = syntaxCursor.currentNode(scanner.getStartPos()); - // Can't reuse a missing node. - if (ts.nodeIsMissing(node)) { - return undefined; - } - // Can't reuse a node that intersected the change range. - if (node.intersectsChange) { - return undefined; - } - // Can't reuse a node that contains a parse error. This is necessary so that we - // produce the same set of errors again. - if (ts.containsParseError(node)) { - return undefined; - } - // We can only reuse a node if it was parsed under the same strict mode that we're - // currently in. i.e. if we originally parsed a node in non-strict mode, but then - // the user added 'using strict' at the top of the file, then we can't use that node - // again as the presence of strict mode may cause us to parse the tokens in the file - // differently. - // - // Note: we *can* reuse tokens when the strict mode changes. That's because tokens - // are unaffected by strict mode. It's just the parser will decide what to do with it - // differently depending on what mode it is in. - // - // This also applies to all our other context flags as well. - var nodeContextFlags = node.flags & 197132288 /* ContextFlags */; - if (nodeContextFlags !== contextFlags) { - return undefined; - } - // Ok, we have a node that looks like it could be reused. Now verify that it is valid - // in the current list parsing context that we're currently at. - if (!canReuseNode(node, parsingContext)) { - return undefined; - } - return node; + else { + return getMutableClone(node); } - function consumeNode(node) { - // Move the scanner so it is after the node we just consumed. - scanner.setTextPos(node.end); - nextToken(); - return node; + } + ts.createExpressionFromEntityName = createExpressionFromEntityName; + function createExpressionForPropertyName(memberName) { + if (ts.isIdentifier(memberName)) { + return createLiteral(memberName, /*location*/ undefined); } - function canReuseNode(node, parsingContext) { - switch (parsingContext) { - case 5 /* ClassMembers */: - return isReusableClassMember(node); - case 2 /* SwitchClauses */: - return isReusableSwitchClause(node); - case 0 /* SourceElements */: - case 1 /* BlockStatements */: - case 3 /* SwitchClauseStatements */: - return isReusableStatement(node); - case 6 /* EnumMembers */: - return isReusableEnumMember(node); - case 4 /* TypeMembers */: - return isReusableTypeMember(node); - case 8 /* VariableDeclarations */: - return isReusableVariableDeclaration(node); - case 16 /* Parameters */: - return isReusableParameter(node); - // Any other lists we do not care about reusing nodes in. But feel free to add if - // you can do so safely. Danger areas involve nodes that may involve speculative - // parsing. If speculative parsing is involved with the node, then the range the - // parser reached while looking ahead might be in the edited range (see the example - // in canReuseVariableDeclaratorNode for a good case of this). - case 20 /* HeritageClauses */: - // This would probably be safe to reuse. There is no speculative parsing with - // heritage clauses. - case 17 /* TypeParameters */: - // This would probably be safe to reuse. There is no speculative parsing with - // type parameters. Note that that's because type *parameters* only occur in - // unambiguous *type* contexts. While type *arguments* occur in very ambiguous - // *expression* contexts. - case 19 /* TupleElementTypes */: - // This would probably be safe to reuse. There is no speculative parsing with - // tuple types. - // Technically, type argument list types are probably safe to reuse. While - // speculative parsing is involved with them (since type argument lists are only - // produced from speculative parsing a < as a type argument list), we only have - // the types because speculative parsing succeeded. Thus, the lookahead never - // went past the end of the list and rewound. - case 18 /* TypeArguments */: - // Note: these are almost certainly not safe to ever reuse. Expressions commonly - // need a large amount of lookahead, and we should not reuse them as they may - // have actually intersected the edit. - case 11 /* ArgumentExpressions */: - // This is not safe to reuse for the same reason as the 'AssignmentExpression' - // cases. i.e. a property assignment may end with an expression, and thus might - // have lookahead far beyond it's old node. - case 12 /* ObjectLiteralMembers */: - // This is probably not safe to reuse. There can be speculative parsing with - // type names in a heritage clause. There can be generic names in the type - // name list, and there can be left hand side expressions (which can have type - // arguments.) - case 7 /* HeritageClauseElement */: - // Perhaps safe to reuse, but it's unlikely we'd see more than a dozen attributes - // on any given element. Same for children. - case 13 /* JsxAttributes */: - case 14 /* JsxChildren */: - } - return false; + else if (ts.isComputedPropertyName(memberName)) { + return getMutableClone(memberName.expression); } - function isReusableClassMember(node) { - if (node) { - switch (node.kind) { - case 148 /* Constructor */: - case 153 /* IndexSignature */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 145 /* PropertyDeclaration */: - case 198 /* SemicolonClassElement */: - return true; - case 147 /* MethodDeclaration */: - // Method declarations are not necessarily reusable. An object-literal - // may have a method calls "constructor(...)" and we must reparse that - // into an actual .ConstructorDeclaration. - var methodDeclaration = node; - var nameIsConstructor = methodDeclaration.name.kind === 69 /* Identifier */ && - methodDeclaration.name.originalKeywordKind === 121 /* ConstructorKeyword */; - return !nameIsConstructor; + else { + return getMutableClone(memberName); + } + } + ts.createExpressionForPropertyName = createExpressionForPropertyName; + function createExpressionForObjectLiteralElementLike(node, property, receiver) { + switch (property.kind) { + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + return createExpressionForAccessorDeclaration(node.properties, property, receiver, node.multiLine); + case 253 /* PropertyAssignment */: + return createExpressionForPropertyAssignment(property, receiver); + case 254 /* ShorthandPropertyAssignment */: + return createExpressionForShorthandPropertyAssignment(property, receiver); + case 147 /* MethodDeclaration */: + return createExpressionForMethodDeclaration(property, receiver); + } + } + ts.createExpressionForObjectLiteralElementLike = createExpressionForObjectLiteralElementLike; + function createExpressionForAccessorDeclaration(properties, property, receiver, multiLine) { + var _a = ts.getAllAccessorDeclarations(properties, property), firstAccessor = _a.firstAccessor, getAccessor = _a.getAccessor, setAccessor = _a.setAccessor; + if (property === firstAccessor) { + var properties_1 = []; + if (getAccessor) { + var getterFunction = createFunctionExpression( + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, getAccessor.parameters, + /*type*/ undefined, getAccessor.body, + /*location*/ getAccessor); + setOriginalNode(getterFunction, getAccessor); + var getter = createPropertyAssignment("get", getterFunction); + properties_1.push(getter); + } + if (setAccessor) { + var setterFunction = createFunctionExpression( + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, setAccessor.parameters, + /*type*/ undefined, setAccessor.body, + /*location*/ setAccessor); + setOriginalNode(setterFunction, setAccessor); + var setter = createPropertyAssignment("set", setterFunction); + properties_1.push(setter); + } + properties_1.push(createPropertyAssignment("enumerable", createLiteral(true))); + properties_1.push(createPropertyAssignment("configurable", createLiteral(true))); + var expression = createCall(createPropertyAccess(createIdentifier("Object"), "defineProperty"), + /*typeArguments*/ undefined, [ + receiver, + createExpressionForPropertyName(property.name), + createObjectLiteral(properties_1, /*location*/ undefined, multiLine) + ], + /*location*/ firstAccessor); + return ts.aggregateTransformFlags(expression); + } + return undefined; + } + function createExpressionForPropertyAssignment(property, receiver) { + return ts.aggregateTransformFlags(setOriginalNode(createAssignment(createMemberAccessForPropertyName(receiver, property.name, /*location*/ property.name), property.initializer, + /*location*/ property), + /*original*/ property)); + } + function createExpressionForShorthandPropertyAssignment(property, receiver) { + return ts.aggregateTransformFlags(setOriginalNode(createAssignment(createMemberAccessForPropertyName(receiver, property.name, /*location*/ property.name), getSynthesizedClone(property.name), + /*location*/ property), + /*original*/ property)); + } + function createExpressionForMethodDeclaration(method, receiver) { + return ts.aggregateTransformFlags(setOriginalNode(createAssignment(createMemberAccessForPropertyName(receiver, method.name, /*location*/ method.name), setOriginalNode(createFunctionExpression(method.asteriskToken, + /*name*/ undefined, + /*typeParameters*/ undefined, method.parameters, + /*type*/ undefined, method.body, + /*location*/ method), + /*original*/ method), + /*location*/ method), + /*original*/ method)); + } + // Utilities + function isUseStrictPrologue(node) { + return node.expression.text === "use strict"; + } + /** + * Add any necessary prologue-directives into target statement-array. + * The function needs to be called during each transformation step. + * This function needs to be called whenever we transform the statement + * list of a source file, namespace, or function-like body. + * + * @param target: result statements array + * @param source: origin statements array + * @param ensureUseStrict: boolean determining whether the function need to add prologue-directives + * @param visitor: Optional callback used to visit any custom prologue directives. + */ + function addPrologueDirectives(target, source, ensureUseStrict, visitor) { + ts.Debug.assert(target.length === 0, "PrologueDirectives should be at the first statement in the target statements array"); + var foundUseStrict = false; + var statementOffset = 0; + var numStatements = source.length; + while (statementOffset < numStatements) { + var statement = source[statementOffset]; + if (ts.isPrologueDirective(statement)) { + if (isUseStrictPrologue(statement)) { + foundUseStrict = true; + } + target.push(statement); + } + else { + if (ensureUseStrict && !foundUseStrict) { + target.push(startOnNewLine(createStatement(createLiteral("use strict")))); + foundUseStrict = true; + } + if (getEmitFlags(statement) & 8388608 /* CustomPrologue */) { + target.push(visitor ? ts.visitNode(statement, visitor, ts.isStatement) : statement); + } + else { + break; } } - return false; + statementOffset++; } - function isReusableSwitchClause(node) { - if (node) { - switch (node.kind) { - case 249 /* CaseClause */: - case 250 /* DefaultClause */: - return true; + return statementOffset; + } + ts.addPrologueDirectives = addPrologueDirectives; + /** + * Wraps the operand to a BinaryExpression in parentheses if they are needed to preserve the intended + * order of operations. + * + * @param binaryOperator The operator for the BinaryExpression. + * @param operand The operand for the BinaryExpression. + * @param isLeftSideOfBinary A value indicating whether the operand is the left side of the + * BinaryExpression. + */ + function parenthesizeBinaryOperand(binaryOperator, operand, isLeftSideOfBinary, leftOperand) { + var skipped = skipPartiallyEmittedExpressions(operand); + // If the resulting expression is already parenthesized, we do not need to do any further processing. + if (skipped.kind === 178 /* ParenthesizedExpression */) { + return operand; + } + return binaryOperandNeedsParentheses(binaryOperator, operand, isLeftSideOfBinary, leftOperand) + ? createParen(operand) + : operand; + } + ts.parenthesizeBinaryOperand = parenthesizeBinaryOperand; + /** + * Determines whether the operand to a BinaryExpression needs to be parenthesized. + * + * @param binaryOperator The operator for the BinaryExpression. + * @param operand The operand for the BinaryExpression. + * @param isLeftSideOfBinary A value indicating whether the operand is the left side of the + * BinaryExpression. + */ + function binaryOperandNeedsParentheses(binaryOperator, operand, isLeftSideOfBinary, leftOperand) { + // If the operand has lower precedence, then it needs to be parenthesized to preserve the + // intent of the expression. For example, if the operand is `a + b` and the operator is + // `*`, then we need to parenthesize the operand to preserve the intended order of + // operations: `(a + b) * x`. + // + // If the operand has higher precedence, then it does not need to be parenthesized. For + // example, if the operand is `a * b` and the operator is `+`, then we do not need to + // parenthesize to preserve the intended order of operations: `a * b + x`. + // + // If the operand has the same precedence, then we need to check the associativity of + // the operator based on whether this is the left or right operand of the expression. + // + // For example, if `a / d` is on the right of operator `*`, we need to parenthesize + // to preserve the intended order of operations: `x * (a / d)` + // + // If `a ** d` is on the left of operator `**`, we need to parenthesize to preserve + // the intended order of operations: `(a ** b) ** c` + var binaryOperatorPrecedence = ts.getOperatorPrecedence(187 /* BinaryExpression */, binaryOperator); + var binaryOperatorAssociativity = ts.getOperatorAssociativity(187 /* BinaryExpression */, binaryOperator); + var emittedOperand = skipPartiallyEmittedExpressions(operand); + var operandPrecedence = ts.getExpressionPrecedence(emittedOperand); + switch (ts.compareValues(operandPrecedence, binaryOperatorPrecedence)) { + case -1 /* LessThan */: + // If the operand is the right side of a right-associative binary operation + // and is a yield expression, then we do not need parentheses. + if (!isLeftSideOfBinary + && binaryOperatorAssociativity === 1 /* Right */ + && operand.kind === 190 /* YieldExpression */) { + return false; + } + return true; + case 1 /* GreaterThan */: + return false; + case 0 /* EqualTo */: + if (isLeftSideOfBinary) { + // No need to parenthesize the left operand when the binary operator is + // left associative: + // (a*b)/x -> a*b/x + // (a**b)/x -> a**b/x + // + // Parentheses are needed for the left operand when the binary operator is + // right associative: + // (a/b)**x -> (a/b)**x + // (a**b)**x -> (a**b)**x + return binaryOperatorAssociativity === 1 /* Right */; + } + else { + if (ts.isBinaryExpression(emittedOperand) + && emittedOperand.operatorToken.kind === binaryOperator) { + // No need to parenthesize the right operand when the binary operator and + // operand are the same and one of the following: + // x*(a*b) => x*a*b + // x|(a|b) => x|a|b + // x&(a&b) => x&a&b + // x^(a^b) => x^a^b + if (operatorHasAssociativeProperty(binaryOperator)) { + return false; + } + // No need to parenthesize the right operand when the binary operator + // is plus (+) if both the left and right operands consist solely of either + // literals of the same kind or binary plus (+) expressions for literals of + // the same kind (recursively). + // "a"+(1+2) => "a"+(1+2) + // "a"+("b"+"c") => "a"+"b"+"c" + if (binaryOperator === 35 /* PlusToken */) { + var leftKind = leftOperand ? getLiteralKindOfBinaryPlusOperand(leftOperand) : 0 /* Unknown */; + if (ts.isLiteralKind(leftKind) && leftKind === getLiteralKindOfBinaryPlusOperand(emittedOperand)) { + return false; + } + } + } + // No need to parenthesize the right operand when the operand is right + // associative: + // x/(a**b) -> x/a**b + // x**(a**b) -> x**a**b + // + // Parentheses are needed for the right operand when the operand is left + // associative: + // x/(a*b) -> x/(a*b) + // x**(a/b) -> x**(a/b) + var operandAssociativity = ts.getExpressionAssociativity(emittedOperand); + return operandAssociativity === 0 /* Left */; } + } + } + /** + * Determines whether a binary operator is mathematically associative. + * + * @param binaryOperator The binary operator. + */ + function operatorHasAssociativeProperty(binaryOperator) { + // The following operators are associative in JavaScript: + // (a*b)*c -> a*(b*c) -> a*b*c + // (a|b)|c -> a|(b|c) -> a|b|c + // (a&b)&c -> a&(b&c) -> a&b&c + // (a^b)^c -> a^(b^c) -> a^b^c + // + // While addition is associative in mathematics, JavaScript's `+` is not + // guaranteed to be associative as it is overloaded with string concatenation. + return binaryOperator === 37 /* AsteriskToken */ + || binaryOperator === 47 /* BarToken */ + || binaryOperator === 46 /* AmpersandToken */ + || binaryOperator === 48 /* CaretToken */; + } + /** + * This function determines whether an expression consists of a homogeneous set of + * literal expressions or binary plus expressions that all share the same literal kind. + * It is used to determine whether the right-hand operand of a binary plus expression can be + * emitted without parentheses. + */ + function getLiteralKindOfBinaryPlusOperand(node) { + node = skipPartiallyEmittedExpressions(node); + if (ts.isLiteralKind(node.kind)) { + return node.kind; + } + if (node.kind === 187 /* BinaryExpression */ && node.operatorToken.kind === 35 /* PlusToken */) { + if (node.cachedLiteralKind !== undefined) { + return node.cachedLiteralKind; } - return false; + var leftKind = getLiteralKindOfBinaryPlusOperand(node.left); + var literalKind = ts.isLiteralKind(leftKind) + && leftKind === getLiteralKindOfBinaryPlusOperand(node.right) + ? leftKind + : 0 /* Unknown */; + node.cachedLiteralKind = literalKind; + return literalKind; } - function isReusableStatement(node) { - if (node) { - switch (node.kind) { - case 220 /* FunctionDeclaration */: - case 200 /* VariableStatement */: - case 199 /* Block */: - case 203 /* IfStatement */: - case 202 /* ExpressionStatement */: - case 215 /* ThrowStatement */: - case 211 /* ReturnStatement */: - case 213 /* SwitchStatement */: - case 210 /* BreakStatement */: - case 209 /* ContinueStatement */: - case 207 /* ForInStatement */: - case 208 /* ForOfStatement */: - case 206 /* ForStatement */: - case 205 /* WhileStatement */: - case 212 /* WithStatement */: - case 201 /* EmptyStatement */: - case 216 /* TryStatement */: - case 214 /* LabeledStatement */: - case 204 /* DoStatement */: - case 217 /* DebuggerStatement */: - case 230 /* ImportDeclaration */: - case 229 /* ImportEqualsDeclaration */: - case 236 /* ExportDeclaration */: - case 235 /* ExportAssignment */: - case 225 /* ModuleDeclaration */: - case 221 /* ClassDeclaration */: - case 222 /* InterfaceDeclaration */: - case 224 /* EnumDeclaration */: - case 223 /* TypeAliasDeclaration */: - return true; + return 0 /* Unknown */; + } + /** + * Wraps an expression in parentheses if it is needed in order to use the expression + * as the expression of a NewExpression node. + * + * @param expression The Expression node. + */ + function parenthesizeForNew(expression) { + var emittedExpression = skipPartiallyEmittedExpressions(expression); + switch (emittedExpression.kind) { + case 174 /* CallExpression */: + return createParen(expression); + case 175 /* NewExpression */: + return emittedExpression.arguments + ? expression + : createParen(expression); + } + return parenthesizeForAccess(expression); + } + ts.parenthesizeForNew = parenthesizeForNew; + /** + * Wraps an expression in parentheses if it is needed in order to use the expression for + * property or element access. + * + * @param expr The expression node. + */ + function parenthesizeForAccess(expression) { + // isLeftHandSideExpression is almost the correct criterion for when it is not necessary + // to parenthesize the expression before a dot. The known exceptions are: + // + // NewExpression: + // new C.x -> not the same as (new C).x + // NumericLiteral + // 1.x -> not the same as (1).x + // + var emittedExpression = skipPartiallyEmittedExpressions(expression); + if (ts.isLeftHandSideExpression(emittedExpression) + && (emittedExpression.kind !== 175 /* NewExpression */ || emittedExpression.arguments) + && emittedExpression.kind !== 8 /* NumericLiteral */) { + return expression; + } + return createParen(expression, /*location*/ expression); + } + ts.parenthesizeForAccess = parenthesizeForAccess; + function parenthesizePostfixOperand(operand) { + return ts.isLeftHandSideExpression(operand) + ? operand + : createParen(operand, /*location*/ operand); + } + ts.parenthesizePostfixOperand = parenthesizePostfixOperand; + function parenthesizePrefixOperand(operand) { + return ts.isUnaryExpression(operand) + ? operand + : createParen(operand, /*location*/ operand); + } + ts.parenthesizePrefixOperand = parenthesizePrefixOperand; + function parenthesizeListElements(elements) { + var result; + for (var i = 0; i < elements.length; i++) { + var element = parenthesizeExpressionForList(elements[i]); + if (result !== undefined || element !== elements[i]) { + if (result === undefined) { + result = elements.slice(0, i); } + result.push(element); } - return false; } - function isReusableEnumMember(node) { - return node.kind === 255 /* EnumMember */; + if (result !== undefined) { + return createNodeArray(result, elements, elements.hasTrailingComma); } - function isReusableTypeMember(node) { - if (node) { - switch (node.kind) { - case 152 /* ConstructSignature */: - case 146 /* MethodSignature */: - case 153 /* IndexSignature */: - case 144 /* PropertySignature */: - case 151 /* CallSignature */: - return true; - } + return elements; + } + function parenthesizeExpressionForList(expression) { + var emittedExpression = skipPartiallyEmittedExpressions(expression); + var expressionPrecedence = ts.getExpressionPrecedence(emittedExpression); + var commaPrecedence = ts.getOperatorPrecedence(187 /* BinaryExpression */, 24 /* CommaToken */); + return expressionPrecedence > commaPrecedence + ? expression + : createParen(expression, /*location*/ expression); + } + ts.parenthesizeExpressionForList = parenthesizeExpressionForList; + function parenthesizeExpressionForExpressionStatement(expression) { + var emittedExpression = skipPartiallyEmittedExpressions(expression); + if (ts.isCallExpression(emittedExpression)) { + var callee = emittedExpression.expression; + var kind = skipPartiallyEmittedExpressions(callee).kind; + if (kind === 179 /* FunctionExpression */ || kind === 180 /* ArrowFunction */) { + var mutableCall = getMutableClone(emittedExpression); + mutableCall.expression = createParen(callee, /*location*/ callee); + return recreatePartiallyEmittedExpressions(expression, mutableCall); } - return false; } - function isReusableVariableDeclaration(node) { - if (node.kind !== 218 /* VariableDeclaration */) { - return false; + else { + var leftmostExpressionKind = getLeftmostExpression(emittedExpression).kind; + if (leftmostExpressionKind === 171 /* ObjectLiteralExpression */ || leftmostExpressionKind === 179 /* FunctionExpression */) { + return createParen(expression, /*location*/ expression); } - // Very subtle incremental parsing bug. Consider the following code: - // - // let v = new List < A, B - // - // This is actually legal code. It's a list of variable declarators "v = new List() - // - // then we have a problem. "v = new List= 0) { - // Always preserve a trailing comma by marking it on the NodeArray - result.hasTrailingComma = true; - } - result.end = getNodeEnd(); - parsingContext = saveParsingContext; - return result; - } - function createMissingList() { - var pos = getNodePos(); - var result = []; - result.pos = pos; - result.end = pos; - return result; + return node; + } + ts.skipParentheses = skipParentheses; + function skipAssertions(node) { + while (ts.isAssertionExpression(node)) { + node = node.expression; } - function parseBracketedList(kind, parseElement, open, close) { - if (parseExpected(open)) { - var result = parseDelimitedList(kind, parseElement); - parseExpected(close); - return result; - } - return createMissingList(); + return node; + } + ts.skipAssertions = skipAssertions; + function skipPartiallyEmittedExpressions(node) { + while (node.kind === 288 /* PartiallyEmittedExpression */) { + node = node.expression; } - // The allowReservedWords parameter controls whether reserved words are permitted after the first dot - function parseEntityName(allowReservedWords, diagnosticMessage) { - var entity = parseIdentifier(diagnosticMessage); - while (parseOptional(21 /* DotToken */)) { - var node = createNode(139 /* QualifiedName */, entity.pos); // !!! - node.left = entity; - node.right = parseRightSideOfDot(allowReservedWords); - entity = finishNode(node); - } - return entity; + return node; + } + ts.skipPartiallyEmittedExpressions = skipPartiallyEmittedExpressions; + function startOnNewLine(node) { + node.startsOnNewLine = true; + return node; + } + ts.startOnNewLine = startOnNewLine; + function setOriginalNode(node, original) { + node.original = original; + if (original) { + var emitNode = original.emitNode; + if (emitNode) + node.emitNode = mergeEmitNode(emitNode, node.emitNode); } - function parseRightSideOfDot(allowIdentifierNames) { - // Technically a keyword is valid here as all identifiers and keywords are identifier names. - // However, often we'll encounter this in error situations when the identifier or keyword - // is actually starting another valid construct. - // - // So, we check for the following specific case: - // - // name. - // identifierOrKeyword identifierNameOrKeyword - // - // Note: the newlines are important here. For example, if that above code - // were rewritten into: - // - // name.identifierOrKeyword - // identifierNameOrKeyword - // - // Then we would consider it valid. That's because ASI would take effect and - // the code would be implicitly: "name.identifierOrKeyword; identifierNameOrKeyword". - // In the first case though, ASI will not take effect because there is not a - // line terminator after the identifier or keyword. - if (scanner.hasPrecedingLineBreak() && ts.tokenIsIdentifierOrKeyword(token())) { - var matchesPattern = lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine); - if (matchesPattern) { - // Report that we need an identifier. However, report it right after the dot, - // and not on the next token. This is because the next token might actually - // be an identifier and the error would be quite confusing. - return createMissingNode(69 /* Identifier */, /*reportAtCurrentPosition*/ true, ts.Diagnostics.Identifier_expected); + return node; + } + ts.setOriginalNode = setOriginalNode; + function mergeEmitNode(sourceEmitNode, destEmitNode) { + var flags = sourceEmitNode.flags, commentRange = sourceEmitNode.commentRange, sourceMapRange = sourceEmitNode.sourceMapRange, tokenSourceMapRanges = sourceEmitNode.tokenSourceMapRanges; + if (!destEmitNode && (flags || commentRange || sourceMapRange || tokenSourceMapRanges)) + destEmitNode = {}; + if (flags) + destEmitNode.flags = flags; + if (commentRange) + destEmitNode.commentRange = commentRange; + if (sourceMapRange) + destEmitNode.sourceMapRange = sourceMapRange; + if (tokenSourceMapRanges) + destEmitNode.tokenSourceMapRanges = mergeTokenSourceMapRanges(tokenSourceMapRanges, destEmitNode.tokenSourceMapRanges); + return destEmitNode; + } + function mergeTokenSourceMapRanges(sourceRanges, destRanges) { + if (!destRanges) + destRanges = ts.createMap(); + ts.copyProperties(sourceRanges, destRanges); + return destRanges; + } + /** + * Clears any EmitNode entries from parse-tree nodes. + * @param sourceFile A source file. + */ + function disposeEmitNodes(sourceFile) { + // During transformation we may need to annotate a parse tree node with transient + // transformation properties. As parse tree nodes live longer than transformation + // nodes, we need to make sure we reclaim any memory allocated for custom ranges + // from these nodes to ensure we do not hold onto entire subtrees just for position + // information. We also need to reset these nodes to a pre-transformation state + // for incremental parsing scenarios so that we do not impact later emit. + sourceFile = ts.getSourceFileOfNode(ts.getParseTreeNode(sourceFile)); + var emitNode = sourceFile && sourceFile.emitNode; + var annotatedNodes = emitNode && emitNode.annotatedNodes; + if (annotatedNodes) { + for (var _i = 0, annotatedNodes_1 = annotatedNodes; _i < annotatedNodes_1.length; _i++) { + var node = annotatedNodes_1[_i]; + node.emitNode = undefined; + } + } + } + ts.disposeEmitNodes = disposeEmitNodes; + /** + * Associates a node with the current transformation, initializing + * various transient transformation properties. + * + * @param node The node. + */ + function getOrCreateEmitNode(node) { + if (!node.emitNode) { + if (ts.isParseTreeNode(node)) { + // To avoid holding onto transformation artifacts, we keep track of any + // parse tree node we are annotating. This allows us to clean them up after + // all transformations have completed. + if (node.kind === 256 /* SourceFile */) { + return node.emitNode = { annotatedNodes: [node] }; } + var sourceFile = ts.getSourceFileOfNode(node); + getOrCreateEmitNode(sourceFile).annotatedNodes.push(node); } - return allowIdentifierNames ? parseIdentifierName() : parseIdentifier(); - } - function parseTemplateExpression() { - var template = createNode(189 /* TemplateExpression */); - template.head = parseTemplateLiteralFragment(); - ts.Debug.assert(template.head.kind === 12 /* TemplateHead */, "Template head has wrong token kind"); - var templateSpans = []; - templateSpans.pos = getNodePos(); - do { - templateSpans.push(parseTemplateSpan()); - } while (ts.lastOrUndefined(templateSpans).literal.kind === 13 /* TemplateMiddle */); - templateSpans.end = getNodeEnd(); - template.templateSpans = templateSpans; - return finishNode(template); - } - function parseTemplateSpan() { - var span = createNode(197 /* TemplateSpan */); - span.expression = allowInAnd(parseExpression); - var literal; - if (token() === 16 /* CloseBraceToken */) { - reScanTemplateToken(); - literal = parseTemplateLiteralFragment(); - } - else { - literal = parseExpectedToken(14 /* TemplateTail */, /*reportAtCurrentPosition*/ false, ts.Diagnostics._0_expected, ts.tokenToString(16 /* CloseBraceToken */)); - } - span.literal = literal; - return finishNode(span); - } - function parseLiteralNode(internName) { - return parseLiteralLikeNode(token(), internName); - } - function parseTemplateLiteralFragment() { - return parseLiteralLikeNode(token(), /*internName*/ false); - } - function parseLiteralLikeNode(kind, internName) { - var node = createNode(kind); - var text = scanner.getTokenValue(); - node.text = internName ? internIdentifier(text) : text; - if (scanner.hasExtendedUnicodeEscape()) { - node.hasExtendedUnicodeEscape = true; - } - if (scanner.isUnterminated()) { - node.isUnterminated = true; - } - var tokenPos = scanner.getTokenPos(); - nextToken(); - finishNode(node); - // Octal literals are not allowed in strict mode or ES5 - // Note that theoretically the following condition would hold true literals like 009, - // which is not octal.But because of how the scanner separates the tokens, we would - // never get a token like this. Instead, we would get 00 and 9 as two separate tokens. - // We also do not need to check for negatives because any prefix operator would be part of a - // parent unary expression. - if (node.kind === 8 /* NumericLiteral */ - && sourceText.charCodeAt(tokenPos) === 48 /* _0 */ - && ts.isOctalDigit(sourceText.charCodeAt(tokenPos + 1))) { - node.isOctalLiteral = true; - } - return node; + node.emitNode = {}; } - // TYPES - function parseTypeReference() { - var typeName = parseEntityName(/*allowReservedWords*/ false, ts.Diagnostics.Type_expected); - var node = createNode(155 /* TypeReference */, typeName.pos); - node.typeName = typeName; - if (!scanner.hasPrecedingLineBreak() && token() === 25 /* LessThanToken */) { - node.typeArguments = parseBracketedList(18 /* TypeArguments */, parseType, 25 /* LessThanToken */, 27 /* GreaterThanToken */); - } - return finishNode(node); + return node.emitNode; + } + /** + * Gets flags that control emit behavior of a node. + * + * @param node The node. + */ + function getEmitFlags(node) { + var emitNode = node.emitNode; + return emitNode && emitNode.flags; + } + ts.getEmitFlags = getEmitFlags; + /** + * Sets flags that control emit behavior of a node. + * + * @param node The node. + * @param emitFlags The NodeEmitFlags for the node. + */ + function setEmitFlags(node, emitFlags) { + getOrCreateEmitNode(node).flags = emitFlags; + return node; + } + ts.setEmitFlags = setEmitFlags; + /** + * Sets a custom text range to use when emitting source maps. + * + * @param node The node. + * @param range The text range. + */ + function setSourceMapRange(node, range) { + getOrCreateEmitNode(node).sourceMapRange = range; + return node; + } + ts.setSourceMapRange = setSourceMapRange; + /** + * Sets the TextRange to use for source maps for a token of a node. + * + * @param node The node. + * @param token The token. + * @param range The text range. + */ + function setTokenSourceMapRange(node, token, range) { + var emitNode = getOrCreateEmitNode(node); + var tokenSourceMapRanges = emitNode.tokenSourceMapRanges || (emitNode.tokenSourceMapRanges = ts.createMap()); + tokenSourceMapRanges[token] = range; + return node; + } + ts.setTokenSourceMapRange = setTokenSourceMapRange; + /** + * Sets a custom text range to use when emitting comments. + */ + function setCommentRange(node, range) { + getOrCreateEmitNode(node).commentRange = range; + return node; + } + ts.setCommentRange = setCommentRange; + /** + * Gets a custom text range to use when emitting comments. + * + * @param node The node. + */ + function getCommentRange(node) { + var emitNode = node.emitNode; + return (emitNode && emitNode.commentRange) || node; + } + ts.getCommentRange = getCommentRange; + /** + * Gets a custom text range to use when emitting source maps. + * + * @param node The node. + */ + function getSourceMapRange(node) { + var emitNode = node.emitNode; + return (emitNode && emitNode.sourceMapRange) || node; + } + ts.getSourceMapRange = getSourceMapRange; + /** + * Gets the TextRange to use for source maps for a token of a node. + * + * @param node The node. + * @param token The token. + */ + function getTokenSourceMapRange(node, token) { + var emitNode = node.emitNode; + var tokenSourceMapRanges = emitNode && emitNode.tokenSourceMapRanges; + return tokenSourceMapRanges && tokenSourceMapRanges[token]; + } + ts.getTokenSourceMapRange = getTokenSourceMapRange; + /** + * Gets the constant value to emit for an expression. + */ + function getConstantValue(node) { + var emitNode = node.emitNode; + return emitNode && emitNode.constantValue; + } + ts.getConstantValue = getConstantValue; + /** + * Sets the constant value to emit for an expression. + */ + function setConstantValue(node, value) { + var emitNode = getOrCreateEmitNode(node); + emitNode.constantValue = value; + return node; + } + ts.setConstantValue = setConstantValue; + function setTextRange(node, location) { + if (location) { + node.pos = location.pos; + node.end = location.end; } - function parseThisTypePredicate(lhs) { - nextToken(); - var node = createNode(154 /* TypePredicate */, lhs.pos); - node.parameterName = lhs; - node.type = parseType(); - return finishNode(node); + return node; + } + ts.setTextRange = setTextRange; + function setNodeFlags(node, flags) { + node.flags = flags; + return node; + } + ts.setNodeFlags = setNodeFlags; + function setMultiLine(node, multiLine) { + node.multiLine = multiLine; + return node; + } + ts.setMultiLine = setMultiLine; + function setHasTrailingComma(nodes, hasTrailingComma) { + nodes.hasTrailingComma = hasTrailingComma; + return nodes; + } + ts.setHasTrailingComma = setHasTrailingComma; + /** + * Get the name of that target module from an import or export declaration + */ + function getLocalNameForExternalImport(node, sourceFile) { + var namespaceDeclaration = ts.getNamespaceDeclarationNode(node); + if (namespaceDeclaration && !ts.isDefaultImport(node)) { + var name_9 = namespaceDeclaration.name; + return ts.isGeneratedIdentifier(name_9) ? name_9 : createIdentifier(ts.getSourceTextOfNodeFromSourceFile(sourceFile, namespaceDeclaration.name)); } - function parseThisTypeNode() { - var node = createNode(165 /* ThisType */); - nextToken(); - return finishNode(node); + if (node.kind === 230 /* ImportDeclaration */ && node.importClause) { + return getGeneratedNameForNode(node); } - function parseTypeQuery() { - var node = createNode(158 /* TypeQuery */); - parseExpected(101 /* TypeOfKeyword */); - node.exprName = parseEntityName(/*allowReservedWords*/ true); - return finishNode(node); + if (node.kind === 236 /* ExportDeclaration */ && node.moduleSpecifier) { + return getGeneratedNameForNode(node); } - function parseTypeParameter() { - var node = createNode(141 /* TypeParameter */); - node.name = parseIdentifier(); - if (parseOptional(83 /* ExtendsKeyword */)) { - // It's not uncommon for people to write improper constraints to a generic. If the - // user writes a constraint that is an expression and not an actual type, then parse - // it out as an expression (so we can recover well), but report that a type is needed - // instead. - if (isStartOfType() || !isStartOfExpression()) { - node.constraint = parseType(); - } - else { - // It was not a type, and it looked like an expression. Parse out an expression - // here so we recover well. Note: it is important that we call parseUnaryExpression - // and not parseExpression here. If the user has: - // - // - // - // We do *not* want to consume the > as we're consuming the expression for "". - node.expression = parseUnaryExpressionOrHigher(); - } - } - return finishNode(node); + return undefined; + } + ts.getLocalNameForExternalImport = getLocalNameForExternalImport; + /** + * Get the name of a target module from an import/export declaration as should be written in the emitted output. + * The emitted output name can be different from the input if: + * 1. The module has a /// + * 2. --out or --outFile is used, making the name relative to the rootDir + * 3- The containing SourceFile has an entry in renamedDependencies for the import as requested by some module loaders (e.g. System). + * Otherwise, a new StringLiteral node representing the module name will be returned. + */ + function getExternalModuleNameLiteral(importNode, sourceFile, host, resolver, compilerOptions) { + var moduleName = ts.getExternalModuleName(importNode); + if (moduleName.kind === 9 /* StringLiteral */) { + return tryGetModuleNameFromDeclaration(importNode, host, resolver, compilerOptions) + || tryRenameExternalModule(moduleName, sourceFile) + || getSynthesizedClone(moduleName); } - function parseTypeParameters() { - if (token() === 25 /* LessThanToken */) { - return parseBracketedList(17 /* TypeParameters */, parseTypeParameter, 25 /* LessThanToken */, 27 /* GreaterThanToken */); - } + return undefined; + } + ts.getExternalModuleNameLiteral = getExternalModuleNameLiteral; + /** + * Some bundlers (SystemJS builder) sometimes want to rename dependencies. + * Here we check if alternative name was provided for a given moduleName and return it if possible. + */ + function tryRenameExternalModule(moduleName, sourceFile) { + if (sourceFile.renamedDependencies && ts.hasProperty(sourceFile.renamedDependencies, moduleName.text)) { + return createLiteral(sourceFile.renamedDependencies[moduleName.text]); } - function parseParameterType() { - if (parseOptional(54 /* ColonToken */)) { - return parseType(); - } + return undefined; + } + /** + * Get the name of a module as should be written in the emitted output. + * The emitted output name can be different from the input if: + * 1. The module has a /// + * 2. --out or --outFile is used, making the name relative to the rootDir + * Otherwise, a new StringLiteral node representing the module name will be returned. + */ + function tryGetModuleNameFromFile(file, host, options) { + if (!file) { return undefined; } - function isStartOfParameter() { - return token() === 22 /* DotDotDotToken */ || isIdentifierOrPattern() || ts.isModifierKind(token()) || token() === 55 /* AtToken */ || token() === 97 /* ThisKeyword */; - } - function setModifiers(node, modifiers) { - if (modifiers) { - node.flags |= modifiers.flags; - node.modifiers = modifiers; - } - } - function parseParameter() { - var node = createNode(142 /* Parameter */); - if (token() === 97 /* ThisKeyword */) { - node.name = createIdentifier(/*isIdentifier*/ true, undefined); - node.type = parseParameterType(); - return finishNode(node); - } - node.decorators = parseDecorators(); - setModifiers(node, parseModifiers()); - node.dotDotDotToken = parseOptionalToken(22 /* DotDotDotToken */); - // FormalParameter [Yield,Await]: - // BindingElement[?Yield,?Await] - node.name = parseIdentifierOrPattern(); - if (ts.getFullWidth(node.name) === 0 && node.flags === 0 && ts.isModifierKind(token())) { - // in cases like - // 'use strict' - // function foo(static) - // isParameter('static') === true, because of isModifier('static') - // however 'static' is not a legal identifier in a strict mode. - // so result of this function will be ParameterDeclaration (flags = 0, name = missing, type = undefined, initializer = undefined) - // and current token will not change => parsing of the enclosing parameter list will last till the end of time (or OOM) - // to avoid this we'll advance cursor to the next token. - nextToken(); - } - node.questionToken = parseOptionalToken(53 /* QuestionToken */); - node.type = parseParameterType(); - node.initializer = parseBindingElementInitializer(/*inParameter*/ true); - // Do not check for initializers in an ambient context for parameters. This is not - // a grammar error because the grammar allows arbitrary call signatures in - // an ambient context. - // It is actually not necessary for this to be an error at all. The reason is that - // function/constructor implementations are syntactically disallowed in ambient - // contexts. In addition, parameter initializers are semantically disallowed in - // overload signatures. So parameter initializers are transitively disallowed in - // ambient contexts. - return addJSDocComment(finishNode(node)); + if (file.moduleName) { + return createLiteral(file.moduleName); } - function parseBindingElementInitializer(inParameter) { - return inParameter ? parseParameterInitializer() : parseNonParameterInitializer(); + if (!ts.isDeclarationFile(file) && (options.out || options.outFile)) { + return createLiteral(ts.getExternalModuleNameFromPath(host, file.fileName)); } - function parseParameterInitializer() { - return parseInitializer(/*inParameter*/ true); + return undefined; + } + ts.tryGetModuleNameFromFile = tryGetModuleNameFromFile; + function tryGetModuleNameFromDeclaration(declaration, host, resolver, compilerOptions) { + return tryGetModuleNameFromFile(resolver.getExternalModuleFileFromDeclaration(declaration), host, compilerOptions); + } +})(ts || (ts = {})); +/// +/// +/// +var ts; +(function (ts) { + var NodeConstructor; + var TokenConstructor; + var IdentifierConstructor; + var SourceFileConstructor; + function createNode(kind, pos, end) { + if (kind === 256 /* SourceFile */) { + return new (SourceFileConstructor || (SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor()))(kind, pos, end); } - function fillSignature(returnToken, yieldContext, awaitContext, requireCompleteParameterList, signature) { - var returnTokenRequired = returnToken === 34 /* EqualsGreaterThanToken */; - signature.typeParameters = parseTypeParameters(); - signature.parameters = parseParameterList(yieldContext, awaitContext, requireCompleteParameterList); - if (returnTokenRequired) { - parseExpected(returnToken); - signature.type = parseTypeOrTypePredicate(); - } - else if (parseOptional(returnToken)) { - signature.type = parseTypeOrTypePredicate(); - } + else if (kind === 69 /* Identifier */) { + return new (IdentifierConstructor || (IdentifierConstructor = ts.objectAllocator.getIdentifierConstructor()))(kind, pos, end); } - function parseParameterList(yieldContext, awaitContext, requireCompleteParameterList) { - // FormalParameters [Yield,Await]: (modified) - // [empty] - // FormalParameterList[?Yield,Await] - // - // FormalParameter[Yield,Await]: (modified) - // BindingElement[?Yield,Await] - // - // BindingElement [Yield,Await]: (modified) - // SingleNameBinding[?Yield,?Await] - // BindingPattern[?Yield,?Await]Initializer [In, ?Yield,?Await] opt - // - // SingleNameBinding [Yield,Await]: - // BindingIdentifier[?Yield,?Await]Initializer [In, ?Yield,?Await] opt - if (parseExpected(17 /* OpenParenToken */)) { - var savedYieldContext = inYieldContext(); - var savedAwaitContext = inAwaitContext(); - setYieldContext(yieldContext); - setAwaitContext(awaitContext); - var result = parseDelimitedList(16 /* Parameters */, parseParameter); - setYieldContext(savedYieldContext); - setAwaitContext(savedAwaitContext); - if (!parseExpected(18 /* CloseParenToken */) && requireCompleteParameterList) { - // Caller insisted that we had to end with a ) We didn't. So just return - // undefined here. - return undefined; - } - return result; - } - // We didn't even have an open paren. If the caller requires a complete parameter list, - // we definitely can't provide that. However, if they're ok with an incomplete one, - // then just return an empty set of parameters. - return requireCompleteParameterList ? undefined : createMissingList(); + else if (kind < 139 /* FirstNode */) { + return new (TokenConstructor || (TokenConstructor = ts.objectAllocator.getTokenConstructor()))(kind, pos, end); } - function parseTypeMemberSemicolon() { - // We allow type members to be separated by commas or (possibly ASI) semicolons. - // First check if it was a comma. If so, we're done with the member. - if (parseOptional(24 /* CommaToken */)) { - return; - } - // Didn't have a comma. We must have a (possible ASI) semicolon. - parseSemicolon(); + else { + return new (NodeConstructor || (NodeConstructor = ts.objectAllocator.getNodeConstructor()))(kind, pos, end); } - function parseSignatureMember(kind) { - var node = createNode(kind); - if (kind === 152 /* ConstructSignature */) { - parseExpected(92 /* NewKeyword */); - } - fillSignature(54 /* ColonToken */, /*yieldContext*/ false, /*awaitContext*/ false, /*requireCompleteParameterList*/ false, node); - parseTypeMemberSemicolon(); - return finishNode(node); + } + ts.createNode = createNode; + function visitNode(cbNode, node) { + if (node) { + return cbNode(node); } - function isIndexSignature() { - if (token() !== 19 /* OpenBracketToken */) { - return false; - } - return lookAhead(isUnambiguouslyIndexSignature); + } + function visitNodeArray(cbNodes, nodes) { + if (nodes) { + return cbNodes(nodes); } - function isUnambiguouslyIndexSignature() { - // The only allowed sequence is: - // - // [id: - // - // However, for error recovery, we also check the following cases: - // - // [... - // [id, - // [id?, - // [id?: - // [id?] - // [public id - // [private id - // [protected id - // [] - // - nextToken(); - if (token() === 22 /* DotDotDotToken */ || token() === 20 /* CloseBracketToken */) { - return true; - } - if (ts.isModifierKind(token())) { - nextToken(); - if (isIdentifier()) { - return true; + } + function visitEachNode(cbNode, nodes) { + if (nodes) { + for (var _i = 0, nodes_1 = nodes; _i < nodes_1.length; _i++) { + var node = nodes_1[_i]; + var result = cbNode(node); + if (result) { + return result; } } - else if (!isIdentifier()) { - return false; - } - else { - // Skip the identifier - nextToken(); - } - // A colon signifies a well formed indexer - // A comma should be a badly formed indexer because comma expressions are not allowed - // in computed properties. - if (token() === 54 /* ColonToken */ || token() === 24 /* CommaToken */) { - return true; - } - // Question mark could be an indexer with an optional property, - // or it could be a conditional expression in a computed property. - if (token() !== 53 /* QuestionToken */) { - return false; - } - // If any of the following tokens are after the question mark, it cannot - // be a conditional expression, so treat it as an indexer. - nextToken(); - return token() === 54 /* ColonToken */ || token() === 24 /* CommaToken */ || token() === 20 /* CloseBracketToken */; - } - function parseIndexSignatureDeclaration(fullStart, decorators, modifiers) { - var node = createNode(153 /* IndexSignature */, fullStart); - node.decorators = decorators; - setModifiers(node, modifiers); - node.parameters = parseBracketedList(16 /* Parameters */, parseParameter, 19 /* OpenBracketToken */, 20 /* CloseBracketToken */); - node.type = parseTypeAnnotation(); - parseTypeMemberSemicolon(); - return finishNode(node); } - function parsePropertyOrMethodSignature(fullStart, modifiers) { - var name = parsePropertyName(); - var questionToken = parseOptionalToken(53 /* QuestionToken */); - if (token() === 17 /* OpenParenToken */ || token() === 25 /* LessThanToken */) { - var method = createNode(146 /* MethodSignature */, fullStart); - setModifiers(method, modifiers); + } + // Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes + // stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise, + // embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns + // a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned. + function forEachChild(node, cbNode, cbNodeArray) { + if (!node) { + return; + } + // The visitXXX functions could be written as local functions that close over the cbNode and cbNodeArray + // callback parameters, but that causes a closure allocation for each invocation with noticeable effects + // on performance. + var visitNodes = cbNodeArray ? visitNodeArray : visitEachNode; + var cbNodes = cbNodeArray || cbNode; + switch (node.kind) { + case 139 /* QualifiedName */: + return visitNode(cbNode, node.left) || + visitNode(cbNode, node.right); + case 141 /* TypeParameter */: + return visitNode(cbNode, node.name) || + visitNode(cbNode, node.constraint) || + visitNode(cbNode, node.expression); + case 254 /* ShorthandPropertyAssignment */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNode(cbNode, node.questionToken) || + visitNode(cbNode, node.equalsToken) || + visitNode(cbNode, node.objectAssignmentInitializer); + case 142 /* Parameter */: + case 145 /* PropertyDeclaration */: + case 144 /* PropertySignature */: + case 253 /* PropertyAssignment */: + case 218 /* VariableDeclaration */: + case 169 /* BindingElement */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.propertyName) || + visitNode(cbNode, node.dotDotDotToken) || + visitNode(cbNode, node.name) || + visitNode(cbNode, node.questionToken) || + visitNode(cbNode, node.type) || + visitNode(cbNode, node.initializer); + case 156 /* FunctionType */: + case 157 /* ConstructorType */: + case 151 /* CallSignature */: + case 152 /* ConstructSignature */: + case 153 /* IndexSignature */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNodes(cbNodes, node.typeParameters) || + visitNodes(cbNodes, node.parameters) || + visitNode(cbNode, node.type); + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + case 148 /* Constructor */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 179 /* FunctionExpression */: + case 220 /* FunctionDeclaration */: + case 180 /* ArrowFunction */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.asteriskToken) || + visitNode(cbNode, node.name) || + visitNode(cbNode, node.questionToken) || + visitNodes(cbNodes, node.typeParameters) || + visitNodes(cbNodes, node.parameters) || + visitNode(cbNode, node.type) || + visitNode(cbNode, node.equalsGreaterThanToken) || + visitNode(cbNode, node.body); + case 155 /* TypeReference */: + return visitNode(cbNode, node.typeName) || + visitNodes(cbNodes, node.typeArguments); + case 154 /* TypePredicate */: + return visitNode(cbNode, node.parameterName) || + visitNode(cbNode, node.type); + case 158 /* TypeQuery */: + return visitNode(cbNode, node.exprName); + case 159 /* TypeLiteral */: + return visitNodes(cbNodes, node.members); + case 160 /* ArrayType */: + return visitNode(cbNode, node.elementType); + case 161 /* TupleType */: + return visitNodes(cbNodes, node.elementTypes); + case 162 /* UnionType */: + case 163 /* IntersectionType */: + return visitNodes(cbNodes, node.types); + case 164 /* ParenthesizedType */: + return visitNode(cbNode, node.type); + case 166 /* LiteralType */: + return visitNode(cbNode, node.literal); + case 167 /* ObjectBindingPattern */: + case 168 /* ArrayBindingPattern */: + return visitNodes(cbNodes, node.elements); + case 170 /* ArrayLiteralExpression */: + return visitNodes(cbNodes, node.elements); + case 171 /* ObjectLiteralExpression */: + return visitNodes(cbNodes, node.properties); + case 172 /* PropertyAccessExpression */: + return visitNode(cbNode, node.expression) || + visitNode(cbNode, node.name); + case 173 /* ElementAccessExpression */: + return visitNode(cbNode, node.expression) || + visitNode(cbNode, node.argumentExpression); + case 174 /* CallExpression */: + case 175 /* NewExpression */: + return visitNode(cbNode, node.expression) || + visitNodes(cbNodes, node.typeArguments) || + visitNodes(cbNodes, node.arguments); + case 176 /* TaggedTemplateExpression */: + return visitNode(cbNode, node.tag) || + visitNode(cbNode, node.template); + case 177 /* TypeAssertionExpression */: + return visitNode(cbNode, node.type) || + visitNode(cbNode, node.expression); + case 178 /* ParenthesizedExpression */: + return visitNode(cbNode, node.expression); + case 181 /* DeleteExpression */: + return visitNode(cbNode, node.expression); + case 182 /* TypeOfExpression */: + return visitNode(cbNode, node.expression); + case 183 /* VoidExpression */: + return visitNode(cbNode, node.expression); + case 185 /* PrefixUnaryExpression */: + return visitNode(cbNode, node.operand); + case 190 /* YieldExpression */: + return visitNode(cbNode, node.asteriskToken) || + visitNode(cbNode, node.expression); + case 184 /* AwaitExpression */: + return visitNode(cbNode, node.expression); + case 186 /* PostfixUnaryExpression */: + return visitNode(cbNode, node.operand); + case 187 /* BinaryExpression */: + return visitNode(cbNode, node.left) || + visitNode(cbNode, node.operatorToken) || + visitNode(cbNode, node.right); + case 195 /* AsExpression */: + return visitNode(cbNode, node.expression) || + visitNode(cbNode, node.type); + case 196 /* NonNullExpression */: + return visitNode(cbNode, node.expression); + case 188 /* ConditionalExpression */: + return visitNode(cbNode, node.condition) || + visitNode(cbNode, node.questionToken) || + visitNode(cbNode, node.whenTrue) || + visitNode(cbNode, node.colonToken) || + visitNode(cbNode, node.whenFalse); + case 191 /* SpreadElementExpression */: + return visitNode(cbNode, node.expression); + case 199 /* Block */: + case 226 /* ModuleBlock */: + return visitNodes(cbNodes, node.statements); + case 256 /* SourceFile */: + return visitNodes(cbNodes, node.statements) || + visitNode(cbNode, node.endOfFileToken); + case 200 /* VariableStatement */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.declarationList); + case 219 /* VariableDeclarationList */: + return visitNodes(cbNodes, node.declarations); + case 202 /* ExpressionStatement */: + return visitNode(cbNode, node.expression); + case 203 /* IfStatement */: + return visitNode(cbNode, node.expression) || + visitNode(cbNode, node.thenStatement) || + visitNode(cbNode, node.elseStatement); + case 204 /* DoStatement */: + return visitNode(cbNode, node.statement) || + visitNode(cbNode, node.expression); + case 205 /* WhileStatement */: + return visitNode(cbNode, node.expression) || + visitNode(cbNode, node.statement); + case 206 /* ForStatement */: + return visitNode(cbNode, node.initializer) || + visitNode(cbNode, node.condition) || + visitNode(cbNode, node.incrementor) || + visitNode(cbNode, node.statement); + case 207 /* ForInStatement */: + return visitNode(cbNode, node.initializer) || + visitNode(cbNode, node.expression) || + visitNode(cbNode, node.statement); + case 208 /* ForOfStatement */: + return visitNode(cbNode, node.initializer) || + visitNode(cbNode, node.expression) || + visitNode(cbNode, node.statement); + case 209 /* ContinueStatement */: + case 210 /* BreakStatement */: + return visitNode(cbNode, node.label); + case 211 /* ReturnStatement */: + return visitNode(cbNode, node.expression); + case 212 /* WithStatement */: + return visitNode(cbNode, node.expression) || + visitNode(cbNode, node.statement); + case 213 /* SwitchStatement */: + return visitNode(cbNode, node.expression) || + visitNode(cbNode, node.caseBlock); + case 227 /* CaseBlock */: + return visitNodes(cbNodes, node.clauses); + case 249 /* CaseClause */: + return visitNode(cbNode, node.expression) || + visitNodes(cbNodes, node.statements); + case 250 /* DefaultClause */: + return visitNodes(cbNodes, node.statements); + case 214 /* LabeledStatement */: + return visitNode(cbNode, node.label) || + visitNode(cbNode, node.statement); + case 215 /* ThrowStatement */: + return visitNode(cbNode, node.expression); + case 216 /* TryStatement */: + return visitNode(cbNode, node.tryBlock) || + visitNode(cbNode, node.catchClause) || + visitNode(cbNode, node.finallyBlock); + case 252 /* CatchClause */: + return visitNode(cbNode, node.variableDeclaration) || + visitNode(cbNode, node.block); + case 143 /* Decorator */: + return visitNode(cbNode, node.expression); + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNodes(cbNodes, node.typeParameters) || + visitNodes(cbNodes, node.heritageClauses) || + visitNodes(cbNodes, node.members); + case 222 /* InterfaceDeclaration */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNodes(cbNodes, node.typeParameters) || + visitNodes(cbNodes, node.heritageClauses) || + visitNodes(cbNodes, node.members); + case 223 /* TypeAliasDeclaration */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNodes(cbNodes, node.typeParameters) || + visitNode(cbNode, node.type); + case 224 /* EnumDeclaration */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNodes(cbNodes, node.members); + case 255 /* EnumMember */: + return visitNode(cbNode, node.name) || + visitNode(cbNode, node.initializer); + case 225 /* ModuleDeclaration */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNode(cbNode, node.body); + case 229 /* ImportEqualsDeclaration */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNode(cbNode, node.moduleReference); + case 230 /* ImportDeclaration */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.importClause) || + visitNode(cbNode, node.moduleSpecifier); + case 231 /* ImportClause */: + return visitNode(cbNode, node.name) || + visitNode(cbNode, node.namedBindings); + case 228 /* NamespaceExportDeclaration */: + return visitNode(cbNode, node.name); + case 232 /* NamespaceImport */: + return visitNode(cbNode, node.name); + case 233 /* NamedImports */: + case 237 /* NamedExports */: + return visitNodes(cbNodes, node.elements); + case 236 /* ExportDeclaration */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.exportClause) || + visitNode(cbNode, node.moduleSpecifier); + case 234 /* ImportSpecifier */: + case 238 /* ExportSpecifier */: + return visitNode(cbNode, node.propertyName) || + visitNode(cbNode, node.name); + case 235 /* ExportAssignment */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.expression); + case 189 /* TemplateExpression */: + return visitNode(cbNode, node.head) || visitNodes(cbNodes, node.templateSpans); + case 197 /* TemplateSpan */: + return visitNode(cbNode, node.expression) || visitNode(cbNode, node.literal); + case 140 /* ComputedPropertyName */: + return visitNode(cbNode, node.expression); + case 251 /* HeritageClause */: + return visitNodes(cbNodes, node.types); + case 194 /* ExpressionWithTypeArguments */: + return visitNode(cbNode, node.expression) || + visitNodes(cbNodes, node.typeArguments); + case 240 /* ExternalModuleReference */: + return visitNode(cbNode, node.expression); + case 239 /* MissingDeclaration */: + return visitNodes(cbNodes, node.decorators); + case 241 /* JsxElement */: + return visitNode(cbNode, node.openingElement) || + visitNodes(cbNodes, node.children) || + visitNode(cbNode, node.closingElement); + case 242 /* JsxSelfClosingElement */: + case 243 /* JsxOpeningElement */: + return visitNode(cbNode, node.tagName) || + visitNodes(cbNodes, node.attributes); + case 246 /* JsxAttribute */: + return visitNode(cbNode, node.name) || + visitNode(cbNode, node.initializer); + case 247 /* JsxSpreadAttribute */: + return visitNode(cbNode, node.expression); + case 248 /* JsxExpression */: + return visitNode(cbNode, node.expression); + case 245 /* JsxClosingElement */: + return visitNode(cbNode, node.tagName); + case 257 /* JSDocTypeExpression */: + return visitNode(cbNode, node.type); + case 261 /* JSDocUnionType */: + return visitNodes(cbNodes, node.types); + case 262 /* JSDocTupleType */: + return visitNodes(cbNodes, node.types); + case 260 /* JSDocArrayType */: + return visitNode(cbNode, node.elementType); + case 264 /* JSDocNonNullableType */: + return visitNode(cbNode, node.type); + case 263 /* JSDocNullableType */: + return visitNode(cbNode, node.type); + case 265 /* JSDocRecordType */: + return visitNode(cbNode, node.literal); + case 267 /* JSDocTypeReference */: + return visitNode(cbNode, node.name) || + visitNodes(cbNodes, node.typeArguments); + case 268 /* JSDocOptionalType */: + return visitNode(cbNode, node.type); + case 269 /* JSDocFunctionType */: + return visitNodes(cbNodes, node.parameters) || + visitNode(cbNode, node.type); + case 270 /* JSDocVariadicType */: + return visitNode(cbNode, node.type); + case 271 /* JSDocConstructorType */: + return visitNode(cbNode, node.type); + case 272 /* JSDocThisType */: + return visitNode(cbNode, node.type); + case 266 /* JSDocRecordMember */: + return visitNode(cbNode, node.name) || + visitNode(cbNode, node.type); + case 273 /* JSDocComment */: + return visitNodes(cbNodes, node.tags); + case 275 /* JSDocParameterTag */: + return visitNode(cbNode, node.preParameterName) || + visitNode(cbNode, node.typeExpression) || + visitNode(cbNode, node.postParameterName); + case 276 /* JSDocReturnTag */: + return visitNode(cbNode, node.typeExpression); + case 277 /* JSDocTypeTag */: + return visitNode(cbNode, node.typeExpression); + case 278 /* JSDocTemplateTag */: + return visitNodes(cbNodes, node.typeParameters); + case 279 /* JSDocTypedefTag */: + return visitNode(cbNode, node.typeExpression) || + visitNode(cbNode, node.name) || + visitNode(cbNode, node.jsDocTypeLiteral); + case 281 /* JSDocTypeLiteral */: + return visitNodes(cbNodes, node.jsDocPropertyTags); + case 280 /* JSDocPropertyTag */: + return visitNode(cbNode, node.typeExpression) || + visitNode(cbNode, node.name); + case 288 /* PartiallyEmittedExpression */: + return visitNode(cbNode, node.expression); + case 282 /* JSDocLiteralType */: + return visitNode(cbNode, node.literal); + } + } + ts.forEachChild = forEachChild; + function createSourceFile(fileName, sourceText, languageVersion, setParentNodes, scriptKind) { + if (setParentNodes === void 0) { setParentNodes = false; } + ts.performance.mark("beforeParse"); + var result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind); + ts.performance.mark("afterParse"); + ts.performance.measure("Parse", "beforeParse", "afterParse"); + return result; + } + ts.createSourceFile = createSourceFile; + function isExternalModule(file) { + return file.externalModuleIndicator !== undefined; + } + ts.isExternalModule = isExternalModule; + // Produces a new SourceFile for the 'newText' provided. The 'textChangeRange' parameter + // indicates what changed between the 'text' that this SourceFile has and the 'newText'. + // The SourceFile will be created with the compiler attempting to reuse as many nodes from + // this file as possible. + // + // Note: this function mutates nodes from this SourceFile. That means any existing nodes + // from this SourceFile that are being held onto may change as a result (including + // becoming detached from any SourceFile). It is recommended that this SourceFile not + // be used once 'update' is called on it. + function updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks) { + return IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); + } + ts.updateSourceFile = updateSourceFile; + /* @internal */ + function parseIsolatedJSDocComment(content, start, length) { + var result = Parser.JSDocParser.parseIsolatedJSDocComment(content, start, length); + if (result && result.jsDoc) { + // because the jsDocComment was parsed out of the source file, it might + // not be covered by the fixupParentReferences. + Parser.fixupParentReferences(result.jsDoc); + } + return result; + } + ts.parseIsolatedJSDocComment = parseIsolatedJSDocComment; + /* @internal */ + // Exposed only for testing. + function parseJSDocTypeExpressionForTests(content, start, length) { + return Parser.JSDocParser.parseJSDocTypeExpressionForTests(content, start, length); + } + ts.parseJSDocTypeExpressionForTests = parseJSDocTypeExpressionForTests; + // Implement the parser as a singleton module. We do this for perf reasons because creating + // parser instances can actually be expensive enough to impact us on projects with many source + // files. + var Parser; + (function (Parser) { + // Share a single scanner across all calls to parse a source file. This helps speed things + // up by avoiding the cost of creating/compiling scanners over and over again. + var scanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ true); + var disallowInAndDecoratorContext = 32768 /* DisallowInContext */ | 131072 /* DecoratorContext */; + // capture constructors in 'initializeState' to avoid null checks + var NodeConstructor; + var TokenConstructor; + var IdentifierConstructor; + var SourceFileConstructor; + var sourceFile; + var parseDiagnostics; + var syntaxCursor; + var currentToken; + var sourceText; + var nodeCount; + var identifiers; + var identifierCount; + var parsingContext; + // Flags that dictate what parsing context we're in. For example: + // Whether or not we are in strict parsing mode. All that changes in strict parsing mode is + // that some tokens that would be considered identifiers may be considered keywords. + // + // When adding more parser context flags, consider which is the more common case that the + // flag will be in. This should be the 'false' state for that flag. The reason for this is + // that we don't store data in our nodes unless the value is in the *non-default* state. So, + // for example, more often than code 'allows-in' (or doesn't 'disallow-in'). We opt for + // 'disallow-in' set to 'false'. Otherwise, if we had 'allowsIn' set to 'true', then almost + // all nodes would need extra state on them to store this info. + // + // Note: 'allowIn' and 'allowYield' track 1:1 with the [in] and [yield] concepts in the ES6 + // grammar specification. + // + // An important thing about these context concepts. By default they are effectively inherited + // while parsing through every grammar production. i.e. if you don't change them, then when + // you parse a sub-production, it will have the same context values as the parent production. + // This is great most of the time. After all, consider all the 'expression' grammar productions + // and how nearly all of them pass along the 'in' and 'yield' context values: + // + // EqualityExpression[In, Yield] : + // RelationalExpression[?In, ?Yield] + // EqualityExpression[?In, ?Yield] == RelationalExpression[?In, ?Yield] + // EqualityExpression[?In, ?Yield] != RelationalExpression[?In, ?Yield] + // EqualityExpression[?In, ?Yield] === RelationalExpression[?In, ?Yield] + // EqualityExpression[?In, ?Yield] !== RelationalExpression[?In, ?Yield] + // + // Where you have to be careful is then understanding what the points are in the grammar + // where the values are *not* passed along. For example: + // + // SingleNameBinding[Yield,GeneratorParameter] + // [+GeneratorParameter]BindingIdentifier[Yield] Initializer[In]opt + // [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt + // + // Here this is saying that if the GeneratorParameter context flag is set, that we should + // explicitly set the 'yield' context flag to false before calling into the BindingIdentifier + // and we should explicitly unset the 'yield' context flag before calling into the Initializer. + // production. Conversely, if the GeneratorParameter context flag is not set, then we + // should leave the 'yield' context flag alone. + // + // Getting this all correct is tricky and requires careful reading of the grammar to + // understand when these values should be changed versus when they should be inherited. + // + // Note: it should not be necessary to save/restore these flags during speculative/lookahead + // parsing. These context flags are naturally stored and restored through normal recursive + // descent parsing and unwinding. + var contextFlags; + // Whether or not we've had a parse error since creating the last AST node. If we have + // encountered an error, it will be stored on the next AST node we create. Parse errors + // can be broken down into three categories: + // + // 1) An error that occurred during scanning. For example, an unterminated literal, or a + // character that was completely not understood. + // + // 2) A token was expected, but was not present. This type of error is commonly produced + // by the 'parseExpected' function. + // + // 3) A token was present that no parsing function was able to consume. This type of error + // only occurs in the 'abortParsingListOrMoveToNextToken' function when the parser + // decides to skip the token. + // + // In all of these cases, we want to mark the next node as having had an error before it. + // With this mark, we can know in incremental settings if this node can be reused, or if + // we have to reparse it. If we don't keep this information around, we may just reuse the + // node. in that event we would then not produce the same errors as we did before, causing + // significant confusion problems. + // + // Note: it is necessary that this value be saved/restored during speculative/lookahead + // parsing. During lookahead parsing, we will often create a node. That node will have + // this value attached, and then this value will be set back to 'false'. If we decide to + // rewind, we must get back to the same value we had prior to the lookahead. + // + // Note: any errors at the end of the file that do not precede a regular node, should get + // attached to the EOF token. + var parseErrorBeforeNextFinishedNode = false; + function parseSourceFile(fileName, _sourceText, languageVersion, _syntaxCursor, setParentNodes, scriptKind) { + scriptKind = ts.ensureScriptKind(fileName, scriptKind); + initializeState(fileName, _sourceText, languageVersion, _syntaxCursor, scriptKind); + var result = parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind); + clearState(); + return result; + } + Parser.parseSourceFile = parseSourceFile; + function getLanguageVariant(scriptKind) { + // .tsx and .jsx files are treated as jsx language variant. + return scriptKind === 4 /* TSX */ || scriptKind === 2 /* JSX */ || scriptKind === 1 /* JS */ ? 1 /* JSX */ : 0 /* Standard */; + } + function initializeState(fileName, _sourceText, languageVersion, _syntaxCursor, scriptKind) { + NodeConstructor = ts.objectAllocator.getNodeConstructor(); + TokenConstructor = ts.objectAllocator.getTokenConstructor(); + IdentifierConstructor = ts.objectAllocator.getIdentifierConstructor(); + SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor(); + sourceText = _sourceText; + syntaxCursor = _syntaxCursor; + parseDiagnostics = []; + parsingContext = 0; + identifiers = ts.createMap(); + identifierCount = 0; + nodeCount = 0; + contextFlags = scriptKind === 1 /* JS */ || scriptKind === 2 /* JSX */ ? 1048576 /* JavaScriptFile */ : 0 /* None */; + parseErrorBeforeNextFinishedNode = false; + // Initialize and prime the scanner before parsing the source elements. + scanner.setText(sourceText); + scanner.setOnError(scanError); + scanner.setScriptTarget(languageVersion); + scanner.setLanguageVariant(getLanguageVariant(scriptKind)); + } + function clearState() { + // Clear out the text the scanner is pointing at, so it doesn't keep anything alive unnecessarily. + scanner.setText(""); + scanner.setOnError(undefined); + // Clear any data. We don't want to accidentally hold onto it for too long. + parseDiagnostics = undefined; + sourceFile = undefined; + identifiers = undefined; + syntaxCursor = undefined; + sourceText = undefined; + } + function parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind) { + sourceFile = createSourceFile(fileName, languageVersion, scriptKind); + sourceFile.flags = contextFlags; + // Prime the scanner. + nextToken(); + processReferenceComments(sourceFile); + sourceFile.statements = parseList(0 /* SourceElements */, parseStatement); + ts.Debug.assert(token() === 1 /* EndOfFileToken */); + sourceFile.endOfFileToken = parseTokenNode(); + setExternalModuleIndicator(sourceFile); + sourceFile.nodeCount = nodeCount; + sourceFile.identifierCount = identifierCount; + sourceFile.identifiers = identifiers; + sourceFile.parseDiagnostics = parseDiagnostics; + if (setParentNodes) { + fixupParentReferences(sourceFile); + } + return sourceFile; + } + function addJSDocComment(node) { + var comments = ts.getJsDocCommentsFromText(node, sourceFile.text); + if (comments) { + for (var _i = 0, comments_2 = comments; _i < comments_2.length; _i++) { + var comment = comments_2[_i]; + var jsDoc = JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos); + if (!jsDoc) { + continue; + } + if (!node.jsDocComments) { + node.jsDocComments = []; + } + node.jsDocComments.push(jsDoc); + } + } + return node; + } + function fixupParentReferences(rootNode) { + // normally parent references are set during binding. However, for clients that only need + // a syntax tree, and no semantic features, then the binding process is an unnecessary + // overhead. This functions allows us to set all the parents, without all the expense of + // binding. + var parent = rootNode; + forEachChild(rootNode, visitNode); + return; + function visitNode(n) { + // walk down setting parents that differ from the parent we think it should be. This + // allows us to quickly bail out of setting parents for subtrees during incremental + // parsing + if (n.parent !== parent) { + n.parent = parent; + var saveParent = parent; + parent = n; + forEachChild(n, visitNode); + if (n.jsDocComments) { + for (var _i = 0, _a = n.jsDocComments; _i < _a.length; _i++) { + var jsDocComment = _a[_i]; + jsDocComment.parent = n; + parent = jsDocComment; + forEachChild(jsDocComment, visitNode); + } + } + parent = saveParent; + } + } + } + Parser.fixupParentReferences = fixupParentReferences; + function createSourceFile(fileName, languageVersion, scriptKind) { + // code from createNode is inlined here so createNode won't have to deal with special case of creating source files + // this is quite rare comparing to other nodes and createNode should be as fast as possible + var sourceFile = new SourceFileConstructor(256 /* SourceFile */, /*pos*/ 0, /* end */ sourceText.length); + nodeCount++; + sourceFile.text = sourceText; + sourceFile.bindDiagnostics = []; + sourceFile.languageVersion = languageVersion; + sourceFile.fileName = ts.normalizePath(fileName); + sourceFile.languageVariant = getLanguageVariant(scriptKind); + sourceFile.isDeclarationFile = ts.fileExtensionIs(sourceFile.fileName, ".d.ts"); + sourceFile.scriptKind = scriptKind; + return sourceFile; + } + function setContextFlag(val, flag) { + if (val) { + contextFlags |= flag; + } + else { + contextFlags &= ~flag; + } + } + function setDisallowInContext(val) { + setContextFlag(val, 32768 /* DisallowInContext */); + } + function setYieldContext(val) { + setContextFlag(val, 65536 /* YieldContext */); + } + function setDecoratorContext(val) { + setContextFlag(val, 131072 /* DecoratorContext */); + } + function setAwaitContext(val) { + setContextFlag(val, 262144 /* AwaitContext */); + } + function doOutsideOfContext(context, func) { + // contextFlagsToClear will contain only the context flags that are + // currently set that we need to temporarily clear + // We don't just blindly reset to the previous flags to ensure + // that we do not mutate cached flags for the incremental + // parser (ThisNodeHasError, ThisNodeOrAnySubNodesHasError, and + // HasAggregatedChildData). + var contextFlagsToClear = context & contextFlags; + if (contextFlagsToClear) { + // clear the requested context flags + setContextFlag(/*val*/ false, contextFlagsToClear); + var result = func(); + // restore the context flags we just cleared + setContextFlag(/*val*/ true, contextFlagsToClear); + return result; + } + // no need to do anything special as we are not in any of the requested contexts + return func(); + } + function doInsideOfContext(context, func) { + // contextFlagsToSet will contain only the context flags that + // are not currently set that we need to temporarily enable. + // We don't just blindly reset to the previous flags to ensure + // that we do not mutate cached flags for the incremental + // parser (ThisNodeHasError, ThisNodeOrAnySubNodesHasError, and + // HasAggregatedChildData). + var contextFlagsToSet = context & ~contextFlags; + if (contextFlagsToSet) { + // set the requested context flags + setContextFlag(/*val*/ true, contextFlagsToSet); + var result = func(); + // reset the context flags we just set + setContextFlag(/*val*/ false, contextFlagsToSet); + return result; + } + // no need to do anything special as we are already in all of the requested contexts + return func(); + } + function allowInAnd(func) { + return doOutsideOfContext(32768 /* DisallowInContext */, func); + } + function disallowInAnd(func) { + return doInsideOfContext(32768 /* DisallowInContext */, func); + } + function doInYieldContext(func) { + return doInsideOfContext(65536 /* YieldContext */, func); + } + function doInDecoratorContext(func) { + return doInsideOfContext(131072 /* DecoratorContext */, func); + } + function doInAwaitContext(func) { + return doInsideOfContext(262144 /* AwaitContext */, func); + } + function doOutsideOfAwaitContext(func) { + return doOutsideOfContext(262144 /* AwaitContext */, func); + } + function doInYieldAndAwaitContext(func) { + return doInsideOfContext(65536 /* YieldContext */ | 262144 /* AwaitContext */, func); + } + function inContext(flags) { + return (contextFlags & flags) !== 0; + } + function inYieldContext() { + return inContext(65536 /* YieldContext */); + } + function inDisallowInContext() { + return inContext(32768 /* DisallowInContext */); + } + function inDecoratorContext() { + return inContext(131072 /* DecoratorContext */); + } + function inAwaitContext() { + return inContext(262144 /* AwaitContext */); + } + function parseErrorAtCurrentToken(message, arg0) { + var start = scanner.getTokenPos(); + var length = scanner.getTextPos() - start; + parseErrorAtPosition(start, length, message, arg0); + } + function parseErrorAtPosition(start, length, message, arg0) { + // Don't report another error if it would just be at the same position as the last error. + var lastError = ts.lastOrUndefined(parseDiagnostics); + if (!lastError || start !== lastError.start) { + parseDiagnostics.push(ts.createFileDiagnostic(sourceFile, start, length, message, arg0)); + } + // Mark that we've encountered an error. We'll set an appropriate bit on the next + // node we finish so that it can't be reused incrementally. + parseErrorBeforeNextFinishedNode = true; + } + function scanError(message, length) { + var pos = scanner.getTextPos(); + parseErrorAtPosition(pos, length || 0, message); + } + function getNodePos() { + return scanner.getStartPos(); + } + function getNodeEnd() { + return scanner.getStartPos(); + } + // Use this function to access the current token instead of reading the currentToken + // variable. Since function results aren't narrowed in control flow analysis, this ensures + // that the type checker doesn't make wrong assumptions about the type of the current + // token (e.g. a call to nextToken() changes the current token but the checker doesn't + // reason about this side effect). Mainstream VMs inline simple functions like this, so + // there is no performance penalty. + function token() { + return currentToken; + } + function nextToken() { + return currentToken = scanner.scan(); + } + function reScanGreaterToken() { + return currentToken = scanner.reScanGreaterToken(); + } + function reScanSlashToken() { + return currentToken = scanner.reScanSlashToken(); + } + function reScanTemplateToken() { + return currentToken = scanner.reScanTemplateToken(); + } + function scanJsxIdentifier() { + return currentToken = scanner.scanJsxIdentifier(); + } + function scanJsxText() { + return currentToken = scanner.scanJsxToken(); + } + function scanJsxAttributeValue() { + return currentToken = scanner.scanJsxAttributeValue(); + } + function speculationHelper(callback, isLookAhead) { + // Keep track of the state we'll need to rollback to if lookahead fails (or if the + // caller asked us to always reset our state). + var saveToken = currentToken; + var saveParseDiagnosticsLength = parseDiagnostics.length; + var saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode; + // Note: it is not actually necessary to save/restore the context flags here. That's + // because the saving/restoring of these flags happens naturally through the recursive + // descent nature of our parser. However, we still store this here just so we can + // assert that invariant holds. + var saveContextFlags = contextFlags; + // If we're only looking ahead, then tell the scanner to only lookahead as well. + // Otherwise, if we're actually speculatively parsing, then tell the scanner to do the + // same. + var result = isLookAhead + ? scanner.lookAhead(callback) + : scanner.tryScan(callback); + ts.Debug.assert(saveContextFlags === contextFlags); + // If our callback returned something 'falsy' or we're just looking ahead, + // then unconditionally restore us to where we were. + if (!result || isLookAhead) { + currentToken = saveToken; + parseDiagnostics.length = saveParseDiagnosticsLength; + parseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode; + } + return result; + } + /** Invokes the provided callback then unconditionally restores the parser to the state it + * was in immediately prior to invoking the callback. The result of invoking the callback + * is returned from this function. + */ + function lookAhead(callback) { + return speculationHelper(callback, /*isLookAhead*/ true); + } + /** Invokes the provided callback. If the callback returns something falsy, then it restores + * the parser to the state it was in immediately prior to invoking the callback. If the + * callback returns something truthy, then the parser state is not rolled back. The result + * of invoking the callback is returned from this function. + */ + function tryParse(callback) { + return speculationHelper(callback, /*isLookAhead*/ false); + } + // Ignore strict mode flag because we will report an error in type checker instead. + function isIdentifier() { + if (token() === 69 /* Identifier */) { + return true; + } + // If we have a 'yield' keyword, and we're in the [yield] context, then 'yield' is + // considered a keyword and is not an identifier. + if (token() === 114 /* YieldKeyword */ && inYieldContext()) { + return false; + } + // If we have a 'await' keyword, and we're in the [Await] context, then 'await' is + // considered a keyword and is not an identifier. + if (token() === 119 /* AwaitKeyword */ && inAwaitContext()) { + return false; + } + return token() > 105 /* LastReservedWord */; + } + function parseExpected(kind, diagnosticMessage, shouldAdvance) { + if (shouldAdvance === void 0) { shouldAdvance = true; } + if (token() === kind) { + if (shouldAdvance) { + nextToken(); + } + return true; + } + // Report specific message if provided with one. Otherwise, report generic fallback message. + if (diagnosticMessage) { + parseErrorAtCurrentToken(diagnosticMessage); + } + else { + parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(kind)); + } + return false; + } + function parseOptional(t) { + if (token() === t) { + nextToken(); + return true; + } + return false; + } + function parseOptionalToken(t) { + if (token() === t) { + return parseTokenNode(); + } + return undefined; + } + function parseExpectedToken(t, reportAtCurrentPosition, diagnosticMessage, arg0) { + return parseOptionalToken(t) || + createMissingNode(t, reportAtCurrentPosition, diagnosticMessage, arg0); + } + function parseTokenNode() { + var node = createNode(token()); + nextToken(); + return finishNode(node); + } + function canParseSemicolon() { + // If there's a real semicolon, then we can always parse it out. + if (token() === 23 /* SemicolonToken */) { + return true; + } + // We can parse out an optional semicolon in ASI cases in the following cases. + return token() === 16 /* CloseBraceToken */ || token() === 1 /* EndOfFileToken */ || scanner.hasPrecedingLineBreak(); + } + function parseSemicolon() { + if (canParseSemicolon()) { + if (token() === 23 /* SemicolonToken */) { + // consume the semicolon if it was explicitly provided. + nextToken(); + } + return true; + } + else { + return parseExpected(23 /* SemicolonToken */); + } + } + // note: this function creates only node + function createNode(kind, pos) { + nodeCount++; + if (!(pos >= 0)) { + pos = scanner.getStartPos(); + } + return kind >= 139 /* FirstNode */ ? new NodeConstructor(kind, pos, pos) : + kind === 69 /* Identifier */ ? new IdentifierConstructor(kind, pos, pos) : + new TokenConstructor(kind, pos, pos); + } + function createNodeArray(elements, pos) { + var array = (elements || []); + if (!(pos >= 0)) { + pos = getNodePos(); + } + array.pos = pos; + array.end = pos; + return array; + } + function finishNode(node, end) { + node.end = end === undefined ? scanner.getStartPos() : end; + if (contextFlags) { + node.flags |= contextFlags; + } + // Keep track on the node if we encountered an error while parsing it. If we did, then + // we cannot reuse the node incrementally. Once we've marked this node, clear out the + // flag so that we don't mark any subsequent nodes. + if (parseErrorBeforeNextFinishedNode) { + parseErrorBeforeNextFinishedNode = false; + node.flags |= 524288 /* ThisNodeHasError */; + } + return node; + } + function createMissingNode(kind, reportAtCurrentPosition, diagnosticMessage, arg0) { + if (reportAtCurrentPosition) { + parseErrorAtPosition(scanner.getStartPos(), 0, diagnosticMessage, arg0); + } + else { + parseErrorAtCurrentToken(diagnosticMessage, arg0); + } + var result = createNode(kind, scanner.getStartPos()); + result.text = ""; + return finishNode(result); + } + function internIdentifier(text) { + text = ts.escapeIdentifier(text); + return identifiers[text] || (identifiers[text] = text); + } + // An identifier that starts with two underscores has an extra underscore character prepended to it to avoid issues + // with magic property names like '__proto__'. The 'identifiers' object is used to share a single string instance for + // each identifier in order to reduce memory consumption. + function createIdentifier(isIdentifier, diagnosticMessage) { + identifierCount++; + if (isIdentifier) { + var node = createNode(69 /* Identifier */); + // Store original token kind if it is not just an Identifier so we can report appropriate error later in type checker + if (token() !== 69 /* Identifier */) { + node.originalKeywordKind = token(); + } + node.text = internIdentifier(scanner.getTokenValue()); + nextToken(); + return finishNode(node); + } + return createMissingNode(69 /* Identifier */, /*reportAtCurrentPosition*/ false, diagnosticMessage || ts.Diagnostics.Identifier_expected); + } + function parseIdentifier(diagnosticMessage) { + return createIdentifier(isIdentifier(), diagnosticMessage); + } + function parseIdentifierName() { + return createIdentifier(ts.tokenIsIdentifierOrKeyword(token())); + } + function isLiteralPropertyName() { + return ts.tokenIsIdentifierOrKeyword(token()) || + token() === 9 /* StringLiteral */ || + token() === 8 /* NumericLiteral */; + } + function parsePropertyNameWorker(allowComputedPropertyNames) { + if (token() === 9 /* StringLiteral */ || token() === 8 /* NumericLiteral */) { + return parseLiteralNode(/*internName*/ true); + } + if (allowComputedPropertyNames && token() === 19 /* OpenBracketToken */) { + return parseComputedPropertyName(); + } + return parseIdentifierName(); + } + function parsePropertyName() { + return parsePropertyNameWorker(/*allowComputedPropertyNames*/ true); + } + function parseSimplePropertyName() { + return parsePropertyNameWorker(/*allowComputedPropertyNames*/ false); + } + function isSimplePropertyName() { + return token() === 9 /* StringLiteral */ || token() === 8 /* NumericLiteral */ || ts.tokenIsIdentifierOrKeyword(token()); + } + function parseComputedPropertyName() { + // PropertyName [Yield]: + // LiteralPropertyName + // ComputedPropertyName[?Yield] + var node = createNode(140 /* ComputedPropertyName */); + parseExpected(19 /* OpenBracketToken */); + // We parse any expression (including a comma expression). But the grammar + // says that only an assignment expression is allowed, so the grammar checker + // will error if it sees a comma expression. + node.expression = allowInAnd(parseExpression); + parseExpected(20 /* CloseBracketToken */); + return finishNode(node); + } + function parseContextualModifier(t) { + return token() === t && tryParse(nextTokenCanFollowModifier); + } + function nextTokenIsOnSameLineAndCanFollowModifier() { + nextToken(); + if (scanner.hasPrecedingLineBreak()) { + return false; + } + return canFollowModifier(); + } + function nextTokenCanFollowModifier() { + if (token() === 74 /* ConstKeyword */) { + // 'const' is only a modifier if followed by 'enum'. + return nextToken() === 81 /* EnumKeyword */; + } + if (token() === 82 /* ExportKeyword */) { + nextToken(); + if (token() === 77 /* DefaultKeyword */) { + return lookAhead(nextTokenIsClassOrFunctionOrAsync); + } + return token() !== 37 /* AsteriskToken */ && token() !== 116 /* AsKeyword */ && token() !== 15 /* OpenBraceToken */ && canFollowModifier(); + } + if (token() === 77 /* DefaultKeyword */) { + return nextTokenIsClassOrFunctionOrAsync(); + } + if (token() === 113 /* StaticKeyword */) { + nextToken(); + return canFollowModifier(); + } + return nextTokenIsOnSameLineAndCanFollowModifier(); + } + function parseAnyContextualModifier() { + return ts.isModifierKind(token()) && tryParse(nextTokenCanFollowModifier); + } + function canFollowModifier() { + return token() === 19 /* OpenBracketToken */ + || token() === 15 /* OpenBraceToken */ + || token() === 37 /* AsteriskToken */ + || token() === 22 /* DotDotDotToken */ + || isLiteralPropertyName(); + } + function nextTokenIsClassOrFunctionOrAsync() { + nextToken(); + return token() === 73 /* ClassKeyword */ || token() === 87 /* FunctionKeyword */ || + (token() === 118 /* AsyncKeyword */ && lookAhead(nextTokenIsFunctionKeywordOnSameLine)); + } + // True if positioned at the start of a list element + function isListElement(parsingContext, inErrorRecovery) { + var node = currentNode(parsingContext); + if (node) { + return true; + } + switch (parsingContext) { + case 0 /* SourceElements */: + case 1 /* BlockStatements */: + case 3 /* SwitchClauseStatements */: + // If we're in error recovery, then we don't want to treat ';' as an empty statement. + // The problem is that ';' can show up in far too many contexts, and if we see one + // and assume it's a statement, then we may bail out inappropriately from whatever + // we're parsing. For example, if we have a semicolon in the middle of a class, then + // we really don't want to assume the class is over and we're on a statement in the + // outer module. We just want to consume and move on. + return !(token() === 23 /* SemicolonToken */ && inErrorRecovery) && isStartOfStatement(); + case 2 /* SwitchClauses */: + return token() === 71 /* CaseKeyword */ || token() === 77 /* DefaultKeyword */; + case 4 /* TypeMembers */: + return lookAhead(isTypeMemberStart); + case 5 /* ClassMembers */: + // We allow semicolons as class elements (as specified by ES6) as long as we're + // not in error recovery. If we're in error recovery, we don't want an errant + // semicolon to be treated as a class member (since they're almost always used + // for statements. + return lookAhead(isClassMemberStart) || (token() === 23 /* SemicolonToken */ && !inErrorRecovery); + case 6 /* EnumMembers */: + // Include open bracket computed properties. This technically also lets in indexers, + // which would be a candidate for improved error reporting. + return token() === 19 /* OpenBracketToken */ || isLiteralPropertyName(); + case 12 /* ObjectLiteralMembers */: + return token() === 19 /* OpenBracketToken */ || token() === 37 /* AsteriskToken */ || isLiteralPropertyName(); + case 9 /* ObjectBindingElements */: + return token() === 19 /* OpenBracketToken */ || isLiteralPropertyName(); + case 7 /* HeritageClauseElement */: + // If we see { } then only consume it as an expression if it is followed by , or { + // That way we won't consume the body of a class in its heritage clause. + if (token() === 15 /* OpenBraceToken */) { + return lookAhead(isValidHeritageClauseObjectLiteral); + } + if (!inErrorRecovery) { + return isStartOfLeftHandSideExpression() && !isHeritageClauseExtendsOrImplementsKeyword(); + } + else { + // If we're in error recovery we tighten up what we're willing to match. + // That way we don't treat something like "this" as a valid heritage clause + // element during recovery. + return isIdentifier() && !isHeritageClauseExtendsOrImplementsKeyword(); + } + case 8 /* VariableDeclarations */: + return isIdentifierOrPattern(); + case 10 /* ArrayBindingElements */: + return token() === 24 /* CommaToken */ || token() === 22 /* DotDotDotToken */ || isIdentifierOrPattern(); + case 17 /* TypeParameters */: + return isIdentifier(); + case 11 /* ArgumentExpressions */: + case 15 /* ArrayLiteralMembers */: + return token() === 24 /* CommaToken */ || token() === 22 /* DotDotDotToken */ || isStartOfExpression(); + case 16 /* Parameters */: + return isStartOfParameter(); + case 18 /* TypeArguments */: + case 19 /* TupleElementTypes */: + return token() === 24 /* CommaToken */ || isStartOfType(); + case 20 /* HeritageClauses */: + return isHeritageClause(); + case 21 /* ImportOrExportSpecifiers */: + return ts.tokenIsIdentifierOrKeyword(token()); + case 13 /* JsxAttributes */: + return ts.tokenIsIdentifierOrKeyword(token()) || token() === 15 /* OpenBraceToken */; + case 14 /* JsxChildren */: + return true; + case 22 /* JSDocFunctionParameters */: + case 23 /* JSDocTypeArguments */: + case 25 /* JSDocTupleTypes */: + return JSDocParser.isJSDocType(); + case 24 /* JSDocRecordMembers */: + return isSimplePropertyName(); + } + ts.Debug.fail("Non-exhaustive case in 'isListElement'."); + } + function isValidHeritageClauseObjectLiteral() { + ts.Debug.assert(token() === 15 /* OpenBraceToken */); + if (nextToken() === 16 /* CloseBraceToken */) { + // if we see "extends {}" then only treat the {} as what we're extending (and not + // the class body) if we have: + // + // extends {} { + // extends {}, + // extends {} extends + // extends {} implements + var next = nextToken(); + return next === 24 /* CommaToken */ || next === 15 /* OpenBraceToken */ || next === 83 /* ExtendsKeyword */ || next === 106 /* ImplementsKeyword */; + } + return true; + } + function nextTokenIsIdentifier() { + nextToken(); + return isIdentifier(); + } + function nextTokenIsIdentifierOrKeyword() { + nextToken(); + return ts.tokenIsIdentifierOrKeyword(token()); + } + function isHeritageClauseExtendsOrImplementsKeyword() { + if (token() === 106 /* ImplementsKeyword */ || + token() === 83 /* ExtendsKeyword */) { + return lookAhead(nextTokenIsStartOfExpression); + } + return false; + } + function nextTokenIsStartOfExpression() { + nextToken(); + return isStartOfExpression(); + } + // True if positioned at a list terminator + function isListTerminator(kind) { + if (token() === 1 /* EndOfFileToken */) { + // Being at the end of the file ends all lists. + return true; + } + switch (kind) { + case 1 /* BlockStatements */: + case 2 /* SwitchClauses */: + case 4 /* TypeMembers */: + case 5 /* ClassMembers */: + case 6 /* EnumMembers */: + case 12 /* ObjectLiteralMembers */: + case 9 /* ObjectBindingElements */: + case 21 /* ImportOrExportSpecifiers */: + return token() === 16 /* CloseBraceToken */; + case 3 /* SwitchClauseStatements */: + return token() === 16 /* CloseBraceToken */ || token() === 71 /* CaseKeyword */ || token() === 77 /* DefaultKeyword */; + case 7 /* HeritageClauseElement */: + return token() === 15 /* OpenBraceToken */ || token() === 83 /* ExtendsKeyword */ || token() === 106 /* ImplementsKeyword */; + case 8 /* VariableDeclarations */: + return isVariableDeclaratorListTerminator(); + case 17 /* TypeParameters */: + // Tokens other than '>' are here for better error recovery + return token() === 27 /* GreaterThanToken */ || token() === 17 /* OpenParenToken */ || token() === 15 /* OpenBraceToken */ || token() === 83 /* ExtendsKeyword */ || token() === 106 /* ImplementsKeyword */; + case 11 /* ArgumentExpressions */: + // Tokens other than ')' are here for better error recovery + return token() === 18 /* CloseParenToken */ || token() === 23 /* SemicolonToken */; + case 15 /* ArrayLiteralMembers */: + case 19 /* TupleElementTypes */: + case 10 /* ArrayBindingElements */: + return token() === 20 /* CloseBracketToken */; + case 16 /* Parameters */: + // Tokens other than ')' and ']' (the latter for index signatures) are here for better error recovery + return token() === 18 /* CloseParenToken */ || token() === 20 /* CloseBracketToken */ /*|| token === SyntaxKind.OpenBraceToken*/; + case 18 /* TypeArguments */: + // Tokens other than '>' are here for better error recovery + return token() === 27 /* GreaterThanToken */ || token() === 17 /* OpenParenToken */; + case 20 /* HeritageClauses */: + return token() === 15 /* OpenBraceToken */ || token() === 16 /* CloseBraceToken */; + case 13 /* JsxAttributes */: + return token() === 27 /* GreaterThanToken */ || token() === 39 /* SlashToken */; + case 14 /* JsxChildren */: + return token() === 25 /* LessThanToken */ && lookAhead(nextTokenIsSlash); + case 22 /* JSDocFunctionParameters */: + return token() === 18 /* CloseParenToken */ || token() === 54 /* ColonToken */ || token() === 16 /* CloseBraceToken */; + case 23 /* JSDocTypeArguments */: + return token() === 27 /* GreaterThanToken */ || token() === 16 /* CloseBraceToken */; + case 25 /* JSDocTupleTypes */: + return token() === 20 /* CloseBracketToken */ || token() === 16 /* CloseBraceToken */; + case 24 /* JSDocRecordMembers */: + return token() === 16 /* CloseBraceToken */; + } + } + function isVariableDeclaratorListTerminator() { + // If we can consume a semicolon (either explicitly, or with ASI), then consider us done + // with parsing the list of variable declarators. + if (canParseSemicolon()) { + return true; + } + // in the case where we're parsing the variable declarator of a 'for-in' statement, we + // are done if we see an 'in' keyword in front of us. Same with for-of + if (isInOrOfKeyword(token())) { + return true; + } + // ERROR RECOVERY TWEAK: + // For better error recovery, if we see an '=>' then we just stop immediately. We've got an + // arrow function here and it's going to be very unlikely that we'll resynchronize and get + // another variable declaration. + if (token() === 34 /* EqualsGreaterThanToken */) { + return true; + } + // Keep trying to parse out variable declarators. + return false; + } + // True if positioned at element or terminator of the current list or any enclosing list + function isInSomeParsingContext() { + for (var kind = 0; kind < 26 /* Count */; kind++) { + if (parsingContext & (1 << kind)) { + if (isListElement(kind, /*inErrorRecovery*/ true) || isListTerminator(kind)) { + return true; + } + } + } + return false; + } + // Parses a list of elements + function parseList(kind, parseElement) { + var saveParsingContext = parsingContext; + parsingContext |= 1 << kind; + var result = createNodeArray(); + while (!isListTerminator(kind)) { + if (isListElement(kind, /*inErrorRecovery*/ false)) { + var element = parseListElement(kind, parseElement); + result.push(element); + continue; + } + if (abortParsingListOrMoveToNextToken(kind)) { + break; + } + } + result.end = getNodeEnd(); + parsingContext = saveParsingContext; + return result; + } + function parseListElement(parsingContext, parseElement) { + var node = currentNode(parsingContext); + if (node) { + return consumeNode(node); + } + return parseElement(); + } + function currentNode(parsingContext) { + // If there is an outstanding parse error that we've encountered, but not attached to + // some node, then we cannot get a node from the old source tree. This is because we + // want to mark the next node we encounter as being unusable. + // + // Note: This may be too conservative. Perhaps we could reuse the node and set the bit + // on it (or its leftmost child) as having the error. For now though, being conservative + // is nice and likely won't ever affect perf. + if (parseErrorBeforeNextFinishedNode) { + return undefined; + } + if (!syntaxCursor) { + // if we don't have a cursor, we could never return a node from the old tree. + return undefined; + } + var node = syntaxCursor.currentNode(scanner.getStartPos()); + // Can't reuse a missing node. + if (ts.nodeIsMissing(node)) { + return undefined; + } + // Can't reuse a node that intersected the change range. + if (node.intersectsChange) { + return undefined; + } + // Can't reuse a node that contains a parse error. This is necessary so that we + // produce the same set of errors again. + if (ts.containsParseError(node)) { + return undefined; + } + // We can only reuse a node if it was parsed under the same strict mode that we're + // currently in. i.e. if we originally parsed a node in non-strict mode, but then + // the user added 'using strict' at the top of the file, then we can't use that node + // again as the presence of strict mode may cause us to parse the tokens in the file + // differently. + // + // Note: we *can* reuse tokens when the strict mode changes. That's because tokens + // are unaffected by strict mode. It's just the parser will decide what to do with it + // differently depending on what mode it is in. + // + // This also applies to all our other context flags as well. + var nodeContextFlags = node.flags & 1540096 /* ContextFlags */; + if (nodeContextFlags !== contextFlags) { + return undefined; + } + // Ok, we have a node that looks like it could be reused. Now verify that it is valid + // in the current list parsing context that we're currently at. + if (!canReuseNode(node, parsingContext)) { + return undefined; + } + return node; + } + function consumeNode(node) { + // Move the scanner so it is after the node we just consumed. + scanner.setTextPos(node.end); + nextToken(); + return node; + } + function canReuseNode(node, parsingContext) { + switch (parsingContext) { + case 5 /* ClassMembers */: + return isReusableClassMember(node); + case 2 /* SwitchClauses */: + return isReusableSwitchClause(node); + case 0 /* SourceElements */: + case 1 /* BlockStatements */: + case 3 /* SwitchClauseStatements */: + return isReusableStatement(node); + case 6 /* EnumMembers */: + return isReusableEnumMember(node); + case 4 /* TypeMembers */: + return isReusableTypeMember(node); + case 8 /* VariableDeclarations */: + return isReusableVariableDeclaration(node); + case 16 /* Parameters */: + return isReusableParameter(node); + // Any other lists we do not care about reusing nodes in. But feel free to add if + // you can do so safely. Danger areas involve nodes that may involve speculative + // parsing. If speculative parsing is involved with the node, then the range the + // parser reached while looking ahead might be in the edited range (see the example + // in canReuseVariableDeclaratorNode for a good case of this). + case 20 /* HeritageClauses */: + // This would probably be safe to reuse. There is no speculative parsing with + // heritage clauses. + case 17 /* TypeParameters */: + // This would probably be safe to reuse. There is no speculative parsing with + // type parameters. Note that that's because type *parameters* only occur in + // unambiguous *type* contexts. While type *arguments* occur in very ambiguous + // *expression* contexts. + case 19 /* TupleElementTypes */: + // This would probably be safe to reuse. There is no speculative parsing with + // tuple types. + // Technically, type argument list types are probably safe to reuse. While + // speculative parsing is involved with them (since type argument lists are only + // produced from speculative parsing a < as a type argument list), we only have + // the types because speculative parsing succeeded. Thus, the lookahead never + // went past the end of the list and rewound. + case 18 /* TypeArguments */: + // Note: these are almost certainly not safe to ever reuse. Expressions commonly + // need a large amount of lookahead, and we should not reuse them as they may + // have actually intersected the edit. + case 11 /* ArgumentExpressions */: + // This is not safe to reuse for the same reason as the 'AssignmentExpression' + // cases. i.e. a property assignment may end with an expression, and thus might + // have lookahead far beyond it's old node. + case 12 /* ObjectLiteralMembers */: + // This is probably not safe to reuse. There can be speculative parsing with + // type names in a heritage clause. There can be generic names in the type + // name list, and there can be left hand side expressions (which can have type + // arguments.) + case 7 /* HeritageClauseElement */: + // Perhaps safe to reuse, but it's unlikely we'd see more than a dozen attributes + // on any given element. Same for children. + case 13 /* JsxAttributes */: + case 14 /* JsxChildren */: + } + return false; + } + function isReusableClassMember(node) { + if (node) { + switch (node.kind) { + case 148 /* Constructor */: + case 153 /* IndexSignature */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 145 /* PropertyDeclaration */: + case 198 /* SemicolonClassElement */: + return true; + case 147 /* MethodDeclaration */: + // Method declarations are not necessarily reusable. An object-literal + // may have a method calls "constructor(...)" and we must reparse that + // into an actual .ConstructorDeclaration. + var methodDeclaration = node; + var nameIsConstructor = methodDeclaration.name.kind === 69 /* Identifier */ && + methodDeclaration.name.originalKeywordKind === 121 /* ConstructorKeyword */; + return !nameIsConstructor; + } + } + return false; + } + function isReusableSwitchClause(node) { + if (node) { + switch (node.kind) { + case 249 /* CaseClause */: + case 250 /* DefaultClause */: + return true; + } + } + return false; + } + function isReusableStatement(node) { + if (node) { + switch (node.kind) { + case 220 /* FunctionDeclaration */: + case 200 /* VariableStatement */: + case 199 /* Block */: + case 203 /* IfStatement */: + case 202 /* ExpressionStatement */: + case 215 /* ThrowStatement */: + case 211 /* ReturnStatement */: + case 213 /* SwitchStatement */: + case 210 /* BreakStatement */: + case 209 /* ContinueStatement */: + case 207 /* ForInStatement */: + case 208 /* ForOfStatement */: + case 206 /* ForStatement */: + case 205 /* WhileStatement */: + case 212 /* WithStatement */: + case 201 /* EmptyStatement */: + case 216 /* TryStatement */: + case 214 /* LabeledStatement */: + case 204 /* DoStatement */: + case 217 /* DebuggerStatement */: + case 230 /* ImportDeclaration */: + case 229 /* ImportEqualsDeclaration */: + case 236 /* ExportDeclaration */: + case 235 /* ExportAssignment */: + case 225 /* ModuleDeclaration */: + case 221 /* ClassDeclaration */: + case 222 /* InterfaceDeclaration */: + case 224 /* EnumDeclaration */: + case 223 /* TypeAliasDeclaration */: + return true; + } + } + return false; + } + function isReusableEnumMember(node) { + return node.kind === 255 /* EnumMember */; + } + function isReusableTypeMember(node) { + if (node) { + switch (node.kind) { + case 152 /* ConstructSignature */: + case 146 /* MethodSignature */: + case 153 /* IndexSignature */: + case 144 /* PropertySignature */: + case 151 /* CallSignature */: + return true; + } + } + return false; + } + function isReusableVariableDeclaration(node) { + if (node.kind !== 218 /* VariableDeclaration */) { + return false; + } + // Very subtle incremental parsing bug. Consider the following code: + // + // let v = new List < A, B + // + // This is actually legal code. It's a list of variable declarators "v = new List() + // + // then we have a problem. "v = new List= 0) { + // Always preserve a trailing comma by marking it on the NodeArray + result.hasTrailingComma = true; + } + result.end = getNodeEnd(); + parsingContext = saveParsingContext; + return result; + } + function createMissingList() { + return createNodeArray(); + } + function parseBracketedList(kind, parseElement, open, close) { + if (parseExpected(open)) { + var result = parseDelimitedList(kind, parseElement); + parseExpected(close); + return result; + } + return createMissingList(); + } + // The allowReservedWords parameter controls whether reserved words are permitted after the first dot + function parseEntityName(allowReservedWords, diagnosticMessage) { + var entity = parseIdentifier(diagnosticMessage); + while (parseOptional(21 /* DotToken */)) { + var node = createNode(139 /* QualifiedName */, entity.pos); // !!! + node.left = entity; + node.right = parseRightSideOfDot(allowReservedWords); + entity = finishNode(node); + } + return entity; + } + function parseRightSideOfDot(allowIdentifierNames) { + // Technically a keyword is valid here as all identifiers and keywords are identifier names. + // However, often we'll encounter this in error situations when the identifier or keyword + // is actually starting another valid construct. + // + // So, we check for the following specific case: + // + // name. + // identifierOrKeyword identifierNameOrKeyword + // + // Note: the newlines are important here. For example, if that above code + // were rewritten into: + // + // name.identifierOrKeyword + // identifierNameOrKeyword + // + // Then we would consider it valid. That's because ASI would take effect and + // the code would be implicitly: "name.identifierOrKeyword; identifierNameOrKeyword". + // In the first case though, ASI will not take effect because there is not a + // line terminator after the identifier or keyword. + if (scanner.hasPrecedingLineBreak() && ts.tokenIsIdentifierOrKeyword(token())) { + var matchesPattern = lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine); + if (matchesPattern) { + // Report that we need an identifier. However, report it right after the dot, + // and not on the next token. This is because the next token might actually + // be an identifier and the error would be quite confusing. + return createMissingNode(69 /* Identifier */, /*reportAtCurrentPosition*/ true, ts.Diagnostics.Identifier_expected); + } + } + return allowIdentifierNames ? parseIdentifierName() : parseIdentifier(); + } + function parseTemplateExpression() { + var template = createNode(189 /* TemplateExpression */); + template.head = parseTemplateLiteralFragment(); + ts.Debug.assert(template.head.kind === 12 /* TemplateHead */, "Template head has wrong token kind"); + var templateSpans = createNodeArray(); + do { + templateSpans.push(parseTemplateSpan()); + } while (ts.lastOrUndefined(templateSpans).literal.kind === 13 /* TemplateMiddle */); + templateSpans.end = getNodeEnd(); + template.templateSpans = templateSpans; + return finishNode(template); + } + function parseTemplateSpan() { + var span = createNode(197 /* TemplateSpan */); + span.expression = allowInAnd(parseExpression); + var literal; + if (token() === 16 /* CloseBraceToken */) { + reScanTemplateToken(); + literal = parseTemplateLiteralFragment(); + } + else { + literal = parseExpectedToken(14 /* TemplateTail */, /*reportAtCurrentPosition*/ false, ts.Diagnostics._0_expected, ts.tokenToString(16 /* CloseBraceToken */)); + } + span.literal = literal; + return finishNode(span); + } + function parseLiteralNode(internName) { + return parseLiteralLikeNode(token(), internName); + } + function parseTemplateLiteralFragment() { + return parseLiteralLikeNode(token(), /*internName*/ false); + } + function parseLiteralLikeNode(kind, internName) { + var node = createNode(kind); + var text = scanner.getTokenValue(); + node.text = internName ? internIdentifier(text) : text; + if (scanner.hasExtendedUnicodeEscape()) { + node.hasExtendedUnicodeEscape = true; + } + if (scanner.isUnterminated()) { + node.isUnterminated = true; + } + var tokenPos = scanner.getTokenPos(); + nextToken(); + finishNode(node); + // Octal literals are not allowed in strict mode or ES5 + // Note that theoretically the following condition would hold true literals like 009, + // which is not octal.But because of how the scanner separates the tokens, we would + // never get a token like this. Instead, we would get 00 and 9 as two separate tokens. + // We also do not need to check for negatives because any prefix operator would be part of a + // parent unary expression. + if (node.kind === 8 /* NumericLiteral */ + && sourceText.charCodeAt(tokenPos) === 48 /* _0 */ + && ts.isOctalDigit(sourceText.charCodeAt(tokenPos + 1))) { + node.isOctalLiteral = true; + } + return node; + } + // TYPES + function parseTypeReference() { + var typeName = parseEntityName(/*allowReservedWords*/ false, ts.Diagnostics.Type_expected); + var node = createNode(155 /* TypeReference */, typeName.pos); + node.typeName = typeName; + if (!scanner.hasPrecedingLineBreak() && token() === 25 /* LessThanToken */) { + node.typeArguments = parseBracketedList(18 /* TypeArguments */, parseType, 25 /* LessThanToken */, 27 /* GreaterThanToken */); + } + return finishNode(node); + } + function parseThisTypePredicate(lhs) { + nextToken(); + var node = createNode(154 /* TypePredicate */, lhs.pos); + node.parameterName = lhs; + node.type = parseType(); + return finishNode(node); + } + function parseThisTypeNode() { + var node = createNode(165 /* ThisType */); + nextToken(); + return finishNode(node); + } + function parseTypeQuery() { + var node = createNode(158 /* TypeQuery */); + parseExpected(101 /* TypeOfKeyword */); + node.exprName = parseEntityName(/*allowReservedWords*/ true); + return finishNode(node); + } + function parseTypeParameter() { + var node = createNode(141 /* TypeParameter */); + node.name = parseIdentifier(); + if (parseOptional(83 /* ExtendsKeyword */)) { + // It's not uncommon for people to write improper constraints to a generic. If the + // user writes a constraint that is an expression and not an actual type, then parse + // it out as an expression (so we can recover well), but report that a type is needed + // instead. + if (isStartOfType() || !isStartOfExpression()) { + node.constraint = parseType(); + } + else { + // It was not a type, and it looked like an expression. Parse out an expression + // here so we recover well. Note: it is important that we call parseUnaryExpression + // and not parseExpression here. If the user has: + // + // + // + // We do *not* want to consume the > as we're consuming the expression for "". + node.expression = parseUnaryExpressionOrHigher(); + } + } + return finishNode(node); + } + function parseTypeParameters() { + if (token() === 25 /* LessThanToken */) { + return parseBracketedList(17 /* TypeParameters */, parseTypeParameter, 25 /* LessThanToken */, 27 /* GreaterThanToken */); + } + } + function parseParameterType() { + if (parseOptional(54 /* ColonToken */)) { + return parseType(); + } + return undefined; + } + function isStartOfParameter() { + return token() === 22 /* DotDotDotToken */ || isIdentifierOrPattern() || ts.isModifierKind(token()) || token() === 55 /* AtToken */ || token() === 97 /* ThisKeyword */; + } + function parseParameter() { + var node = createNode(142 /* Parameter */); + if (token() === 97 /* ThisKeyword */) { + node.name = createIdentifier(/*isIdentifier*/ true, undefined); + node.type = parseParameterType(); + return finishNode(node); + } + node.decorators = parseDecorators(); + node.modifiers = parseModifiers(); + node.dotDotDotToken = parseOptionalToken(22 /* DotDotDotToken */); + // FormalParameter [Yield,Await]: + // BindingElement[?Yield,?Await] + node.name = parseIdentifierOrPattern(); + if (ts.getFullWidth(node.name) === 0 && !ts.hasModifiers(node) && ts.isModifierKind(token())) { + // in cases like + // 'use strict' + // function foo(static) + // isParameter('static') === true, because of isModifier('static') + // however 'static' is not a legal identifier in a strict mode. + // so result of this function will be ParameterDeclaration (flags = 0, name = missing, type = undefined, initializer = undefined) + // and current token will not change => parsing of the enclosing parameter list will last till the end of time (or OOM) + // to avoid this we'll advance cursor to the next token. + nextToken(); + } + node.questionToken = parseOptionalToken(53 /* QuestionToken */); + node.type = parseParameterType(); + node.initializer = parseBindingElementInitializer(/*inParameter*/ true); + // Do not check for initializers in an ambient context for parameters. This is not + // a grammar error because the grammar allows arbitrary call signatures in + // an ambient context. + // It is actually not necessary for this to be an error at all. The reason is that + // function/constructor implementations are syntactically disallowed in ambient + // contexts. In addition, parameter initializers are semantically disallowed in + // overload signatures. So parameter initializers are transitively disallowed in + // ambient contexts. + return addJSDocComment(finishNode(node)); + } + function parseBindingElementInitializer(inParameter) { + return inParameter ? parseParameterInitializer() : parseNonParameterInitializer(); + } + function parseParameterInitializer() { + return parseInitializer(/*inParameter*/ true); + } + function fillSignature(returnToken, yieldContext, awaitContext, requireCompleteParameterList, signature) { + var returnTokenRequired = returnToken === 34 /* EqualsGreaterThanToken */; + signature.typeParameters = parseTypeParameters(); + signature.parameters = parseParameterList(yieldContext, awaitContext, requireCompleteParameterList); + if (returnTokenRequired) { + parseExpected(returnToken); + signature.type = parseTypeOrTypePredicate(); + } + else if (parseOptional(returnToken)) { + signature.type = parseTypeOrTypePredicate(); + } + } + function parseParameterList(yieldContext, awaitContext, requireCompleteParameterList) { + // FormalParameters [Yield,Await]: (modified) + // [empty] + // FormalParameterList[?Yield,Await] + // + // FormalParameter[Yield,Await]: (modified) + // BindingElement[?Yield,Await] + // + // BindingElement [Yield,Await]: (modified) + // SingleNameBinding[?Yield,?Await] + // BindingPattern[?Yield,?Await]Initializer [In, ?Yield,?Await] opt + // + // SingleNameBinding [Yield,Await]: + // BindingIdentifier[?Yield,?Await]Initializer [In, ?Yield,?Await] opt + if (parseExpected(17 /* OpenParenToken */)) { + var savedYieldContext = inYieldContext(); + var savedAwaitContext = inAwaitContext(); + setYieldContext(yieldContext); + setAwaitContext(awaitContext); + var result = parseDelimitedList(16 /* Parameters */, parseParameter); + setYieldContext(savedYieldContext); + setAwaitContext(savedAwaitContext); + if (!parseExpected(18 /* CloseParenToken */) && requireCompleteParameterList) { + // Caller insisted that we had to end with a ) We didn't. So just return + // undefined here. + return undefined; + } + return result; + } + // We didn't even have an open paren. If the caller requires a complete parameter list, + // we definitely can't provide that. However, if they're ok with an incomplete one, + // then just return an empty set of parameters. + return requireCompleteParameterList ? undefined : createMissingList(); + } + function parseTypeMemberSemicolon() { + // We allow type members to be separated by commas or (possibly ASI) semicolons. + // First check if it was a comma. If so, we're done with the member. + if (parseOptional(24 /* CommaToken */)) { + return; + } + // Didn't have a comma. We must have a (possible ASI) semicolon. + parseSemicolon(); + } + function parseSignatureMember(kind) { + var node = createNode(kind); + if (kind === 152 /* ConstructSignature */) { + parseExpected(92 /* NewKeyword */); + } + fillSignature(54 /* ColonToken */, /*yieldContext*/ false, /*awaitContext*/ false, /*requireCompleteParameterList*/ false, node); + parseTypeMemberSemicolon(); + return addJSDocComment(finishNode(node)); + } + function isIndexSignature() { + if (token() !== 19 /* OpenBracketToken */) { + return false; + } + return lookAhead(isUnambiguouslyIndexSignature); + } + function isUnambiguouslyIndexSignature() { + // The only allowed sequence is: + // + // [id: + // + // However, for error recovery, we also check the following cases: + // + // [... + // [id, + // [id?, + // [id?: + // [id?] + // [public id + // [private id + // [protected id + // [] + // + nextToken(); + if (token() === 22 /* DotDotDotToken */ || token() === 20 /* CloseBracketToken */) { + return true; + } + if (ts.isModifierKind(token())) { + nextToken(); + if (isIdentifier()) { + return true; + } + } + else if (!isIdentifier()) { + return false; + } + else { + // Skip the identifier + nextToken(); + } + // A colon signifies a well formed indexer + // A comma should be a badly formed indexer because comma expressions are not allowed + // in computed properties. + if (token() === 54 /* ColonToken */ || token() === 24 /* CommaToken */) { + return true; + } + // Question mark could be an indexer with an optional property, + // or it could be a conditional expression in a computed property. + if (token() !== 53 /* QuestionToken */) { + return false; + } + // If any of the following tokens are after the question mark, it cannot + // be a conditional expression, so treat it as an indexer. + nextToken(); + return token() === 54 /* ColonToken */ || token() === 24 /* CommaToken */ || token() === 20 /* CloseBracketToken */; + } + function parseIndexSignatureDeclaration(fullStart, decorators, modifiers) { + var node = createNode(153 /* IndexSignature */, fullStart); + node.decorators = decorators; + node.modifiers = modifiers; + node.parameters = parseBracketedList(16 /* Parameters */, parseParameter, 19 /* OpenBracketToken */, 20 /* CloseBracketToken */); + node.type = parseTypeAnnotation(); + parseTypeMemberSemicolon(); + return finishNode(node); + } + function parsePropertyOrMethodSignature(fullStart, modifiers) { + var name = parsePropertyName(); + var questionToken = parseOptionalToken(53 /* QuestionToken */); + if (token() === 17 /* OpenParenToken */ || token() === 25 /* LessThanToken */) { + var method = createNode(146 /* MethodSignature */, fullStart); + method.modifiers = modifiers; method.name = name; method.questionToken = questionToken; // Method signatures don't exist in expression contexts. So they have neither // [Yield] nor [Await] fillSignature(54 /* ColonToken */, /*yieldContext*/ false, /*awaitContext*/ false, /*requireCompleteParameterList*/ false, method); parseTypeMemberSemicolon(); - return finishNode(method); + return addJSDocComment(finishNode(method)); } else { var property = createNode(144 /* PropertySignature */, fullStart); - setModifiers(property, modifiers); + property.modifiers = modifiers; property.name = name; property.questionToken = questionToken; property.type = parseTypeAnnotation(); @@ -10271,7 +14786,7 @@ var ts; property.initializer = parseNonParameterInitializer(); } parseTypeMemberSemicolon(); - return finishNode(property); + return addJSDocComment(finishNode(property)); } } function isTypeMemberStart() { @@ -10465,8 +14980,7 @@ var ts; function parseUnionOrIntersectionType(kind, parseConstituentType, operator) { var type = parseConstituentType(); if (token() === operator) { - var types = [type]; - types.pos = type.pos; + var types = createNodeArray([type], type.pos); while (parseOptional(operator)) { types.push(parseConstituentType()); } @@ -10557,7 +15071,7 @@ var ts; function parseType() { // The rules about 'yield' only apply to actual code/expression contexts. They don't // apply to 'type' contexts. So we disable these parameters here before moving on. - return doOutsideOfContext(41943040 /* TypeExcludesFlags */, parseTypeWorker); + return doOutsideOfContext(327680 /* TypeExcludesFlags */, parseTypeWorker); } function parseTypeWorker() { if (isStartOfFunctionType()) { @@ -10788,7 +15302,7 @@ var ts; var node; if (asyncModifier) { node = createNode(180 /* ArrowFunction */, asyncModifier.pos); - setModifiers(node, asyncModifier); + node.modifiers = asyncModifier; } else { node = createNode(180 /* ArrowFunction */, identifier.pos); @@ -10796,12 +15310,11 @@ var ts; var parameter = createNode(142 /* Parameter */, identifier.pos); parameter.name = identifier; finishNode(parameter); - node.parameters = [parameter]; - node.parameters.pos = parameter.pos; + node.parameters = createNodeArray([parameter], parameter.pos); node.parameters.end = parameter.end; node.equalsGreaterThanToken = parseExpectedToken(34 /* EqualsGreaterThanToken */, /*reportAtCurrentPosition*/ false, ts.Diagnostics._0_expected, "=>"); node.body = parseArrowFunctionExpressionBody(/*isAsync*/ !!asyncModifier); - return finishNode(node); + return addJSDocComment(finishNode(node)); } function tryParseParenthesizedArrowFunctionExpression() { var triState = isParenthesizedArrowFunctionExpression(); @@ -10820,7 +15333,7 @@ var ts; // Didn't appear to actually be a parenthesized arrow function. Just bail out. return undefined; } - var isAsync = !!(arrowFunction.flags & 256 /* Async */); + var isAsync = !!(ts.getModifierFlags(arrowFunction) & 256 /* Async */); // If we have an arrow, then try to parse the body. Even if not, try to parse if we // have an opening brace, just in case we're in an error state. var lastToken = token(); @@ -10828,7 +15341,7 @@ var ts; arrowFunction.body = (lastToken === 34 /* EqualsGreaterThanToken */ || lastToken === 15 /* OpenBraceToken */) ? parseArrowFunctionExpressionBody(isAsync) : parseIdentifier(); - return finishNode(arrowFunction); + return addJSDocComment(finishNode(arrowFunction)); } // True -> We definitely expect a parenthesized arrow function here. // False -> There *cannot* be a parenthesized arrow function here. @@ -10977,8 +15490,8 @@ var ts; } function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity) { var node = createNode(180 /* ArrowFunction */); - setModifiers(node, parseModifiersForArrowFunction()); - var isAsync = !!(node.flags & 256 /* Async */); + node.modifiers = parseModifiersForArrowFunction(); + var isAsync = !!(ts.getModifierFlags(node) & 256 /* Async */); // Arrow functions are never generators. // // If we're speculatively parsing a signature for a parenthesized arrow function, then @@ -11546,8 +16059,7 @@ var ts; ts.Debug.fail("Unknown JSX child kind " + token()); } function parseJsxChildren(openingTagName) { - var result = []; - result.pos = scanner.getStartPos(); + var result = createNodeArray(); var saveParsingContext = parsingContext; parsingContext |= 1 << 14 /* JsxChildren */; while (true) { @@ -11635,8 +16147,8 @@ var ts; scanJsxIdentifier(); var node = createNode(246 /* JsxAttribute */); node.name = parseIdentifierName(); - if (parseOptional(56 /* EqualsToken */)) { - switch (token()) { + if (token() === 56 /* EqualsToken */) { + switch (scanJsxAttributeValue()) { case 9 /* StringLiteral */: node.initializer = parseLiteralNode(); break; @@ -11884,7 +16396,7 @@ var ts; } function tryParseAccessorDeclaration(fullStart, decorators, modifiers) { if (parseContextualModifier(123 /* GetKeyword */)) { - return addJSDocComment(parseAccessorDeclaration(149 /* GetAccessor */, fullStart, decorators, modifiers)); + return parseAccessorDeclaration(149 /* GetAccessor */, fullStart, decorators, modifiers); } else if (parseContextualModifier(131 /* SetKeyword */)) { return parseAccessorDeclaration(150 /* SetAccessor */, fullStart, decorators, modifiers); @@ -11955,11 +16467,11 @@ var ts; setDecoratorContext(/*val*/ false); } var node = createNode(179 /* FunctionExpression */); - setModifiers(node, parseModifiers()); + node.modifiers = parseModifiers(); parseExpected(87 /* FunctionKeyword */); node.asteriskToken = parseOptionalToken(37 /* AsteriskToken */); var isGenerator = !!node.asteriskToken; - var isAsync = !!(node.flags & 256 /* Async */); + var isAsync = !!(ts.getModifierFlags(node) & 256 /* Async */); node.name = isGenerator && isAsync ? doInYieldAndAwaitContext(parseOptionalIdentifier) : isGenerator ? doInYieldContext(parseOptionalIdentifier) : @@ -11989,6 +16501,9 @@ var ts; function parseBlock(ignoreMissingOpenBrace, diagnosticMessage) { var node = createNode(199 /* Block */); if (parseExpected(15 /* OpenBraceToken */, diagnosticMessage) || ignoreMissingOpenBrace) { + if (scanner.hasPrecedingLineBreak()) { + node.multiLine = true; + } node.statements = parseList(1 /* BlockStatements */, parseStatement); parseExpected(16 /* CloseBraceToken */); } @@ -12483,7 +16998,7 @@ var ts; var node = createMissingNode(239 /* MissingDeclaration */, /*reportAtCurrentPosition*/ true, ts.Diagnostics.Declaration_expected); node.pos = fullStart; node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; return finishNode(node); } } @@ -12566,10 +17081,10 @@ var ts; case 102 /* VarKeyword */: break; case 108 /* LetKeyword */: - node.flags |= 1024 /* Let */; + node.flags |= 1 /* Let */; break; case 74 /* ConstKeyword */: - node.flags |= 2048 /* Const */; + node.flags |= 2 /* Const */; break; default: ts.Debug.fail(); @@ -12601,7 +17116,7 @@ var ts; function parseVariableStatement(fullStart, decorators, modifiers) { var node = createNode(200 /* VariableStatement */, fullStart); node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; node.declarationList = parseVariableDeclarationList(/*inForStatementInitializer*/ false); parseSemicolon(); return addJSDocComment(finishNode(node)); @@ -12609,12 +17124,12 @@ var ts; function parseFunctionDeclaration(fullStart, decorators, modifiers) { var node = createNode(220 /* FunctionDeclaration */, fullStart); node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; parseExpected(87 /* FunctionKeyword */); node.asteriskToken = parseOptionalToken(37 /* AsteriskToken */); - node.name = node.flags & 512 /* Default */ ? parseOptionalIdentifier() : parseIdentifier(); + node.name = ts.hasModifier(node, 512 /* Default */) ? parseOptionalIdentifier() : parseIdentifier(); var isGenerator = !!node.asteriskToken; - var isAsync = !!(node.flags & 256 /* Async */); + var isAsync = ts.hasModifier(node, 256 /* Async */); fillSignature(54 /* ColonToken */, /*yieldContext*/ isGenerator, /*awaitContext*/ isAsync, /*requireCompleteParameterList*/ false, node); node.body = parseFunctionBlockOrSemicolon(isGenerator, isAsync, ts.Diagnostics.or_expected); return addJSDocComment(finishNode(node)); @@ -12622,7 +17137,7 @@ var ts; function parseConstructorDeclaration(pos, decorators, modifiers) { var node = createNode(148 /* Constructor */, pos); node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; parseExpected(121 /* ConstructorKeyword */); fillSignature(54 /* ColonToken */, /*yieldContext*/ false, /*awaitContext*/ false, /*requireCompleteParameterList*/ false, node); node.body = parseFunctionBlockOrSemicolon(/*isGenerator*/ false, /*isAsync*/ false, ts.Diagnostics.or_expected); @@ -12631,12 +17146,12 @@ var ts; function parseMethodDeclaration(fullStart, decorators, modifiers, asteriskToken, name, questionToken, diagnosticMessage) { var method = createNode(147 /* MethodDeclaration */, fullStart); method.decorators = decorators; - setModifiers(method, modifiers); + method.modifiers = modifiers; method.asteriskToken = asteriskToken; method.name = name; method.questionToken = questionToken; var isGenerator = !!asteriskToken; - var isAsync = !!(method.flags & 256 /* Async */); + var isAsync = ts.hasModifier(method, 256 /* Async */); fillSignature(54 /* ColonToken */, /*yieldContext*/ isGenerator, /*awaitContext*/ isAsync, /*requireCompleteParameterList*/ false, method); method.body = parseFunctionBlockOrSemicolon(isGenerator, isAsync, diagnosticMessage); return addJSDocComment(finishNode(method)); @@ -12644,7 +17159,7 @@ var ts; function parsePropertyDeclaration(fullStart, decorators, modifiers, name, questionToken) { var property = createNode(145 /* PropertyDeclaration */, fullStart); property.decorators = decorators; - setModifiers(property, modifiers); + property.modifiers = modifiers; property.name = name; property.questionToken = questionToken; property.type = parseTypeAnnotation(); @@ -12657,11 +17172,11 @@ var ts; // AccessibilityModifier_opt static_opt PropertyName TypeAnnotation_opt Initializer_opt[In, ?Yield]; // // The checker may still error in the static case to explicitly disallow the yield expression. - property.initializer = modifiers && modifiers.flags & 32 /* Static */ + property.initializer = ts.hasModifier(property, 32 /* Static */) ? allowInAnd(parseNonParameterInitializer) - : doOutsideOfContext(8388608 /* YieldContext */ | 4194304 /* DisallowInContext */, parseNonParameterInitializer); + : doOutsideOfContext(65536 /* YieldContext */ | 32768 /* DisallowInContext */, parseNonParameterInitializer); parseSemicolon(); - return finishNode(property); + return addJSDocComment(finishNode(property)); } function parsePropertyOrMethodDeclaration(fullStart, decorators, modifiers) { var asteriskToken = parseOptionalToken(37 /* AsteriskToken */); @@ -12682,11 +17197,11 @@ var ts; function parseAccessorDeclaration(kind, fullStart, decorators, modifiers) { var node = createNode(kind, fullStart); node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; node.name = parsePropertyName(); fillSignature(54 /* ColonToken */, /*yieldContext*/ false, /*awaitContext*/ false, /*requireCompleteParameterList*/ false, node); node.body = parseFunctionBlockOrSemicolon(/*isGenerator*/ false, /*isAsync*/ false); - return finishNode(node); + return addJSDocComment(finishNode(node)); } function isClassMemberModifier(idToken) { switch (idToken) { @@ -12765,13 +17280,15 @@ var ts; if (!parseOptional(55 /* AtToken */)) { break; } - if (!decorators) { - decorators = []; - decorators.pos = decoratorStart; - } var decorator = createNode(143 /* Decorator */, decoratorStart); decorator.expression = doInDecoratorContext(parseLeftHandSideExpressionOrHigher); - decorators.push(finishNode(decorator)); + finishNode(decorator); + if (!decorators) { + decorators = createNodeArray([decorator], decoratorStart); + } + else { + decorators.push(decorator); + } } if (decorators) { decorators.end = getNodeEnd(); @@ -12786,7 +17303,6 @@ var ts; * In such situations, 'permitInvalidConstAsModifier' should be set to true. */ function parseModifiers(permitInvalidConstAsModifier) { - var flags = 0; var modifiers; while (true) { var modifierStart = scanner.getStartPos(); @@ -12803,31 +17319,27 @@ var ts; break; } } + var modifier = finishNode(createNode(modifierKind, modifierStart)); if (!modifiers) { - modifiers = []; - modifiers.pos = modifierStart; + modifiers = createNodeArray([modifier], modifierStart); + } + else { + modifiers.push(modifier); } - flags |= ts.modifierToFlag(modifierKind); - modifiers.push(finishNode(createNode(modifierKind, modifierStart))); } if (modifiers) { - modifiers.flags = flags; modifiers.end = scanner.getStartPos(); } return modifiers; } function parseModifiersForArrowFunction() { - var flags = 0; var modifiers; if (token() === 118 /* AsyncKeyword */) { var modifierStart = scanner.getStartPos(); var modifierKind = token(); nextToken(); - modifiers = []; - modifiers.pos = modifierStart; - flags |= ts.modifierToFlag(modifierKind); - modifiers.push(finishNode(createNode(modifierKind, modifierStart))); - modifiers.flags = flags; + var modifier = finishNode(createNode(modifierKind, modifierStart)); + modifiers = createNodeArray([modifier], modifierStart); modifiers.end = scanner.getStartPos(); } return modifiers; @@ -12862,8 +17374,8 @@ var ts; } if (decorators || modifiers) { // treat this as a property declaration with a missing name. - var name_7 = createMissingNode(69 /* Identifier */, /*reportAtCurrentPosition*/ true, ts.Diagnostics.Declaration_expected); - return parsePropertyDeclaration(fullStart, decorators, modifiers, name_7, /*questionToken*/ undefined); + var name_10 = createMissingNode(69 /* Identifier */, /*reportAtCurrentPosition*/ true, ts.Diagnostics.Declaration_expected); + return parsePropertyDeclaration(fullStart, decorators, modifiers, name_10, /*questionToken*/ undefined); } // 'isClassMemberStart' should have hinted not to attempt parsing. ts.Debug.fail("Should not have attempted to parse class member declaration."); @@ -12880,7 +17392,7 @@ var ts; function parseClassDeclarationOrExpression(fullStart, decorators, modifiers, kind) { var node = createNode(kind, fullStart); node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; parseExpected(73 /* ClassKeyword */); node.name = parseNameOfClassDeclarationOrExpression(); node.typeParameters = parseTypeParameters(); @@ -12894,7 +17406,7 @@ var ts; else { node.members = createMissingList(); } - return finishNode(node); + return addJSDocComment(finishNode(node)); } function parseNameOfClassDeclarationOrExpression() { // implements is a future reserved word so @@ -12944,18 +17456,18 @@ var ts; function parseInterfaceDeclaration(fullStart, decorators, modifiers) { var node = createNode(222 /* InterfaceDeclaration */, fullStart); node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; parseExpected(107 /* InterfaceKeyword */); node.name = parseIdentifier(); node.typeParameters = parseTypeParameters(); node.heritageClauses = parseHeritageClauses(/*isClassHeritageClause*/ false); node.members = parseObjectTypeMembers(); - return finishNode(node); + return addJSDocComment(finishNode(node)); } function parseTypeAliasDeclaration(fullStart, decorators, modifiers) { var node = createNode(223 /* TypeAliasDeclaration */, fullStart); node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; parseExpected(134 /* TypeKeyword */); node.name = parseIdentifier(); node.typeParameters = parseTypeParameters(); @@ -12972,12 +17484,12 @@ var ts; var node = createNode(255 /* EnumMember */, scanner.getStartPos()); node.name = parsePropertyName(); node.initializer = allowInAnd(parseNonParameterInitializer); - return finishNode(node); + return addJSDocComment(finishNode(node)); } function parseEnumDeclaration(fullStart, decorators, modifiers) { var node = createNode(224 /* EnumDeclaration */, fullStart); node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; parseExpected(81 /* EnumKeyword */); node.name = parseIdentifier(); if (parseExpected(15 /* OpenBraceToken */)) { @@ -12987,7 +17499,7 @@ var ts; else { node.members = createMissingList(); } - return finishNode(node); + return addJSDocComment(finishNode(node)); } function parseModuleBlock() { var node = createNode(226 /* ModuleBlock */, scanner.getStartPos()); @@ -13004,24 +17516,24 @@ var ts; var node = createNode(225 /* ModuleDeclaration */, fullStart); // If we are parsing a dotted namespace name, we want to // propagate the 'Namespace' flag across the names if set. - var namespaceFlag = flags & 4096 /* Namespace */; + var namespaceFlag = flags & 16 /* Namespace */; node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; node.flags |= flags; node.name = parseIdentifier(); node.body = parseOptional(21 /* DotToken */) - ? parseModuleOrNamespaceDeclaration(getNodePos(), /*decorators*/ undefined, /*modifiers*/ undefined, 1 /* Export */ | namespaceFlag) + ? parseModuleOrNamespaceDeclaration(getNodePos(), /*decorators*/ undefined, /*modifiers*/ undefined, 4 /* NestedNamespace */ | namespaceFlag) : parseModuleBlock(); - return finishNode(node); + return addJSDocComment(finishNode(node)); } function parseAmbientExternalModuleDeclaration(fullStart, decorators, modifiers) { var node = createNode(225 /* ModuleDeclaration */, fullStart); node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; if (token() === 137 /* GlobalKeyword */) { // parse 'global' as name of global scope augmentation node.name = parseIdentifier(); - node.flags |= 131072 /* GlobalAugmentation */; + node.flags |= 512 /* GlobalAugmentation */; } else { node.name = parseLiteralNode(/*internName*/ true); @@ -13035,13 +17547,13 @@ var ts; return finishNode(node); } function parseModuleDeclaration(fullStart, decorators, modifiers) { - var flags = modifiers ? modifiers.flags : 0; + var flags = 0; if (token() === 137 /* GlobalKeyword */) { // global augmentation return parseAmbientExternalModuleDeclaration(fullStart, decorators, modifiers); } else if (parseOptional(126 /* NamespaceKeyword */)) { - flags |= 4096 /* Namespace */; + flags |= 16 /* Namespace */; } else { parseExpected(125 /* ModuleKeyword */); @@ -13083,18 +17595,18 @@ var ts; // import x = M.x; var importEqualsDeclaration = createNode(229 /* ImportEqualsDeclaration */, fullStart); importEqualsDeclaration.decorators = decorators; - setModifiers(importEqualsDeclaration, modifiers); + importEqualsDeclaration.modifiers = modifiers; importEqualsDeclaration.name = identifier; parseExpected(56 /* EqualsToken */); importEqualsDeclaration.moduleReference = parseModuleReference(); parseSemicolon(); - return finishNode(importEqualsDeclaration); + return addJSDocComment(finishNode(importEqualsDeclaration)); } } // Import statement var importDeclaration = createNode(230 /* ImportDeclaration */, fullStart); importDeclaration.decorators = decorators; - setModifiers(importDeclaration, modifiers); + importDeclaration.modifiers = modifiers; // ImportDeclaration: // import ImportClause from ModuleSpecifier ; // import ModuleSpecifier; @@ -13214,7 +17726,7 @@ var ts; function parseExportDeclaration(fullStart, decorators, modifiers) { var node = createNode(236 /* ExportDeclaration */, fullStart); node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; if (parseOptional(37 /* AsteriskToken */)) { parseExpected(136 /* FromKeyword */); node.moduleSpecifier = parseModuleSpecifier(); @@ -13235,7 +17747,7 @@ var ts; function parseExportAssignment(fullStart, decorators, modifiers) { var node = createNode(235 /* ExportAssignment */, fullStart); node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; if (parseOptional(56 /* EqualsToken */)) { node.isExportEquals = true; } @@ -13314,7 +17826,7 @@ var ts; } function setExternalModuleIndicator(sourceFile) { sourceFile.externalModuleIndicator = ts.forEach(sourceFile.statements, function (node) { - return node.flags & 1 /* Export */ + return ts.hasModifier(node, 1 /* Export */) || node.kind === 229 /* ImportEqualsDeclaration */ && node.moduleReference.kind === 240 /* ExternalModuleReference */ || node.kind === 230 /* ImportDeclaration */ || node.kind === 235 /* ExportAssignment */ @@ -13380,6 +17892,7 @@ var ts; JSDocParser.isJSDocType = isJSDocType; function parseJSDocTypeExpressionForTests(content, start, length) { initializeState("file.js", content, 2 /* Latest */, /*_syntaxCursor:*/ undefined, 1 /* JS */); + sourceFile = createSourceFile("file.js", 2 /* Latest */, 1 /* JS */); scanner.setText(content, start, length); currentToken = scanner.scan(); var jsDocTypeExpression = parseJSDocTypeExpression(); @@ -13566,19 +18079,7 @@ var ts; } function parseJSDocRecordType() { var result = createNode(265 /* JSDocRecordType */); - nextToken(); - result.members = parseDelimitedList(24 /* JSDocRecordMembers */, parseJSDocRecordMember); - checkForTrailingComma(result.members); - parseExpected(16 /* CloseBraceToken */); - return finishNode(result); - } - function parseJSDocRecordMember() { - var result = createNode(266 /* JSDocRecordMember */); - result.name = parseSimplePropertyName(); - if (token() === 54 /* ColonToken */) { - nextToken(); - result.type = parseJSDocType(); - } + result.literal = parseTypeLiteral(); return finishNode(result); } function parseJSDocNonNullableType() { @@ -13610,2929 +18111,4388 @@ var ts; } function parseJSDocTypeList(firstType) { ts.Debug.assert(!!firstType); - var types = []; - types.pos = firstType.pos; - types.push(firstType); + var types = createNodeArray([firstType], firstType.pos); while (parseOptional(47 /* BarToken */)) { types.push(parseJSDocType()); } - types.end = scanner.getStartPos(); - return types; - } - function parseJSDocAllType() { - var result = createNode(258 /* JSDocAllType */); - nextToken(); - return finishNode(result); - } - function parseJSDocLiteralType() { - var result = createNode(282 /* JSDocLiteralType */); - result.literal = parseLiteralTypeNode(); - return finishNode(result); - } - function parseJSDocUnknownOrNullableType() { - var pos = scanner.getStartPos(); - // skip the ? - nextToken(); - // Need to lookahead to decide if this is a nullable or unknown type. - // Here are cases where we'll pick the unknown type: - // - // Foo(?, - // { a: ? } - // Foo(?) - // Foo - // Foo(?= - // (?| - if (token() === 24 /* CommaToken */ || - token() === 16 /* CloseBraceToken */ || - token() === 18 /* CloseParenToken */ || - token() === 27 /* GreaterThanToken */ || - token() === 56 /* EqualsToken */ || - token() === 47 /* BarToken */) { - var result = createNode(259 /* JSDocUnknownType */, pos); + types.end = scanner.getStartPos(); + return types; + } + function parseJSDocAllType() { + var result = createNode(258 /* JSDocAllType */); + nextToken(); + return finishNode(result); + } + function parseJSDocLiteralType() { + var result = createNode(282 /* JSDocLiteralType */); + result.literal = parseLiteralTypeNode(); + return finishNode(result); + } + function parseJSDocUnknownOrNullableType() { + var pos = scanner.getStartPos(); + // skip the ? + nextToken(); + // Need to lookahead to decide if this is a nullable or unknown type. + // Here are cases where we'll pick the unknown type: + // + // Foo(?, + // { a: ? } + // Foo(?) + // Foo + // Foo(?= + // (?| + if (token() === 24 /* CommaToken */ || + token() === 16 /* CloseBraceToken */ || + token() === 18 /* CloseParenToken */ || + token() === 27 /* GreaterThanToken */ || + token() === 56 /* EqualsToken */ || + token() === 47 /* BarToken */) { + var result = createNode(259 /* JSDocUnknownType */, pos); + return finishNode(result); + } + else { + var result = createNode(263 /* JSDocNullableType */, pos); + result.type = parseJSDocType(); + return finishNode(result); + } + } + function parseIsolatedJSDocComment(content, start, length) { + initializeState("file.js", content, 2 /* Latest */, /*_syntaxCursor:*/ undefined, 1 /* JS */); + sourceFile = { languageVariant: 0 /* Standard */, text: content }; + var jsDoc = parseJSDocCommentWorker(start, length); + var diagnostics = parseDiagnostics; + clearState(); + return jsDoc ? { jsDoc: jsDoc, diagnostics: diagnostics } : undefined; + } + JSDocParser.parseIsolatedJSDocComment = parseIsolatedJSDocComment; + function parseJSDocComment(parent, start, length) { + var saveToken = currentToken; + var saveParseDiagnosticsLength = parseDiagnostics.length; + var saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode; + var comment = parseJSDocCommentWorker(start, length); + if (comment) { + comment.parent = parent; + } + currentToken = saveToken; + parseDiagnostics.length = saveParseDiagnosticsLength; + parseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode; + return comment; + } + JSDocParser.parseJSDocComment = parseJSDocComment; + var JSDocState; + (function (JSDocState) { + JSDocState[JSDocState["BeginningOfLine"] = 0] = "BeginningOfLine"; + JSDocState[JSDocState["SawAsterisk"] = 1] = "SawAsterisk"; + JSDocState[JSDocState["SavingComments"] = 2] = "SavingComments"; + })(JSDocState || (JSDocState = {})); + function parseJSDocCommentWorker(start, length) { + var content = sourceText; + start = start || 0; + var end = length === undefined ? content.length : start + length; + length = end - start; + ts.Debug.assert(start >= 0); + ts.Debug.assert(start <= end); + ts.Debug.assert(end <= content.length); + var tags; + var comments = []; + var result; + // Check for /** (JSDoc opening part) + if (!isJsDocStart(content, start)) { + return result; + } + // + 3 for leading /**, - 5 in total for /** */ + scanner.scanRange(start + 3, length - 5, function () { + // Initially we can parse out a tag. We also have seen a starting asterisk. + // This is so that /** * @type */ doesn't parse. + var advanceToken = true; + var state = 1 /* SawAsterisk */; + var margin = undefined; + // + 4 for leading '/** ' + var indent = start - Math.max(content.lastIndexOf("\n", start), 0) + 4; + function pushComment(text) { + if (!margin) { + margin = indent; + } + comments.push(text); + indent += text.length; + } + nextJSDocToken(); + while (token() === 5 /* WhitespaceTrivia */) { + nextJSDocToken(); + } + if (token() === 4 /* NewLineTrivia */) { + state = 0 /* BeginningOfLine */; + nextJSDocToken(); + } + while (token() !== 1 /* EndOfFileToken */) { + switch (token()) { + case 55 /* AtToken */: + if (state === 0 /* BeginningOfLine */ || state === 1 /* SawAsterisk */) { + removeTrailingNewlines(comments); + parseTag(indent); + // NOTE: According to usejsdoc.org, a tag goes to end of line, except the last tag. + // Real-world comments may break this rule, so "BeginningOfLine" will not be a real line beginning + // for malformed examples like `/** @param {string} x @returns {number} the length */` + state = 0 /* BeginningOfLine */; + advanceToken = false; + margin = undefined; + indent++; + } + else { + pushComment(scanner.getTokenText()); + } + break; + case 4 /* NewLineTrivia */: + comments.push(scanner.getTokenText()); + state = 0 /* BeginningOfLine */; + indent = 0; + break; + case 37 /* AsteriskToken */: + var asterisk = scanner.getTokenText(); + if (state === 1 /* SawAsterisk */) { + // If we've already seen an asterisk, then we can no longer parse a tag on this line + state = 2 /* SavingComments */; + pushComment(asterisk); + } + else { + // Ignore the first asterisk on a line + state = 1 /* SawAsterisk */; + indent += asterisk.length; + } + break; + case 69 /* Identifier */: + // Anything else is doc comment text. We just save it. Because it + // wasn't a tag, we can no longer parse a tag on this line until we hit the next + // line break. + pushComment(scanner.getTokenText()); + state = 2 /* SavingComments */; + break; + case 5 /* WhitespaceTrivia */: + // only collect whitespace if we're already saving comments or have just crossed the comment indent margin + var whitespace = scanner.getTokenText(); + if (state === 2 /* SavingComments */ || margin !== undefined && indent + whitespace.length > margin) { + comments.push(whitespace.slice(margin - indent - 1)); + } + indent += whitespace.length; + break; + case 1 /* EndOfFileToken */: + break; + default: + pushComment(scanner.getTokenText()); + break; + } + if (advanceToken) { + nextJSDocToken(); + } + else { + advanceToken = true; + } + } + removeLeadingNewlines(comments); + removeTrailingNewlines(comments); + result = createJSDocComment(); + }); + return result; + function removeLeadingNewlines(comments) { + while (comments.length && (comments[0] === "\n" || comments[0] === "\r")) { + comments.shift(); + } + } + function removeTrailingNewlines(comments) { + while (comments.length && (comments[comments.length - 1] === "\n" || comments[comments.length - 1] === "\r")) { + comments.pop(); + } + } + function isJsDocStart(content, start) { + return content.charCodeAt(start) === 47 /* slash */ && + content.charCodeAt(start + 1) === 42 /* asterisk */ && + content.charCodeAt(start + 2) === 42 /* asterisk */ && + content.charCodeAt(start + 3) !== 42 /* asterisk */; + } + function createJSDocComment() { + var result = createNode(273 /* JSDocComment */, start); + result.tags = tags; + result.comment = comments.length ? comments.join("") : undefined; + return finishNode(result, end); + } + function skipWhitespace() { + while (token() === 5 /* WhitespaceTrivia */ || token() === 4 /* NewLineTrivia */) { + nextJSDocToken(); + } + } + function parseTag(indent) { + ts.Debug.assert(token() === 55 /* AtToken */); + var atToken = createNode(55 /* AtToken */, scanner.getTokenPos()); + atToken.end = scanner.getTextPos(); + nextJSDocToken(); + var tagName = parseJSDocIdentifierName(); + skipWhitespace(); + if (!tagName) { + return; + } + var tag; + if (tagName) { + switch (tagName.text) { + case "param": + tag = parseParamTag(atToken, tagName); + break; + case "return": + case "returns": + tag = parseReturnTag(atToken, tagName); + break; + case "template": + tag = parseTemplateTag(atToken, tagName); + break; + case "type": + tag = parseTypeTag(atToken, tagName); + break; + case "typedef": + tag = parseTypedefTag(atToken, tagName); + break; + default: + tag = parseUnknownTag(atToken, tagName); + break; + } + } + else { + tag = parseUnknownTag(atToken, tagName); + } + if (!tag) { + // a badly malformed tag should not be added to the list of tags + return; + } + addTag(tag, parseTagComments(indent + tag.end - tag.pos)); + } + function parseTagComments(indent) { + var comments = []; + var state = 1 /* SawAsterisk */; + var margin; + function pushComment(text) { + if (!margin) { + margin = indent; + } + comments.push(text); + indent += text.length; + } + while (token() !== 55 /* AtToken */ && token() !== 1 /* EndOfFileToken */) { + switch (token()) { + case 4 /* NewLineTrivia */: + if (state >= 1 /* SawAsterisk */) { + state = 0 /* BeginningOfLine */; + comments.push(scanner.getTokenText()); + } + indent = 0; + break; + case 55 /* AtToken */: + // Done + break; + case 5 /* WhitespaceTrivia */: + if (state === 2 /* SavingComments */) { + pushComment(scanner.getTokenText()); + } + else { + var whitespace = scanner.getTokenText(); + // if the whitespace crosses the margin, take only the whitespace that passes the margin + if (margin !== undefined && indent + whitespace.length > margin) { + comments.push(whitespace.slice(margin - indent - 1)); + } + indent += whitespace.length; + } + break; + case 37 /* AsteriskToken */: + if (state === 0 /* BeginningOfLine */) { + // leading asterisks start recording on the *next* (non-whitespace) token + state = 1 /* SawAsterisk */; + indent += scanner.getTokenText().length; + break; + } + // FALLTHROUGH otherwise to record the * as a comment + default: + state = 2 /* SavingComments */; // leading identifiers start recording as well + pushComment(scanner.getTokenText()); + break; + } + if (token() === 55 /* AtToken */) { + // Done + break; + } + nextJSDocToken(); + } + removeLeadingNewlines(comments); + removeTrailingNewlines(comments); + return comments; + } + function parseUnknownTag(atToken, tagName) { + var result = createNode(274 /* JSDocTag */, atToken.pos); + result.atToken = atToken; + result.tagName = tagName; + return finishNode(result); + } + function addTag(tag, comments) { + tag.comment = comments.join(""); + if (!tags) { + tags = createNodeArray([tag], tag.pos); + } + else { + tags.push(tag); + } + tags.end = tag.end; + } + function tryParseTypeExpression() { + return tryParse(function () { + skipWhitespace(); + if (token() !== 15 /* OpenBraceToken */) { + return undefined; + } + return parseJSDocTypeExpression(); + }); + } + function parseParamTag(atToken, tagName) { + var typeExpression = tryParseTypeExpression(); + skipWhitespace(); + var name; + var isBracketed; + // Looking for something like '[foo]' or 'foo' + if (parseOptionalToken(19 /* OpenBracketToken */)) { + name = parseJSDocIdentifierName(); + skipWhitespace(); + isBracketed = true; + // May have an optional default, e.g. '[foo = 42]' + if (parseOptionalToken(56 /* EqualsToken */)) { + parseExpression(); + } + parseExpected(20 /* CloseBracketToken */); + } + else if (ts.tokenIsIdentifierOrKeyword(token())) { + name = parseJSDocIdentifierName(); + } + if (!name) { + parseErrorAtPosition(scanner.getStartPos(), 0, ts.Diagnostics.Identifier_expected); + return undefined; + } + var preName, postName; + if (typeExpression) { + postName = name; + } + else { + preName = name; + } + if (!typeExpression) { + typeExpression = tryParseTypeExpression(); + } + var result = createNode(275 /* JSDocParameterTag */, atToken.pos); + result.atToken = atToken; + result.tagName = tagName; + result.preParameterName = preName; + result.typeExpression = typeExpression; + result.postParameterName = postName; + result.parameterName = postName || preName; + result.isBracketed = isBracketed; + return finishNode(result); + } + function parseReturnTag(atToken, tagName) { + if (ts.forEach(tags, function (t) { return t.kind === 276 /* JSDocReturnTag */; })) { + parseErrorAtPosition(tagName.pos, scanner.getTokenPos() - tagName.pos, ts.Diagnostics._0_tag_already_specified, tagName.text); + } + var result = createNode(276 /* JSDocReturnTag */, atToken.pos); + result.atToken = atToken; + result.tagName = tagName; + result.typeExpression = tryParseTypeExpression(); return finishNode(result); } - else { - var result = createNode(263 /* JSDocNullableType */, pos); - result.type = parseJSDocType(); + function parseTypeTag(atToken, tagName) { + if (ts.forEach(tags, function (t) { return t.kind === 277 /* JSDocTypeTag */; })) { + parseErrorAtPosition(tagName.pos, scanner.getTokenPos() - tagName.pos, ts.Diagnostics._0_tag_already_specified, tagName.text); + } + var result = createNode(277 /* JSDocTypeTag */, atToken.pos); + result.atToken = atToken; + result.tagName = tagName; + result.typeExpression = tryParseTypeExpression(); return finishNode(result); } - } - function parseIsolatedJSDocComment(content, start, length) { - initializeState("file.js", content, 2 /* Latest */, /*_syntaxCursor:*/ undefined, 1 /* JS */); - sourceFile = { languageVariant: 0 /* Standard */, text: content }; - var jsDocComment = parseJSDocCommentWorker(start, length); - var diagnostics = parseDiagnostics; - clearState(); - return jsDocComment ? { jsDocComment: jsDocComment, diagnostics: diagnostics } : undefined; - } - JSDocParser.parseIsolatedJSDocComment = parseIsolatedJSDocComment; - function parseJSDocComment(parent, start, length) { - var saveToken = currentToken; - var saveParseDiagnosticsLength = parseDiagnostics.length; - var saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode; - var comment = parseJSDocCommentWorker(start, length); - if (comment) { - comment.parent = parent; + function parsePropertyTag(atToken, tagName) { + var typeExpression = tryParseTypeExpression(); + skipWhitespace(); + var name = parseJSDocIdentifierName(); + skipWhitespace(); + if (!name) { + parseErrorAtPosition(scanner.getStartPos(), /*length*/ 0, ts.Diagnostics.Identifier_expected); + return undefined; + } + var result = createNode(280 /* JSDocPropertyTag */, atToken.pos); + result.atToken = atToken; + result.tagName = tagName; + result.name = name; + result.typeExpression = typeExpression; + return finishNode(result); } - currentToken = saveToken; - parseDiagnostics.length = saveParseDiagnosticsLength; - parseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode; - return comment; - } - JSDocParser.parseJSDocComment = parseJSDocComment; - function parseJSDocCommentWorker(start, length) { - var content = sourceText; - start = start || 0; - var end = length === undefined ? content.length : start + length; - length = end - start; - ts.Debug.assert(start >= 0); - ts.Debug.assert(start <= end); - ts.Debug.assert(end <= content.length); - var tags; - var result; - // Check for /** (JSDoc opening part) - if (content.charCodeAt(start) === 47 /* slash */ && - content.charCodeAt(start + 1) === 42 /* asterisk */ && - content.charCodeAt(start + 2) === 42 /* asterisk */ && - content.charCodeAt(start + 3) !== 42 /* asterisk */) { - // + 3 for leading /**, - 5 in total for /** */ - scanner.scanRange(start + 3, length - 5, function () { - // Initially we can parse out a tag. We also have seen a starting asterisk. - // This is so that /** * @type */ doesn't parse. + function parseTypedefTag(atToken, tagName) { + var typeExpression = tryParseTypeExpression(); + skipWhitespace(); + var typedefTag = createNode(279 /* JSDocTypedefTag */, atToken.pos); + typedefTag.atToken = atToken; + typedefTag.tagName = tagName; + typedefTag.name = parseJSDocIdentifierName(); + typedefTag.typeExpression = typeExpression; + skipWhitespace(); + if (typeExpression) { + if (typeExpression.type.kind === 267 /* JSDocTypeReference */) { + var jsDocTypeReference = typeExpression.type; + if (jsDocTypeReference.name.kind === 69 /* Identifier */) { + var name_11 = jsDocTypeReference.name; + if (name_11.text === "Object") { + typedefTag.jsDocTypeLiteral = scanChildTags(); + } + } + } + if (!typedefTag.jsDocTypeLiteral) { + typedefTag.jsDocTypeLiteral = typeExpression.type; + } + } + else { + typedefTag.jsDocTypeLiteral = scanChildTags(); + } + return finishNode(typedefTag); + function scanChildTags() { + var jsDocTypeLiteral = createNode(281 /* JSDocTypeLiteral */, scanner.getStartPos()); + var resumePos = scanner.getStartPos(); var canParseTag = true; - var seenAsterisk = true; - nextJSDocToken(); - while (token() !== 1 /* EndOfFileToken */) { + var seenAsterisk = false; + var parentTagTerminated = false; + while (token() !== 1 /* EndOfFileToken */ && !parentTagTerminated) { + nextJSDocToken(); switch (token()) { case 55 /* AtToken */: if (canParseTag) { - parseTag(); + parentTagTerminated = !tryParseChildTag(jsDocTypeLiteral); + if (!parentTagTerminated) { + resumePos = scanner.getStartPos(); + } } - // This will take us to the end of the line, so it's OK to parse a tag on the next pass through the loop seenAsterisk = false; break; case 4 /* NewLineTrivia */: - // After a line break, we can parse a tag, and we haven't seen an asterisk on the next line yet + resumePos = scanner.getStartPos() - 1; canParseTag = true; seenAsterisk = false; break; case 37 /* AsteriskToken */: if (seenAsterisk) { - // If we've already seen an asterisk, then we can no longer parse a tag on this line canParseTag = false; } - // Ignore the first asterisk on a line seenAsterisk = true; break; case 69 /* Identifier */: - // Anything else is doc comment text. We can't do anything with it. Because it - // wasn't a tag, we can no longer parse a tag on this line until we hit the next - // line break. canParseTag = false; - break; case 1 /* EndOfFileToken */: break; } - nextJSDocToken(); } - result = createJSDocComment(); - }); - } - return result; - function createJSDocComment() { - if (!tags) { - return undefined; - } - var result = createNode(273 /* JSDocComment */, start); - result.tags = tags; - return finishNode(result, end); - } - function skipWhitespace() { - while (token() === 5 /* WhitespaceTrivia */ || token() === 4 /* NewLineTrivia */) { - nextJSDocToken(); + scanner.setTextPos(resumePos); + return finishNode(jsDocTypeLiteral); } } - function parseTag() { + function tryParseChildTag(parentTag) { ts.Debug.assert(token() === 55 /* AtToken */); - var atToken = createNode(55 /* AtToken */, scanner.getTokenPos()); + var atToken = createNode(55 /* AtToken */, scanner.getStartPos()); atToken.end = scanner.getTextPos(); nextJSDocToken(); var tagName = parseJSDocIdentifierName(); + skipWhitespace(); if (!tagName) { - return; + return false; + } + switch (tagName.text) { + case "type": + if (parentTag.jsDocTypeTag) { + // already has a @type tag, terminate the parent tag now. + return false; + } + parentTag.jsDocTypeTag = parseTypeTag(atToken, tagName); + return true; + case "prop": + case "property": + if (!parentTag.jsDocPropertyTags) { + parentTag.jsDocPropertyTags = []; + } + var propertyTag = parsePropertyTag(atToken, tagName); + parentTag.jsDocPropertyTags.push(propertyTag); + return true; } - var tag = handleTag(atToken, tagName) || handleUnknownTag(atToken, tagName); - addTag(tag); + return false; } - function handleTag(atToken, tagName) { - if (tagName) { - switch (tagName.text) { - case "param": - return handleParamTag(atToken, tagName); - case "return": - case "returns": - return handleReturnTag(atToken, tagName); - case "template": - return handleTemplateTag(atToken, tagName); - case "type": - return handleTypeTag(atToken, tagName); - case "typedef": - return handleTypedefTag(atToken, tagName); + function parseTemplateTag(atToken, tagName) { + if (ts.forEach(tags, function (t) { return t.kind === 278 /* JSDocTemplateTag */; })) { + parseErrorAtPosition(tagName.pos, scanner.getTokenPos() - tagName.pos, ts.Diagnostics._0_tag_already_specified, tagName.text); + } + // Type parameter list looks like '@template T,U,V' + var typeParameters = createNodeArray(); + while (true) { + var name_12 = parseJSDocIdentifierName(); + skipWhitespace(); + if (!name_12) { + parseErrorAtPosition(scanner.getStartPos(), 0, ts.Diagnostics.Identifier_expected); + return undefined; + } + var typeParameter = createNode(141 /* TypeParameter */, name_12.pos); + typeParameter.name = name_12; + finishNode(typeParameter); + typeParameters.push(typeParameter); + if (token() === 24 /* CommaToken */) { + nextJSDocToken(); + skipWhitespace(); + } + else { + break; } } - return undefined; - } - function handleUnknownTag(atToken, tagName) { - var result = createNode(274 /* JSDocTag */, atToken.pos); + var result = createNode(278 /* JSDocTemplateTag */, atToken.pos); result.atToken = atToken; result.tagName = tagName; - return finishNode(result); + result.typeParameters = typeParameters; + finishNode(result); + typeParameters.end = result.end; + return result; + } + function nextJSDocToken() { + return currentToken = scanner.scanJSDocToken(); + } + function parseJSDocIdentifierName() { + return createJSDocIdentifier(ts.tokenIsIdentifierOrKeyword(token())); + } + function createJSDocIdentifier(isIdentifier) { + if (!isIdentifier) { + parseErrorAtCurrentToken(ts.Diagnostics.Identifier_expected); + return undefined; + } + var pos = scanner.getTokenPos(); + var end = scanner.getTextPos(); + var result = createNode(69 /* Identifier */, pos); + result.text = content.substring(pos, end); + finishNode(result, end); + nextJSDocToken(); + return result; + } + } + JSDocParser.parseJSDocCommentWorker = parseJSDocCommentWorker; + })(JSDocParser = Parser.JSDocParser || (Parser.JSDocParser = {})); + })(Parser || (Parser = {})); + var IncrementalParser; + (function (IncrementalParser) { + function updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks) { + aggressiveChecks = aggressiveChecks || ts.Debug.shouldAssert(2 /* Aggressive */); + checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks); + if (ts.textChangeRangeIsUnchanged(textChangeRange)) { + // if the text didn't change, then we can just return our current source file as-is. + return sourceFile; + } + if (sourceFile.statements.length === 0) { + // If we don't have any statements in the current source file, then there's no real + // way to incrementally parse. So just do a full parse instead. + return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setParentNodes*/ true, sourceFile.scriptKind); + } + // Make sure we're not trying to incrementally update a source file more than once. Once + // we do an update the original source file is considered unusable from that point onwards. + // + // This is because we do incremental parsing in-place. i.e. we take nodes from the old + // tree and give them new positions and parents. From that point on, trusting the old + // tree at all is not possible as far too much of it may violate invariants. + var incrementalSourceFile = sourceFile; + ts.Debug.assert(!incrementalSourceFile.hasBeenIncrementallyParsed); + incrementalSourceFile.hasBeenIncrementallyParsed = true; + var oldText = sourceFile.text; + var syntaxCursor = createSyntaxCursor(sourceFile); + // Make the actual change larger so that we know to reparse anything whose lookahead + // might have intersected the change. + var changeRange = extendToAffectedRange(sourceFile, textChangeRange); + checkChangeRange(sourceFile, newText, changeRange, aggressiveChecks); + // Ensure that extending the affected range only moved the start of the change range + // earlier in the file. + ts.Debug.assert(changeRange.span.start <= textChangeRange.span.start); + ts.Debug.assert(ts.textSpanEnd(changeRange.span) === ts.textSpanEnd(textChangeRange.span)); + ts.Debug.assert(ts.textSpanEnd(ts.textChangeRangeNewSpan(changeRange)) === ts.textSpanEnd(ts.textChangeRangeNewSpan(textChangeRange))); + // The is the amount the nodes after the edit range need to be adjusted. It can be + // positive (if the edit added characters), negative (if the edit deleted characters) + // or zero (if this was a pure overwrite with nothing added/removed). + var delta = ts.textChangeRangeNewSpan(changeRange).length - changeRange.span.length; + // If we added or removed characters during the edit, then we need to go and adjust all + // the nodes after the edit. Those nodes may move forward (if we inserted chars) or they + // may move backward (if we deleted chars). + // + // Doing this helps us out in two ways. First, it means that any nodes/tokens we want + // to reuse are already at the appropriate position in the new text. That way when we + // reuse them, we don't have to figure out if they need to be adjusted. Second, it makes + // it very easy to determine if we can reuse a node. If the node's position is at where + // we are in the text, then we can reuse it. Otherwise we can't. If the node's position + // is ahead of us, then we'll need to rescan tokens. If the node's position is behind + // us, then we'll need to skip it or crumble it as appropriate + // + // We will also adjust the positions of nodes that intersect the change range as well. + // By doing this, we ensure that all the positions in the old tree are consistent, not + // just the positions of nodes entirely before/after the change range. By being + // consistent, we can then easily map from positions to nodes in the old tree easily. + // + // Also, mark any syntax elements that intersect the changed span. We know, up front, + // that we cannot reuse these elements. + updateTokenPositionsAndMarkElements(incrementalSourceFile, changeRange.span.start, ts.textSpanEnd(changeRange.span), ts.textSpanEnd(ts.textChangeRangeNewSpan(changeRange)), delta, oldText, newText, aggressiveChecks); + // Now that we've set up our internal incremental state just proceed and parse the + // source file in the normal fashion. When possible the parser will retrieve and + // reuse nodes from the old tree. + // + // Note: passing in 'true' for setNodeParents is very important. When incrementally + // parsing, we will be reusing nodes from the old tree, and placing it into new + // parents. If we don't set the parents now, we'll end up with an observably + // inconsistent tree. Setting the parents on the new tree should be very fast. We + // will immediately bail out of walking any subtrees when we can see that their parents + // are already correct. + var result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /*setParentNodes*/ true, sourceFile.scriptKind); + return result; + } + IncrementalParser.updateSourceFile = updateSourceFile; + function moveElementEntirelyPastChangeRange(element, isArray, delta, oldText, newText, aggressiveChecks) { + if (isArray) { + visitArray(element); + } + else { + visitNode(element); + } + return; + function visitNode(node) { + var text = ""; + if (aggressiveChecks && shouldCheckNode(node)) { + text = oldText.substring(node.pos, node.end); + } + // Ditch any existing LS children we may have created. This way we can avoid + // moving them forward. + if (node._children) { + node._children = undefined; + } + node.pos += delta; + node.end += delta; + if (aggressiveChecks && shouldCheckNode(node)) { + ts.Debug.assert(text === newText.substring(node.pos, node.end)); + } + forEachChild(node, visitNode, visitArray); + if (node.jsDocComments) { + for (var _i = 0, _a = node.jsDocComments; _i < _a.length; _i++) { + var jsDocComment = _a[_i]; + forEachChild(jsDocComment, visitNode, visitArray); + } + } + checkNodePositions(node, aggressiveChecks); + } + function visitArray(array) { + array._children = undefined; + array.pos += delta; + array.end += delta; + for (var _i = 0, array_8 = array; _i < array_8.length; _i++) { + var node = array_8[_i]; + visitNode(node); + } + } + } + function shouldCheckNode(node) { + switch (node.kind) { + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: + case 69 /* Identifier */: + return true; + } + return false; + } + function adjustIntersectingElement(element, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta) { + ts.Debug.assert(element.end >= changeStart, "Adjusting an element that was entirely before the change range"); + ts.Debug.assert(element.pos <= changeRangeOldEnd, "Adjusting an element that was entirely after the change range"); + ts.Debug.assert(element.pos <= element.end); + // We have an element that intersects the change range in some way. It may have its + // start, or its end (or both) in the changed range. We want to adjust any part + // that intersects such that the final tree is in a consistent state. i.e. all + // children have spans within the span of their parent, and all siblings are ordered + // properly. + // We may need to update both the 'pos' and the 'end' of the element. + // If the 'pos' is before the start of the change, then we don't need to touch it. + // If it isn't, then the 'pos' must be inside the change. How we update it will + // depend if delta is positive or negative. If delta is positive then we have + // something like: + // + // -------------------AAA----------------- + // -------------------BBBCCCCCCC----------------- + // + // In this case, we consider any node that started in the change range to still be + // starting at the same position. + // + // however, if the delta is negative, then we instead have something like this: + // + // -------------------XXXYYYYYYY----------------- + // -------------------ZZZ----------------- + // + // In this case, any element that started in the 'X' range will keep its position. + // However any element that started after that will have their pos adjusted to be + // at the end of the new range. i.e. any node that started in the 'Y' range will + // be adjusted to have their start at the end of the 'Z' range. + // + // The element will keep its position if possible. Or Move backward to the new-end + // if it's in the 'Y' range. + element.pos = Math.min(element.pos, changeRangeNewEnd); + // If the 'end' is after the change range, then we always adjust it by the delta + // amount. However, if the end is in the change range, then how we adjust it + // will depend on if delta is positive or negative. If delta is positive then we + // have something like: + // + // -------------------AAA----------------- + // -------------------BBBCCCCCCC----------------- + // + // In this case, we consider any node that ended inside the change range to keep its + // end position. + // + // however, if the delta is negative, then we instead have something like this: + // + // -------------------XXXYYYYYYY----------------- + // -------------------ZZZ----------------- + // + // In this case, any element that ended in the 'X' range will keep its position. + // However any element that ended after that will have their pos adjusted to be + // at the end of the new range. i.e. any node that ended in the 'Y' range will + // be adjusted to have their end at the end of the 'Z' range. + if (element.end >= changeRangeOldEnd) { + // Element ends after the change range. Always adjust the end pos. + element.end += delta; + } + else { + // Element ends in the change range. The element will keep its position if + // possible. Or Move backward to the new-end if it's in the 'Y' range. + element.end = Math.min(element.end, changeRangeNewEnd); + } + ts.Debug.assert(element.pos <= element.end); + if (element.parent) { + ts.Debug.assert(element.pos >= element.parent.pos); + ts.Debug.assert(element.end <= element.parent.end); + } + } + function checkNodePositions(node, aggressiveChecks) { + if (aggressiveChecks) { + var pos_2 = node.pos; + forEachChild(node, function (child) { + ts.Debug.assert(child.pos >= pos_2); + pos_2 = child.end; + }); + ts.Debug.assert(pos_2 <= node.end); + } + } + function updateTokenPositionsAndMarkElements(sourceFile, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta, oldText, newText, aggressiveChecks) { + visitNode(sourceFile); + return; + function visitNode(child) { + ts.Debug.assert(child.pos <= child.end); + if (child.pos > changeRangeOldEnd) { + // Node is entirely past the change range. We need to move both its pos and + // end, forward or backward appropriately. + moveElementEntirelyPastChangeRange(child, /*isArray*/ false, delta, oldText, newText, aggressiveChecks); + return; + } + // Check if the element intersects the change range. If it does, then it is not + // reusable. Also, we'll need to recurse to see what constituent portions we may + // be able to use. + var fullEnd = child.end; + if (fullEnd >= changeStart) { + child.intersectsChange = true; + child._children = undefined; + // Adjust the pos or end (or both) of the intersecting element accordingly. + adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta); + forEachChild(child, visitNode, visitArray); + checkNodePositions(child, aggressiveChecks); + return; + } + // Otherwise, the node is entirely before the change range. No need to do anything with it. + ts.Debug.assert(fullEnd < changeStart); + } + function visitArray(array) { + ts.Debug.assert(array.pos <= array.end); + if (array.pos > changeRangeOldEnd) { + // Array is entirely after the change range. We need to move it, and move any of + // its children. + moveElementEntirelyPastChangeRange(array, /*isArray*/ true, delta, oldText, newText, aggressiveChecks); + return; + } + // Check if the element intersects the change range. If it does, then it is not + // reusable. Also, we'll need to recurse to see what constituent portions we may + // be able to use. + var fullEnd = array.end; + if (fullEnd >= changeStart) { + array.intersectsChange = true; + array._children = undefined; + // Adjust the pos or end (or both) of the intersecting array accordingly. + adjustIntersectingElement(array, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta); + for (var _i = 0, array_9 = array; _i < array_9.length; _i++) { + var node = array_9[_i]; + visitNode(node); + } + return; + } + // Otherwise, the array is entirely before the change range. No need to do anything with it. + ts.Debug.assert(fullEnd < changeStart); + } + } + function extendToAffectedRange(sourceFile, changeRange) { + // Consider the following code: + // void foo() { /; } + // + // If the text changes with an insertion of / just before the semicolon then we end up with: + // void foo() { //; } + // + // If we were to just use the changeRange a is, then we would not rescan the { token + // (as it does not intersect the actual original change range). Because an edit may + // change the token touching it, we actually need to look back *at least* one token so + // that the prior token sees that change. + var maxLookahead = 1; + var start = changeRange.span.start; + // the first iteration aligns us with the change start. subsequent iteration move us to + // the left by maxLookahead tokens. We only need to do this as long as we're not at the + // start of the tree. + for (var i = 0; start > 0 && i <= maxLookahead; i++) { + var nearestNode = findNearestNodeStartingBeforeOrAtPosition(sourceFile, start); + ts.Debug.assert(nearestNode.pos <= start); + var position = nearestNode.pos; + start = Math.max(0, position - 1); + } + var finalSpan = ts.createTextSpanFromBounds(start, ts.textSpanEnd(changeRange.span)); + var finalLength = changeRange.newLength + (changeRange.span.start - start); + return ts.createTextChangeRange(finalSpan, finalLength); + } + function findNearestNodeStartingBeforeOrAtPosition(sourceFile, position) { + var bestResult = sourceFile; + var lastNodeEntirelyBeforePosition; + forEachChild(sourceFile, visit); + if (lastNodeEntirelyBeforePosition) { + var lastChildOfLastEntireNodeBeforePosition = getLastChild(lastNodeEntirelyBeforePosition); + if (lastChildOfLastEntireNodeBeforePosition.pos > bestResult.pos) { + bestResult = lastChildOfLastEntireNodeBeforePosition; } - function addTag(tag) { - if (tag) { - if (!tags) { - tags = []; - tags.pos = tag.pos; - } - tags.push(tag); - tags.end = tag.end; + } + return bestResult; + function getLastChild(node) { + while (true) { + var lastChild = getLastChildWorker(node); + if (lastChild) { + node = lastChild; } - } - function tryParseTypeExpression() { - if (token() !== 15 /* OpenBraceToken */) { - return undefined; + else { + return node; } - var typeExpression = parseJSDocTypeExpression(); - return typeExpression; } - function handleParamTag(atToken, tagName) { - var typeExpression = tryParseTypeExpression(); - skipWhitespace(); - var name; - var isBracketed; - // Looking for something like '[foo]' or 'foo' - if (parseOptionalToken(19 /* OpenBracketToken */)) { - name = parseJSDocIdentifierName(); - isBracketed = true; - // May have an optional default, e.g. '[foo = 42]' - if (parseOptionalToken(56 /* EqualsToken */)) { - parseExpression(); - } - parseExpected(20 /* CloseBracketToken */); - } - else if (ts.tokenIsIdentifierOrKeyword(token())) { - name = parseJSDocIdentifierName(); + } + function getLastChildWorker(node) { + var last = undefined; + forEachChild(node, function (child) { + if (ts.nodeIsPresent(child)) { + last = child; } - if (!name) { - parseErrorAtPosition(scanner.getStartPos(), 0, ts.Diagnostics.Identifier_expected); - return undefined; + }); + return last; + } + function visit(child) { + if (ts.nodeIsMissing(child)) { + // Missing nodes are effectively invisible to us. We never even consider them + // When trying to find the nearest node before us. + return; + } + // If the child intersects this position, then this node is currently the nearest + // node that starts before the position. + if (child.pos <= position) { + if (child.pos >= bestResult.pos) { + // This node starts before the position, and is closer to the position than + // the previous best node we found. It is now the new best node. + bestResult = child; } - var preName, postName; - if (typeExpression) { - postName = name; + // Now, the node may overlap the position, or it may end entirely before the + // position. If it overlaps with the position, then either it, or one of its + // children must be the nearest node before the position. So we can just + // recurse into this child to see if we can find something better. + if (position < child.end) { + // The nearest node is either this child, or one of the children inside + // of it. We've already marked this child as the best so far. Recurse + // in case one of the children is better. + forEachChild(child, visit); + // Once we look at the children of this node, then there's no need to + // continue any further. + return true; } else { - preName = name; - } - if (!typeExpression) { - typeExpression = tryParseTypeExpression(); + ts.Debug.assert(child.end <= position); + // The child ends entirely before this position. Say you have the following + // (where $ is the position) + // + // ? $ : <...> <...> + // + // We would want to find the nearest preceding node in "complex expr 2". + // To support that, we keep track of this node, and once we're done searching + // for a best node, we recurse down this node to see if we can find a good + // result in it. + // + // This approach allows us to quickly skip over nodes that are entirely + // before the position, while still allowing us to find any nodes in the + // last one that might be what we want. + lastNodeEntirelyBeforePosition = child; } - var result = createNode(275 /* JSDocParameterTag */, atToken.pos); - result.atToken = atToken; - result.tagName = tagName; - result.preParameterName = preName; - result.typeExpression = typeExpression; - result.postParameterName = postName; - result.isBracketed = isBracketed; - return finishNode(result); } - function handleReturnTag(atToken, tagName) { - if (ts.forEach(tags, function (t) { return t.kind === 276 /* JSDocReturnTag */; })) { - parseErrorAtPosition(tagName.pos, scanner.getTokenPos() - tagName.pos, ts.Diagnostics._0_tag_already_specified, tagName.text); - } - var result = createNode(276 /* JSDocReturnTag */, atToken.pos); - result.atToken = atToken; - result.tagName = tagName; - result.typeExpression = tryParseTypeExpression(); - return finishNode(result); + else { + ts.Debug.assert(child.pos > position); + // We're now at a node that is entirely past the position we're searching for. + // This node (and all following nodes) could never contribute to the result, + // so just skip them by returning 'true' here. + return true; } - function handleTypeTag(atToken, tagName) { - if (ts.forEach(tags, function (t) { return t.kind === 277 /* JSDocTypeTag */; })) { - parseErrorAtPosition(tagName.pos, scanner.getTokenPos() - tagName.pos, ts.Diagnostics._0_tag_already_specified, tagName.text); + } + } + function checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks) { + var oldText = sourceFile.text; + if (textChangeRange) { + ts.Debug.assert((oldText.length - textChangeRange.span.length + textChangeRange.newLength) === newText.length); + if (aggressiveChecks || ts.Debug.shouldAssert(3 /* VeryAggressive */)) { + var oldTextPrefix = oldText.substr(0, textChangeRange.span.start); + var newTextPrefix = newText.substr(0, textChangeRange.span.start); + ts.Debug.assert(oldTextPrefix === newTextPrefix); + var oldTextSuffix = oldText.substring(ts.textSpanEnd(textChangeRange.span), oldText.length); + var newTextSuffix = newText.substring(ts.textSpanEnd(ts.textChangeRangeNewSpan(textChangeRange)), newText.length); + ts.Debug.assert(oldTextSuffix === newTextSuffix); + } + } + } + function createSyntaxCursor(sourceFile) { + var currentArray = sourceFile.statements; + var currentArrayIndex = 0; + ts.Debug.assert(currentArrayIndex < currentArray.length); + var current = currentArray[currentArrayIndex]; + var lastQueriedPosition = -1 /* Value */; + return { + currentNode: function (position) { + // Only compute the current node if the position is different than the last time + // we were asked. The parser commonly asks for the node at the same position + // twice. Once to know if can read an appropriate list element at a certain point, + // and then to actually read and consume the node. + if (position !== lastQueriedPosition) { + // Much of the time the parser will need the very next node in the array that + // we just returned a node from.So just simply check for that case and move + // forward in the array instead of searching for the node again. + if (current && current.end === position && currentArrayIndex < (currentArray.length - 1)) { + currentArrayIndex++; + current = currentArray[currentArrayIndex]; + } + // If we don't have a node, or the node we have isn't in the right position, + // then try to find a viable node at the position requested. + if (!current || current.pos !== position) { + findHighestListElementThatStartsAtPosition(position); + } } - var result = createNode(277 /* JSDocTypeTag */, atToken.pos); - result.atToken = atToken; - result.tagName = tagName; - result.typeExpression = tryParseTypeExpression(); - return finishNode(result); + // Cache this query so that we don't do any extra work if the parser calls back + // into us. Note: this is very common as the parser will make pairs of calls like + // 'isListElement -> parseListElement'. If we were unable to find a node when + // called with 'isListElement', we don't want to redo the work when parseListElement + // is called immediately after. + lastQueriedPosition = position; + // Either we don'd have a node, or we have a node at the position being asked for. + ts.Debug.assert(!current || current.pos === position); + return current; } - function handlePropertyTag(atToken, tagName) { - var typeExpression = tryParseTypeExpression(); - skipWhitespace(); - var name = parseJSDocIdentifierName(); - if (!name) { - parseErrorAtPosition(scanner.getStartPos(), /*length*/ 0, ts.Diagnostics.Identifier_expected); - return undefined; + }; + // Finds the highest element in the tree we can find that starts at the provided position. + // The element must be a direct child of some node list in the tree. This way after we + // return it, we can easily return its next sibling in the list. + function findHighestListElementThatStartsAtPosition(position) { + // Clear out any cached state about the last node we found. + currentArray = undefined; + currentArrayIndex = -1 /* Value */; + current = undefined; + // Recurse into the source file to find the highest node at this position. + forEachChild(sourceFile, visitNode, visitArray); + return; + function visitNode(node) { + if (position >= node.pos && position < node.end) { + // Position was within this node. Keep searching deeper to find the node. + forEachChild(node, visitNode, visitArray); + // don't proceed any further in the search. + return true; } - var result = createNode(280 /* JSDocPropertyTag */, atToken.pos); - result.atToken = atToken; - result.tagName = tagName; - result.name = name; - result.typeExpression = typeExpression; - return finishNode(result); + // position wasn't in this node, have to keep searching. + return false; } - function handleTypedefTag(atToken, tagName) { - var typeExpression = tryParseTypeExpression(); - skipWhitespace(); - var typedefTag = createNode(279 /* JSDocTypedefTag */, atToken.pos); - typedefTag.atToken = atToken; - typedefTag.tagName = tagName; - typedefTag.name = parseJSDocIdentifierName(); - typedefTag.typeExpression = typeExpression; - if (typeExpression) { - if (typeExpression.type.kind === 267 /* JSDocTypeReference */) { - var jsDocTypeReference = typeExpression.type; - if (jsDocTypeReference.name.kind === 69 /* Identifier */) { - var name_8 = jsDocTypeReference.name; - if (name_8.text === "Object") { - typedefTag.jsDocTypeLiteral = scanChildTags(); + function visitArray(array) { + if (position >= array.pos && position < array.end) { + // position was in this array. Search through this array to see if we find a + // viable element. + for (var i = 0, n = array.length; i < n; i++) { + var child = array[i]; + if (child) { + if (child.pos === position) { + // Found the right node. We're done. + currentArray = array; + currentArrayIndex = i; + current = child; + return true; + } + else { + if (child.pos < position && position < child.end) { + // Position in somewhere within this child. Search in it and + // stop searching in this array. + forEachChild(child, visitNode, visitArray); + return true; + } } } } - if (!typedefTag.jsDocTypeLiteral) { - typedefTag.jsDocTypeLiteral = typeExpression.type; - } } - else { - typedefTag.jsDocTypeLiteral = scanChildTags(); + // position wasn't in this array, have to keep searching. + return false; + } + } + } + var InvalidPosition; + (function (InvalidPosition) { + InvalidPosition[InvalidPosition["Value"] = -1] = "Value"; + })(InvalidPosition || (InvalidPosition = {})); + })(IncrementalParser || (IncrementalParser = {})); +})(ts || (ts = {})); +/// +/// +/* @internal */ +var ts; +(function (ts) { + (function (ModuleInstanceState) { + ModuleInstanceState[ModuleInstanceState["NonInstantiated"] = 0] = "NonInstantiated"; + ModuleInstanceState[ModuleInstanceState["Instantiated"] = 1] = "Instantiated"; + ModuleInstanceState[ModuleInstanceState["ConstEnumOnly"] = 2] = "ConstEnumOnly"; + })(ts.ModuleInstanceState || (ts.ModuleInstanceState = {})); + var ModuleInstanceState = ts.ModuleInstanceState; + function getModuleInstanceState(node) { + // A module is uninstantiated if it contains only + // 1. interface declarations, type alias declarations + if (node.kind === 222 /* InterfaceDeclaration */ || node.kind === 223 /* TypeAliasDeclaration */) { + return 0 /* NonInstantiated */; + } + else if (ts.isConstEnumDeclaration(node)) { + return 2 /* ConstEnumOnly */; + } + else if ((node.kind === 230 /* ImportDeclaration */ || node.kind === 229 /* ImportEqualsDeclaration */) && !(ts.hasModifier(node, 1 /* Export */))) { + return 0 /* NonInstantiated */; + } + else if (node.kind === 226 /* ModuleBlock */) { + var state_1 = 0 /* NonInstantiated */; + ts.forEachChild(node, function (n) { + switch (getModuleInstanceState(n)) { + case 0 /* NonInstantiated */: + // child is non-instantiated - continue searching + return false; + case 2 /* ConstEnumOnly */: + // child is const enum only - record state and continue searching + state_1 = 2 /* ConstEnumOnly */; + return false; + case 1 /* Instantiated */: + // child is instantiated - record state and stop + state_1 = 1 /* Instantiated */; + return true; + } + }); + return state_1; + } + else if (node.kind === 225 /* ModuleDeclaration */) { + var body = node.body; + return body ? getModuleInstanceState(body) : 1 /* Instantiated */; + } + else { + return 1 /* Instantiated */; + } + } + ts.getModuleInstanceState = getModuleInstanceState; + var ContainerFlags; + (function (ContainerFlags) { + // The current node is not a container, and no container manipulation should happen before + // recursing into it. + ContainerFlags[ContainerFlags["None"] = 0] = "None"; + // The current node is a container. It should be set as the current container (and block- + // container) before recursing into it. The current node does not have locals. Examples: + // + // Classes, ObjectLiterals, TypeLiterals, Interfaces... + ContainerFlags[ContainerFlags["IsContainer"] = 1] = "IsContainer"; + // The current node is a block-scoped-container. It should be set as the current block- + // container before recursing into it. Examples: + // + // Blocks (when not parented by functions), Catch clauses, For/For-in/For-of statements... + ContainerFlags[ContainerFlags["IsBlockScopedContainer"] = 2] = "IsBlockScopedContainer"; + // The current node is the container of a control flow path. The current control flow should + // be saved and restored, and a new control flow initialized within the container. + ContainerFlags[ContainerFlags["IsControlFlowContainer"] = 4] = "IsControlFlowContainer"; + ContainerFlags[ContainerFlags["IsFunctionLike"] = 8] = "IsFunctionLike"; + ContainerFlags[ContainerFlags["IsFunctionExpression"] = 16] = "IsFunctionExpression"; + ContainerFlags[ContainerFlags["HasLocals"] = 32] = "HasLocals"; + ContainerFlags[ContainerFlags["IsInterface"] = 64] = "IsInterface"; + })(ContainerFlags || (ContainerFlags = {})); + var binder = createBinder(); + function bindSourceFile(file, options) { + ts.performance.mark("beforeBind"); + binder(file, options); + ts.performance.mark("afterBind"); + ts.performance.measure("Bind", "beforeBind", "afterBind"); + } + ts.bindSourceFile = bindSourceFile; + function createBinder() { + var file; + var options; + var languageVersion; + var parent; + var container; + var blockScopeContainer; + var lastContainer; + var seenThisKeyword; + // state used by control flow analysis + var currentFlow; + var currentBreakTarget; + var currentContinueTarget; + var currentReturnTarget; + var currentTrueTarget; + var currentFalseTarget; + var preSwitchCaseFlow; + var activeLabels; + var hasExplicitReturn; + // state used for emit helpers + var emitFlags; + // If this file is an external module, then it is automatically in strict-mode according to + // ES6. If it is not an external module, then we'll determine if it is in strict mode or + // not depending on if we see "use strict" in certain places (or if we hit a class/namespace). + var inStrictMode; + var symbolCount = 0; + var Symbol; + var classifiableNames; + var unreachableFlow = { flags: 1 /* Unreachable */ }; + var reportedUnreachableFlow = { flags: 1 /* Unreachable */ }; + // state used to aggregate transform flags during bind. + var subtreeTransformFlags = 0 /* None */; + var skipTransformFlagAggregation; + function bindSourceFile(f, opts) { + file = f; + options = opts; + languageVersion = ts.getEmitScriptTarget(options); + inStrictMode = !!file.externalModuleIndicator; + classifiableNames = ts.createMap(); + symbolCount = 0; + skipTransformFlagAggregation = ts.isDeclarationFile(file); + Symbol = ts.objectAllocator.getSymbolConstructor(); + if (!file.locals) { + bind(file); + file.symbolCount = symbolCount; + file.classifiableNames = classifiableNames; + } + file = undefined; + options = undefined; + languageVersion = undefined; + parent = undefined; + container = undefined; + blockScopeContainer = undefined; + lastContainer = undefined; + seenThisKeyword = false; + currentFlow = undefined; + currentBreakTarget = undefined; + currentContinueTarget = undefined; + currentReturnTarget = undefined; + currentTrueTarget = undefined; + currentFalseTarget = undefined; + activeLabels = undefined; + hasExplicitReturn = false; + emitFlags = 0 /* None */; + subtreeTransformFlags = 0 /* None */; + } + return bindSourceFile; + function createSymbol(flags, name) { + symbolCount++; + return new Symbol(flags, name); + } + function addDeclarationToSymbol(symbol, node, symbolFlags) { + symbol.flags |= symbolFlags; + node.symbol = symbol; + if (!symbol.declarations) { + symbol.declarations = []; + } + symbol.declarations.push(node); + if (symbolFlags & 1952 /* HasExports */ && !symbol.exports) { + symbol.exports = ts.createMap(); + } + if (symbolFlags & 6240 /* HasMembers */ && !symbol.members) { + symbol.members = ts.createMap(); + } + if (symbolFlags & 107455 /* Value */) { + var valueDeclaration = symbol.valueDeclaration; + if (!valueDeclaration || + (valueDeclaration.kind !== node.kind && valueDeclaration.kind === 225 /* ModuleDeclaration */)) { + // other kinds of value declarations take precedence over modules + symbol.valueDeclaration = node; + } + } + } + // Should not be called on a declaration with a computed property name, + // unless it is a well known Symbol. + function getDeclarationName(node) { + if (node.name) { + if (ts.isAmbientModule(node)) { + return ts.isGlobalScopeAugmentation(node) ? "__global" : "\"" + node.name.text + "\""; + } + if (node.name.kind === 140 /* ComputedPropertyName */) { + var nameExpression = node.name.expression; + // treat computed property names where expression is string/numeric literal as just string/numeric literal + if (ts.isStringOrNumericLiteral(nameExpression.kind)) { + return nameExpression.text; } - return finishNode(typedefTag); - function scanChildTags() { - var jsDocTypeLiteral = createNode(281 /* JSDocTypeLiteral */, scanner.getStartPos()); - var resumePos = scanner.getStartPos(); - var canParseTag = true; - var seenAsterisk = false; - var parentTagTerminated = false; - while (token() !== 1 /* EndOfFileToken */ && !parentTagTerminated) { - nextJSDocToken(); - switch (token()) { - case 55 /* AtToken */: - if (canParseTag) { - parentTagTerminated = !tryParseChildTag(jsDocTypeLiteral); - if (!parentTagTerminated) { - resumePos = scanner.getStartPos(); - } - } - seenAsterisk = false; - break; - case 4 /* NewLineTrivia */: - resumePos = scanner.getStartPos() - 1; - canParseTag = true; - seenAsterisk = false; - break; - case 37 /* AsteriskToken */: - if (seenAsterisk) { - canParseTag = false; - } - seenAsterisk = true; - break; - case 69 /* Identifier */: - canParseTag = false; - case 1 /* EndOfFileToken */: - break; + ts.Debug.assert(ts.isWellKnownSymbolSyntactically(nameExpression)); + return ts.getPropertyNameForKnownSymbolName(nameExpression.name.text); + } + return node.name.text; + } + switch (node.kind) { + case 148 /* Constructor */: + return "__constructor"; + case 156 /* FunctionType */: + case 151 /* CallSignature */: + return "__call"; + case 157 /* ConstructorType */: + case 152 /* ConstructSignature */: + return "__new"; + case 153 /* IndexSignature */: + return "__index"; + case 236 /* ExportDeclaration */: + return "__export"; + case 235 /* ExportAssignment */: + return node.isExportEquals ? "export=" : "default"; + case 187 /* BinaryExpression */: + switch (ts.getSpecialPropertyAssignmentKind(node)) { + case 2 /* ModuleExports */: + // module.exports = ... + return "export="; + case 1 /* ExportsProperty */: + case 4 /* ThisProperty */: + // exports.x = ... or this.y = ... + return node.left.name.text; + case 3 /* PrototypeProperty */: + // className.prototype.methodName = ... + return node.left.expression.name.text; + } + ts.Debug.fail("Unknown binary declaration kind"); + break; + case 220 /* FunctionDeclaration */: + case 221 /* ClassDeclaration */: + return ts.hasModifier(node, 512 /* Default */) ? "default" : undefined; + case 269 /* JSDocFunctionType */: + return ts.isJSDocConstructSignature(node) ? "__new" : "__call"; + case 142 /* Parameter */: + // Parameters with names are handled at the top of this function. Parameters + // without names can only come from JSDocFunctionTypes. + ts.Debug.assert(node.parent.kind === 269 /* JSDocFunctionType */); + var functionType = node.parent; + var index = ts.indexOf(functionType.parameters, node); + return "arg" + index; + case 279 /* JSDocTypedefTag */: + var parentNode = node.parent && node.parent.parent; + var nameFromParentNode = void 0; + if (parentNode && parentNode.kind === 200 /* VariableStatement */) { + if (parentNode.declarationList.declarations.length > 0) { + var nameIdentifier = parentNode.declarationList.declarations[0].name; + if (nameIdentifier.kind === 69 /* Identifier */) { + nameFromParentNode = nameIdentifier.text; } } - scanner.setTextPos(resumePos); - return finishNode(jsDocTypeLiteral); } + return nameFromParentNode; + } + } + function getDisplayName(node) { + return node.name ? ts.declarationNameToString(node.name) : getDeclarationName(node); + } + /** + * Declares a Symbol for the node and adds it to symbols. Reports errors for conflicting identifier names. + * @param symbolTable - The symbol table which node will be added to. + * @param parent - node's parent declaration. + * @param node - The declaration to be added to the symbol table + * @param includes - The SymbolFlags that node has in addition to its declaration type (eg: export, ambient, etc.) + * @param excludes - The flags which node cannot be declared alongside in a symbol table. Used to report forbidden declarations. + */ + function declareSymbol(symbolTable, parent, node, includes, excludes) { + ts.Debug.assert(!ts.hasDynamicName(node)); + var isDefaultExport = ts.hasModifier(node, 512 /* Default */); + // The exported symbol for an export default function/class node is always named "default" + var name = isDefaultExport && parent ? "default" : getDeclarationName(node); + var symbol; + if (name === undefined) { + symbol = createSymbol(0 /* None */, "__missing"); + } + else { + // Check and see if the symbol table already has a symbol with this name. If not, + // create a new symbol with this name and add it to the table. Note that we don't + // give the new symbol any flags *yet*. This ensures that it will not conflict + // with the 'excludes' flags we pass in. + // + // If we do get an existing symbol, see if it conflicts with the new symbol we're + // creating. For example, a 'var' symbol and a 'class' symbol will conflict within + // the same symbol table. If we have a conflict, report the issue on each + // declaration we have for this symbol, and then create a new symbol for this + // declaration. + // + // Note that when properties declared in Javascript constructors + // (marked by isReplaceableByMethod) conflict with another symbol, the property loses. + // Always. This allows the common Javascript pattern of overwriting a prototype method + // with an bound instance method of the same type: `this.method = this.method.bind(this)` + // + // If we created a new symbol, either because we didn't have a symbol with this name + // in the symbol table, or we conflicted with an existing symbol, then just add this + // node as the sole declaration of the new symbol. + // + // Otherwise, we'll be merging into a compatible existing symbol (for example when + // you have multiple 'vars' with the same name in the same container). In this case + // just add this node into the declarations list of the symbol. + symbol = symbolTable[name] || (symbolTable[name] = createSymbol(0 /* None */, name)); + if (name && (includes & 788448 /* Classifiable */)) { + classifiableNames[name] = name; } - function tryParseChildTag(parentTag) { - ts.Debug.assert(token() === 55 /* AtToken */); - var atToken = createNode(55 /* AtToken */, scanner.getStartPos()); - atToken.end = scanner.getTextPos(); - nextJSDocToken(); - var tagName = parseJSDocIdentifierName(); - if (!tagName) { - return false; + if (symbol.flags & excludes) { + if (symbol.isReplaceableByMethod) { + // Javascript constructor-declared symbols can be discarded in favor of + // prototype symbols like methods. + symbol = symbolTable[name] = createSymbol(0 /* None */, name); } - switch (tagName.text) { - case "type": - if (parentTag.jsDocTypeTag) { - // already has a @type tag, terminate the parent tag now. - return false; - } - parentTag.jsDocTypeTag = handleTypeTag(atToken, tagName); - return true; - case "prop": - case "property": - if (!parentTag.jsDocPropertyTags) { - parentTag.jsDocPropertyTags = []; + else { + if (node.name) { + node.name.parent = node; + } + // Report errors every position with duplicate declaration + // Report errors on previous encountered declarations + var message_1 = symbol.flags & 2 /* BlockScopedVariable */ + ? ts.Diagnostics.Cannot_redeclare_block_scoped_variable_0 + : ts.Diagnostics.Duplicate_identifier_0; + ts.forEach(symbol.declarations, function (declaration) { + if (ts.hasModifier(declaration, 512 /* Default */)) { + message_1 = ts.Diagnostics.A_module_cannot_have_multiple_default_exports; } - var propertyTag = handlePropertyTag(atToken, tagName); - parentTag.jsDocPropertyTags.push(propertyTag); - return true; + }); + ts.forEach(symbol.declarations, function (declaration) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(declaration.name || declaration, message_1, getDisplayName(declaration))); + }); + file.bindDiagnostics.push(ts.createDiagnosticForNode(node.name || node, message_1, getDisplayName(node))); + symbol = createSymbol(0 /* None */, name); } - return false; } - function handleTemplateTag(atToken, tagName) { - if (ts.forEach(tags, function (t) { return t.kind === 278 /* JSDocTemplateTag */; })) { - parseErrorAtPosition(tagName.pos, scanner.getTokenPos() - tagName.pos, ts.Diagnostics._0_tag_already_specified, tagName.text); - } - // Type parameter list looks like '@template T,U,V' - var typeParameters = []; - typeParameters.pos = scanner.getStartPos(); - while (true) { - var name_9 = parseJSDocIdentifierName(); - if (!name_9) { - parseErrorAtPosition(scanner.getStartPos(), 0, ts.Diagnostics.Identifier_expected); - return undefined; - } - var typeParameter = createNode(141 /* TypeParameter */, name_9.pos); - typeParameter.name = name_9; - finishNode(typeParameter); - typeParameters.push(typeParameter); - if (token() === 24 /* CommaToken */) { - nextJSDocToken(); - } - else { - break; - } - } - var result = createNode(278 /* JSDocTemplateTag */, atToken.pos); - result.atToken = atToken; - result.tagName = tagName; - result.typeParameters = typeParameters; - finishNode(result); - typeParameters.end = result.end; - return result; + } + addDeclarationToSymbol(symbol, node, includes); + symbol.parent = parent; + return symbol; + } + function declareModuleMember(node, symbolFlags, symbolExcludes) { + var hasExportModifier = ts.getCombinedModifierFlags(node) & 1 /* Export */; + if (symbolFlags & 8388608 /* Alias */) { + if (node.kind === 238 /* ExportSpecifier */ || (node.kind === 229 /* ImportEqualsDeclaration */ && hasExportModifier)) { + return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); } - function nextJSDocToken() { - return currentToken = scanner.scanJSDocToken(); + else { + return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); } - function parseJSDocIdentifierName() { - return createJSDocIdentifier(ts.tokenIsIdentifierOrKeyword(token())); + } + else { + // Exported module members are given 2 symbols: A local symbol that is classified with an ExportValue, + // ExportType, or ExportContainer flag, and an associated export symbol with all the correct flags set + // on it. There are 2 main reasons: + // + // 1. We treat locals and exports of the same name as mutually exclusive within a container. + // That means the binder will issue a Duplicate Identifier error if you mix locals and exports + // with the same name in the same container. + // TODO: Make this a more specific error and decouple it from the exclusion logic. + // 2. When we checkIdentifier in the checker, we set its resolved symbol to the local symbol, + // but return the export symbol (by calling getExportSymbolOfValueSymbolIfExported). That way + // when the emitter comes back to it, it knows not to qualify the name if it was found in a containing scope. + // NOTE: Nested ambient modules always should go to to 'locals' table to prevent their automatic merge + // during global merging in the checker. Why? The only case when ambient module is permitted inside another module is module augmentation + // and this case is specially handled. Module augmentations should only be merged with original module definition + // and should never be merged directly with other augmentation, and the latter case would be possible if automatic merge is allowed. + if (!ts.isAmbientModule(node) && (hasExportModifier || container.flags & 32 /* ExportContext */)) { + var exportKind = (symbolFlags & 107455 /* Value */ ? 1048576 /* ExportValue */ : 0) | + (symbolFlags & 793064 /* Type */ ? 2097152 /* ExportType */ : 0) | + (symbolFlags & 1920 /* Namespace */ ? 4194304 /* ExportNamespace */ : 0); + var local = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes); + local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); + node.localSymbol = local; + return local; } - function createJSDocIdentifier(isIdentifier) { - if (!isIdentifier) { - parseErrorAtCurrentToken(ts.Diagnostics.Identifier_expected); - return undefined; - } - var pos = scanner.getTokenPos(); - var end = scanner.getTextPos(); - var result = createNode(69 /* Identifier */, pos); - result.text = content.substring(pos, end); - finishNode(result, end); - nextJSDocToken(); - return result; + else { + return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); } } - JSDocParser.parseJSDocCommentWorker = parseJSDocCommentWorker; - })(JSDocParser = Parser.JSDocParser || (Parser.JSDocParser = {})); - })(Parser || (Parser = {})); - var IncrementalParser; - (function (IncrementalParser) { - function updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks) { - aggressiveChecks = aggressiveChecks || ts.Debug.shouldAssert(2 /* Aggressive */); - checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks); - if (ts.textChangeRangeIsUnchanged(textChangeRange)) { - // if the text didn't change, then we can just return our current source file as-is. - return sourceFile; - } - if (sourceFile.statements.length === 0) { - // If we don't have any statements in the current source file, then there's no real - // way to incrementally parse. So just do a full parse instead. - return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setParentNodes*/ true, sourceFile.scriptKind); - } - // Make sure we're not trying to incrementally update a source file more than once. Once - // we do an update the original source file is considered unusable from that point onwards. - // - // This is because we do incremental parsing in-place. i.e. we take nodes from the old - // tree and give them new positions and parents. From that point on, trusting the old - // tree at all is not possible as far too much of it may violate invariants. - var incrementalSourceFile = sourceFile; - ts.Debug.assert(!incrementalSourceFile.hasBeenIncrementallyParsed); - incrementalSourceFile.hasBeenIncrementallyParsed = true; - var oldText = sourceFile.text; - var syntaxCursor = createSyntaxCursor(sourceFile); - // Make the actual change larger so that we know to reparse anything whose lookahead - // might have intersected the change. - var changeRange = extendToAffectedRange(sourceFile, textChangeRange); - checkChangeRange(sourceFile, newText, changeRange, aggressiveChecks); - // Ensure that extending the affected range only moved the start of the change range - // earlier in the file. - ts.Debug.assert(changeRange.span.start <= textChangeRange.span.start); - ts.Debug.assert(ts.textSpanEnd(changeRange.span) === ts.textSpanEnd(textChangeRange.span)); - ts.Debug.assert(ts.textSpanEnd(ts.textChangeRangeNewSpan(changeRange)) === ts.textSpanEnd(ts.textChangeRangeNewSpan(textChangeRange))); - // The is the amount the nodes after the edit range need to be adjusted. It can be - // positive (if the edit added characters), negative (if the edit deleted characters) - // or zero (if this was a pure overwrite with nothing added/removed). - var delta = ts.textChangeRangeNewSpan(changeRange).length - changeRange.span.length; - // If we added or removed characters during the edit, then we need to go and adjust all - // the nodes after the edit. Those nodes may move forward (if we inserted chars) or they - // may move backward (if we deleted chars). - // - // Doing this helps us out in two ways. First, it means that any nodes/tokens we want - // to reuse are already at the appropriate position in the new text. That way when we - // reuse them, we don't have to figure out if they need to be adjusted. Second, it makes - // it very easy to determine if we can reuse a node. If the node's position is at where - // we are in the text, then we can reuse it. Otherwise we can't. If the node's position - // is ahead of us, then we'll need to rescan tokens. If the node's position is behind - // us, then we'll need to skip it or crumble it as appropriate - // - // We will also adjust the positions of nodes that intersect the change range as well. - // By doing this, we ensure that all the positions in the old tree are consistent, not - // just the positions of nodes entirely before/after the change range. By being - // consistent, we can then easily map from positions to nodes in the old tree easily. + } + // All container nodes are kept on a linked list in declaration order. This list is used by + // the getLocalNameOfContainer function in the type checker to validate that the local name + // used for a container is unique. + function bindContainer(node, containerFlags) { + // Before we recurse into a node's children, we first save the existing parent, container + // and block-container. Then after we pop out of processing the children, we restore + // these saved values. + var saveContainer = container; + var savedBlockScopeContainer = blockScopeContainer; + // Depending on what kind of node this is, we may have to adjust the current container + // and block-container. If the current node is a container, then it is automatically + // considered the current block-container as well. Also, for containers that we know + // may contain locals, we proactively initialize the .locals field. We do this because + // it's highly likely that the .locals will be needed to place some child in (for example, + // a parameter, or variable declaration). // - // Also, mark any syntax elements that intersect the changed span. We know, up front, - // that we cannot reuse these elements. - updateTokenPositionsAndMarkElements(incrementalSourceFile, changeRange.span.start, ts.textSpanEnd(changeRange.span), ts.textSpanEnd(ts.textChangeRangeNewSpan(changeRange)), delta, oldText, newText, aggressiveChecks); - // Now that we've set up our internal incremental state just proceed and parse the - // source file in the normal fashion. When possible the parser will retrieve and - // reuse nodes from the old tree. + // However, we do not proactively create the .locals for block-containers because it's + // totally normal and common for block-containers to never actually have a block-scoped + // variable in them. We don't want to end up allocating an object for every 'block' we + // run into when most of them won't be necessary. // - // Note: passing in 'true' for setNodeParents is very important. When incrementally - // parsing, we will be reusing nodes from the old tree, and placing it into new - // parents. If we don't set the parents now, we'll end up with an observably - // inconsistent tree. Setting the parents on the new tree should be very fast. We - // will immediately bail out of walking any subtrees when we can see that their parents - // are already correct. - var result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /*setParentNodes*/ true, sourceFile.scriptKind); - return result; - } - IncrementalParser.updateSourceFile = updateSourceFile; - function moveElementEntirelyPastChangeRange(element, isArray, delta, oldText, newText, aggressiveChecks) { - if (isArray) { - visitArray(element); + // Finally, if this is a block-container, then we clear out any existing .locals object + // it may contain within it. This happens in incremental scenarios. Because we can be + // reusing a node from a previous compilation, that node may have had 'locals' created + // for it. We must clear this so we don't accidentally move any stale data forward from + // a previous compilation. + if (containerFlags & 1 /* IsContainer */) { + container = blockScopeContainer = node; + if (containerFlags & 32 /* HasLocals */) { + container.locals = ts.createMap(); + } + addToContainerChain(container); } - else { - visitNode(element); + else if (containerFlags & 2 /* IsBlockScopedContainer */) { + blockScopeContainer = node; + blockScopeContainer.locals = undefined; } - return; - function visitNode(node) { - var text = ""; - if (aggressiveChecks && shouldCheckNode(node)) { - text = oldText.substring(node.pos, node.end); + if (containerFlags & 4 /* IsControlFlowContainer */) { + var saveCurrentFlow = currentFlow; + var saveBreakTarget = currentBreakTarget; + var saveContinueTarget = currentContinueTarget; + var saveReturnTarget = currentReturnTarget; + var saveActiveLabels = activeLabels; + var saveHasExplicitReturn = hasExplicitReturn; + var isIIFE = containerFlags & 16 /* IsFunctionExpression */ && !!ts.getImmediatelyInvokedFunctionExpression(node); + // An IIFE is considered part of the containing control flow. Return statements behave + // similarly to break statements that exit to a label just past the statement body. + if (isIIFE) { + currentReturnTarget = createBranchLabel(); } - // Ditch any existing LS children we may have created. This way we can avoid - // moving them forward. - if (node._children) { - node._children = undefined; + else { + currentFlow = { flags: 2 /* Start */ }; + if (containerFlags & 16 /* IsFunctionExpression */) { + currentFlow.container = node; + } + currentReturnTarget = undefined; } - node.pos += delta; - node.end += delta; - if (aggressiveChecks && shouldCheckNode(node)) { - ts.Debug.assert(text === newText.substring(node.pos, node.end)); + currentBreakTarget = undefined; + currentContinueTarget = undefined; + activeLabels = undefined; + hasExplicitReturn = false; + bindChildren(node); + // Reset all reachability check related flags on node (for incremental scenarios) + // Reset all emit helper flags on node (for incremental scenarios) + node.flags &= ~32128 /* ReachabilityAndEmitFlags */; + if (!(currentFlow.flags & 1 /* Unreachable */) && containerFlags & 8 /* IsFunctionLike */ && ts.nodeIsPresent(node.body)) { + node.flags |= 128 /* HasImplicitReturn */; + if (hasExplicitReturn) + node.flags |= 256 /* HasExplicitReturn */; } - forEachChild(node, visitNode, visitArray); - if (node.jsDocComments) { - for (var _i = 0, _a = node.jsDocComments; _i < _a.length; _i++) { - var jsDocComment = _a[_i]; - forEachChild(jsDocComment, visitNode, visitArray); - } + if (node.kind === 256 /* SourceFile */) { + node.flags |= emitFlags; } - checkNodePositions(node, aggressiveChecks); - } - function visitArray(array) { - array._children = undefined; - array.pos += delta; - array.end += delta; - for (var _i = 0, array_9 = array; _i < array_9.length; _i++) { - var node = array_9[_i]; - visitNode(node); + if (isIIFE) { + addAntecedent(currentReturnTarget, currentFlow); + currentFlow = finishFlowLabel(currentReturnTarget); } + else { + currentFlow = saveCurrentFlow; + } + currentBreakTarget = saveBreakTarget; + currentContinueTarget = saveContinueTarget; + currentReturnTarget = saveReturnTarget; + activeLabels = saveActiveLabels; + hasExplicitReturn = saveHasExplicitReturn; } - } - function shouldCheckNode(node) { - switch (node.kind) { - case 9 /* StringLiteral */: - case 8 /* NumericLiteral */: - case 69 /* Identifier */: - return true; + else if (containerFlags & 64 /* IsInterface */) { + seenThisKeyword = false; + bindChildren(node); + node.flags = seenThisKeyword ? node.flags | 64 /* ContainsThis */ : node.flags & ~64 /* ContainsThis */; } - return false; + else { + bindChildren(node); + } + container = saveContainer; + blockScopeContainer = savedBlockScopeContainer; } - function adjustIntersectingElement(element, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta) { - ts.Debug.assert(element.end >= changeStart, "Adjusting an element that was entirely before the change range"); - ts.Debug.assert(element.pos <= changeRangeOldEnd, "Adjusting an element that was entirely after the change range"); - ts.Debug.assert(element.pos <= element.end); - // We have an element that intersects the change range in some way. It may have its - // start, or its end (or both) in the changed range. We want to adjust any part - // that intersects such that the final tree is in a consistent state. i.e. all - // children have spans within the span of their parent, and all siblings are ordered - // properly. - // We may need to update both the 'pos' and the 'end' of the element. - // If the 'pos' is before the start of the change, then we don't need to touch it. - // If it isn't, then the 'pos' must be inside the change. How we update it will - // depend if delta is positive or negative. If delta is positive then we have - // something like: - // - // -------------------AAA----------------- - // -------------------BBBCCCCCCC----------------- - // - // In this case, we consider any node that started in the change range to still be - // starting at the same position. - // - // however, if the delta is negative, then we instead have something like this: - // - // -------------------XXXYYYYYYY----------------- - // -------------------ZZZ----------------- - // - // In this case, any element that started in the 'X' range will keep its position. - // However any element that started after that will have their pos adjusted to be - // at the end of the new range. i.e. any node that started in the 'Y' range will - // be adjusted to have their start at the end of the 'Z' range. - // - // The element will keep its position if possible. Or Move backward to the new-end - // if it's in the 'Y' range. - element.pos = Math.min(element.pos, changeRangeNewEnd); - // If the 'end' is after the change range, then we always adjust it by the delta - // amount. However, if the end is in the change range, then how we adjust it - // will depend on if delta is positive or negative. If delta is positive then we - // have something like: - // - // -------------------AAA----------------- - // -------------------BBBCCCCCCC----------------- - // - // In this case, we consider any node that ended inside the change range to keep its - // end position. - // - // however, if the delta is negative, then we instead have something like this: - // - // -------------------XXXYYYYYYY----------------- - // -------------------ZZZ----------------- - // - // In this case, any element that ended in the 'X' range will keep its position. - // However any element that ended after that will have their pos adjusted to be - // at the end of the new range. i.e. any node that ended in the 'Y' range will - // be adjusted to have their end at the end of the 'Z' range. - if (element.end >= changeRangeOldEnd) { - // Element ends after the change range. Always adjust the end pos. - element.end += delta; + function bindChildren(node) { + if (skipTransformFlagAggregation) { + bindChildrenWorker(node); + } + else if (node.transformFlags & 536870912 /* HasComputedFlags */) { + skipTransformFlagAggregation = true; + bindChildrenWorker(node); + skipTransformFlagAggregation = false; } else { - // Element ends in the change range. The element will keep its position if - // possible. Or Move backward to the new-end if it's in the 'Y' range. - element.end = Math.min(element.end, changeRangeNewEnd); + var savedSubtreeTransformFlags = subtreeTransformFlags; + subtreeTransformFlags = 0; + bindChildrenWorker(node); + subtreeTransformFlags = savedSubtreeTransformFlags | computeTransformFlagsForNode(node, subtreeTransformFlags); } - ts.Debug.assert(element.pos <= element.end); - if (element.parent) { - ts.Debug.assert(element.pos >= element.parent.pos); - ts.Debug.assert(element.end <= element.parent.end); + } + function bindChildrenWorker(node) { + // Binding of JsDocComment should be done before the current block scope container changes. + // because the scope of JsDocComment should not be affected by whether the current node is a + // container or not. + if (ts.isInJavaScriptFile(node) && node.jsDocComments) { + ts.forEach(node.jsDocComments, bind); + } + if (checkUnreachable(node)) { + ts.forEachChild(node, bind); + return; + } + switch (node.kind) { + case 205 /* WhileStatement */: + bindWhileStatement(node); + break; + case 204 /* DoStatement */: + bindDoStatement(node); + break; + case 206 /* ForStatement */: + bindForStatement(node); + break; + case 207 /* ForInStatement */: + case 208 /* ForOfStatement */: + bindForInOrForOfStatement(node); + break; + case 203 /* IfStatement */: + bindIfStatement(node); + break; + case 211 /* ReturnStatement */: + case 215 /* ThrowStatement */: + bindReturnOrThrow(node); + break; + case 210 /* BreakStatement */: + case 209 /* ContinueStatement */: + bindBreakOrContinueStatement(node); + break; + case 216 /* TryStatement */: + bindTryStatement(node); + break; + case 213 /* SwitchStatement */: + bindSwitchStatement(node); + break; + case 227 /* CaseBlock */: + bindCaseBlock(node); + break; + case 249 /* CaseClause */: + bindCaseClause(node); + break; + case 214 /* LabeledStatement */: + bindLabeledStatement(node); + break; + case 185 /* PrefixUnaryExpression */: + bindPrefixUnaryExpressionFlow(node); + break; + case 186 /* PostfixUnaryExpression */: + bindPostfixUnaryExpressionFlow(node); + break; + case 187 /* BinaryExpression */: + bindBinaryExpressionFlow(node); + break; + case 181 /* DeleteExpression */: + bindDeleteExpressionFlow(node); + break; + case 188 /* ConditionalExpression */: + bindConditionalExpressionFlow(node); + break; + case 218 /* VariableDeclaration */: + bindVariableDeclarationFlow(node); + break; + case 174 /* CallExpression */: + bindCallExpressionFlow(node); + break; + default: + ts.forEachChild(node, bind); + break; } } - function checkNodePositions(node, aggressiveChecks) { - if (aggressiveChecks) { - var pos_2 = node.pos; - forEachChild(node, function (child) { - ts.Debug.assert(child.pos >= pos_2); - pos_2 = child.end; - }); - ts.Debug.assert(pos_2 <= node.end); + function isNarrowingExpression(expr) { + switch (expr.kind) { + case 69 /* Identifier */: + case 97 /* ThisKeyword */: + case 172 /* PropertyAccessExpression */: + return isNarrowableReference(expr); + case 174 /* CallExpression */: + return hasNarrowableArgument(expr); + case 178 /* ParenthesizedExpression */: + return isNarrowingExpression(expr.expression); + case 187 /* BinaryExpression */: + return isNarrowingBinaryExpression(expr); + case 185 /* PrefixUnaryExpression */: + return expr.operator === 49 /* ExclamationToken */ && isNarrowingExpression(expr.operand); } + return false; } - function updateTokenPositionsAndMarkElements(sourceFile, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta, oldText, newText, aggressiveChecks) { - visitNode(sourceFile); - return; - function visitNode(child) { - ts.Debug.assert(child.pos <= child.end); - if (child.pos > changeRangeOldEnd) { - // Node is entirely past the change range. We need to move both its pos and - // end, forward or backward appropriately. - moveElementEntirelyPastChangeRange(child, /*isArray*/ false, delta, oldText, newText, aggressiveChecks); - return; - } - // Check if the element intersects the change range. If it does, then it is not - // reusable. Also, we'll need to recurse to see what constituent portions we may - // be able to use. - var fullEnd = child.end; - if (fullEnd >= changeStart) { - child.intersectsChange = true; - child._children = undefined; - // Adjust the pos or end (or both) of the intersecting element accordingly. - adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta); - forEachChild(child, visitNode, visitArray); - checkNodePositions(child, aggressiveChecks); - return; + function isNarrowableReference(expr) { + return expr.kind === 69 /* Identifier */ || + expr.kind === 97 /* ThisKeyword */ || + expr.kind === 172 /* PropertyAccessExpression */ && isNarrowableReference(expr.expression); + } + function hasNarrowableArgument(expr) { + if (expr.arguments) { + for (var _i = 0, _a = expr.arguments; _i < _a.length; _i++) { + var argument = _a[_i]; + if (isNarrowableReference(argument)) { + return true; + } } - // Otherwise, the node is entirely before the change range. No need to do anything with it. - ts.Debug.assert(fullEnd < changeStart); } - function visitArray(array) { - ts.Debug.assert(array.pos <= array.end); - if (array.pos > changeRangeOldEnd) { - // Array is entirely after the change range. We need to move it, and move any of - // its children. - moveElementEntirelyPastChangeRange(array, /*isArray*/ true, delta, oldText, newText, aggressiveChecks); - return; - } - // Check if the element intersects the change range. If it does, then it is not - // reusable. Also, we'll need to recurse to see what constituent portions we may - // be able to use. - var fullEnd = array.end; - if (fullEnd >= changeStart) { - array.intersectsChange = true; - array._children = undefined; - // Adjust the pos or end (or both) of the intersecting array accordingly. - adjustIntersectingElement(array, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta); - for (var _i = 0, array_10 = array; _i < array_10.length; _i++) { - var node = array_10[_i]; - visitNode(node); + if (expr.expression.kind === 172 /* PropertyAccessExpression */ && + isNarrowableReference(expr.expression.expression)) { + return true; + } + return false; + } + function isNarrowingTypeofOperands(expr1, expr2) { + return expr1.kind === 182 /* TypeOfExpression */ && isNarrowableOperand(expr1.expression) && expr2.kind === 9 /* StringLiteral */; + } + function isNarrowingBinaryExpression(expr) { + switch (expr.operatorToken.kind) { + case 56 /* EqualsToken */: + return isNarrowableReference(expr.left); + case 30 /* EqualsEqualsToken */: + case 31 /* ExclamationEqualsToken */: + case 32 /* EqualsEqualsEqualsToken */: + case 33 /* ExclamationEqualsEqualsToken */: + return isNarrowableOperand(expr.left) || isNarrowableOperand(expr.right) || + isNarrowingTypeofOperands(expr.right, expr.left) || isNarrowingTypeofOperands(expr.left, expr.right); + case 91 /* InstanceOfKeyword */: + return isNarrowableOperand(expr.left); + case 24 /* CommaToken */: + return isNarrowingExpression(expr.right); + } + return false; + } + function isNarrowableOperand(expr) { + switch (expr.kind) { + case 178 /* ParenthesizedExpression */: + return isNarrowableOperand(expr.expression); + case 187 /* BinaryExpression */: + switch (expr.operatorToken.kind) { + case 56 /* EqualsToken */: + return isNarrowableOperand(expr.left); + case 24 /* CommaToken */: + return isNarrowableOperand(expr.right); } - return; - } - // Otherwise, the array is entirely before the change range. No need to do anything with it. - ts.Debug.assert(fullEnd < changeStart); } + return isNarrowableReference(expr); } - function extendToAffectedRange(sourceFile, changeRange) { - // Consider the following code: - // void foo() { /; } - // - // If the text changes with an insertion of / just before the semicolon then we end up with: - // void foo() { //; } - // - // If we were to just use the changeRange a is, then we would not rescan the { token - // (as it does not intersect the actual original change range). Because an edit may - // change the token touching it, we actually need to look back *at least* one token so - // that the prior token sees that change. - var maxLookahead = 1; - var start = changeRange.span.start; - // the first iteration aligns us with the change start. subsequent iteration move us to - // the left by maxLookahead tokens. We only need to do this as long as we're not at the - // start of the tree. - for (var i = 0; start > 0 && i <= maxLookahead; i++) { - var nearestNode = findNearestNodeStartingBeforeOrAtPosition(sourceFile, start); - ts.Debug.assert(nearestNode.pos <= start); - var position = nearestNode.pos; - start = Math.max(0, position - 1); + function createBranchLabel() { + return { + flags: 4 /* BranchLabel */, + antecedents: undefined + }; + } + function createLoopLabel() { + return { + flags: 8 /* LoopLabel */, + antecedents: undefined + }; + } + function setFlowNodeReferenced(flow) { + // On first reference we set the Referenced flag, thereafter we set the Shared flag + flow.flags |= flow.flags & 256 /* Referenced */ ? 512 /* Shared */ : 256 /* Referenced */; + } + function addAntecedent(label, antecedent) { + if (!(antecedent.flags & 1 /* Unreachable */) && !ts.contains(label.antecedents, antecedent)) { + (label.antecedents || (label.antecedents = [])).push(antecedent); + setFlowNodeReferenced(antecedent); } - var finalSpan = ts.createTextSpanFromBounds(start, ts.textSpanEnd(changeRange.span)); - var finalLength = changeRange.newLength + (changeRange.span.start - start); - return ts.createTextChangeRange(finalSpan, finalLength); } - function findNearestNodeStartingBeforeOrAtPosition(sourceFile, position) { - var bestResult = sourceFile; - var lastNodeEntirelyBeforePosition; - forEachChild(sourceFile, visit); - if (lastNodeEntirelyBeforePosition) { - var lastChildOfLastEntireNodeBeforePosition = getLastChild(lastNodeEntirelyBeforePosition); - if (lastChildOfLastEntireNodeBeforePosition.pos > bestResult.pos) { - bestResult = lastChildOfLastEntireNodeBeforePosition; - } + function createFlowCondition(flags, antecedent, expression) { + if (antecedent.flags & 1 /* Unreachable */) { + return antecedent; } - return bestResult; - function getLastChild(node) { - while (true) { - var lastChild = getLastChildWorker(node); - if (lastChild) { - node = lastChild; - } - else { - return node; - } - } + if (!expression) { + return flags & 32 /* TrueCondition */ ? antecedent : unreachableFlow; } - function getLastChildWorker(node) { - var last = undefined; - forEachChild(node, function (child) { - if (ts.nodeIsPresent(child)) { - last = child; - } - }); - return last; + if (expression.kind === 99 /* TrueKeyword */ && flags & 64 /* FalseCondition */ || + expression.kind === 84 /* FalseKeyword */ && flags & 32 /* TrueCondition */) { + return unreachableFlow; } - function visit(child) { - if (ts.nodeIsMissing(child)) { - // Missing nodes are effectively invisible to us. We never even consider them - // When trying to find the nearest node before us. - return; - } - // If the child intersects this position, then this node is currently the nearest - // node that starts before the position. - if (child.pos <= position) { - if (child.pos >= bestResult.pos) { - // This node starts before the position, and is closer to the position than - // the previous best node we found. It is now the new best node. - bestResult = child; - } - // Now, the node may overlap the position, or it may end entirely before the - // position. If it overlaps with the position, then either it, or one of its - // children must be the nearest node before the position. So we can just - // recurse into this child to see if we can find something better. - if (position < child.end) { - // The nearest node is either this child, or one of the children inside - // of it. We've already marked this child as the best so far. Recurse - // in case one of the children is better. - forEachChild(child, visit); - // Once we look at the children of this node, then there's no need to - // continue any further. - return true; - } - else { - ts.Debug.assert(child.end <= position); - // The child ends entirely before this position. Say you have the following - // (where $ is the position) - // - // ? $ : <...> <...> - // - // We would want to find the nearest preceding node in "complex expr 2". - // To support that, we keep track of this node, and once we're done searching - // for a best node, we recurse down this node to see if we can find a good - // result in it. - // - // This approach allows us to quickly skip over nodes that are entirely - // before the position, while still allowing us to find any nodes in the - // last one that might be what we want. - lastNodeEntirelyBeforePosition = child; - } - } - else { - ts.Debug.assert(child.pos > position); - // We're now at a node that is entirely past the position we're searching for. - // This node (and all following nodes) could never contribute to the result, - // so just skip them by returning 'true' here. - return true; - } + if (!isNarrowingExpression(expression)) { + return antecedent; } + setFlowNodeReferenced(antecedent); + return { + flags: flags, + expression: expression, + antecedent: antecedent + }; } - function checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks) { - var oldText = sourceFile.text; - if (textChangeRange) { - ts.Debug.assert((oldText.length - textChangeRange.span.length + textChangeRange.newLength) === newText.length); - if (aggressiveChecks || ts.Debug.shouldAssert(3 /* VeryAggressive */)) { - var oldTextPrefix = oldText.substr(0, textChangeRange.span.start); - var newTextPrefix = newText.substr(0, textChangeRange.span.start); - ts.Debug.assert(oldTextPrefix === newTextPrefix); - var oldTextSuffix = oldText.substring(ts.textSpanEnd(textChangeRange.span), oldText.length); - var newTextSuffix = newText.substring(ts.textSpanEnd(ts.textChangeRangeNewSpan(textChangeRange)), newText.length); - ts.Debug.assert(oldTextSuffix === newTextSuffix); - } + function createFlowSwitchClause(antecedent, switchStatement, clauseStart, clauseEnd) { + if (!isNarrowingExpression(switchStatement.expression)) { + return antecedent; } + setFlowNodeReferenced(antecedent); + return { + flags: 128 /* SwitchClause */, + switchStatement: switchStatement, + clauseStart: clauseStart, + clauseEnd: clauseEnd, + antecedent: antecedent + }; } - function createSyntaxCursor(sourceFile) { - var currentArray = sourceFile.statements; - var currentArrayIndex = 0; - ts.Debug.assert(currentArrayIndex < currentArray.length); - var current = currentArray[currentArrayIndex]; - var lastQueriedPosition = -1 /* Value */; + function createFlowAssignment(antecedent, node) { + setFlowNodeReferenced(antecedent); return { - currentNode: function (position) { - // Only compute the current node if the position is different than the last time - // we were asked. The parser commonly asks for the node at the same position - // twice. Once to know if can read an appropriate list element at a certain point, - // and then to actually read and consume the node. - if (position !== lastQueriedPosition) { - // Much of the time the parser will need the very next node in the array that - // we just returned a node from.So just simply check for that case and move - // forward in the array instead of searching for the node again. - if (current && current.end === position && currentArrayIndex < (currentArray.length - 1)) { - currentArrayIndex++; - current = currentArray[currentArrayIndex]; - } - // If we don't have a node, or the node we have isn't in the right position, - // then try to find a viable node at the position requested. - if (!current || current.pos !== position) { - findHighestListElementThatStartsAtPosition(position); - } - } - // Cache this query so that we don't do any extra work if the parser calls back - // into us. Note: this is very common as the parser will make pairs of calls like - // 'isListElement -> parseListElement'. If we were unable to find a node when - // called with 'isListElement', we don't want to redo the work when parseListElement - // is called immediately after. - lastQueriedPosition = position; - // Either we don'd have a node, or we have a node at the position being asked for. - ts.Debug.assert(!current || current.pos === position); - return current; - } + flags: 16 /* Assignment */, + antecedent: antecedent, + node: node }; - // Finds the highest element in the tree we can find that starts at the provided position. - // The element must be a direct child of some node list in the tree. This way after we - // return it, we can easily return its next sibling in the list. - function findHighestListElementThatStartsAtPosition(position) { - // Clear out any cached state about the last node we found. - currentArray = undefined; - currentArrayIndex = -1 /* Value */; - current = undefined; - // Recurse into the source file to find the highest node at this position. - forEachChild(sourceFile, visitNode, visitArray); - return; - function visitNode(node) { - if (position >= node.pos && position < node.end) { - // Position was within this node. Keep searching deeper to find the node. - forEachChild(node, visitNode, visitArray); - // don't proceed any further in the search. - return true; - } - // position wasn't in this node, have to keep searching. - return false; + } + function finishFlowLabel(flow) { + var antecedents = flow.antecedents; + if (!antecedents) { + return unreachableFlow; + } + if (antecedents.length === 1) { + return antecedents[0]; + } + return flow; + } + function isStatementCondition(node) { + var parent = node.parent; + switch (parent.kind) { + case 203 /* IfStatement */: + case 205 /* WhileStatement */: + case 204 /* DoStatement */: + return parent.expression === node; + case 206 /* ForStatement */: + case 188 /* ConditionalExpression */: + return parent.condition === node; + } + return false; + } + function isLogicalExpression(node) { + while (true) { + if (node.kind === 178 /* ParenthesizedExpression */) { + node = node.expression; } - function visitArray(array) { - if (position >= array.pos && position < array.end) { - // position was in this array. Search through this array to see if we find a - // viable element. - for (var i = 0, n = array.length; i < n; i++) { - var child = array[i]; - if (child) { - if (child.pos === position) { - // Found the right node. We're done. - currentArray = array; - currentArrayIndex = i; - current = child; - return true; - } - else { - if (child.pos < position && position < child.end) { - // Position in somewhere within this child. Search in it and - // stop searching in this array. - forEachChild(child, visitNode, visitArray); - return true; - } - } - } - } - } - // position wasn't in this array, have to keep searching. - return false; + else if (node.kind === 185 /* PrefixUnaryExpression */ && node.operator === 49 /* ExclamationToken */) { + node = node.operand; + } + else { + return node.kind === 187 /* BinaryExpression */ && (node.operatorToken.kind === 51 /* AmpersandAmpersandToken */ || + node.operatorToken.kind === 52 /* BarBarToken */); } } } - var InvalidPosition; - (function (InvalidPosition) { - InvalidPosition[InvalidPosition["Value"] = -1] = "Value"; - })(InvalidPosition || (InvalidPosition = {})); - })(IncrementalParser || (IncrementalParser = {})); -})(ts || (ts = {})); -/// -/// -/* @internal */ -var ts; -(function (ts) { - (function (ModuleInstanceState) { - ModuleInstanceState[ModuleInstanceState["NonInstantiated"] = 0] = "NonInstantiated"; - ModuleInstanceState[ModuleInstanceState["Instantiated"] = 1] = "Instantiated"; - ModuleInstanceState[ModuleInstanceState["ConstEnumOnly"] = 2] = "ConstEnumOnly"; - })(ts.ModuleInstanceState || (ts.ModuleInstanceState = {})); - var ModuleInstanceState = ts.ModuleInstanceState; - function getModuleInstanceState(node) { - // A module is uninstantiated if it contains only - // 1. interface declarations, type alias declarations - if (node.kind === 222 /* InterfaceDeclaration */ || node.kind === 223 /* TypeAliasDeclaration */) { - return 0 /* NonInstantiated */; + function isTopLevelLogicalExpression(node) { + while (node.parent.kind === 178 /* ParenthesizedExpression */ || + node.parent.kind === 185 /* PrefixUnaryExpression */ && + node.parent.operator === 49 /* ExclamationToken */) { + node = node.parent; + } + return !isStatementCondition(node) && !isLogicalExpression(node.parent); } - else if (ts.isConstEnumDeclaration(node)) { - return 2 /* ConstEnumOnly */; + function bindCondition(node, trueTarget, falseTarget) { + var saveTrueTarget = currentTrueTarget; + var saveFalseTarget = currentFalseTarget; + currentTrueTarget = trueTarget; + currentFalseTarget = falseTarget; + bind(node); + currentTrueTarget = saveTrueTarget; + currentFalseTarget = saveFalseTarget; + if (!node || !isLogicalExpression(node)) { + addAntecedent(trueTarget, createFlowCondition(32 /* TrueCondition */, currentFlow, node)); + addAntecedent(falseTarget, createFlowCondition(64 /* FalseCondition */, currentFlow, node)); + } } - else if ((node.kind === 230 /* ImportDeclaration */ || node.kind === 229 /* ImportEqualsDeclaration */) && !(node.flags & 1 /* Export */)) { - return 0 /* NonInstantiated */; + function bindIterativeStatement(node, breakTarget, continueTarget) { + var saveBreakTarget = currentBreakTarget; + var saveContinueTarget = currentContinueTarget; + currentBreakTarget = breakTarget; + currentContinueTarget = continueTarget; + bind(node); + currentBreakTarget = saveBreakTarget; + currentContinueTarget = saveContinueTarget; } - else if (node.kind === 226 /* ModuleBlock */) { - var state_1 = 0 /* NonInstantiated */; - ts.forEachChild(node, function (n) { - switch (getModuleInstanceState(n)) { - case 0 /* NonInstantiated */: - // child is non-instantiated - continue searching - return false; - case 2 /* ConstEnumOnly */: - // child is const enum only - record state and continue searching - state_1 = 2 /* ConstEnumOnly */; - return false; - case 1 /* Instantiated */: - // child is instantiated - record state and stop - state_1 = 1 /* Instantiated */; - return true; - } - }); - return state_1; + function bindWhileStatement(node) { + var preWhileLabel = createLoopLabel(); + var preBodyLabel = createBranchLabel(); + var postWhileLabel = createBranchLabel(); + addAntecedent(preWhileLabel, currentFlow); + currentFlow = preWhileLabel; + bindCondition(node.expression, preBodyLabel, postWhileLabel); + currentFlow = finishFlowLabel(preBodyLabel); + bindIterativeStatement(node.statement, postWhileLabel, preWhileLabel); + addAntecedent(preWhileLabel, currentFlow); + currentFlow = finishFlowLabel(postWhileLabel); + } + function bindDoStatement(node) { + var preDoLabel = createLoopLabel(); + var preConditionLabel = createBranchLabel(); + var postDoLabel = createBranchLabel(); + addAntecedent(preDoLabel, currentFlow); + currentFlow = preDoLabel; + bindIterativeStatement(node.statement, postDoLabel, preConditionLabel); + addAntecedent(preConditionLabel, currentFlow); + currentFlow = finishFlowLabel(preConditionLabel); + bindCondition(node.expression, preDoLabel, postDoLabel); + currentFlow = finishFlowLabel(postDoLabel); + } + function bindForStatement(node) { + var preLoopLabel = createLoopLabel(); + var preBodyLabel = createBranchLabel(); + var postLoopLabel = createBranchLabel(); + bind(node.initializer); + addAntecedent(preLoopLabel, currentFlow); + currentFlow = preLoopLabel; + bindCondition(node.condition, preBodyLabel, postLoopLabel); + currentFlow = finishFlowLabel(preBodyLabel); + bindIterativeStatement(node.statement, postLoopLabel, preLoopLabel); + bind(node.incrementor); + addAntecedent(preLoopLabel, currentFlow); + currentFlow = finishFlowLabel(postLoopLabel); } - else if (node.kind === 225 /* ModuleDeclaration */) { - var body = node.body; - return body ? getModuleInstanceState(body) : 1 /* Instantiated */; + function bindForInOrForOfStatement(node) { + var preLoopLabel = createLoopLabel(); + var postLoopLabel = createBranchLabel(); + addAntecedent(preLoopLabel, currentFlow); + currentFlow = preLoopLabel; + bind(node.expression); + addAntecedent(postLoopLabel, currentFlow); + bind(node.initializer); + if (node.initializer.kind !== 219 /* VariableDeclarationList */) { + bindAssignmentTargetFlow(node.initializer); + } + bindIterativeStatement(node.statement, postLoopLabel, preLoopLabel); + addAntecedent(preLoopLabel, currentFlow); + currentFlow = finishFlowLabel(postLoopLabel); } - else { - return 1 /* Instantiated */; + function bindIfStatement(node) { + var thenLabel = createBranchLabel(); + var elseLabel = createBranchLabel(); + var postIfLabel = createBranchLabel(); + bindCondition(node.expression, thenLabel, elseLabel); + currentFlow = finishFlowLabel(thenLabel); + bind(node.thenStatement); + addAntecedent(postIfLabel, currentFlow); + currentFlow = finishFlowLabel(elseLabel); + bind(node.elseStatement); + addAntecedent(postIfLabel, currentFlow); + currentFlow = finishFlowLabel(postIfLabel); } - } - ts.getModuleInstanceState = getModuleInstanceState; - var ContainerFlags; - (function (ContainerFlags) { - // The current node is not a container, and no container manipulation should happen before - // recursing into it. - ContainerFlags[ContainerFlags["None"] = 0] = "None"; - // The current node is a container. It should be set as the current container (and block- - // container) before recursing into it. The current node does not have locals. Examples: - // - // Classes, ObjectLiterals, TypeLiterals, Interfaces... - ContainerFlags[ContainerFlags["IsContainer"] = 1] = "IsContainer"; - // The current node is a block-scoped-container. It should be set as the current block- - // container before recursing into it. Examples: - // - // Blocks (when not parented by functions), Catch clauses, For/For-in/For-of statements... - ContainerFlags[ContainerFlags["IsBlockScopedContainer"] = 2] = "IsBlockScopedContainer"; - // The current node is the container of a control flow path. The current control flow should - // be saved and restored, and a new control flow initialized within the container. - ContainerFlags[ContainerFlags["IsControlFlowContainer"] = 4] = "IsControlFlowContainer"; - ContainerFlags[ContainerFlags["IsFunctionLike"] = 8] = "IsFunctionLike"; - ContainerFlags[ContainerFlags["IsFunctionExpression"] = 16] = "IsFunctionExpression"; - ContainerFlags[ContainerFlags["HasLocals"] = 32] = "HasLocals"; - ContainerFlags[ContainerFlags["IsInterface"] = 64] = "IsInterface"; - })(ContainerFlags || (ContainerFlags = {})); - var binder = createBinder(); - function bindSourceFile(file, options) { - ts.performance.mark("beforeBind"); - binder(file, options); - ts.performance.mark("afterBind"); - ts.performance.measure("Bind", "beforeBind", "afterBind"); - } - ts.bindSourceFile = bindSourceFile; - function createBinder() { - var file; - var options; - var languageVersion; - var parent; - var container; - var blockScopeContainer; - var lastContainer; - var seenThisKeyword; - // state used by control flow analysis - var currentFlow; - var currentBreakTarget; - var currentContinueTarget; - var currentReturnTarget; - var currentTrueTarget; - var currentFalseTarget; - var preSwitchCaseFlow; - var activeLabels; - var hasExplicitReturn; - // state used for emit helpers - var emitFlags; - // If this file is an external module, then it is automatically in strict-mode according to - // ES6. If it is not an external module, then we'll determine if it is in strict mode or - // not depending on if we see "use strict" in certain places (or if we hit a class/namespace). - var inStrictMode; - var symbolCount = 0; - var Symbol; - var classifiableNames; - var unreachableFlow = { flags: 1 /* Unreachable */ }; - var reportedUnreachableFlow = { flags: 1 /* Unreachable */ }; - function bindSourceFile(f, opts) { - file = f; - options = opts; - languageVersion = ts.getEmitScriptTarget(options); - inStrictMode = !!file.externalModuleIndicator; - classifiableNames = ts.createMap(); - symbolCount = 0; - Symbol = ts.objectAllocator.getSymbolConstructor(); - if (!file.locals) { - bind(file); - file.symbolCount = symbolCount; - file.classifiableNames = classifiableNames; + function bindReturnOrThrow(node) { + bind(node.expression); + if (node.kind === 211 /* ReturnStatement */) { + hasExplicitReturn = true; + if (currentReturnTarget) { + addAntecedent(currentReturnTarget, currentFlow); + } } - file = undefined; - options = undefined; - languageVersion = undefined; - parent = undefined; - container = undefined; - blockScopeContainer = undefined; - lastContainer = undefined; - seenThisKeyword = false; - currentFlow = undefined; - currentBreakTarget = undefined; - currentContinueTarget = undefined; - currentReturnTarget = undefined; - currentTrueTarget = undefined; - currentFalseTarget = undefined; - activeLabels = undefined; - hasExplicitReturn = false; - emitFlags = 0 /* None */; + currentFlow = unreachableFlow; } - return bindSourceFile; - function createSymbol(flags, name) { - symbolCount++; - return new Symbol(flags, name); + function findActiveLabel(name) { + if (activeLabels) { + for (var _i = 0, activeLabels_1 = activeLabels; _i < activeLabels_1.length; _i++) { + var label = activeLabels_1[_i]; + if (label.name === name) { + return label; + } + } + } + return undefined; } - function addDeclarationToSymbol(symbol, node, symbolFlags) { - symbol.flags |= symbolFlags; - node.symbol = symbol; - if (!symbol.declarations) { - symbol.declarations = []; + function bindbreakOrContinueFlow(node, breakTarget, continueTarget) { + var flowLabel = node.kind === 210 /* BreakStatement */ ? breakTarget : continueTarget; + if (flowLabel) { + addAntecedent(flowLabel, currentFlow); + currentFlow = unreachableFlow; } - symbol.declarations.push(node); - if (symbolFlags & 1952 /* HasExports */ && !symbol.exports) { - symbol.exports = ts.createMap(); + } + function bindBreakOrContinueStatement(node) { + bind(node.label); + if (node.label) { + var activeLabel = findActiveLabel(node.label.text); + if (activeLabel) { + activeLabel.referenced = true; + bindbreakOrContinueFlow(node, activeLabel.breakTarget, activeLabel.continueTarget); + } } - if (symbolFlags & 6240 /* HasMembers */ && !symbol.members) { - symbol.members = ts.createMap(); + else { + bindbreakOrContinueFlow(node, currentBreakTarget, currentContinueTarget); } - if (symbolFlags & 107455 /* Value */) { - var valueDeclaration = symbol.valueDeclaration; - if (!valueDeclaration || - (valueDeclaration.kind !== node.kind && valueDeclaration.kind === 225 /* ModuleDeclaration */)) { - // other kinds of value declarations take precedence over modules - symbol.valueDeclaration = node; - } + } + function bindTryStatement(node) { + var postFinallyLabel = createBranchLabel(); + var preTryFlow = currentFlow; + // TODO: Every statement in try block is potentially an exit point! + bind(node.tryBlock); + addAntecedent(postFinallyLabel, currentFlow); + if (node.catchClause) { + currentFlow = preTryFlow; + bind(node.catchClause); + addAntecedent(postFinallyLabel, currentFlow); + } + if (node.finallyBlock) { + currentFlow = preTryFlow; + bind(node.finallyBlock); } + currentFlow = finishFlowLabel(postFinallyLabel); } - // Should not be called on a declaration with a computed property name, - // unless it is a well known Symbol. - function getDeclarationName(node) { - if (node.name) { - if (ts.isAmbientModule(node)) { - return ts.isGlobalScopeAugmentation(node) ? "__global" : "\"" + node.name.text + "\""; + function bindSwitchStatement(node) { + var postSwitchLabel = createBranchLabel(); + bind(node.expression); + var saveBreakTarget = currentBreakTarget; + var savePreSwitchCaseFlow = preSwitchCaseFlow; + currentBreakTarget = postSwitchLabel; + preSwitchCaseFlow = currentFlow; + bind(node.caseBlock); + addAntecedent(postSwitchLabel, currentFlow); + var hasDefault = ts.forEach(node.caseBlock.clauses, function (c) { return c.kind === 250 /* DefaultClause */; }); + // We mark a switch statement as possibly exhaustive if it has no default clause and if all + // case clauses have unreachable end points (e.g. they all return). + node.possiblyExhaustive = !hasDefault && !postSwitchLabel.antecedents; + if (!hasDefault) { + addAntecedent(postSwitchLabel, createFlowSwitchClause(preSwitchCaseFlow, node, 0, 0)); + } + currentBreakTarget = saveBreakTarget; + preSwitchCaseFlow = savePreSwitchCaseFlow; + currentFlow = finishFlowLabel(postSwitchLabel); + } + function bindCaseBlock(node) { + var clauses = node.clauses; + var fallthroughFlow = unreachableFlow; + for (var i = 0; i < clauses.length; i++) { + var clauseStart = i; + while (!clauses[i].statements.length && i + 1 < clauses.length) { + bind(clauses[i]); + i++; } - if (node.name.kind === 140 /* ComputedPropertyName */) { - var nameExpression = node.name.expression; - // treat computed property names where expression is string/numeric literal as just string/numeric literal - if (ts.isStringOrNumericLiteral(nameExpression.kind)) { - return nameExpression.text; - } - ts.Debug.assert(ts.isWellKnownSymbolSyntactically(nameExpression)); - return ts.getPropertyNameForKnownSymbolName(nameExpression.name.text); + var preCaseLabel = createBranchLabel(); + addAntecedent(preCaseLabel, createFlowSwitchClause(preSwitchCaseFlow, node.parent, clauseStart, i + 1)); + addAntecedent(preCaseLabel, fallthroughFlow); + currentFlow = finishFlowLabel(preCaseLabel); + var clause = clauses[i]; + bind(clause); + fallthroughFlow = currentFlow; + if (!(currentFlow.flags & 1 /* Unreachable */) && i !== clauses.length - 1 && options.noFallthroughCasesInSwitch) { + errorOnFirstToken(clause, ts.Diagnostics.Fallthrough_case_in_switch); } - return node.name.text; - } - switch (node.kind) { - case 148 /* Constructor */: - return "__constructor"; - case 156 /* FunctionType */: - case 151 /* CallSignature */: - return "__call"; - case 157 /* ConstructorType */: - case 152 /* ConstructSignature */: - return "__new"; - case 153 /* IndexSignature */: - return "__index"; - case 236 /* ExportDeclaration */: - return "__export"; - case 235 /* ExportAssignment */: - return node.isExportEquals ? "export=" : "default"; - case 187 /* BinaryExpression */: - switch (ts.getSpecialPropertyAssignmentKind(node)) { - case 2 /* ModuleExports */: - // module.exports = ... - return "export="; - case 1 /* ExportsProperty */: - case 4 /* ThisProperty */: - // exports.x = ... or this.y = ... - return node.left.name.text; - case 3 /* PrototypeProperty */: - // className.prototype.methodName = ... - return node.left.expression.name.text; - } - ts.Debug.fail("Unknown binary declaration kind"); - break; - case 220 /* FunctionDeclaration */: - case 221 /* ClassDeclaration */: - return node.flags & 512 /* Default */ ? "default" : undefined; - case 269 /* JSDocFunctionType */: - return ts.isJSDocConstructSignature(node) ? "__new" : "__call"; - case 142 /* Parameter */: - // Parameters with names are handled at the top of this function. Parameters - // without names can only come from JSDocFunctionTypes. - ts.Debug.assert(node.parent.kind === 269 /* JSDocFunctionType */); - var functionType = node.parent; - var index = ts.indexOf(functionType.parameters, node); - return "p" + index; - case 279 /* JSDocTypedefTag */: - var parentNode = node.parent && node.parent.parent; - var nameFromParentNode = void 0; - if (parentNode && parentNode.kind === 200 /* VariableStatement */) { - if (parentNode.declarationList.declarations.length > 0) { - var nameIdentifier = parentNode.declarationList.declarations[0].name; - if (nameIdentifier.kind === 69 /* Identifier */) { - nameFromParentNode = nameIdentifier.text; - } - } - } - return nameFromParentNode; } } - function getDisplayName(node) { - return node.name ? ts.declarationNameToString(node.name) : getDeclarationName(node); + function bindCaseClause(node) { + var saveCurrentFlow = currentFlow; + currentFlow = preSwitchCaseFlow; + bind(node.expression); + currentFlow = saveCurrentFlow; + ts.forEach(node.statements, bind); } - /** - * Declares a Symbol for the node and adds it to symbols. Reports errors for conflicting identifier names. - * @param symbolTable - The symbol table which node will be added to. - * @param parent - node's parent declaration. - * @param node - The declaration to be added to the symbol table - * @param includes - The SymbolFlags that node has in addition to its declaration type (eg: export, ambient, etc.) - * @param excludes - The flags which node cannot be declared alongside in a symbol table. Used to report forbidden declarations. - */ - function declareSymbol(symbolTable, parent, node, includes, excludes) { - ts.Debug.assert(!ts.hasDynamicName(node)); - var isDefaultExport = node.flags & 512 /* Default */; - // The exported symbol for an export default function/class node is always named "default" - var name = isDefaultExport && parent ? "default" : getDeclarationName(node); - var symbol; - if (name === undefined) { - symbol = createSymbol(0 /* None */, "__missing"); + function pushActiveLabel(name, breakTarget, continueTarget) { + var activeLabel = { + name: name, + breakTarget: breakTarget, + continueTarget: continueTarget, + referenced: false + }; + (activeLabels || (activeLabels = [])).push(activeLabel); + return activeLabel; + } + function popActiveLabel() { + activeLabels.pop(); + } + function bindLabeledStatement(node) { + var preStatementLabel = createLoopLabel(); + var postStatementLabel = createBranchLabel(); + bind(node.label); + addAntecedent(preStatementLabel, currentFlow); + var activeLabel = pushActiveLabel(node.label.text, postStatementLabel, preStatementLabel); + bind(node.statement); + popActiveLabel(); + if (!activeLabel.referenced && !options.allowUnusedLabels) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(node.label, ts.Diagnostics.Unused_label)); + } + addAntecedent(postStatementLabel, currentFlow); + currentFlow = finishFlowLabel(postStatementLabel); + } + function bindDestructuringTargetFlow(node) { + if (node.kind === 187 /* BinaryExpression */ && node.operatorToken.kind === 56 /* EqualsToken */) { + bindAssignmentTargetFlow(node.left); } else { - // Check and see if the symbol table already has a symbol with this name. If not, - // create a new symbol with this name and add it to the table. Note that we don't - // give the new symbol any flags *yet*. This ensures that it will not conflict - // with the 'excludes' flags we pass in. - // - // If we do get an existing symbol, see if it conflicts with the new symbol we're - // creating. For example, a 'var' symbol and a 'class' symbol will conflict within - // the same symbol table. If we have a conflict, report the issue on each - // declaration we have for this symbol, and then create a new symbol for this - // declaration. - // - // Note that when properties declared in Javascript constructors - // (marked by isReplaceableByMethod) conflict with another symbol, the property loses. - // Always. This allows the common Javascript pattern of overwriting a prototype method - // with an bound instance method of the same type: `this.method = this.method.bind(this)` - // - // If we created a new symbol, either because we didn't have a symbol with this name - // in the symbol table, or we conflicted with an existing symbol, then just add this - // node as the sole declaration of the new symbol. - // - // Otherwise, we'll be merging into a compatible existing symbol (for example when - // you have multiple 'vars' with the same name in the same container). In this case - // just add this node into the declarations list of the symbol. - symbol = symbolTable[name] || (symbolTable[name] = createSymbol(0 /* None */, name)); - if (name && (includes & 788448 /* Classifiable */)) { - classifiableNames[name] = name; - } - if (symbol.flags & excludes) { - if (symbol.isReplaceableByMethod) { - // Javascript constructor-declared symbols can be discarded in favor of - // prototype symbols like methods. - symbol = symbolTable[name] = createSymbol(0 /* None */, name); + bindAssignmentTargetFlow(node); + } + } + function bindAssignmentTargetFlow(node) { + if (isNarrowableReference(node)) { + currentFlow = createFlowAssignment(currentFlow, node); + } + else if (node.kind === 170 /* ArrayLiteralExpression */) { + for (var _i = 0, _a = node.elements; _i < _a.length; _i++) { + var e = _a[_i]; + if (e.kind === 191 /* SpreadElementExpression */) { + bindAssignmentTargetFlow(e.expression); } else { - if (node.name) { - node.name.parent = node; - } - // Report errors every position with duplicate declaration - // Report errors on previous encountered declarations - var message_1 = symbol.flags & 2 /* BlockScopedVariable */ - ? ts.Diagnostics.Cannot_redeclare_block_scoped_variable_0 - : ts.Diagnostics.Duplicate_identifier_0; - ts.forEach(symbol.declarations, function (declaration) { - if (declaration.flags & 512 /* Default */) { - message_1 = ts.Diagnostics.A_module_cannot_have_multiple_default_exports; - } - }); - ts.forEach(symbol.declarations, function (declaration) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(declaration.name || declaration, message_1, getDisplayName(declaration))); - }); - file.bindDiagnostics.push(ts.createDiagnosticForNode(node.name || node, message_1, getDisplayName(node))); - symbol = createSymbol(0 /* None */, name); + bindDestructuringTargetFlow(e); } } } - addDeclarationToSymbol(symbol, node, includes); - symbol.parent = parent; - return symbol; - } - function declareModuleMember(node, symbolFlags, symbolExcludes) { - var hasExportModifier = ts.getCombinedNodeFlags(node) & 1 /* Export */; - if (symbolFlags & 8388608 /* Alias */) { - if (node.kind === 238 /* ExportSpecifier */ || (node.kind === 229 /* ImportEqualsDeclaration */ && hasExportModifier)) { - return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); - } - else { - return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); + else if (node.kind === 171 /* ObjectLiteralExpression */) { + for (var _b = 0, _c = node.properties; _b < _c.length; _b++) { + var p = _c[_b]; + if (p.kind === 253 /* PropertyAssignment */) { + bindDestructuringTargetFlow(p.initializer); + } + else if (p.kind === 254 /* ShorthandPropertyAssignment */) { + bindAssignmentTargetFlow(p.name); + } } } + } + function bindLogicalExpression(node, trueTarget, falseTarget) { + var preRightLabel = createBranchLabel(); + if (node.operatorToken.kind === 51 /* AmpersandAmpersandToken */) { + bindCondition(node.left, preRightLabel, falseTarget); + } else { - // Exported module members are given 2 symbols: A local symbol that is classified with an ExportValue, - // ExportType, or ExportContainer flag, and an associated export symbol with all the correct flags set - // on it. There are 2 main reasons: - // - // 1. We treat locals and exports of the same name as mutually exclusive within a container. - // That means the binder will issue a Duplicate Identifier error if you mix locals and exports - // with the same name in the same container. - // TODO: Make this a more specific error and decouple it from the exclusion logic. - // 2. When we checkIdentifier in the checker, we set its resolved symbol to the local symbol, - // but return the export symbol (by calling getExportSymbolOfValueSymbolIfExported). That way - // when the emitter comes back to it, it knows not to qualify the name if it was found in a containing scope. - // NOTE: Nested ambient modules always should go to to 'locals' table to prevent their automatic merge - // during global merging in the checker. Why? The only case when ambient module is permitted inside another module is module augmentation - // and this case is specially handled. Module augmentations should only be merged with original module definition - // and should never be merged directly with other augmentation, and the latter case would be possible if automatic merge is allowed. - if (!ts.isAmbientModule(node) && (hasExportModifier || container.flags & 8192 /* ExportContext */)) { - var exportKind = (symbolFlags & 107455 /* Value */ ? 1048576 /* ExportValue */ : 0) | - (symbolFlags & 793064 /* Type */ ? 2097152 /* ExportType */ : 0) | - (symbolFlags & 1920 /* Namespace */ ? 4194304 /* ExportNamespace */ : 0); - var local = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes); - local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); - node.localSymbol = local; - return local; - } - else { - return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); - } + bindCondition(node.left, trueTarget, preRightLabel); } + currentFlow = finishFlowLabel(preRightLabel); + bind(node.operatorToken); + bindCondition(node.right, trueTarget, falseTarget); } - // All container nodes are kept on a linked list in declaration order. This list is used by - // the getLocalNameOfContainer function in the type checker to validate that the local name - // used for a container is unique. - function bindContainer(node, containerFlags) { - // Before we recurse into a node's children, we first save the existing parent, container - // and block-container. Then after we pop out of processing the children, we restore - // these saved values. - var saveContainer = container; - var savedBlockScopeContainer = blockScopeContainer; - // Depending on what kind of node this is, we may have to adjust the current container - // and block-container. If the current node is a container, then it is automatically - // considered the current block-container as well. Also, for containers that we know - // may contain locals, we proactively initialize the .locals field. We do this because - // it's highly likely that the .locals will be needed to place some child in (for example, - // a parameter, or variable declaration). - // - // However, we do not proactively create the .locals for block-containers because it's - // totally normal and common for block-containers to never actually have a block-scoped - // variable in them. We don't want to end up allocating an object for every 'block' we - // run into when most of them won't be necessary. - // - // Finally, if this is a block-container, then we clear out any existing .locals object - // it may contain within it. This happens in incremental scenarios. Because we can be - // reusing a node from a previous compilation, that node may have had 'locals' created - // for it. We must clear this so we don't accidentally move any stale data forward from - // a previous compilation. - if (containerFlags & 1 /* IsContainer */) { - container = blockScopeContainer = node; - if (containerFlags & 32 /* HasLocals */) { - container.locals = ts.createMap(); + function bindPrefixUnaryExpressionFlow(node) { + if (node.operator === 49 /* ExclamationToken */) { + var saveTrueTarget = currentTrueTarget; + currentTrueTarget = currentFalseTarget; + currentFalseTarget = saveTrueTarget; + ts.forEachChild(node, bind); + currentFalseTarget = currentTrueTarget; + currentTrueTarget = saveTrueTarget; + } + else { + ts.forEachChild(node, bind); + if (node.operator === 57 /* PlusEqualsToken */ || node.operator === 42 /* MinusMinusToken */) { + bindAssignmentTargetFlow(node.operand); } - addToContainerChain(container); } - else if (containerFlags & 2 /* IsBlockScopedContainer */) { - blockScopeContainer = node; - blockScopeContainer.locals = undefined; + } + function bindPostfixUnaryExpressionFlow(node) { + ts.forEachChild(node, bind); + if (node.operator === 41 /* PlusPlusToken */ || node.operator === 42 /* MinusMinusToken */) { + bindAssignmentTargetFlow(node.operand); } - if (containerFlags & 4 /* IsControlFlowContainer */) { - var saveCurrentFlow = currentFlow; - var saveBreakTarget = currentBreakTarget; - var saveContinueTarget = currentContinueTarget; - var saveReturnTarget = currentReturnTarget; - var saveActiveLabels = activeLabels; - var saveHasExplicitReturn = hasExplicitReturn; - var isIIFE = containerFlags & 16 /* IsFunctionExpression */ && !!ts.getImmediatelyInvokedFunctionExpression(node); - // An IIFE is considered part of the containing control flow. Return statements behave - // similarly to break statements that exit to a label just past the statement body. - if (isIIFE) { - currentReturnTarget = createBranchLabel(); + } + function bindBinaryExpressionFlow(node) { + var operator = node.operatorToken.kind; + if (operator === 51 /* AmpersandAmpersandToken */ || operator === 52 /* BarBarToken */) { + if (isTopLevelLogicalExpression(node)) { + var postExpressionLabel = createBranchLabel(); + bindLogicalExpression(node, postExpressionLabel, postExpressionLabel); + currentFlow = finishFlowLabel(postExpressionLabel); } else { - currentFlow = { flags: 2 /* Start */ }; - if (containerFlags & 16 /* IsFunctionExpression */) { - currentFlow.container = node; - } - currentReturnTarget = undefined; - } - currentBreakTarget = undefined; - currentContinueTarget = undefined; - activeLabels = undefined; - hasExplicitReturn = false; - bindChildren(node); - // Reset all reachability check related flags on node (for incremental scenarios) - // Reset all emit helper flags on node (for incremental scenarios) - node.flags &= ~4030464 /* ReachabilityAndEmitFlags */; - if (!(currentFlow.flags & 1 /* Unreachable */) && containerFlags & 8 /* IsFunctionLike */ && ts.nodeIsPresent(node.body)) { - node.flags |= 32768 /* HasImplicitReturn */; - if (hasExplicitReturn) - node.flags |= 65536 /* HasExplicitReturn */; - } - if (node.kind === 256 /* SourceFile */) { - node.flags |= emitFlags; - } - if (isIIFE) { - addAntecedent(currentReturnTarget, currentFlow); - currentFlow = finishFlowLabel(currentReturnTarget); + bindLogicalExpression(node, currentTrueTarget, currentFalseTarget); } - else { - currentFlow = saveCurrentFlow; + } + else { + ts.forEachChild(node, bind); + if (operator === 56 /* EqualsToken */ && !ts.isAssignmentTarget(node)) { + bindAssignmentTargetFlow(node.left); } - currentBreakTarget = saveBreakTarget; - currentContinueTarget = saveContinueTarget; - currentReturnTarget = saveReturnTarget; - activeLabels = saveActiveLabels; - hasExplicitReturn = saveHasExplicitReturn; } - else if (containerFlags & 64 /* IsInterface */) { - seenThisKeyword = false; - bindChildren(node); - node.flags = seenThisKeyword ? node.flags | 16384 /* ContainsThis */ : node.flags & ~16384 /* ContainsThis */; + } + function bindDeleteExpressionFlow(node) { + ts.forEachChild(node, bind); + if (node.expression.kind === 172 /* PropertyAccessExpression */) { + bindAssignmentTargetFlow(node.expression); + } + } + function bindConditionalExpressionFlow(node) { + var trueLabel = createBranchLabel(); + var falseLabel = createBranchLabel(); + var postExpressionLabel = createBranchLabel(); + bindCondition(node.condition, trueLabel, falseLabel); + currentFlow = finishFlowLabel(trueLabel); + bind(node.whenTrue); + addAntecedent(postExpressionLabel, currentFlow); + currentFlow = finishFlowLabel(falseLabel); + bind(node.whenFalse); + addAntecedent(postExpressionLabel, currentFlow); + currentFlow = finishFlowLabel(postExpressionLabel); + } + function bindInitializedVariableFlow(node) { + var name = !ts.isOmittedExpression(node) ? node.name : undefined; + if (ts.isBindingPattern(name)) { + for (var _i = 0, _a = name.elements; _i < _a.length; _i++) { + var child = _a[_i]; + bindInitializedVariableFlow(child); + } } else { - bindChildren(node); + currentFlow = createFlowAssignment(currentFlow, node); } - container = saveContainer; - blockScopeContainer = savedBlockScopeContainer; } - function bindChildren(node) { - // Binding of JsDocComment should be done before the current block scope container changes. - // because the scope of JsDocComment should not be affected by whether the current node is a - // container or not. - if (ts.isInJavaScriptFile(node) && node.jsDocComments) { - for (var _i = 0, _a = node.jsDocComments; _i < _a.length; _i++) { - var jsDocComment = _a[_i]; - bind(jsDocComment); - } + function bindVariableDeclarationFlow(node) { + ts.forEachChild(node, bind); + if (node.initializer || node.parent.parent.kind === 207 /* ForInStatement */ || node.parent.parent.kind === 208 /* ForOfStatement */) { + bindInitializedVariableFlow(node); } - if (checkUnreachable(node)) { + } + function bindCallExpressionFlow(node) { + // If the target of the call expression is a function expression or arrow function we have + // an immediately invoked function expression (IIFE). Initialize the flowNode property to + // the current control flow (which includes evaluation of the IIFE arguments). + var expr = node.expression; + while (expr.kind === 178 /* ParenthesizedExpression */) { + expr = expr.expression; + } + if (expr.kind === 179 /* FunctionExpression */ || expr.kind === 180 /* ArrowFunction */) { + ts.forEach(node.typeArguments, bind); + ts.forEach(node.arguments, bind); + bind(node.expression); + } + else { ts.forEachChild(node, bind); - return; } + } + function getContainerFlags(node) { switch (node.kind) { - case 205 /* WhileStatement */: - bindWhileStatement(node); - break; - case 204 /* DoStatement */: - bindDoStatement(node); - break; + case 192 /* ClassExpression */: + case 221 /* ClassDeclaration */: + case 224 /* EnumDeclaration */: + case 171 /* ObjectLiteralExpression */: + case 159 /* TypeLiteral */: + case 281 /* JSDocTypeLiteral */: + case 265 /* JSDocRecordType */: + return 1 /* IsContainer */; + case 222 /* InterfaceDeclaration */: + return 1 /* IsContainer */ | 64 /* IsInterface */; + case 269 /* JSDocFunctionType */: + case 225 /* ModuleDeclaration */: + case 223 /* TypeAliasDeclaration */: + return 1 /* IsContainer */ | 32 /* HasLocals */; + case 256 /* SourceFile */: + return 1 /* IsContainer */ | 4 /* IsControlFlowContainer */ | 32 /* HasLocals */; + case 148 /* Constructor */: + case 220 /* FunctionDeclaration */: + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 151 /* CallSignature */: + case 152 /* ConstructSignature */: + case 153 /* IndexSignature */: + case 156 /* FunctionType */: + case 157 /* ConstructorType */: + return 1 /* IsContainer */ | 4 /* IsControlFlowContainer */ | 32 /* HasLocals */ | 8 /* IsFunctionLike */; + case 179 /* FunctionExpression */: + case 180 /* ArrowFunction */: + return 1 /* IsContainer */ | 4 /* IsControlFlowContainer */ | 32 /* HasLocals */ | 8 /* IsFunctionLike */ | 16 /* IsFunctionExpression */; + case 226 /* ModuleBlock */: + return 4 /* IsControlFlowContainer */; + case 145 /* PropertyDeclaration */: + return node.initializer ? 4 /* IsControlFlowContainer */ : 0; + case 252 /* CatchClause */: case 206 /* ForStatement */: - bindForStatement(node); - break; case 207 /* ForInStatement */: case 208 /* ForOfStatement */: - bindForInOrForOfStatement(node); - break; - case 203 /* IfStatement */: - bindIfStatement(node); - break; - case 211 /* ReturnStatement */: - case 215 /* ThrowStatement */: - bindReturnOrThrow(node); - break; - case 210 /* BreakStatement */: - case 209 /* ContinueStatement */: - bindBreakOrContinueStatement(node); - break; - case 216 /* TryStatement */: - bindTryStatement(node); - break; - case 213 /* SwitchStatement */: - bindSwitchStatement(node); - break; case 227 /* CaseBlock */: - bindCaseBlock(node); - break; - case 249 /* CaseClause */: - bindCaseClause(node); - break; - case 214 /* LabeledStatement */: - bindLabeledStatement(node); - break; - case 185 /* PrefixUnaryExpression */: - bindPrefixUnaryExpressionFlow(node); - break; - case 187 /* BinaryExpression */: - bindBinaryExpressionFlow(node); - break; - case 181 /* DeleteExpression */: - bindDeleteExpressionFlow(node); - break; - case 188 /* ConditionalExpression */: - bindConditionalExpressionFlow(node); - break; - case 218 /* VariableDeclaration */: - bindVariableDeclarationFlow(node); - break; - case 174 /* CallExpression */: - bindCallExpressionFlow(node); - break; - default: - ts.forEachChild(node, bind); - break; + return 2 /* IsBlockScopedContainer */; + case 199 /* Block */: + // do not treat blocks directly inside a function as a block-scoped-container. + // Locals that reside in this block should go to the function locals. Otherwise 'x' + // would not appear to be a redeclaration of a block scoped local in the following + // example: + // + // function foo() { + // var x; + // let x; + // } + // + // If we placed 'var x' into the function locals and 'let x' into the locals of + // the block, then there would be no collision. + // + // By not creating a new block-scoped-container here, we ensure that both 'var x' + // and 'let x' go into the Function-container's locals, and we do get a collision + // conflict. + return ts.isFunctionLike(node.parent) ? 0 /* None */ : 2 /* IsBlockScopedContainer */; } + return 0 /* None */; } - function isNarrowingExpression(expr) { - switch (expr.kind) { - case 69 /* Identifier */: - case 97 /* ThisKeyword */: - case 172 /* PropertyAccessExpression */: - return isNarrowableReference(expr); - case 174 /* CallExpression */: - return hasNarrowableArgument(expr); - case 178 /* ParenthesizedExpression */: - return isNarrowingExpression(expr.expression); - case 187 /* BinaryExpression */: - return isNarrowingBinaryExpression(expr); - case 185 /* PrefixUnaryExpression */: - return expr.operator === 49 /* ExclamationToken */ && isNarrowingExpression(expr.operand); + function addToContainerChain(next) { + if (lastContainer) { + lastContainer.nextContainer = next; } - return false; + lastContainer = next; } - function isNarrowableReference(expr) { - return expr.kind === 69 /* Identifier */ || - expr.kind === 97 /* ThisKeyword */ || - expr.kind === 172 /* PropertyAccessExpression */ && isNarrowableReference(expr.expression); + function declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes) { + // Just call this directly so that the return type of this function stays "void". + return declareSymbolAndAddToSymbolTableWorker(node, symbolFlags, symbolExcludes); } - function hasNarrowableArgument(expr) { - if (expr.arguments) { - for (var _i = 0, _a = expr.arguments; _i < _a.length; _i++) { - var argument = _a[_i]; - if (isNarrowableReference(argument)) { + function declareSymbolAndAddToSymbolTableWorker(node, symbolFlags, symbolExcludes) { + switch (container.kind) { + // Modules, source files, and classes need specialized handling for how their + // members are declared (for example, a member of a class will go into a specific + // symbol table depending on if it is static or not). We defer to specialized + // handlers to take care of declaring these child members. + case 225 /* ModuleDeclaration */: + return declareModuleMember(node, symbolFlags, symbolExcludes); + case 256 /* SourceFile */: + return declareSourceFileMember(node, symbolFlags, symbolExcludes); + case 192 /* ClassExpression */: + case 221 /* ClassDeclaration */: + return declareClassMember(node, symbolFlags, symbolExcludes); + case 224 /* EnumDeclaration */: + return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); + case 159 /* TypeLiteral */: + case 171 /* ObjectLiteralExpression */: + case 222 /* InterfaceDeclaration */: + case 265 /* JSDocRecordType */: + case 281 /* JSDocTypeLiteral */: + // Interface/Object-types always have their children added to the 'members' of + // their container. They are only accessible through an instance of their + // container, and are never in scope otherwise (even inside the body of the + // object / type / interface declaring them). An exception is type parameters, + // which are in scope without qualification (similar to 'locals'). + return declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); + case 156 /* FunctionType */: + case 157 /* ConstructorType */: + case 151 /* CallSignature */: + case 152 /* ConstructSignature */: + case 153 /* IndexSignature */: + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + case 148 /* Constructor */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + case 180 /* ArrowFunction */: + case 269 /* JSDocFunctionType */: + case 223 /* TypeAliasDeclaration */: + // All the children of these container types are never visible through another + // symbol (i.e. through another symbol's 'exports' or 'members'). Instead, + // they're only accessed 'lexically' (i.e. from code that exists underneath + // their container in the tree. To accomplish this, we simply add their declared + // symbol to the 'locals' of the container. These symbols can then be found as + // the type checker walks up the containers, checking them for matching names. + return declareSymbol(container.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes); + } + } + function declareClassMember(node, symbolFlags, symbolExcludes) { + return ts.hasModifier(node, 32 /* Static */) + ? declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes) + : declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); + } + function declareSourceFileMember(node, symbolFlags, symbolExcludes) { + return ts.isExternalModule(file) + ? declareModuleMember(node, symbolFlags, symbolExcludes) + : declareSymbol(file.locals, undefined, node, symbolFlags, symbolExcludes); + } + function hasExportDeclarations(node) { + var body = node.kind === 256 /* SourceFile */ ? node : node.body; + if (body && (body.kind === 256 /* SourceFile */ || body.kind === 226 /* ModuleBlock */)) { + for (var _i = 0, _a = body.statements; _i < _a.length; _i++) { + var stat = _a[_i]; + if (stat.kind === 236 /* ExportDeclaration */ || stat.kind === 235 /* ExportAssignment */) { return true; } } } - if (expr.expression.kind === 172 /* PropertyAccessExpression */ && - isNarrowableReference(expr.expression.expression)) { - return true; - } return false; } - function isNarrowingTypeofOperands(expr1, expr2) { - return expr1.kind === 182 /* TypeOfExpression */ && isNarrowableOperand(expr1.expression) && expr2.kind === 9 /* StringLiteral */; + function setExportContextFlag(node) { + // A declaration source file or ambient module declaration that contains no export declarations (but possibly regular + // declarations with export modifiers) is an export context in which declarations are implicitly exported. + if (ts.isInAmbientContext(node) && !hasExportDeclarations(node)) { + node.flags |= 32 /* ExportContext */; + } + else { + node.flags &= ~32 /* ExportContext */; + } } - function isNarrowingBinaryExpression(expr) { - switch (expr.operatorToken.kind) { - case 56 /* EqualsToken */: - return isNarrowableReference(expr.left); - case 30 /* EqualsEqualsToken */: - case 31 /* ExclamationEqualsToken */: - case 32 /* EqualsEqualsEqualsToken */: - case 33 /* ExclamationEqualsEqualsToken */: - return isNarrowableOperand(expr.left) || isNarrowableOperand(expr.right) || - isNarrowingTypeofOperands(expr.right, expr.left) || isNarrowingTypeofOperands(expr.left, expr.right); - case 91 /* InstanceOfKeyword */: - return isNarrowableOperand(expr.left); - case 24 /* CommaToken */: - return isNarrowingExpression(expr.right); + function bindModuleDeclaration(node) { + setExportContextFlag(node); + if (ts.isAmbientModule(node)) { + if (ts.hasModifier(node, 1 /* Export */)) { + errorOnFirstToken(node, ts.Diagnostics.export_modifier_cannot_be_applied_to_ambient_modules_and_module_augmentations_since_they_are_always_visible); + } + if (ts.isExternalModuleAugmentation(node)) { + declareSymbolAndAddToSymbolTable(node, 1024 /* NamespaceModule */, 0 /* NamespaceModuleExcludes */); + } + else { + var pattern = void 0; + if (node.name.kind === 9 /* StringLiteral */) { + var text = node.name.text; + if (ts.hasZeroOrOneAsteriskCharacter(text)) { + pattern = ts.tryParsePattern(text); + } + else { + errorOnFirstToken(node.name, ts.Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, text); + } + } + var symbol = declareSymbolAndAddToSymbolTable(node, 512 /* ValueModule */, 106639 /* ValueModuleExcludes */); + if (pattern) { + (file.patternAmbientModules || (file.patternAmbientModules = [])).push({ pattern: pattern, symbol: symbol }); + } + } + } + else { + var state = getModuleInstanceState(node); + if (state === 0 /* NonInstantiated */) { + declareSymbolAndAddToSymbolTable(node, 1024 /* NamespaceModule */, 0 /* NamespaceModuleExcludes */); + } + else { + declareSymbolAndAddToSymbolTable(node, 512 /* ValueModule */, 106639 /* ValueModuleExcludes */); + if (node.symbol.flags & (16 /* Function */ | 32 /* Class */ | 256 /* RegularEnum */)) { + // if module was already merged with some function, class or non-const enum + // treat is a non-const-enum-only + node.symbol.constEnumOnlyModule = false; + } + else { + var currentModuleIsConstEnumOnly = state === 2 /* ConstEnumOnly */; + if (node.symbol.constEnumOnlyModule === undefined) { + // non-merged case - use the current state + node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly; + } + else { + // merged case: module is const enum only if all its pieces are non-instantiated or const enum + node.symbol.constEnumOnlyModule = node.symbol.constEnumOnlyModule && currentModuleIsConstEnumOnly; + } + } + } } - return false; } - function isNarrowableOperand(expr) { - switch (expr.kind) { - case 178 /* ParenthesizedExpression */: - return isNarrowableOperand(expr.expression); - case 187 /* BinaryExpression */: - switch (expr.operatorToken.kind) { - case 56 /* EqualsToken */: - return isNarrowableOperand(expr.left); - case 24 /* CommaToken */: - return isNarrowableOperand(expr.right); + function bindFunctionOrConstructorType(node) { + // For a given function symbol "<...>(...) => T" we want to generate a symbol identical + // to the one we would get for: { <...>(...): T } + // + // We do that by making an anonymous type literal symbol, and then setting the function + // symbol as its sole member. To the rest of the system, this symbol will be indistinguishable + // from an actual type literal symbol you would have gotten had you used the long form. + var symbol = createSymbol(131072 /* Signature */, getDeclarationName(node)); + addDeclarationToSymbol(symbol, node, 131072 /* Signature */); + var typeLiteralSymbol = createSymbol(2048 /* TypeLiteral */, "__type"); + addDeclarationToSymbol(typeLiteralSymbol, node, 2048 /* TypeLiteral */); + typeLiteralSymbol.members = ts.createMap(); + typeLiteralSymbol.members[symbol.name] = symbol; + } + function bindObjectLiteralExpression(node) { + var ElementKind; + (function (ElementKind) { + ElementKind[ElementKind["Property"] = 1] = "Property"; + ElementKind[ElementKind["Accessor"] = 2] = "Accessor"; + })(ElementKind || (ElementKind = {})); + if (inStrictMode) { + var seen = ts.createMap(); + for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { + var prop = _a[_i]; + if (prop.name.kind !== 69 /* Identifier */) { + continue; + } + var identifier = prop.name; + // ECMA-262 11.1.5 Object Initializer + // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true + // a.This production is contained in strict code and IsDataDescriptor(previous) is true and + // IsDataDescriptor(propId.descriptor) is true. + // b.IsDataDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true. + // c.IsAccessorDescriptor(previous) is true and IsDataDescriptor(propId.descriptor) is true. + // d.IsAccessorDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true + // and either both previous and propId.descriptor have[[Get]] fields or both previous and propId.descriptor have[[Set]] fields + var currentKind = prop.kind === 253 /* PropertyAssignment */ || prop.kind === 254 /* ShorthandPropertyAssignment */ || prop.kind === 147 /* MethodDeclaration */ + ? 1 /* Property */ + : 2 /* Accessor */; + var existingKind = seen[identifier.text]; + if (!existingKind) { + seen[identifier.text] = currentKind; + continue; + } + if (currentKind === 1 /* Property */ && existingKind === 1 /* Property */) { + var span_1 = ts.getErrorSpanForNode(file, identifier); + file.bindDiagnostics.push(ts.createFileDiagnostic(file, span_1.start, span_1.length, ts.Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode)); } + } } - return isNarrowableReference(expr); + return bindAnonymousDeclaration(node, 4096 /* ObjectLiteral */, "__object"); } - function createBranchLabel() { - return { - flags: 4 /* BranchLabel */, - antecedents: undefined - }; + function bindAnonymousDeclaration(node, symbolFlags, name) { + var symbol = createSymbol(symbolFlags, name); + addDeclarationToSymbol(symbol, node, symbolFlags); } - function createLoopLabel() { - return { - flags: 8 /* LoopLabel */, - antecedents: undefined - }; + function bindBlockScopedDeclaration(node, symbolFlags, symbolExcludes) { + switch (blockScopeContainer.kind) { + case 225 /* ModuleDeclaration */: + declareModuleMember(node, symbolFlags, symbolExcludes); + break; + case 256 /* SourceFile */: + if (ts.isExternalModule(container)) { + declareModuleMember(node, symbolFlags, symbolExcludes); + break; + } + // fall through. + default: + if (!blockScopeContainer.locals) { + blockScopeContainer.locals = ts.createMap(); + addToContainerChain(blockScopeContainer); + } + declareSymbol(blockScopeContainer.locals, undefined, node, symbolFlags, symbolExcludes); + } } - function setFlowNodeReferenced(flow) { - // On first reference we set the Referenced flag, thereafter we set the Shared flag - flow.flags |= flow.flags & 256 /* Referenced */ ? 512 /* Shared */ : 256 /* Referenced */; + function bindBlockScopedVariableDeclaration(node) { + bindBlockScopedDeclaration(node, 2 /* BlockScopedVariable */, 107455 /* BlockScopedVariableExcludes */); } - function addAntecedent(label, antecedent) { - if (!(antecedent.flags & 1 /* Unreachable */) && !ts.contains(label.antecedents, antecedent)) { - (label.antecedents || (label.antecedents = [])).push(antecedent); - setFlowNodeReferenced(antecedent); + // The binder visits every node in the syntax tree so it is a convenient place to perform a single localized + // check for reserved words used as identifiers in strict mode code. + function checkStrictModeIdentifier(node) { + if (inStrictMode && + node.originalKeywordKind >= 106 /* FirstFutureReservedWord */ && + node.originalKeywordKind <= 114 /* LastFutureReservedWord */ && + !ts.isIdentifierName(node) && + !ts.isInAmbientContext(node)) { + // Report error only if there are no parse errors in file + if (!file.parseDiagnostics.length) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(node, getStrictModeIdentifierMessage(node), ts.declarationNameToString(node))); + } } } - function createFlowCondition(flags, antecedent, expression) { - if (antecedent.flags & 1 /* Unreachable */) { - return antecedent; + function getStrictModeIdentifierMessage(node) { + // Provide specialized messages to help the user understand why we think they're in + // strict mode. + if (ts.getContainingClass(node)) { + return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode; } - if (!expression) { - return flags & 32 /* TrueCondition */ ? antecedent : unreachableFlow; + if (file.externalModuleIndicator) { + return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Modules_are_automatically_in_strict_mode; } - if (expression.kind === 99 /* TrueKeyword */ && flags & 64 /* FalseCondition */ || - expression.kind === 84 /* FalseKeyword */ && flags & 32 /* TrueCondition */) { - return unreachableFlow; + return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode; + } + function checkStrictModeBinaryExpression(node) { + if (inStrictMode && ts.isLeftHandSideExpression(node.left) && ts.isAssignmentOperator(node.operatorToken.kind)) { + // ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an + // Assignment operator(11.13) or of a PostfixExpression(11.3) + checkStrictModeEvalOrArguments(node, node.left); } - if (!isNarrowingExpression(expression)) { - return antecedent; + } + function checkStrictModeCatchClause(node) { + // It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the + // Catch production is eval or arguments + if (inStrictMode && node.variableDeclaration) { + checkStrictModeEvalOrArguments(node, node.variableDeclaration.name); } - setFlowNodeReferenced(antecedent); - return { - flags: flags, - expression: expression, - antecedent: antecedent - }; } - function createFlowSwitchClause(antecedent, switchStatement, clauseStart, clauseEnd) { - if (!isNarrowingExpression(switchStatement.expression)) { - return antecedent; + function checkStrictModeDeleteExpression(node) { + // Grammar checking + if (inStrictMode && node.expression.kind === 69 /* Identifier */) { + // When a delete operator occurs within strict mode code, a SyntaxError is thrown if its + // UnaryExpression is a direct reference to a variable, function argument, or function name + var span_2 = ts.getErrorSpanForNode(file, node.expression); + file.bindDiagnostics.push(ts.createFileDiagnostic(file, span_2.start, span_2.length, ts.Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode)); } - setFlowNodeReferenced(antecedent); - return { - flags: 128 /* SwitchClause */, - switchStatement: switchStatement, - clauseStart: clauseStart, - clauseEnd: clauseEnd, - antecedent: antecedent - }; } - function createFlowAssignment(antecedent, node) { - setFlowNodeReferenced(antecedent); - return { - flags: 16 /* Assignment */, - antecedent: antecedent, - node: node - }; + function isEvalOrArgumentsIdentifier(node) { + return node.kind === 69 /* Identifier */ && + (node.text === "eval" || node.text === "arguments"); } - function finishFlowLabel(flow) { - var antecedents = flow.antecedents; - if (!antecedents) { - return unreachableFlow; + function checkStrictModeEvalOrArguments(contextNode, name) { + if (name && name.kind === 69 /* Identifier */) { + var identifier = name; + if (isEvalOrArgumentsIdentifier(identifier)) { + // We check first if the name is inside class declaration or class expression; if so give explicit message + // otherwise report generic error message. + var span_3 = ts.getErrorSpanForNode(file, name); + file.bindDiagnostics.push(ts.createFileDiagnostic(file, span_3.start, span_3.length, getStrictModeEvalOrArgumentsMessage(contextNode), identifier.text)); + } } - if (antecedents.length === 1) { - return antecedents[0]; + } + function getStrictModeEvalOrArgumentsMessage(node) { + // Provide specialized messages to help the user understand why we think they're in + // strict mode. + if (ts.getContainingClass(node)) { + return ts.Diagnostics.Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode; } - return flow; + if (file.externalModuleIndicator) { + return ts.Diagnostics.Invalid_use_of_0_Modules_are_automatically_in_strict_mode; + } + return ts.Diagnostics.Invalid_use_of_0_in_strict_mode; } - function isStatementCondition(node) { - var parent = node.parent; - switch (parent.kind) { - case 203 /* IfStatement */: - case 205 /* WhileStatement */: - case 204 /* DoStatement */: - return parent.expression === node; - case 206 /* ForStatement */: - case 188 /* ConditionalExpression */: - return parent.condition === node; + function checkStrictModeFunctionName(node) { + if (inStrictMode) { + // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a strict mode FunctionDeclaration or FunctionExpression (13.1)) + checkStrictModeEvalOrArguments(node, node.name); } - return false; } - function isLogicalExpression(node) { - while (true) { - if (node.kind === 178 /* ParenthesizedExpression */) { - node = node.expression; - } - else if (node.kind === 185 /* PrefixUnaryExpression */ && node.operator === 49 /* ExclamationToken */) { - node = node.operand; - } - else { - return node.kind === 187 /* BinaryExpression */ && (node.operatorToken.kind === 51 /* AmpersandAmpersandToken */ || - node.operatorToken.kind === 52 /* BarBarToken */); + function getStrictModeBlockScopeFunctionDeclarationMessage(node) { + // Provide specialized messages to help the user understand why we think they're in + // strict mode. + if (ts.getContainingClass(node)) { + return ts.Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Class_definitions_are_automatically_in_strict_mode; + } + if (file.externalModuleIndicator) { + return ts.Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Modules_are_automatically_in_strict_mode; + } + return ts.Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5; + } + function checkStrictModeFunctionDeclaration(node) { + if (languageVersion < 2 /* ES6 */) { + // Report error if function is not top level function declaration + if (blockScopeContainer.kind !== 256 /* SourceFile */ && + blockScopeContainer.kind !== 225 /* ModuleDeclaration */ && + !ts.isFunctionLike(blockScopeContainer)) { + // We check first if the name is inside class declaration or class expression; if so give explicit message + // otherwise report generic error message. + var errorSpan = ts.getErrorSpanForNode(file, node); + file.bindDiagnostics.push(ts.createFileDiagnostic(file, errorSpan.start, errorSpan.length, getStrictModeBlockScopeFunctionDeclarationMessage(node))); } } } - function isTopLevelLogicalExpression(node) { - while (node.parent.kind === 178 /* ParenthesizedExpression */ || - node.parent.kind === 185 /* PrefixUnaryExpression */ && - node.parent.operator === 49 /* ExclamationToken */) { - node = node.parent; + function checkStrictModeNumericLiteral(node) { + if (inStrictMode && node.isOctalLiteral) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Octal_literals_are_not_allowed_in_strict_mode)); } - return !isStatementCondition(node) && !isLogicalExpression(node.parent); } - function bindCondition(node, trueTarget, falseTarget) { - var saveTrueTarget = currentTrueTarget; - var saveFalseTarget = currentFalseTarget; - currentTrueTarget = trueTarget; - currentFalseTarget = falseTarget; - bind(node); - currentTrueTarget = saveTrueTarget; - currentFalseTarget = saveFalseTarget; - if (!node || !isLogicalExpression(node)) { - addAntecedent(trueTarget, createFlowCondition(32 /* TrueCondition */, currentFlow, node)); - addAntecedent(falseTarget, createFlowCondition(64 /* FalseCondition */, currentFlow, node)); + function checkStrictModePostfixUnaryExpression(node) { + // Grammar checking + // The identifier eval or arguments may not appear as the LeftHandSideExpression of an + // Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression + // operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator. + if (inStrictMode) { + checkStrictModeEvalOrArguments(node, node.operand); } } - function bindIterativeStatement(node, breakTarget, continueTarget) { - var saveBreakTarget = currentBreakTarget; - var saveContinueTarget = currentContinueTarget; - currentBreakTarget = breakTarget; - currentContinueTarget = continueTarget; - bind(node); - currentBreakTarget = saveBreakTarget; - currentContinueTarget = saveContinueTarget; + function checkStrictModePrefixUnaryExpression(node) { + // Grammar checking + if (inStrictMode) { + if (node.operator === 41 /* PlusPlusToken */ || node.operator === 42 /* MinusMinusToken */) { + checkStrictModeEvalOrArguments(node, node.operand); + } + } } - function bindWhileStatement(node) { - var preWhileLabel = createLoopLabel(); - var preBodyLabel = createBranchLabel(); - var postWhileLabel = createBranchLabel(); - addAntecedent(preWhileLabel, currentFlow); - currentFlow = preWhileLabel; - bindCondition(node.expression, preBodyLabel, postWhileLabel); - currentFlow = finishFlowLabel(preBodyLabel); - bindIterativeStatement(node.statement, postWhileLabel, preWhileLabel); - addAntecedent(preWhileLabel, currentFlow); - currentFlow = finishFlowLabel(postWhileLabel); + function checkStrictModeWithStatement(node) { + // Grammar checking for withStatement + if (inStrictMode) { + errorOnFirstToken(node, ts.Diagnostics.with_statements_are_not_allowed_in_strict_mode); + } } - function bindDoStatement(node) { - var preDoLabel = createLoopLabel(); - var preConditionLabel = createBranchLabel(); - var postDoLabel = createBranchLabel(); - addAntecedent(preDoLabel, currentFlow); - currentFlow = preDoLabel; - bindIterativeStatement(node.statement, postDoLabel, preConditionLabel); - addAntecedent(preConditionLabel, currentFlow); - currentFlow = finishFlowLabel(preConditionLabel); - bindCondition(node.expression, preDoLabel, postDoLabel); - currentFlow = finishFlowLabel(postDoLabel); + function errorOnFirstToken(node, message, arg0, arg1, arg2) { + var span = ts.getSpanOfTokenAtPosition(file, node.pos); + file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, message, arg0, arg1, arg2)); } - function bindForStatement(node) { - var preLoopLabel = createLoopLabel(); - var preBodyLabel = createBranchLabel(); - var postLoopLabel = createBranchLabel(); - bind(node.initializer); - addAntecedent(preLoopLabel, currentFlow); - currentFlow = preLoopLabel; - bindCondition(node.condition, preBodyLabel, postLoopLabel); - currentFlow = finishFlowLabel(preBodyLabel); - bindIterativeStatement(node.statement, postLoopLabel, preLoopLabel); - bind(node.incrementor); - addAntecedent(preLoopLabel, currentFlow); - currentFlow = finishFlowLabel(postLoopLabel); + function getDestructuringParameterName(node) { + return "__" + ts.indexOf(node.parent.parameters, node); } - function bindForInOrForOfStatement(node) { - var preLoopLabel = createLoopLabel(); - var postLoopLabel = createBranchLabel(); - addAntecedent(preLoopLabel, currentFlow); - currentFlow = preLoopLabel; - bind(node.expression); - addAntecedent(postLoopLabel, currentFlow); - bind(node.initializer); - if (node.initializer.kind !== 219 /* VariableDeclarationList */) { - bindAssignmentTargetFlow(node.initializer); + function bind(node) { + if (!node) { + return; } - bindIterativeStatement(node.statement, postLoopLabel, preLoopLabel); - addAntecedent(preLoopLabel, currentFlow); - currentFlow = finishFlowLabel(postLoopLabel); - } - function bindIfStatement(node) { - var thenLabel = createBranchLabel(); - var elseLabel = createBranchLabel(); - var postIfLabel = createBranchLabel(); - bindCondition(node.expression, thenLabel, elseLabel); - currentFlow = finishFlowLabel(thenLabel); - bind(node.thenStatement); - addAntecedent(postIfLabel, currentFlow); - currentFlow = finishFlowLabel(elseLabel); - bind(node.elseStatement); - addAntecedent(postIfLabel, currentFlow); - currentFlow = finishFlowLabel(postIfLabel); - } - function bindReturnOrThrow(node) { - bind(node.expression); - if (node.kind === 211 /* ReturnStatement */) { - hasExplicitReturn = true; - if (currentReturnTarget) { - addAntecedent(currentReturnTarget, currentFlow); + node.parent = parent; + var saveInStrictMode = inStrictMode; + // First we bind declaration nodes to a symbol if possible. We'll both create a symbol + // and then potentially add the symbol to an appropriate symbol table. Possible + // destination symbol tables are: + // + // 1) The 'exports' table of the current container's symbol. + // 2) The 'members' table of the current container's symbol. + // 3) The 'locals' table of the current container. + // + // However, not all symbols will end up in any of these tables. 'Anonymous' symbols + // (like TypeLiterals for example) will not be put in any table. + bindWorker(node); + // Then we recurse into the children of the node to bind them as well. For certain + // symbols we do specialized work when we recurse. For example, we'll keep track of + // the current 'container' node when it changes. This helps us know which symbol table + // a local should go into for example. Since terminal nodes are known not to have + // children, as an optimization we don't process those. + if (node.kind > 138 /* LastToken */) { + var saveParent = parent; + parent = node; + var containerFlags = getContainerFlags(node); + if (containerFlags === 0 /* None */) { + bindChildren(node); } + else { + bindContainer(node, containerFlags); + } + parent = saveParent; } - currentFlow = unreachableFlow; + else if (!skipTransformFlagAggregation && (node.transformFlags & 536870912 /* HasComputedFlags */) === 0) { + subtreeTransformFlags |= computeTransformFlagsForNode(node, 0); + } + inStrictMode = saveInStrictMode; } - function findActiveLabel(name) { - if (activeLabels) { - for (var _i = 0, activeLabels_1 = activeLabels; _i < activeLabels_1.length; _i++) { - var label = activeLabels_1[_i]; - if (label.name === name) { - return label; + function updateStrictModeStatementList(statements) { + if (!inStrictMode) { + for (var _i = 0, statements_1 = statements; _i < statements_1.length; _i++) { + var statement = statements_1[_i]; + if (!ts.isPrologueDirective(statement)) { + return; + } + if (isUseStrictPrologueDirective(statement)) { + inStrictMode = true; + return; } } } - return undefined; } - function bindbreakOrContinueFlow(node, breakTarget, continueTarget) { - var flowLabel = node.kind === 210 /* BreakStatement */ ? breakTarget : continueTarget; - if (flowLabel) { - addAntecedent(flowLabel, currentFlow); - currentFlow = unreachableFlow; + /// Should be called only on prologue directives (isPrologueDirective(node) should be true) + function isUseStrictPrologueDirective(node) { + var nodeText = ts.getTextOfNodeFromSourceText(file.text, node.expression); + // Note: the node text must be exactly "use strict" or 'use strict'. It is not ok for the + // string to contain unicode escapes (as per ES5). + return nodeText === '"use strict"' || nodeText === "'use strict'"; + } + function bindWorker(node) { + switch (node.kind) { + /* Strict mode checks */ + case 69 /* Identifier */: + case 97 /* ThisKeyword */: + if (currentFlow && (ts.isExpression(node) || parent.kind === 254 /* ShorthandPropertyAssignment */)) { + node.flowNode = currentFlow; + } + return checkStrictModeIdentifier(node); + case 172 /* PropertyAccessExpression */: + if (currentFlow && isNarrowableReference(node)) { + node.flowNode = currentFlow; + } + break; + case 187 /* BinaryExpression */: + if (ts.isInJavaScriptFile(node)) { + var specialKind = ts.getSpecialPropertyAssignmentKind(node); + switch (specialKind) { + case 1 /* ExportsProperty */: + bindExportsPropertyAssignment(node); + break; + case 2 /* ModuleExports */: + bindModuleExportsAssignment(node); + break; + case 3 /* PrototypeProperty */: + bindPrototypePropertyAssignment(node); + break; + case 4 /* ThisProperty */: + bindThisPropertyAssignment(node); + break; + case 0 /* None */: + // Nothing to do + break; + default: + ts.Debug.fail("Unknown special property assignment kind"); + } + } + return checkStrictModeBinaryExpression(node); + case 252 /* CatchClause */: + return checkStrictModeCatchClause(node); + case 181 /* DeleteExpression */: + return checkStrictModeDeleteExpression(node); + case 8 /* NumericLiteral */: + return checkStrictModeNumericLiteral(node); + case 186 /* PostfixUnaryExpression */: + return checkStrictModePostfixUnaryExpression(node); + case 185 /* PrefixUnaryExpression */: + return checkStrictModePrefixUnaryExpression(node); + case 212 /* WithStatement */: + return checkStrictModeWithStatement(node); + case 165 /* ThisType */: + seenThisKeyword = true; + return; + case 154 /* TypePredicate */: + return checkTypePredicate(node); + case 141 /* TypeParameter */: + return declareSymbolAndAddToSymbolTable(node, 262144 /* TypeParameter */, 530920 /* TypeParameterExcludes */); + case 142 /* Parameter */: + return bindParameter(node); + case 218 /* VariableDeclaration */: + case 169 /* BindingElement */: + return bindVariableDeclarationOrBindingElement(node); + case 145 /* PropertyDeclaration */: + case 144 /* PropertySignature */: + case 266 /* JSDocRecordMember */: + return bindPropertyOrMethodOrAccessor(node, 4 /* Property */ | (node.questionToken ? 536870912 /* Optional */ : 0 /* None */), 0 /* PropertyExcludes */); + case 280 /* JSDocPropertyTag */: + return bindJSDocProperty(node); + case 253 /* PropertyAssignment */: + case 254 /* ShorthandPropertyAssignment */: + return bindPropertyOrMethodOrAccessor(node, 4 /* Property */, 0 /* PropertyExcludes */); + case 255 /* EnumMember */: + return bindPropertyOrMethodOrAccessor(node, 8 /* EnumMember */, 900095 /* EnumMemberExcludes */); + case 247 /* JsxSpreadAttribute */: + emitFlags |= 16384 /* HasJsxSpreadAttributes */; + return; + case 151 /* CallSignature */: + case 152 /* ConstructSignature */: + case 153 /* IndexSignature */: + return declareSymbolAndAddToSymbolTable(node, 131072 /* Signature */, 0 /* None */); + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + // If this is an ObjectLiteralExpression method, then it sits in the same space + // as other properties in the object literal. So we use SymbolFlags.PropertyExcludes + // so that it will conflict with any other object literal members with the same + // name. + return bindPropertyOrMethodOrAccessor(node, 8192 /* Method */ | (node.questionToken ? 536870912 /* Optional */ : 0 /* None */), ts.isObjectLiteralMethod(node) ? 0 /* PropertyExcludes */ : 99263 /* MethodExcludes */); + case 220 /* FunctionDeclaration */: + return bindFunctionDeclaration(node); + case 148 /* Constructor */: + return declareSymbolAndAddToSymbolTable(node, 16384 /* Constructor */, /*symbolExcludes:*/ 0 /* None */); + case 149 /* GetAccessor */: + return bindPropertyOrMethodOrAccessor(node, 32768 /* GetAccessor */, 41919 /* GetAccessorExcludes */); + case 150 /* SetAccessor */: + return bindPropertyOrMethodOrAccessor(node, 65536 /* SetAccessor */, 74687 /* SetAccessorExcludes */); + case 156 /* FunctionType */: + case 157 /* ConstructorType */: + case 269 /* JSDocFunctionType */: + return bindFunctionOrConstructorType(node); + case 159 /* TypeLiteral */: + case 281 /* JSDocTypeLiteral */: + case 265 /* JSDocRecordType */: + return bindAnonymousDeclaration(node, 2048 /* TypeLiteral */, "__type"); + case 171 /* ObjectLiteralExpression */: + return bindObjectLiteralExpression(node); + case 179 /* FunctionExpression */: + case 180 /* ArrowFunction */: + return bindFunctionExpression(node); + case 174 /* CallExpression */: + if (ts.isInJavaScriptFile(node)) { + bindCallExpression(node); + } + break; + // Members of classes, interfaces, and modules + case 192 /* ClassExpression */: + case 221 /* ClassDeclaration */: + // All classes are automatically in strict mode in ES6. + inStrictMode = true; + return bindClassLikeDeclaration(node); + case 222 /* InterfaceDeclaration */: + return bindBlockScopedDeclaration(node, 64 /* Interface */, 792968 /* InterfaceExcludes */); + case 279 /* JSDocTypedefTag */: + case 223 /* TypeAliasDeclaration */: + return bindBlockScopedDeclaration(node, 524288 /* TypeAlias */, 793064 /* TypeAliasExcludes */); + case 224 /* EnumDeclaration */: + return bindEnumDeclaration(node); + case 225 /* ModuleDeclaration */: + return bindModuleDeclaration(node); + // Imports and exports + case 229 /* ImportEqualsDeclaration */: + case 232 /* NamespaceImport */: + case 234 /* ImportSpecifier */: + case 238 /* ExportSpecifier */: + return declareSymbolAndAddToSymbolTable(node, 8388608 /* Alias */, 8388608 /* AliasExcludes */); + case 228 /* NamespaceExportDeclaration */: + return bindNamespaceExportDeclaration(node); + case 231 /* ImportClause */: + return bindImportClause(node); + case 236 /* ExportDeclaration */: + return bindExportDeclaration(node); + case 235 /* ExportAssignment */: + return bindExportAssignment(node); + case 256 /* SourceFile */: + updateStrictModeStatementList(node.statements); + return bindSourceFileIfExternalModule(); + case 199 /* Block */: + if (!ts.isFunctionLike(node.parent)) { + return; + } + // Fall through + case 226 /* ModuleBlock */: + return updateStrictModeStatementList(node.statements); } } - function bindBreakOrContinueStatement(node) { - bind(node.label); - if (node.label) { - var activeLabel = findActiveLabel(node.label.text); - if (activeLabel) { - activeLabel.referenced = true; - bindbreakOrContinueFlow(node, activeLabel.breakTarget, activeLabel.continueTarget); - } + function checkTypePredicate(node) { + var parameterName = node.parameterName, type = node.type; + if (parameterName && parameterName.kind === 69 /* Identifier */) { + checkStrictModeIdentifier(parameterName); + } + if (parameterName && parameterName.kind === 165 /* ThisType */) { + seenThisKeyword = true; + } + bind(type); + } + function bindSourceFileIfExternalModule() { + setExportContextFlag(file); + if (ts.isExternalModule(file)) { + bindSourceFileAsExternalModule(); + } + } + function bindSourceFileAsExternalModule() { + bindAnonymousDeclaration(file, 512 /* ValueModule */, "\"" + ts.removeFileExtension(file.fileName) + "\""); + } + function bindExportAssignment(node) { + if (!container.symbol || !container.symbol.exports) { + // Export assignment in some sort of block construct + bindAnonymousDeclaration(node, 8388608 /* Alias */, getDeclarationName(node)); + } + else { + var flags = node.kind === 235 /* ExportAssignment */ && ts.exportAssignmentIsAlias(node) + ? 8388608 /* Alias */ + : 4 /* Property */; + declareSymbol(container.symbol.exports, container.symbol, node, flags, 0 /* PropertyExcludes */ | 8388608 /* AliasExcludes */); + } + } + function bindNamespaceExportDeclaration(node) { + if (node.modifiers && node.modifiers.length) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Modifiers_cannot_appear_here)); + } + if (node.parent.kind !== 256 /* SourceFile */) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Global_module_exports_may_only_appear_at_top_level)); + return; } else { - bindbreakOrContinueFlow(node, currentBreakTarget, currentContinueTarget); + var parent_6 = node.parent; + if (!ts.isExternalModule(parent_6)) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Global_module_exports_may_only_appear_in_module_files)); + return; + } + if (!parent_6.isDeclarationFile) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Global_module_exports_may_only_appear_in_declaration_files)); + return; + } } + file.symbol.globalExports = file.symbol.globalExports || ts.createMap(); + declareSymbol(file.symbol.globalExports, file.symbol, node, 8388608 /* Alias */, 8388608 /* AliasExcludes */); } - function bindTryStatement(node) { - var postFinallyLabel = createBranchLabel(); - var preTryFlow = currentFlow; - // TODO: Every statement in try block is potentially an exit point! - bind(node.tryBlock); - addAntecedent(postFinallyLabel, currentFlow); - if (node.catchClause) { - currentFlow = preTryFlow; - bind(node.catchClause); - addAntecedent(postFinallyLabel, currentFlow); + function bindExportDeclaration(node) { + if (!container.symbol || !container.symbol.exports) { + // Export * in some sort of block construct + bindAnonymousDeclaration(node, 1073741824 /* ExportStar */, getDeclarationName(node)); } - if (node.finallyBlock) { - currentFlow = preTryFlow; - bind(node.finallyBlock); + else if (!node.exportClause) { + // All export * declarations are collected in an __export symbol + declareSymbol(container.symbol.exports, container.symbol, node, 1073741824 /* ExportStar */, 0 /* None */); } - currentFlow = finishFlowLabel(postFinallyLabel); } - function bindSwitchStatement(node) { - var postSwitchLabel = createBranchLabel(); - bind(node.expression); - var saveBreakTarget = currentBreakTarget; - var savePreSwitchCaseFlow = preSwitchCaseFlow; - currentBreakTarget = postSwitchLabel; - preSwitchCaseFlow = currentFlow; - bind(node.caseBlock); - addAntecedent(postSwitchLabel, currentFlow); - var hasDefault = ts.forEach(node.caseBlock.clauses, function (c) { return c.kind === 250 /* DefaultClause */; }); - // We mark a switch statement as possibly exhaustive if it has no default clause and if all - // case clauses have unreachable end points (e.g. they all return). - node.possiblyExhaustive = !hasDefault && !postSwitchLabel.antecedents; - if (!hasDefault) { - addAntecedent(postSwitchLabel, createFlowSwitchClause(preSwitchCaseFlow, node, 0, 0)); + function bindImportClause(node) { + if (node.name) { + declareSymbolAndAddToSymbolTable(node, 8388608 /* Alias */, 8388608 /* AliasExcludes */); } - currentBreakTarget = saveBreakTarget; - preSwitchCaseFlow = savePreSwitchCaseFlow; - currentFlow = finishFlowLabel(postSwitchLabel); } - function bindCaseBlock(node) { - var clauses = node.clauses; - var fallthroughFlow = unreachableFlow; - for (var i = 0; i < clauses.length; i++) { - var clauseStart = i; - while (!clauses[i].statements.length && i + 1 < clauses.length) { - bind(clauses[i]); - i++; - } - var preCaseLabel = createBranchLabel(); - addAntecedent(preCaseLabel, createFlowSwitchClause(preSwitchCaseFlow, node.parent, clauseStart, i + 1)); - addAntecedent(preCaseLabel, fallthroughFlow); - currentFlow = finishFlowLabel(preCaseLabel); - var clause = clauses[i]; - bind(clause); - fallthroughFlow = currentFlow; - if (!(currentFlow.flags & 1 /* Unreachable */) && i !== clauses.length - 1 && options.noFallthroughCasesInSwitch) { - errorOnFirstToken(clause, ts.Diagnostics.Fallthrough_case_in_switch); - } + function setCommonJsModuleIndicator(node) { + if (!file.commonJsModuleIndicator) { + file.commonJsModuleIndicator = node; + bindSourceFileAsExternalModule(); } } - function bindCaseClause(node) { - var saveCurrentFlow = currentFlow; - currentFlow = preSwitchCaseFlow; - bind(node.expression); - currentFlow = saveCurrentFlow; - ts.forEach(node.statements, bind); - } - function pushActiveLabel(name, breakTarget, continueTarget) { - var activeLabel = { - name: name, - breakTarget: breakTarget, - continueTarget: continueTarget, - referenced: false - }; - (activeLabels || (activeLabels = [])).push(activeLabel); - return activeLabel; + function bindExportsPropertyAssignment(node) { + // When we create a property via 'exports.foo = bar', the 'exports.foo' property access + // expression is the declaration + setCommonJsModuleIndicator(node); + declareSymbol(file.symbol.exports, file.symbol, node.left, 4 /* Property */ | 7340032 /* Export */, 0 /* None */); } - function popActiveLabel() { - activeLabels.pop(); + function bindModuleExportsAssignment(node) { + // 'module.exports = expr' assignment + setCommonJsModuleIndicator(node); + declareSymbol(file.symbol.exports, file.symbol, node, 4 /* Property */ | 7340032 /* Export */ | 512 /* ValueModule */, 0 /* None */); } - function bindLabeledStatement(node) { - var preStatementLabel = createLoopLabel(); - var postStatementLabel = createBranchLabel(); - bind(node.label); - addAntecedent(preStatementLabel, currentFlow); - var activeLabel = pushActiveLabel(node.label.text, postStatementLabel, preStatementLabel); - bind(node.statement); - popActiveLabel(); - if (!activeLabel.referenced && !options.allowUnusedLabels) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(node.label, ts.Diagnostics.Unused_label)); + function bindThisPropertyAssignment(node) { + ts.Debug.assert(ts.isInJavaScriptFile(node)); + // Declare a 'member' if the container is an ES5 class or ES6 constructor + if (container.kind === 220 /* FunctionDeclaration */ || container.kind === 179 /* FunctionExpression */) { + container.symbol.members = container.symbol.members || ts.createMap(); + // It's acceptable for multiple 'this' assignments of the same identifier to occur + declareSymbol(container.symbol.members, container.symbol, node, 4 /* Property */, 0 /* PropertyExcludes */ & ~4 /* Property */); + } + else if (container.kind === 148 /* Constructor */) { + // this.foo assignment in a JavaScript class + // Bind this property to the containing class + var saveContainer = container; + container = container.parent; + var symbol = bindPropertyOrMethodOrAccessor(node, 4 /* Property */, 0 /* None */); + if (symbol) { + // constructor-declared symbols can be overwritten by subsequent method declarations + symbol.isReplaceableByMethod = true; + } + container = saveContainer; } - addAntecedent(postStatementLabel, currentFlow); - currentFlow = finishFlowLabel(postStatementLabel); } - function bindDestructuringTargetFlow(node) { - if (node.kind === 187 /* BinaryExpression */ && node.operatorToken.kind === 56 /* EqualsToken */) { - bindAssignmentTargetFlow(node.left); + function bindPrototypePropertyAssignment(node) { + // We saw a node of the form 'x.prototype.y = z'. Declare a 'member' y on x if x was a function. + // Look up the function in the local scope, since prototype assignments should + // follow the function declaration + var leftSideOfAssignment = node.left; + var classPrototype = leftSideOfAssignment.expression; + var constructorFunction = classPrototype.expression; + // Fix up parent pointers since we're going to use these nodes before we bind into them + leftSideOfAssignment.parent = node; + constructorFunction.parent = classPrototype; + classPrototype.parent = leftSideOfAssignment; + var funcSymbol = container.locals[constructorFunction.text]; + if (!funcSymbol || !(funcSymbol.flags & 16 /* Function */ || ts.isDeclarationOfFunctionExpression(funcSymbol))) { + return; } - else { - bindAssignmentTargetFlow(node); + // Set up the members collection if it doesn't exist already + if (!funcSymbol.members) { + funcSymbol.members = ts.createMap(); } + // Declare the method/property + declareSymbol(funcSymbol.members, funcSymbol, leftSideOfAssignment, 4 /* Property */, 0 /* PropertyExcludes */); } - function bindAssignmentTargetFlow(node) { - if (isNarrowableReference(node)) { - currentFlow = createFlowAssignment(currentFlow, node); + function bindCallExpression(node) { + // We're only inspecting call expressions to detect CommonJS modules, so we can skip + // this check if we've already seen the module indicator + if (!file.commonJsModuleIndicator && ts.isRequireCall(node, /*checkArgumentIsStringLiteral*/ false)) { + setCommonJsModuleIndicator(node); } - else if (node.kind === 170 /* ArrayLiteralExpression */) { - for (var _i = 0, _a = node.elements; _i < _a.length; _i++) { - var e = _a[_i]; - if (e.kind === 191 /* SpreadElementExpression */) { - bindAssignmentTargetFlow(e.expression); - } - else { - bindDestructuringTargetFlow(e); - } + } + function bindClassLikeDeclaration(node) { + if (!ts.isDeclarationFile(file) && !ts.isInAmbientContext(node)) { + if (ts.getClassExtendsHeritageClauseElement(node) !== undefined) { + emitFlags |= 1024 /* HasClassExtends */; } - } - else if (node.kind === 171 /* ObjectLiteralExpression */) { - for (var _b = 0, _c = node.properties; _b < _c.length; _b++) { - var p = _c[_b]; - if (p.kind === 253 /* PropertyAssignment */) { - bindDestructuringTargetFlow(p.initializer); - } - else if (p.kind === 254 /* ShorthandPropertyAssignment */) { - bindAssignmentTargetFlow(p.name); - } + if (ts.nodeIsDecorated(node)) { + emitFlags |= 2048 /* HasDecorators */; } } - } - function bindLogicalExpression(node, trueTarget, falseTarget) { - var preRightLabel = createBranchLabel(); - if (node.operatorToken.kind === 51 /* AmpersandAmpersandToken */) { - bindCondition(node.left, preRightLabel, falseTarget); + if (node.kind === 221 /* ClassDeclaration */) { + bindBlockScopedDeclaration(node, 32 /* Class */, 899519 /* ClassExcludes */); } else { - bindCondition(node.left, trueTarget, preRightLabel); - } - currentFlow = finishFlowLabel(preRightLabel); - bind(node.operatorToken); - bindCondition(node.right, trueTarget, falseTarget); - } - function bindPrefixUnaryExpressionFlow(node) { - if (node.operator === 49 /* ExclamationToken */) { - var saveTrueTarget = currentTrueTarget; - currentTrueTarget = currentFalseTarget; - currentFalseTarget = saveTrueTarget; - ts.forEachChild(node, bind); - currentFalseTarget = currentTrueTarget; - currentTrueTarget = saveTrueTarget; + var bindingName = node.name ? node.name.text : "__class"; + bindAnonymousDeclaration(node, 32 /* Class */, bindingName); + // Add name of class expression into the map for semantic classifier + if (node.name) { + classifiableNames[node.name.text] = node.name.text; + } } - else { - ts.forEachChild(node, bind); + var symbol = node.symbol; + // TypeScript 1.0 spec (April 2014): 8.4 + // Every class automatically contains a static property member named 'prototype', the + // type of which is an instantiation of the class type with type Any supplied as a type + // argument for each type parameter. It is an error to explicitly declare a static + // property member with the name 'prototype'. + // + // Note: we check for this here because this class may be merging into a module. The + // module might have an exported variable called 'prototype'. We can't allow that as + // that would clash with the built-in 'prototype' for the class. + var prototypeSymbol = createSymbol(4 /* Property */ | 134217728 /* Prototype */, "prototype"); + if (symbol.exports[prototypeSymbol.name]) { + if (node.name) { + node.name.parent = node; + } + file.bindDiagnostics.push(ts.createDiagnosticForNode(symbol.exports[prototypeSymbol.name].declarations[0], ts.Diagnostics.Duplicate_identifier_0, prototypeSymbol.name)); } + symbol.exports[prototypeSymbol.name] = prototypeSymbol; + prototypeSymbol.parent = symbol; } - function bindBinaryExpressionFlow(node) { - var operator = node.operatorToken.kind; - if (operator === 51 /* AmpersandAmpersandToken */ || operator === 52 /* BarBarToken */) { - if (isTopLevelLogicalExpression(node)) { - var postExpressionLabel = createBranchLabel(); - bindLogicalExpression(node, postExpressionLabel, postExpressionLabel); - currentFlow = finishFlowLabel(postExpressionLabel); + function bindEnumDeclaration(node) { + return ts.isConst(node) + ? bindBlockScopedDeclaration(node, 128 /* ConstEnum */, 899967 /* ConstEnumExcludes */) + : bindBlockScopedDeclaration(node, 256 /* RegularEnum */, 899327 /* RegularEnumExcludes */); + } + function bindVariableDeclarationOrBindingElement(node) { + if (inStrictMode) { + checkStrictModeEvalOrArguments(node, node.name); + } + if (!ts.isBindingPattern(node.name)) { + if (ts.isBlockOrCatchScoped(node)) { + bindBlockScopedVariableDeclaration(node); } - else { - bindLogicalExpression(node, currentTrueTarget, currentFalseTarget); + else if (ts.isParameterDeclaration(node)) { + // It is safe to walk up parent chain to find whether the node is a destructing parameter declaration + // because its parent chain has already been set up, since parents are set before descending into children. + // + // If node is a binding element in parameter declaration, we need to use ParameterExcludes. + // Using ParameterExcludes flag allows the compiler to report an error on duplicate identifiers in Parameter Declaration + // For example: + // function foo([a,a]) {} // Duplicate Identifier error + // function bar(a,a) {} // Duplicate Identifier error, parameter declaration in this case is handled in bindParameter + // // which correctly set excluded symbols + declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 107455 /* ParameterExcludes */); } - } - else { - ts.forEachChild(node, bind); - if (operator === 56 /* EqualsToken */ && !ts.isAssignmentTarget(node)) { - bindAssignmentTargetFlow(node.left); + else { + declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 107454 /* FunctionScopedVariableExcludes */); } } } - function bindDeleteExpressionFlow(node) { - ts.forEachChild(node, bind); - if (node.expression.kind === 172 /* PropertyAccessExpression */) { - bindAssignmentTargetFlow(node.expression); + function bindParameter(node) { + if (!ts.isDeclarationFile(file) && + !ts.isInAmbientContext(node) && + ts.nodeIsDecorated(node)) { + emitFlags |= (2048 /* HasDecorators */ | 4096 /* HasParamDecorators */); } - } - function bindConditionalExpressionFlow(node) { - var trueLabel = createBranchLabel(); - var falseLabel = createBranchLabel(); - var postExpressionLabel = createBranchLabel(); - bindCondition(node.condition, trueLabel, falseLabel); - currentFlow = finishFlowLabel(trueLabel); - bind(node.whenTrue); - addAntecedent(postExpressionLabel, currentFlow); - currentFlow = finishFlowLabel(falseLabel); - bind(node.whenFalse); - addAntecedent(postExpressionLabel, currentFlow); - currentFlow = finishFlowLabel(postExpressionLabel); - } - function bindInitializedVariableFlow(node) { - var name = node.name; - if (ts.isBindingPattern(name)) { - for (var _i = 0, _a = name.elements; _i < _a.length; _i++) { - var child = _a[_i]; - bindInitializedVariableFlow(child); - } + if (inStrictMode) { + // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a + // strict mode FunctionLikeDeclaration or FunctionExpression(13.1) + checkStrictModeEvalOrArguments(node, node.name); + } + if (ts.isBindingPattern(node.name)) { + bindAnonymousDeclaration(node, 1 /* FunctionScopedVariable */, getDestructuringParameterName(node)); } else { - currentFlow = createFlowAssignment(currentFlow, node); + declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 107455 /* ParameterExcludes */); } - } - function bindVariableDeclarationFlow(node) { - ts.forEachChild(node, bind); - if (node.initializer || node.parent.parent.kind === 207 /* ForInStatement */ || node.parent.parent.kind === 208 /* ForOfStatement */) { - bindInitializedVariableFlow(node); + // If this is a property-parameter, then also declare the property symbol into the + // containing class. + if (ts.isParameterPropertyDeclaration(node)) { + var classDeclaration = node.parent.parent; + declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, 4 /* Property */ | (node.questionToken ? 536870912 /* Optional */ : 0 /* None */), 0 /* PropertyExcludes */); } } - function bindCallExpressionFlow(node) { - // If the target of the call expression is a function expression or arrow function we have - // an immediately invoked function expression (IIFE). Initialize the flowNode property to - // the current control flow (which includes evaluation of the IIFE arguments). - var expr = node.expression; - while (expr.kind === 178 /* ParenthesizedExpression */) { - expr = expr.expression; + function bindFunctionDeclaration(node) { + if (!ts.isDeclarationFile(file) && !ts.isInAmbientContext(node)) { + if (ts.isAsyncFunctionLike(node)) { + emitFlags |= 8192 /* HasAsyncFunctions */; + } } - if (expr.kind === 179 /* FunctionExpression */ || expr.kind === 180 /* ArrowFunction */) { - ts.forEach(node.typeArguments, bind); - ts.forEach(node.arguments, bind); - bind(node.expression); + checkStrictModeFunctionName(node); + if (inStrictMode) { + checkStrictModeFunctionDeclaration(node); + bindBlockScopedDeclaration(node, 16 /* Function */, 106927 /* FunctionExcludes */); } else { - ts.forEachChild(node, bind); + declareSymbolAndAddToSymbolTable(node, 16 /* Function */, 106927 /* FunctionExcludes */); } } - function getContainerFlags(node) { - switch (node.kind) { - case 192 /* ClassExpression */: - case 221 /* ClassDeclaration */: - case 224 /* EnumDeclaration */: - case 171 /* ObjectLiteralExpression */: - case 159 /* TypeLiteral */: - case 281 /* JSDocTypeLiteral */: - case 265 /* JSDocRecordType */: - return 1 /* IsContainer */; - case 222 /* InterfaceDeclaration */: - return 1 /* IsContainer */ | 64 /* IsInterface */; - case 269 /* JSDocFunctionType */: - case 225 /* ModuleDeclaration */: - case 223 /* TypeAliasDeclaration */: - return 1 /* IsContainer */ | 32 /* HasLocals */; - case 256 /* SourceFile */: - return 1 /* IsContainer */ | 4 /* IsControlFlowContainer */ | 32 /* HasLocals */; - case 148 /* Constructor */: - case 220 /* FunctionDeclaration */: - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 151 /* CallSignature */: - case 152 /* ConstructSignature */: - case 153 /* IndexSignature */: - case 156 /* FunctionType */: - case 157 /* ConstructorType */: - return 1 /* IsContainer */ | 4 /* IsControlFlowContainer */ | 32 /* HasLocals */ | 8 /* IsFunctionLike */; - case 179 /* FunctionExpression */: - case 180 /* ArrowFunction */: - return 1 /* IsContainer */ | 4 /* IsControlFlowContainer */ | 32 /* HasLocals */ | 8 /* IsFunctionLike */ | 16 /* IsFunctionExpression */; - case 226 /* ModuleBlock */: - return 4 /* IsControlFlowContainer */; - case 145 /* PropertyDeclaration */: - return node.initializer ? 4 /* IsControlFlowContainer */ : 0; - case 252 /* CatchClause */: - case 206 /* ForStatement */: - case 207 /* ForInStatement */: - case 208 /* ForOfStatement */: - case 227 /* CaseBlock */: - return 2 /* IsBlockScopedContainer */; - case 199 /* Block */: - // do not treat blocks directly inside a function as a block-scoped-container. - // Locals that reside in this block should go to the function locals. Otherwise 'x' - // would not appear to be a redeclaration of a block scoped local in the following - // example: - // - // function foo() { - // var x; - // let x; - // } - // - // If we placed 'var x' into the function locals and 'let x' into the locals of - // the block, then there would be no collision. - // - // By not creating a new block-scoped-container here, we ensure that both 'var x' - // and 'let x' go into the Function-container's locals, and we do get a collision - // conflict. - return ts.isFunctionLike(node.parent) ? 0 /* None */ : 2 /* IsBlockScopedContainer */; + function bindFunctionExpression(node) { + if (!ts.isDeclarationFile(file) && !ts.isInAmbientContext(node)) { + if (ts.isAsyncFunctionLike(node)) { + emitFlags |= 8192 /* HasAsyncFunctions */; + } } - return 0 /* None */; + if (currentFlow) { + node.flowNode = currentFlow; + } + checkStrictModeFunctionName(node); + var bindingName = node.name ? node.name.text : "__function"; + return bindAnonymousDeclaration(node, 16 /* Function */, bindingName); } - function addToContainerChain(next) { - if (lastContainer) { - lastContainer.nextContainer = next; + function bindPropertyOrMethodOrAccessor(node, symbolFlags, symbolExcludes) { + if (!ts.isDeclarationFile(file) && !ts.isInAmbientContext(node)) { + if (ts.isAsyncFunctionLike(node)) { + emitFlags |= 8192 /* HasAsyncFunctions */; + } + if (ts.nodeIsDecorated(node)) { + emitFlags |= 2048 /* HasDecorators */; + } } - lastContainer = next; + return ts.hasDynamicName(node) + ? bindAnonymousDeclaration(node, symbolFlags, "__computed") + : declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); + } + function bindJSDocProperty(node) { + return declareSymbolAndAddToSymbolTable(node, 4 /* Property */, 0 /* PropertyExcludes */); + } + // reachability checks + function shouldReportErrorOnModuleDeclaration(node) { + var instanceState = getModuleInstanceState(node); + return instanceState === 1 /* Instantiated */ || (instanceState === 2 /* ConstEnumOnly */ && options.preserveConstEnums); + } + function checkUnreachable(node) { + if (!(currentFlow.flags & 1 /* Unreachable */)) { + return false; + } + if (currentFlow === unreachableFlow) { + var reportError = + // report error on all statements except empty ones + (ts.isStatementButNotDeclaration(node) && node.kind !== 201 /* EmptyStatement */) || + // report error on class declarations + node.kind === 221 /* ClassDeclaration */ || + // report error on instantiated modules or const-enums only modules if preserveConstEnums is set + (node.kind === 225 /* ModuleDeclaration */ && shouldReportErrorOnModuleDeclaration(node)) || + // report error on regular enums and const enums if preserveConstEnums is set + (node.kind === 224 /* EnumDeclaration */ && (!ts.isConstEnumDeclaration(node) || options.preserveConstEnums)); + if (reportError) { + currentFlow = reportedUnreachableFlow; + // unreachable code is reported if + // - user has explicitly asked about it AND + // - statement is in not ambient context (statements in ambient context is already an error + // so we should not report extras) AND + // - node is not variable statement OR + // - node is block scoped variable statement OR + // - node is not block scoped variable statement and at least one variable declaration has initializer + // Rationale: we don't want to report errors on non-initialized var's since they are hoisted + // On the other side we do want to report errors on non-initialized 'lets' because of TDZ + var reportUnreachableCode = !options.allowUnreachableCode && + !ts.isInAmbientContext(node) && + (node.kind !== 200 /* VariableStatement */ || + ts.getCombinedNodeFlags(node.declarationList) & 3 /* BlockScoped */ || + ts.forEach(node.declarationList.declarations, function (d) { return d.initializer; })); + if (reportUnreachableCode) { + errorOnFirstToken(node, ts.Diagnostics.Unreachable_code_detected); + } + } + } + return true; + } + } + /** + * Computes the transform flags for a node, given the transform flags of its subtree + * + * @param node The node to analyze + * @param subtreeFlags Transform flags computed for this node's subtree + */ + function computeTransformFlagsForNode(node, subtreeFlags) { + var kind = node.kind; + switch (kind) { + case 174 /* CallExpression */: + return computeCallExpression(node, subtreeFlags); + case 225 /* ModuleDeclaration */: + return computeModuleDeclaration(node, subtreeFlags); + case 178 /* ParenthesizedExpression */: + return computeParenthesizedExpression(node, subtreeFlags); + case 187 /* BinaryExpression */: + return computeBinaryExpression(node, subtreeFlags); + case 202 /* ExpressionStatement */: + return computeExpressionStatement(node, subtreeFlags); + case 142 /* Parameter */: + return computeParameter(node, subtreeFlags); + case 180 /* ArrowFunction */: + return computeArrowFunction(node, subtreeFlags); + case 179 /* FunctionExpression */: + return computeFunctionExpression(node, subtreeFlags); + case 220 /* FunctionDeclaration */: + return computeFunctionDeclaration(node, subtreeFlags); + case 218 /* VariableDeclaration */: + return computeVariableDeclaration(node, subtreeFlags); + case 219 /* VariableDeclarationList */: + return computeVariableDeclarationList(node, subtreeFlags); + case 200 /* VariableStatement */: + return computeVariableStatement(node, subtreeFlags); + case 214 /* LabeledStatement */: + return computeLabeledStatement(node, subtreeFlags); + case 221 /* ClassDeclaration */: + return computeClassDeclaration(node, subtreeFlags); + case 192 /* ClassExpression */: + return computeClassExpression(node, subtreeFlags); + case 251 /* HeritageClause */: + return computeHeritageClause(node, subtreeFlags); + case 194 /* ExpressionWithTypeArguments */: + return computeExpressionWithTypeArguments(node, subtreeFlags); + case 148 /* Constructor */: + return computeConstructor(node, subtreeFlags); + case 145 /* PropertyDeclaration */: + return computePropertyDeclaration(node, subtreeFlags); + case 147 /* MethodDeclaration */: + return computeMethod(node, subtreeFlags); + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + return computeAccessor(node, subtreeFlags); + case 229 /* ImportEqualsDeclaration */: + return computeImportEquals(node, subtreeFlags); + case 172 /* PropertyAccessExpression */: + return computePropertyAccess(node, subtreeFlags); + default: + return computeOther(node, kind, subtreeFlags); } - function declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes) { - // Just call this directly so that the return type of this function stays "void". - return declareSymbolAndAddToSymbolTableWorker(node, symbolFlags, symbolExcludes); + } + ts.computeTransformFlagsForNode = computeTransformFlagsForNode; + function computeCallExpression(node, subtreeFlags) { + var transformFlags = subtreeFlags; + var expression = node.expression; + var expressionKind = expression.kind; + if (subtreeFlags & 262144 /* ContainsSpreadElementExpression */ + || isSuperOrSuperProperty(expression, expressionKind)) { + // If the this node contains a SpreadElementExpression, or is a super call, then it is an ES6 + // node. + transformFlags |= 192 /* AssertES6 */; } - function declareSymbolAndAddToSymbolTableWorker(node, symbolFlags, symbolExcludes) { - switch (container.kind) { - // Modules, source files, and classes need specialized handling for how their - // members are declared (for example, a member of a class will go into a specific - // symbol table depending on if it is static or not). We defer to specialized - // handlers to take care of declaring these child members. - case 225 /* ModuleDeclaration */: - return declareModuleMember(node, symbolFlags, symbolExcludes); - case 256 /* SourceFile */: - return declareSourceFileMember(node, symbolFlags, symbolExcludes); - case 192 /* ClassExpression */: - case 221 /* ClassDeclaration */: - return declareClassMember(node, symbolFlags, symbolExcludes); - case 224 /* EnumDeclaration */: - return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); - case 159 /* TypeLiteral */: - case 171 /* ObjectLiteralExpression */: - case 222 /* InterfaceDeclaration */: - case 265 /* JSDocRecordType */: - case 281 /* JSDocTypeLiteral */: - // Interface/Object-types always have their children added to the 'members' of - // their container. They are only accessible through an instance of their - // container, and are never in scope otherwise (even inside the body of the - // object / type / interface declaring them). An exception is type parameters, - // which are in scope without qualification (similar to 'locals'). - return declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); - case 156 /* FunctionType */: - case 157 /* ConstructorType */: - case 151 /* CallSignature */: - case 152 /* ConstructSignature */: - case 153 /* IndexSignature */: - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - case 148 /* Constructor */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - case 180 /* ArrowFunction */: - case 269 /* JSDocFunctionType */: - case 223 /* TypeAliasDeclaration */: - // All the children of these container types are never visible through another - // symbol (i.e. through another symbol's 'exports' or 'members'). Instead, - // they're only accessed 'lexically' (i.e. from code that exists underneath - // their container in the tree. To accomplish this, we simply add their declared - // symbol to the 'locals' of the container. These symbols can then be found as - // the type checker walks up the containers, checking them for matching names. - return declareSymbol(container.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes); - } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~537133909 /* ArrayLiteralOrCallOrNewExcludes */; + } + function isSuperOrSuperProperty(node, kind) { + switch (kind) { + case 95 /* SuperKeyword */: + return true; + case 172 /* PropertyAccessExpression */: + case 173 /* ElementAccessExpression */: + var expression = node.expression; + var expressionKind = expression.kind; + return expressionKind === 95 /* SuperKeyword */; } - function declareClassMember(node, symbolFlags, symbolExcludes) { - return node.flags & 32 /* Static */ - ? declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes) - : declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); + return false; + } + function computeBinaryExpression(node, subtreeFlags) { + var transformFlags = subtreeFlags; + var operatorTokenKind = node.operatorToken.kind; + var leftKind = node.left.kind; + if (operatorTokenKind === 56 /* EqualsToken */ + && (leftKind === 171 /* ObjectLiteralExpression */ + || leftKind === 170 /* ArrayLiteralExpression */)) { + // Destructuring assignments are ES6 syntax. + transformFlags |= 192 /* AssertES6 */ | 256 /* DestructuringAssignment */; + } + else if (operatorTokenKind === 38 /* AsteriskAsteriskToken */ + || operatorTokenKind === 60 /* AsteriskAsteriskEqualsToken */) { + // Exponentiation is ES7 syntax. + transformFlags |= 48 /* AssertES7 */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~536871765 /* NodeExcludes */; + } + function computeParameter(node, subtreeFlags) { + var transformFlags = subtreeFlags; + var modifierFlags = ts.getModifierFlags(node); + var name = node.name; + var initializer = node.initializer; + var dotDotDotToken = node.dotDotDotToken; + // If the parameter has a question token, then it is TypeScript syntax. + if (node.questionToken) { + transformFlags |= 3 /* AssertTypeScript */; + } + // If the parameter's name is 'this', then it is TypeScript syntax. + if (subtreeFlags & 2048 /* ContainsDecorators */ + || (name && ts.isIdentifier(name) && name.originalKeywordKind === 97 /* ThisKeyword */)) { + transformFlags |= 3 /* AssertTypeScript */; + } + // If a parameter has an accessibility modifier, then it is TypeScript syntax. + if (modifierFlags & 92 /* ParameterPropertyModifier */) { + transformFlags |= 3 /* AssertTypeScript */ | 131072 /* ContainsParameterPropertyAssignments */; + } + // If a parameter has an initializer, a binding pattern or a dotDotDot token, then + // it is ES6 syntax and its container must emit default value assignments or parameter destructuring downlevel. + if (subtreeFlags & 2097152 /* ContainsBindingPattern */ || initializer || dotDotDotToken) { + transformFlags |= 192 /* AssertES6 */ | 65536 /* ContainsDefaultValueAssignments */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~538968917 /* ParameterExcludes */; + } + function computeParenthesizedExpression(node, subtreeFlags) { + var transformFlags = subtreeFlags; + var expression = node.expression; + var expressionKind = expression.kind; + var expressionTransformFlags = expression.transformFlags; + // If the node is synthesized, it means the emitter put the parentheses there, + // not the user. If we didn't want them, the emitter would not have put them + // there. + if (expressionKind === 195 /* AsExpression */ + || expressionKind === 177 /* TypeAssertionExpression */) { + transformFlags |= 3 /* AssertTypeScript */; + } + // If the expression of a ParenthesizedExpression is a destructuring assignment, + // then the ParenthesizedExpression is a destructuring assignment. + if (expressionTransformFlags & 256 /* DestructuringAssignment */) { + transformFlags |= 256 /* DestructuringAssignment */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~536871765 /* NodeExcludes */; + } + function computeClassDeclaration(node, subtreeFlags) { + var transformFlags; + var modifierFlags = ts.getModifierFlags(node); + if (modifierFlags & 2 /* Ambient */) { + // An ambient declaration is TypeScript syntax. + transformFlags = 3 /* AssertTypeScript */; } - function declareSourceFileMember(node, symbolFlags, symbolExcludes) { - return ts.isExternalModule(file) - ? declareModuleMember(node, symbolFlags, symbolExcludes) - : declareSymbol(file.locals, undefined, node, symbolFlags, symbolExcludes); + else { + // A ClassDeclaration is ES6 syntax. + transformFlags = subtreeFlags | 192 /* AssertES6 */; + // A class with a parameter property assignment, property initializer, or decorator is + // TypeScript syntax. + // An exported declaration may be TypeScript syntax. + if ((subtreeFlags & 137216 /* TypeScriptClassSyntaxMask */) + || (modifierFlags & 1 /* Export */)) { + transformFlags |= 3 /* AssertTypeScript */; + } + if (subtreeFlags & 32768 /* ContainsLexicalThisInComputedPropertyName */) { + // A computed property name containing `this` might need to be rewritten, + // so propagate the ContainsLexicalThis flag upward. + transformFlags |= 8192 /* ContainsLexicalThis */; + } + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~537590613 /* ClassExcludes */; + } + function computeClassExpression(node, subtreeFlags) { + // A ClassExpression is ES6 syntax. + var transformFlags = subtreeFlags | 192 /* AssertES6 */; + // A class with a parameter property assignment, property initializer, or decorator is + // TypeScript syntax. + if (subtreeFlags & 137216 /* TypeScriptClassSyntaxMask */) { + transformFlags |= 3 /* AssertTypeScript */; + } + if (subtreeFlags & 32768 /* ContainsLexicalThisInComputedPropertyName */) { + // A computed property name containing `this` might need to be rewritten, + // so propagate the ContainsLexicalThis flag upward. + transformFlags |= 8192 /* ContainsLexicalThis */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~537590613 /* ClassExcludes */; + } + function computeHeritageClause(node, subtreeFlags) { + var transformFlags = subtreeFlags; + switch (node.token) { + case 83 /* ExtendsKeyword */: + // An `extends` HeritageClause is ES6 syntax. + transformFlags |= 192 /* AssertES6 */; + break; + case 106 /* ImplementsKeyword */: + // An `implements` HeritageClause is TypeScript syntax. + transformFlags |= 3 /* AssertTypeScript */; + break; + default: + ts.Debug.fail("Unexpected token for heritage clause"); + break; } - function hasExportDeclarations(node) { - var body = node.kind === 256 /* SourceFile */ ? node : node.body; - if (body && (body.kind === 256 /* SourceFile */ || body.kind === 226 /* ModuleBlock */)) { - for (var _i = 0, _a = body.statements; _i < _a.length; _i++) { - var stat = _a[_i]; - if (stat.kind === 236 /* ExportDeclaration */ || stat.kind === 235 /* ExportAssignment */) { - return true; - } - } - } - return false; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~536871765 /* NodeExcludes */; + } + function computeExpressionWithTypeArguments(node, subtreeFlags) { + // An ExpressionWithTypeArguments is ES6 syntax, as it is used in the + // extends clause of a class. + var transformFlags = subtreeFlags | 192 /* AssertES6 */; + // If an ExpressionWithTypeArguments contains type arguments, then it + // is TypeScript syntax. + if (node.typeArguments) { + transformFlags |= 3 /* AssertTypeScript */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~536871765 /* NodeExcludes */; + } + function computeConstructor(node, subtreeFlags) { + var transformFlags = subtreeFlags; + var body = node.body; + if (body === undefined) { + // An overload constructor is TypeScript syntax. + transformFlags |= 3 /* AssertTypeScript */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~550593365 /* ConstructorExcludes */; + } + function computeMethod(node, subtreeFlags) { + // A MethodDeclaration is ES6 syntax. + var transformFlags = subtreeFlags | 192 /* AssertES6 */; + var modifierFlags = ts.getModifierFlags(node); + var body = node.body; + var typeParameters = node.typeParameters; + var asteriskToken = node.asteriskToken; + // A MethodDeclaration is TypeScript syntax if it is either async, abstract, overloaded, + // generic, or has a decorator. + if (!body + || typeParameters + || (modifierFlags & (256 /* Async */ | 128 /* Abstract */)) + || (subtreeFlags & 2048 /* ContainsDecorators */)) { + transformFlags |= 3 /* AssertTypeScript */; + } + // Currently, we only support generators that were originally async function bodies. + if (asteriskToken && ts.getEmitFlags(node) & 2097152 /* AsyncFunctionBody */) { + transformFlags |= 1536 /* AssertGenerator */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~550593365 /* MethodOrAccessorExcludes */; + } + function computeAccessor(node, subtreeFlags) { + var transformFlags = subtreeFlags; + var modifierFlags = ts.getModifierFlags(node); + var body = node.body; + // A MethodDeclaration is TypeScript syntax if it is either async, abstract, overloaded, + // generic, or has a decorator. + if (!body + || (modifierFlags & (256 /* Async */ | 128 /* Abstract */)) + || (subtreeFlags & 2048 /* ContainsDecorators */)) { + transformFlags |= 3 /* AssertTypeScript */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~550593365 /* MethodOrAccessorExcludes */; + } + function computePropertyDeclaration(node, subtreeFlags) { + // A PropertyDeclaration is TypeScript syntax. + var transformFlags = subtreeFlags | 3 /* AssertTypeScript */; + // If the PropertyDeclaration has an initializer, we need to inform its ancestor + // so that it handle the transformation. + if (node.initializer) { + transformFlags |= 4096 /* ContainsPropertyInitializer */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~536871765 /* NodeExcludes */; + } + function computeFunctionDeclaration(node, subtreeFlags) { + var transformFlags; + var modifierFlags = ts.getModifierFlags(node); + var body = node.body; + var asteriskToken = node.asteriskToken; + if (!body || (modifierFlags & 2 /* Ambient */)) { + // An ambient declaration is TypeScript syntax. + // A FunctionDeclaration without a body is an overload and is TypeScript syntax. + transformFlags = 3 /* AssertTypeScript */; } - function setExportContextFlag(node) { - // A declaration source file or ambient module declaration that contains no export declarations (but possibly regular - // declarations with export modifiers) is an export context in which declarations are implicitly exported. - if (ts.isInAmbientContext(node) && !hasExportDeclarations(node)) { - node.flags |= 8192 /* ExportContext */; - } - else { - node.flags &= ~8192 /* ExportContext */; - } + else { + transformFlags = subtreeFlags | 8388608 /* ContainsHoistedDeclarationOrCompletion */; + // If a FunctionDeclaration is exported, then it is either ES6 or TypeScript syntax. + if (modifierFlags & 1 /* Export */) { + transformFlags |= 3 /* AssertTypeScript */ | 192 /* AssertES6 */; + } + // If a FunctionDeclaration is async, then it is TypeScript syntax. + if (modifierFlags & 256 /* Async */) { + transformFlags |= 3 /* AssertTypeScript */; + } + // If a FunctionDeclaration's subtree has marked the container as needing to capture the + // lexical this, or the function contains parameters with initializers, then this node is + // ES6 syntax. + if (subtreeFlags & 81920 /* ES6FunctionSyntaxMask */) { + transformFlags |= 192 /* AssertES6 */; + } + // If a FunctionDeclaration is generator function and is the body of a + // transformed async function, then this node can be transformed to a + // down-level generator. + // Currently we do not support transforming any other generator fucntions + // down level. + if (asteriskToken && ts.getEmitFlags(node) & 2097152 /* AsyncFunctionBody */) { + transformFlags |= 1536 /* AssertGenerator */; + } + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~550726485 /* FunctionExcludes */; + } + function computeFunctionExpression(node, subtreeFlags) { + var transformFlags = subtreeFlags; + var modifierFlags = ts.getModifierFlags(node); + var asteriskToken = node.asteriskToken; + // An async function expression is TypeScript syntax. + if (modifierFlags & 256 /* Async */) { + transformFlags |= 3 /* AssertTypeScript */; + } + // If a FunctionExpression's subtree has marked the container as needing to capture the + // lexical this, or the function contains parameters with initializers, then this node is + // ES6 syntax. + if (subtreeFlags & 81920 /* ES6FunctionSyntaxMask */) { + transformFlags |= 192 /* AssertES6 */; + } + // If a FunctionExpression is generator function and is the body of a + // transformed async function, then this node can be transformed to a + // down-level generator. + // Currently we do not support transforming any other generator fucntions + // down level. + if (asteriskToken && ts.getEmitFlags(node) & 2097152 /* AsyncFunctionBody */) { + transformFlags |= 1536 /* AssertGenerator */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~550726485 /* FunctionExcludes */; + } + function computeArrowFunction(node, subtreeFlags) { + // An ArrowFunction is ES6 syntax, and excludes markers that should not escape the scope of an ArrowFunction. + var transformFlags = subtreeFlags | 192 /* AssertES6 */; + var modifierFlags = ts.getModifierFlags(node); + // An async arrow function is TypeScript syntax. + if (modifierFlags & 256 /* Async */) { + transformFlags |= 3 /* AssertTypeScript */; + } + // If an ArrowFunction contains a lexical this, its container must capture the lexical this. + if (subtreeFlags & 8192 /* ContainsLexicalThis */) { + transformFlags |= 16384 /* ContainsCapturedLexicalThis */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~550710101 /* ArrowFunctionExcludes */; + } + function computePropertyAccess(node, subtreeFlags) { + var transformFlags = subtreeFlags; + var expression = node.expression; + var expressionKind = expression.kind; + // If a PropertyAccessExpression starts with a super keyword, then it is + // ES6 syntax, and requires a lexical `this` binding. + if (expressionKind === 95 /* SuperKeyword */) { + transformFlags |= 8192 /* ContainsLexicalThis */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~536871765 /* NodeExcludes */; + } + function computeVariableDeclaration(node, subtreeFlags) { + var transformFlags = subtreeFlags; + var nameKind = node.name.kind; + // A VariableDeclaration with a binding pattern is ES6 syntax. + if (nameKind === 167 /* ObjectBindingPattern */ || nameKind === 168 /* ArrayBindingPattern */) { + transformFlags |= 192 /* AssertES6 */ | 2097152 /* ContainsBindingPattern */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~536871765 /* NodeExcludes */; + } + function computeVariableStatement(node, subtreeFlags) { + var transformFlags; + var modifierFlags = ts.getModifierFlags(node); + var declarationListTransformFlags = node.declarationList.transformFlags; + // An ambient declaration is TypeScript syntax. + if (modifierFlags & 2 /* Ambient */) { + transformFlags = 3 /* AssertTypeScript */; } - function bindModuleDeclaration(node) { - setExportContextFlag(node); - if (ts.isAmbientModule(node)) { - if (node.flags & 1 /* Export */) { - errorOnFirstToken(node, ts.Diagnostics.export_modifier_cannot_be_applied_to_ambient_modules_and_module_augmentations_since_they_are_always_visible); + else { + transformFlags = subtreeFlags; + // If a VariableStatement is exported, then it is either ES6 or TypeScript syntax. + if (modifierFlags & 1 /* Export */) { + transformFlags |= 192 /* AssertES6 */ | 3 /* AssertTypeScript */; + } + if (declarationListTransformFlags & 2097152 /* ContainsBindingPattern */) { + transformFlags |= 192 /* AssertES6 */; + } + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~536871765 /* NodeExcludes */; + } + function computeLabeledStatement(node, subtreeFlags) { + var transformFlags = subtreeFlags; + // A labeled statement containing a block scoped binding *may* need to be transformed from ES6. + if (subtreeFlags & 1048576 /* ContainsBlockScopedBinding */ + && ts.isIterationStatement(node, /*lookInLabeledStatements*/ true)) { + transformFlags |= 192 /* AssertES6 */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~536871765 /* NodeExcludes */; + } + function computeImportEquals(node, subtreeFlags) { + var transformFlags = subtreeFlags; + // An ImportEqualsDeclaration with a namespace reference is TypeScript. + if (!ts.isExternalModuleImportEqualsDeclaration(node)) { + transformFlags |= 3 /* AssertTypeScript */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~536871765 /* NodeExcludes */; + } + function computeExpressionStatement(node, subtreeFlags) { + var transformFlags = subtreeFlags; + // If the expression of an expression statement is a destructuring assignment, + // then we treat the statement as ES6 so that we can indicate that we do not + // need to hold on to the right-hand side. + if (node.expression.transformFlags & 256 /* DestructuringAssignment */) { + transformFlags |= 192 /* AssertES6 */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~536871765 /* NodeExcludes */; + } + function computeModuleDeclaration(node, subtreeFlags) { + var transformFlags = 3 /* AssertTypeScript */; + var modifierFlags = ts.getModifierFlags(node); + if ((modifierFlags & 2 /* Ambient */) === 0) { + transformFlags |= subtreeFlags; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~546335573 /* ModuleExcludes */; + } + function computeVariableDeclarationList(node, subtreeFlags) { + var transformFlags = subtreeFlags | 8388608 /* ContainsHoistedDeclarationOrCompletion */; + if (subtreeFlags & 2097152 /* ContainsBindingPattern */) { + transformFlags |= 192 /* AssertES6 */; + } + // If a VariableDeclarationList is `let` or `const`, then it is ES6 syntax. + if (node.flags & 3 /* BlockScoped */) { + transformFlags |= 192 /* AssertES6 */ | 1048576 /* ContainsBlockScopedBinding */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~538968917 /* VariableDeclarationListExcludes */; + } + function computeOther(node, kind, subtreeFlags) { + // Mark transformations needed for each node + var transformFlags = subtreeFlags; + var excludeFlags = 536871765 /* NodeExcludes */; + switch (kind) { + case 112 /* PublicKeyword */: + case 110 /* PrivateKeyword */: + case 111 /* ProtectedKeyword */: + case 115 /* AbstractKeyword */: + case 122 /* DeclareKeyword */: + case 118 /* AsyncKeyword */: + case 74 /* ConstKeyword */: + case 184 /* AwaitExpression */: + case 224 /* EnumDeclaration */: + case 255 /* EnumMember */: + case 177 /* TypeAssertionExpression */: + case 195 /* AsExpression */: + case 196 /* NonNullExpression */: + case 128 /* ReadonlyKeyword */: + // These nodes are TypeScript syntax. + transformFlags |= 3 /* AssertTypeScript */; + break; + case 241 /* JsxElement */: + case 242 /* JsxSelfClosingElement */: + case 243 /* JsxOpeningElement */: + case 244 /* JsxText */: + case 245 /* JsxClosingElement */: + case 246 /* JsxAttribute */: + case 247 /* JsxSpreadAttribute */: + case 248 /* JsxExpression */: + // These nodes are Jsx syntax. + transformFlags |= 12 /* AssertJsx */; + break; + case 82 /* ExportKeyword */: + // This node is both ES6 and TypeScript syntax. + transformFlags |= 192 /* AssertES6 */ | 3 /* AssertTypeScript */; + break; + case 77 /* DefaultKeyword */: + case 11 /* NoSubstitutionTemplateLiteral */: + case 12 /* TemplateHead */: + case 13 /* TemplateMiddle */: + case 14 /* TemplateTail */: + case 189 /* TemplateExpression */: + case 176 /* TaggedTemplateExpression */: + case 254 /* ShorthandPropertyAssignment */: + case 208 /* ForOfStatement */: + // These nodes are ES6 syntax. + transformFlags |= 192 /* AssertES6 */; + break; + case 190 /* YieldExpression */: + // This node is ES6 syntax. + transformFlags |= 192 /* AssertES6 */ | 4194304 /* ContainsYield */; + break; + case 117 /* AnyKeyword */: + case 130 /* NumberKeyword */: + case 127 /* NeverKeyword */: + case 132 /* StringKeyword */: + case 120 /* BooleanKeyword */: + case 133 /* SymbolKeyword */: + case 103 /* VoidKeyword */: + case 141 /* TypeParameter */: + case 144 /* PropertySignature */: + case 146 /* MethodSignature */: + case 151 /* CallSignature */: + case 152 /* ConstructSignature */: + case 153 /* IndexSignature */: + case 154 /* TypePredicate */: + case 155 /* TypeReference */: + case 156 /* FunctionType */: + case 157 /* ConstructorType */: + case 158 /* TypeQuery */: + case 159 /* TypeLiteral */: + case 160 /* ArrayType */: + case 161 /* TupleType */: + case 162 /* UnionType */: + case 163 /* IntersectionType */: + case 164 /* ParenthesizedType */: + case 222 /* InterfaceDeclaration */: + case 223 /* TypeAliasDeclaration */: + case 165 /* ThisType */: + case 166 /* LiteralType */: + // Types and signatures are TypeScript syntax, and exclude all other facts. + transformFlags = 3 /* AssertTypeScript */; + excludeFlags = -3 /* TypeExcludes */; + break; + case 140 /* ComputedPropertyName */: + // Even though computed property names are ES6, we don't treat them as such. + // This is so that they can flow through PropertyName transforms unaffected. + // Instead, we mark the container as ES6, so that it can properly handle the transform. + transformFlags |= 524288 /* ContainsComputedPropertyName */; + if (subtreeFlags & 8192 /* ContainsLexicalThis */) { + // A computed method name like `[this.getName()](x: string) { ... }` needs to + // distinguish itself from the normal case of a method body containing `this`: + // `this` inside a method doesn't need to be rewritten (the method provides `this`), + // whereas `this` inside a computed name *might* need to be rewritten if the class/object + // is inside an arrow function: + // `_this = this; () => class K { [_this.getName()]() { ... } }` + // To make this distinction, use ContainsLexicalThisInComputedPropertyName + // instead of ContainsLexicalThis for computed property names + transformFlags |= 32768 /* ContainsLexicalThisInComputedPropertyName */; } - if (ts.isExternalModuleAugmentation(node)) { - declareSymbolAndAddToSymbolTable(node, 1024 /* NamespaceModule */, 0 /* NamespaceModuleExcludes */); + break; + case 191 /* SpreadElementExpression */: + // This node is ES6 syntax, but is handled by a containing node. + transformFlags |= 262144 /* ContainsSpreadElementExpression */; + break; + case 95 /* SuperKeyword */: + // This node is ES6 syntax. + transformFlags |= 192 /* AssertES6 */; + break; + case 97 /* ThisKeyword */: + // Mark this node and its ancestors as containing a lexical `this` keyword. + transformFlags |= 8192 /* ContainsLexicalThis */; + break; + case 167 /* ObjectBindingPattern */: + case 168 /* ArrayBindingPattern */: + // These nodes are ES6 syntax. + transformFlags |= 192 /* AssertES6 */ | 2097152 /* ContainsBindingPattern */; + break; + case 143 /* Decorator */: + // This node is TypeScript syntax, and marks its container as also being TypeScript syntax. + transformFlags |= 3 /* AssertTypeScript */ | 2048 /* ContainsDecorators */; + break; + case 171 /* ObjectLiteralExpression */: + excludeFlags = 537430869 /* ObjectLiteralExcludes */; + if (subtreeFlags & 524288 /* ContainsComputedPropertyName */) { + // If an ObjectLiteralExpression contains a ComputedPropertyName, then it + // is an ES6 node. + transformFlags |= 192 /* AssertES6 */; } - else { - var pattern = void 0; - if (node.name.kind === 9 /* StringLiteral */) { - var text = node.name.text; - if (ts.hasZeroOrOneAsteriskCharacter(text)) { - pattern = ts.tryParsePattern(text); - } - else { - errorOnFirstToken(node.name, ts.Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, text); - } - } - var symbol = declareSymbolAndAddToSymbolTable(node, 512 /* ValueModule */, 106639 /* ValueModuleExcludes */); - if (pattern) { - (file.patternAmbientModules || (file.patternAmbientModules = [])).push({ pattern: pattern, symbol: symbol }); - } + if (subtreeFlags & 32768 /* ContainsLexicalThisInComputedPropertyName */) { + // A computed property name containing `this` might need to be rewritten, + // so propagate the ContainsLexicalThis flag upward. + transformFlags |= 8192 /* ContainsLexicalThis */; } - } - else { - var state = getModuleInstanceState(node); - if (state === 0 /* NonInstantiated */) { - declareSymbolAndAddToSymbolTable(node, 1024 /* NamespaceModule */, 0 /* NamespaceModuleExcludes */); + break; + case 170 /* ArrayLiteralExpression */: + case 175 /* NewExpression */: + excludeFlags = 537133909 /* ArrayLiteralOrCallOrNewExcludes */; + if (subtreeFlags & 262144 /* ContainsSpreadElementExpression */) { + // If the this node contains a SpreadElementExpression, then it is an ES6 + // node. + transformFlags |= 192 /* AssertES6 */; } - else { - declareSymbolAndAddToSymbolTable(node, 512 /* ValueModule */, 106639 /* ValueModuleExcludes */); - if (node.symbol.flags & (16 /* Function */ | 32 /* Class */ | 256 /* RegularEnum */)) { - // if module was already merged with some function, class or non-const enum - // treat is a non-const-enum-only - node.symbol.constEnumOnlyModule = false; - } - else { - var currentModuleIsConstEnumOnly = state === 2 /* ConstEnumOnly */; - if (node.symbol.constEnumOnlyModule === undefined) { - // non-merged case - use the current state - node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly; - } - else { - // merged case: module is const enum only if all its pieces are non-instantiated or const enum - node.symbol.constEnumOnlyModule = node.symbol.constEnumOnlyModule && currentModuleIsConstEnumOnly; - } - } + break; + case 204 /* DoStatement */: + case 205 /* WhileStatement */: + case 206 /* ForStatement */: + case 207 /* ForInStatement */: + // A loop containing a block scoped binding *may* need to be transformed from ES6. + if (subtreeFlags & 1048576 /* ContainsBlockScopedBinding */) { + transformFlags |= 192 /* AssertES6 */; } - } - } - function bindFunctionOrConstructorType(node) { - // For a given function symbol "<...>(...) => T" we want to generate a symbol identical - // to the one we would get for: { <...>(...): T } - // - // We do that by making an anonymous type literal symbol, and then setting the function - // symbol as its sole member. To the rest of the system, this symbol will be indistinguishable - // from an actual type literal symbol you would have gotten had you used the long form. - var symbol = createSymbol(131072 /* Signature */, getDeclarationName(node)); - addDeclarationToSymbol(symbol, node, 131072 /* Signature */); - var typeLiteralSymbol = createSymbol(2048 /* TypeLiteral */, "__type"); - addDeclarationToSymbol(typeLiteralSymbol, node, 2048 /* TypeLiteral */); - typeLiteralSymbol.members = ts.createMap(); - typeLiteralSymbol.members[symbol.name] = symbol; - } - function bindObjectLiteralExpression(node) { - var ElementKind; - (function (ElementKind) { - ElementKind[ElementKind["Property"] = 1] = "Property"; - ElementKind[ElementKind["Accessor"] = 2] = "Accessor"; - })(ElementKind || (ElementKind = {})); - if (inStrictMode) { - var seen = ts.createMap(); - for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { - var prop = _a[_i]; - if (prop.name.kind !== 69 /* Identifier */) { - continue; - } - var identifier = prop.name; - // ECMA-262 11.1.5 Object Initializer - // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true - // a.This production is contained in strict code and IsDataDescriptor(previous) is true and - // IsDataDescriptor(propId.descriptor) is true. - // b.IsDataDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true. - // c.IsAccessorDescriptor(previous) is true and IsDataDescriptor(propId.descriptor) is true. - // d.IsAccessorDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true - // and either both previous and propId.descriptor have[[Get]] fields or both previous and propId.descriptor have[[Set]] fields - var currentKind = prop.kind === 253 /* PropertyAssignment */ || prop.kind === 254 /* ShorthandPropertyAssignment */ || prop.kind === 147 /* MethodDeclaration */ - ? 1 /* Property */ - : 2 /* Accessor */; - var existingKind = seen[identifier.text]; - if (!existingKind) { - seen[identifier.text] = currentKind; - continue; - } - if (currentKind === 1 /* Property */ && existingKind === 1 /* Property */) { - var span = ts.getErrorSpanForNode(file, identifier); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, ts.Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode)); - } + break; + case 256 /* SourceFile */: + if (subtreeFlags & 16384 /* ContainsCapturedLexicalThis */) { + transformFlags |= 192 /* AssertES6 */; } - } - return bindAnonymousDeclaration(node, 4096 /* ObjectLiteral */, "__object"); - } - function bindAnonymousDeclaration(node, symbolFlags, name) { - var symbol = createSymbol(symbolFlags, name); - addDeclarationToSymbol(symbol, node, symbolFlags); + break; + case 211 /* ReturnStatement */: + case 209 /* ContinueStatement */: + case 210 /* BreakStatement */: + transformFlags |= 8388608 /* ContainsHoistedDeclarationOrCompletion */; + break; } - function bindBlockScopedDeclaration(node, symbolFlags, symbolExcludes) { - switch (blockScopeContainer.kind) { - case 225 /* ModuleDeclaration */: - declareModuleMember(node, symbolFlags, symbolExcludes); - break; - case 256 /* SourceFile */: - if (ts.isExternalModule(container)) { - declareModuleMember(node, symbolFlags, symbolExcludes); - break; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~excludeFlags; + } +})(ts || (ts = {})); +/// +/// +var ts; +(function (ts) { + function trace(host, message) { + host.trace(ts.formatMessage.apply(undefined, arguments)); + } + ts.trace = trace; + /* @internal */ + function isTraceEnabled(compilerOptions, host) { + return compilerOptions.traceResolution && host.trace !== undefined; + } + ts.isTraceEnabled = isTraceEnabled; + /* @internal */ + function createResolvedModule(resolvedFileName, isExternalLibraryImport, failedLookupLocations) { + return { resolvedModule: resolvedFileName ? { resolvedFileName: resolvedFileName, isExternalLibraryImport: isExternalLibraryImport } : undefined, failedLookupLocations: failedLookupLocations }; + } + ts.createResolvedModule = createResolvedModule; + function moduleHasNonRelativeName(moduleName) { + return !(ts.isRootedDiskPath(moduleName) || ts.isExternalModuleNameRelative(moduleName)); + } + function tryReadTypesSection(packageJsonPath, baseDirectory, state) { + var jsonContent = readJson(packageJsonPath, state.host); + function tryReadFromField(fieldName) { + if (ts.hasProperty(jsonContent, fieldName)) { + var typesFile = jsonContent[fieldName]; + if (typeof typesFile === "string") { + var typesFilePath_1 = ts.normalizePath(ts.combinePaths(baseDirectory, typesFile)); + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.package_json_has_0_field_1_that_references_2, fieldName, typesFile, typesFilePath_1); } - // fall through. - default: - if (!blockScopeContainer.locals) { - blockScopeContainer.locals = ts.createMap(); - addToContainerChain(blockScopeContainer); + return typesFilePath_1; + } + else { + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, fieldName, typeof typesFile); } - declareSymbol(blockScopeContainer.locals, undefined, node, symbolFlags, symbolExcludes); - } - } - function bindBlockScopedVariableDeclaration(node) { - bindBlockScopedDeclaration(node, 2 /* BlockScopedVariable */, 107455 /* BlockScopedVariableExcludes */); - } - // The binder visits every node in the syntax tree so it is a convenient place to perform a single localized - // check for reserved words used as identifiers in strict mode code. - function checkStrictModeIdentifier(node) { - if (inStrictMode && - node.originalKeywordKind >= 106 /* FirstFutureReservedWord */ && - node.originalKeywordKind <= 114 /* LastFutureReservedWord */ && - !ts.isIdentifierName(node) && - !ts.isInAmbientContext(node)) { - // Report error only if there are no parse errors in file - if (!file.parseDiagnostics.length) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(node, getStrictModeIdentifierMessage(node), ts.declarationNameToString(node))); } } } - function getStrictModeIdentifierMessage(node) { - // Provide specialized messages to help the user understand why we think they're in - // strict mode. - if (ts.getContainingClass(node)) { - return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode; - } - if (file.externalModuleIndicator) { - return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Modules_are_automatically_in_strict_mode; - } - return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode; + var typesFilePath = tryReadFromField("typings") || tryReadFromField("types"); + if (typesFilePath) { + return typesFilePath; } - function checkStrictModeBinaryExpression(node) { - if (inStrictMode && ts.isLeftHandSideExpression(node.left) && ts.isAssignmentOperator(node.operatorToken.kind)) { - // ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an - // Assignment operator(11.13) or of a PostfixExpression(11.3) - checkStrictModeEvalOrArguments(node, node.left); + // Use the main module for inferring types if no types package specified and the allowJs is set + if (state.compilerOptions.allowJs && jsonContent.main && typeof jsonContent.main === "string") { + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.No_types_specified_in_package_json_but_allowJs_is_set_so_returning_main_value_of_0, jsonContent.main); } + var mainFilePath = ts.normalizePath(ts.combinePaths(baseDirectory, jsonContent.main)); + return mainFilePath; } - function checkStrictModeCatchClause(node) { - // It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the - // Catch production is eval or arguments - if (inStrictMode && node.variableDeclaration) { - checkStrictModeEvalOrArguments(node, node.variableDeclaration.name); - } + return undefined; + } + function readJson(path, host) { + try { + var jsonText = host.readFile(path); + return jsonText ? JSON.parse(jsonText) : {}; } - function checkStrictModeDeleteExpression(node) { - // Grammar checking - if (inStrictMode && node.expression.kind === 69 /* Identifier */) { - // When a delete operator occurs within strict mode code, a SyntaxError is thrown if its - // UnaryExpression is a direct reference to a variable, function argument, or function name - var span = ts.getErrorSpanForNode(file, node.expression); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, ts.Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode)); - } + catch (e) { + // gracefully handle if readFile fails or returns not JSON + return {}; } - function isEvalOrArgumentsIdentifier(node) { - return node.kind === 69 /* Identifier */ && - (node.text === "eval" || node.text === "arguments"); + } + var typeReferenceExtensions = [".d.ts"]; + function getEffectiveTypeRoots(options, host) { + if (options.typeRoots) { + return options.typeRoots; } - function checkStrictModeEvalOrArguments(contextNode, name) { - if (name && name.kind === 69 /* Identifier */) { - var identifier = name; - if (isEvalOrArgumentsIdentifier(identifier)) { - // We check first if the name is inside class declaration or class expression; if so give explicit message - // otherwise report generic error message. - var span = ts.getErrorSpanForNode(file, name); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, getStrictModeEvalOrArgumentsMessage(contextNode), identifier.text)); - } - } + var currentDirectory; + if (options.configFilePath) { + currentDirectory = ts.getDirectoryPath(options.configFilePath); } - function getStrictModeEvalOrArgumentsMessage(node) { - // Provide specialized messages to help the user understand why we think they're in - // strict mode. - if (ts.getContainingClass(node)) { - return ts.Diagnostics.Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode; - } - if (file.externalModuleIndicator) { - return ts.Diagnostics.Invalid_use_of_0_Modules_are_automatically_in_strict_mode; - } - return ts.Diagnostics.Invalid_use_of_0_in_strict_mode; + else if (host.getCurrentDirectory) { + currentDirectory = host.getCurrentDirectory(); } - function checkStrictModeFunctionName(node) { - if (inStrictMode) { - // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a strict mode FunctionDeclaration or FunctionExpression (13.1)) - checkStrictModeEvalOrArguments(node, node.name); - } + return currentDirectory && getDefaultTypeRoots(currentDirectory, host); + } + ts.getEffectiveTypeRoots = getEffectiveTypeRoots; + /** + * Returns the path to every node_modules/@types directory from some ancestor directory. + * Returns undefined if there are none. + */ + function getDefaultTypeRoots(currentDirectory, host) { + if (!host.directoryExists) { + return [ts.combinePaths(currentDirectory, nodeModulesAtTypes)]; } - function getStrictModeBlockScopeFunctionDeclarationMessage(node) { - // Provide specialized messages to help the user understand why we think they're in - // strict mode. - if (ts.getContainingClass(node)) { - return ts.Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Class_definitions_are_automatically_in_strict_mode; + var typeRoots; + while (true) { + var atTypes = ts.combinePaths(currentDirectory, nodeModulesAtTypes); + if (host.directoryExists(atTypes)) { + (typeRoots || (typeRoots = [])).push(atTypes); } - if (file.externalModuleIndicator) { - return ts.Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Modules_are_automatically_in_strict_mode; + var parent_7 = ts.getDirectoryPath(currentDirectory); + if (parent_7 === currentDirectory) { + break; } - return ts.Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5; + currentDirectory = parent_7; } - function checkStrictModeFunctionDeclaration(node) { - if (languageVersion < 2 /* ES6 */) { - // Report error if function is not top level function declaration - if (blockScopeContainer.kind !== 256 /* SourceFile */ && - blockScopeContainer.kind !== 225 /* ModuleDeclaration */ && - !ts.isFunctionLike(blockScopeContainer)) { - // We check first if the name is inside class declaration or class expression; if so give explicit message - // otherwise report generic error message. - var errorSpan = ts.getErrorSpanForNode(file, node); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, errorSpan.start, errorSpan.length, getStrictModeBlockScopeFunctionDeclarationMessage(node))); + return typeRoots; + } + var nodeModulesAtTypes = ts.combinePaths("node_modules", "@types"); + /** + * @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. + * This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups + * is assumed to be the same as root directory of the project. + */ + function resolveTypeReferenceDirective(typeReferenceDirectiveName, containingFile, options, host) { + var traceEnabled = isTraceEnabled(options, host); + var moduleResolutionState = { + compilerOptions: options, + host: host, + skipTsx: true, + traceEnabled: traceEnabled + }; + var typeRoots = getEffectiveTypeRoots(options, host); + if (traceEnabled) { + if (containingFile === undefined) { + if (typeRoots === undefined) { + trace(host, ts.Diagnostics.Resolving_type_reference_directive_0_containing_file_not_set_root_directory_not_set, typeReferenceDirectiveName); + } + else { + trace(host, ts.Diagnostics.Resolving_type_reference_directive_0_containing_file_not_set_root_directory_1, typeReferenceDirectiveName, typeRoots); } } - } - function checkStrictModeNumericLiteral(node) { - if (inStrictMode && node.isOctalLiteral) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Octal_literals_are_not_allowed_in_strict_mode)); - } - } - function checkStrictModePostfixUnaryExpression(node) { - // Grammar checking - // The identifier eval or arguments may not appear as the LeftHandSideExpression of an - // Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression - // operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator. - if (inStrictMode) { - checkStrictModeEvalOrArguments(node, node.operand); - } - } - function checkStrictModePrefixUnaryExpression(node) { - // Grammar checking - if (inStrictMode) { - if (node.operator === 41 /* PlusPlusToken */ || node.operator === 42 /* MinusMinusToken */) { - checkStrictModeEvalOrArguments(node, node.operand); + else { + if (typeRoots === undefined) { + trace(host, ts.Diagnostics.Resolving_type_reference_directive_0_containing_file_1_root_directory_not_set, typeReferenceDirectiveName, containingFile); + } + else { + trace(host, ts.Diagnostics.Resolving_type_reference_directive_0_containing_file_1_root_directory_2, typeReferenceDirectiveName, containingFile, typeRoots); } } } - function checkStrictModeWithStatement(node) { - // Grammar checking for withStatement - if (inStrictMode) { - errorOnFirstToken(node, ts.Diagnostics.with_statements_are_not_allowed_in_strict_mode); + var failedLookupLocations = []; + // Check primary library paths + if (typeRoots && typeRoots.length) { + if (traceEnabled) { + trace(host, ts.Diagnostics.Resolving_with_primary_search_path_0, typeRoots.join(", ")); + } + var primarySearchPaths = typeRoots; + for (var _i = 0, primarySearchPaths_1 = primarySearchPaths; _i < primarySearchPaths_1.length; _i++) { + var typeRoot = primarySearchPaths_1[_i]; + var candidate = ts.combinePaths(typeRoot, typeReferenceDirectiveName); + var candidateDirectory = ts.getDirectoryPath(candidate); + var resolvedFile_1 = loadNodeModuleFromDirectory(typeReferenceExtensions, candidate, failedLookupLocations, !directoryProbablyExists(candidateDirectory, host), moduleResolutionState); + if (resolvedFile_1) { + if (traceEnabled) { + trace(host, ts.Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, resolvedFile_1, true); + } + return { + resolvedTypeReferenceDirective: { primary: true, resolvedFileName: resolvedFile_1 }, + failedLookupLocations: failedLookupLocations + }; + } } } - function errorOnFirstToken(node, message, arg0, arg1, arg2) { - var span = ts.getSpanOfTokenAtPosition(file, node.pos); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, message, arg0, arg1, arg2)); + else { + if (traceEnabled) { + trace(host, ts.Diagnostics.Root_directory_cannot_be_determined_skipping_primary_search_paths); + } } - function getDestructuringParameterName(node) { - return "__" + ts.indexOf(node.parent.parameters, node); + var resolvedFile; + var initialLocationForSecondaryLookup; + if (containingFile) { + initialLocationForSecondaryLookup = ts.getDirectoryPath(containingFile); } - function bind(node) { - if (!node) { - return; + if (initialLocationForSecondaryLookup !== undefined) { + // check secondary locations + if (traceEnabled) { + trace(host, ts.Diagnostics.Looking_up_in_node_modules_folder_initial_location_0, initialLocationForSecondaryLookup); } - node.parent = parent; - var saveInStrictMode = inStrictMode; - // First we bind declaration nodes to a symbol if possible. We'll both create a symbol - // and then potentially add the symbol to an appropriate symbol table. Possible - // destination symbol tables are: - // - // 1) The 'exports' table of the current container's symbol. - // 2) The 'members' table of the current container's symbol. - // 3) The 'locals' table of the current container. - // - // However, not all symbols will end up in any of these tables. 'Anonymous' symbols - // (like TypeLiterals for example) will not be put in any table. - bindWorker(node); - // Then we recurse into the children of the node to bind them as well. For certain - // symbols we do specialized work when we recurse. For example, we'll keep track of - // the current 'container' node when it changes. This helps us know which symbol table - // a local should go into for example. Since terminal nodes are known not to have - // children, as an optimization we don't process those. - if (node.kind > 138 /* LastToken */) { - var saveParent = parent; - parent = node; - var containerFlags = getContainerFlags(node); - if (containerFlags === 0 /* None */) { - bindChildren(node); + resolvedFile = loadModuleFromNodeModules(typeReferenceDirectiveName, initialLocationForSecondaryLookup, failedLookupLocations, moduleResolutionState, /*checkOneLevel*/ false); + if (traceEnabled) { + if (resolvedFile) { + trace(host, ts.Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, resolvedFile, false); } else { - bindContainer(node, containerFlags); + trace(host, ts.Diagnostics.Type_reference_directive_0_was_not_resolved, typeReferenceDirectiveName); } - parent = saveParent; } - inStrictMode = saveInStrictMode; } - function updateStrictModeStatementList(statements) { - if (!inStrictMode) { - for (var _i = 0, statements_1 = statements; _i < statements_1.length; _i++) { - var statement = statements_1[_i]; - if (!ts.isPrologueDirective(statement)) { - return; - } - if (isUseStrictPrologueDirective(statement)) { - inStrictMode = true; - return; - } - } + else { + if (traceEnabled) { + trace(host, ts.Diagnostics.Containing_file_is_not_specified_and_root_directory_cannot_be_determined_skipping_lookup_in_node_modules_folder); } } - /// Should be called only on prologue directives (isPrologueDirective(node) should be true) - function isUseStrictPrologueDirective(node) { - var nodeText = ts.getTextOfNodeFromSourceText(file.text, node.expression); - // Note: the node text must be exactly "use strict" or 'use strict'. It is not ok for the - // string to contain unicode escapes (as per ES5). - return nodeText === '"use strict"' || nodeText === "'use strict'"; + return { + resolvedTypeReferenceDirective: resolvedFile + ? { primary: false, resolvedFileName: resolvedFile } + : undefined, + failedLookupLocations: failedLookupLocations + }; + } + ts.resolveTypeReferenceDirective = resolveTypeReferenceDirective; + /** + * Given a set of options, returns the set of type directive names + * that should be included for this program automatically. + * This list could either come from the config file, + * or from enumerating the types root + initial secondary types lookup location. + * More type directives might appear in the program later as a result of loading actual source files; + * this list is only the set of defaults that are implicitly included. + */ + function getAutomaticTypeDirectiveNames(options, host) { + // Use explicit type list from tsconfig.json + if (options.types) { + return options.types; } - function bindWorker(node) { - switch (node.kind) { - /* Strict mode checks */ - case 69 /* Identifier */: - case 97 /* ThisKeyword */: - if (currentFlow && (ts.isExpression(node) || parent.kind === 254 /* ShorthandPropertyAssignment */)) { - node.flowNode = currentFlow; - } - return checkStrictModeIdentifier(node); - case 172 /* PropertyAccessExpression */: - if (currentFlow && isNarrowableReference(node)) { - node.flowNode = currentFlow; - } - break; - case 187 /* BinaryExpression */: - if (ts.isInJavaScriptFile(node)) { - var specialKind = ts.getSpecialPropertyAssignmentKind(node); - switch (specialKind) { - case 1 /* ExportsProperty */: - bindExportsPropertyAssignment(node); - break; - case 2 /* ModuleExports */: - bindModuleExportsAssignment(node); - break; - case 3 /* PrototypeProperty */: - bindPrototypePropertyAssignment(node); - break; - case 4 /* ThisProperty */: - bindThisPropertyAssignment(node); - break; - case 0 /* None */: - // Nothing to do - break; - default: - ts.Debug.fail("Unknown special property assignment kind"); + // Walk the primary type lookup locations + var result = []; + if (host.directoryExists && host.getDirectories) { + var typeRoots = getEffectiveTypeRoots(options, host); + if (typeRoots) { + for (var _i = 0, typeRoots_1 = typeRoots; _i < typeRoots_1.length; _i++) { + var root = typeRoots_1[_i]; + if (host.directoryExists(root)) { + for (var _a = 0, _b = host.getDirectories(root); _a < _b.length; _a++) { + var typeDirectivePath = _b[_a]; + var normalized = ts.normalizePath(typeDirectivePath); + var packageJsonPath = pathToPackageJson(ts.combinePaths(root, normalized)); + // tslint:disable-next-line:no-null-keyword + var isNotNeededPackage = host.fileExists(packageJsonPath) && readJson(packageJsonPath, host).typings === null; + if (!isNotNeededPackage) { + // Return just the type directive names + result.push(ts.getBaseFileName(normalized)); + } } } - return checkStrictModeBinaryExpression(node); - case 252 /* CatchClause */: - return checkStrictModeCatchClause(node); - case 181 /* DeleteExpression */: - return checkStrictModeDeleteExpression(node); - case 8 /* NumericLiteral */: - return checkStrictModeNumericLiteral(node); - case 186 /* PostfixUnaryExpression */: - return checkStrictModePostfixUnaryExpression(node); - case 185 /* PrefixUnaryExpression */: - return checkStrictModePrefixUnaryExpression(node); - case 212 /* WithStatement */: - return checkStrictModeWithStatement(node); - case 165 /* ThisType */: - seenThisKeyword = true; - return; - case 154 /* TypePredicate */: - return checkTypePredicate(node); - case 141 /* TypeParameter */: - return declareSymbolAndAddToSymbolTable(node, 262144 /* TypeParameter */, 530920 /* TypeParameterExcludes */); - case 142 /* Parameter */: - return bindParameter(node); - case 218 /* VariableDeclaration */: - case 169 /* BindingElement */: - return bindVariableDeclarationOrBindingElement(node); - case 145 /* PropertyDeclaration */: - case 144 /* PropertySignature */: - case 266 /* JSDocRecordMember */: - return bindPropertyOrMethodOrAccessor(node, 4 /* Property */ | (node.questionToken ? 536870912 /* Optional */ : 0 /* None */), 0 /* PropertyExcludes */); - case 280 /* JSDocPropertyTag */: - return bindJSDocProperty(node); - case 253 /* PropertyAssignment */: - case 254 /* ShorthandPropertyAssignment */: - return bindPropertyOrMethodOrAccessor(node, 4 /* Property */, 0 /* PropertyExcludes */); - case 255 /* EnumMember */: - return bindPropertyOrMethodOrAccessor(node, 8 /* EnumMember */, 900095 /* EnumMemberExcludes */); - case 247 /* JsxSpreadAttribute */: - emitFlags |= 1073741824 /* HasJsxSpreadAttribute */; - return; - case 151 /* CallSignature */: - case 152 /* ConstructSignature */: - case 153 /* IndexSignature */: - return declareSymbolAndAddToSymbolTable(node, 131072 /* Signature */, 0 /* None */); - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - // If this is an ObjectLiteralExpression method, then it sits in the same space - // as other properties in the object literal. So we use SymbolFlags.PropertyExcludes - // so that it will conflict with any other object literal members with the same - // name. - return bindPropertyOrMethodOrAccessor(node, 8192 /* Method */ | (node.questionToken ? 536870912 /* Optional */ : 0 /* None */), ts.isObjectLiteralMethod(node) ? 0 /* PropertyExcludes */ : 99263 /* MethodExcludes */); - case 220 /* FunctionDeclaration */: - return bindFunctionDeclaration(node); - case 148 /* Constructor */: - return declareSymbolAndAddToSymbolTable(node, 16384 /* Constructor */, /*symbolExcludes:*/ 0 /* None */); - case 149 /* GetAccessor */: - return bindPropertyOrMethodOrAccessor(node, 32768 /* GetAccessor */, 41919 /* GetAccessorExcludes */); - case 150 /* SetAccessor */: - return bindPropertyOrMethodOrAccessor(node, 65536 /* SetAccessor */, 74687 /* SetAccessorExcludes */); - case 156 /* FunctionType */: - case 157 /* ConstructorType */: - case 269 /* JSDocFunctionType */: - return bindFunctionOrConstructorType(node); - case 159 /* TypeLiteral */: - case 281 /* JSDocTypeLiteral */: - case 265 /* JSDocRecordType */: - return bindAnonymousDeclaration(node, 2048 /* TypeLiteral */, "__type"); - case 171 /* ObjectLiteralExpression */: - return bindObjectLiteralExpression(node); - case 179 /* FunctionExpression */: - case 180 /* ArrowFunction */: - return bindFunctionExpression(node); - case 174 /* CallExpression */: - if (ts.isInJavaScriptFile(node)) { - bindCallExpression(node); - } - break; - // Members of classes, interfaces, and modules - case 192 /* ClassExpression */: - case 221 /* ClassDeclaration */: - // All classes are automatically in strict mode in ES6. - inStrictMode = true; - return bindClassLikeDeclaration(node); - case 222 /* InterfaceDeclaration */: - return bindBlockScopedDeclaration(node, 64 /* Interface */, 792968 /* InterfaceExcludes */); - case 279 /* JSDocTypedefTag */: - case 223 /* TypeAliasDeclaration */: - return bindBlockScopedDeclaration(node, 524288 /* TypeAlias */, 793064 /* TypeAliasExcludes */); - case 224 /* EnumDeclaration */: - return bindEnumDeclaration(node); - case 225 /* ModuleDeclaration */: - return bindModuleDeclaration(node); - // Imports and exports - case 229 /* ImportEqualsDeclaration */: - case 232 /* NamespaceImport */: - case 234 /* ImportSpecifier */: - case 238 /* ExportSpecifier */: - return declareSymbolAndAddToSymbolTable(node, 8388608 /* Alias */, 8388608 /* AliasExcludes */); - case 228 /* NamespaceExportDeclaration */: - return bindNamespaceExportDeclaration(node); - case 231 /* ImportClause */: - return bindImportClause(node); - case 236 /* ExportDeclaration */: - return bindExportDeclaration(node); - case 235 /* ExportAssignment */: - return bindExportAssignment(node); - case 256 /* SourceFile */: - updateStrictModeStatementList(node.statements); - return bindSourceFileIfExternalModule(); - case 199 /* Block */: - if (!ts.isFunctionLike(node.parent)) { - return; - } - // Fall through - case 226 /* ModuleBlock */: - return updateStrictModeStatementList(node.statements); + } } } - function checkTypePredicate(node) { - var parameterName = node.parameterName, type = node.type; - if (parameterName && parameterName.kind === 69 /* Identifier */) { - checkStrictModeIdentifier(parameterName); - } - if (parameterName && parameterName.kind === 165 /* ThisType */) { - seenThisKeyword = true; - } - bind(type); + return result; + } + ts.getAutomaticTypeDirectiveNames = getAutomaticTypeDirectiveNames; + function resolveModuleName(moduleName, containingFile, compilerOptions, host) { + var traceEnabled = isTraceEnabled(compilerOptions, host); + if (traceEnabled) { + trace(host, ts.Diagnostics.Resolving_module_0_from_1, moduleName, containingFile); } - function bindSourceFileIfExternalModule() { - setExportContextFlag(file); - if (ts.isExternalModule(file)) { - bindSourceFileAsExternalModule(); + var moduleResolution = compilerOptions.moduleResolution; + if (moduleResolution === undefined) { + moduleResolution = ts.getEmitModuleKind(compilerOptions) === ts.ModuleKind.CommonJS ? ts.ModuleResolutionKind.NodeJs : ts.ModuleResolutionKind.Classic; + if (traceEnabled) { + trace(host, ts.Diagnostics.Module_resolution_kind_is_not_specified_using_0, ts.ModuleResolutionKind[moduleResolution]); } } - function bindSourceFileAsExternalModule() { - bindAnonymousDeclaration(file, 512 /* ValueModule */, "\"" + ts.removeFileExtension(file.fileName) + "\""); - } - function bindExportAssignment(node) { - if (!container.symbol || !container.symbol.exports) { - // Export assignment in some sort of block construct - bindAnonymousDeclaration(node, 8388608 /* Alias */, getDeclarationName(node)); - } - else { - var flags = node.kind === 235 /* ExportAssignment */ && ts.exportAssignmentIsAlias(node) - ? 8388608 /* Alias */ - : 4 /* Property */; - declareSymbol(container.symbol.exports, container.symbol, node, flags, 0 /* PropertyExcludes */ | 8388608 /* AliasExcludes */); + else { + if (traceEnabled) { + trace(host, ts.Diagnostics.Explicitly_specified_module_resolution_kind_Colon_0, ts.ModuleResolutionKind[moduleResolution]); } } - function bindNamespaceExportDeclaration(node) { - if (node.modifiers && node.modifiers.length) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Modifiers_cannot_appear_here)); - } - if (node.parent.kind !== 256 /* SourceFile */) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Global_module_exports_may_only_appear_at_top_level)); - return; - } - else { - var parent_6 = node.parent; - if (!ts.isExternalModule(parent_6)) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Global_module_exports_may_only_appear_in_module_files)); - return; - } - if (!parent_6.isDeclarationFile) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Global_module_exports_may_only_appear_in_declaration_files)); - return; - } - } - file.symbol.globalExports = file.symbol.globalExports || ts.createMap(); - declareSymbol(file.symbol.globalExports, file.symbol, node, 8388608 /* Alias */, 8388608 /* AliasExcludes */); + var result; + switch (moduleResolution) { + case ts.ModuleResolutionKind.NodeJs: + result = nodeModuleNameResolver(moduleName, containingFile, compilerOptions, host); + break; + case ts.ModuleResolutionKind.Classic: + result = classicNameResolver(moduleName, containingFile, compilerOptions, host); + break; } - function bindExportDeclaration(node) { - if (!container.symbol || !container.symbol.exports) { - // Export * in some sort of block construct - bindAnonymousDeclaration(node, 1073741824 /* ExportStar */, getDeclarationName(node)); + if (traceEnabled) { + if (result.resolvedModule) { + trace(host, ts.Diagnostics.Module_name_0_was_successfully_resolved_to_1, moduleName, result.resolvedModule.resolvedFileName); } - else if (!node.exportClause) { - // All export * declarations are collected in an __export symbol - declareSymbol(container.symbol.exports, container.symbol, node, 1073741824 /* ExportStar */, 0 /* None */); + else { + trace(host, ts.Diagnostics.Module_name_0_was_not_resolved, moduleName); } } - function bindImportClause(node) { - if (node.name) { - declareSymbolAndAddToSymbolTable(node, 8388608 /* Alias */, 8388608 /* AliasExcludes */); - } + return result; + } + ts.resolveModuleName = resolveModuleName; + /** + * Any module resolution kind can be augmented with optional settings: 'baseUrl', 'paths' and 'rootDirs' - they are used to + * mitigate differences between design time structure of the project and its runtime counterpart so the same import name + * can be resolved successfully by TypeScript compiler and runtime module loader. + * If these settings are set then loading procedure will try to use them to resolve module name and it can of failure it will + * fallback to standard resolution routine. + * + * - baseUrl - this setting controls how non-relative module names are resolved. If this setting is specified then non-relative + * names will be resolved relative to baseUrl: i.e. if baseUrl is '/a/b' then candidate location to resolve module name 'c/d' will + * be '/a/b/c/d' + * - paths - this setting can only be used when baseUrl is specified. allows to tune how non-relative module names + * will be resolved based on the content of the module name. + * Structure of 'paths' compiler options + * 'paths': { + * pattern-1: [...substitutions], + * pattern-2: [...substitutions], + * ... + * pattern-n: [...substitutions] + * } + * Pattern here is a string that can contain zero or one '*' character. During module resolution module name will be matched against + * all patterns in the list. Matching for patterns that don't contain '*' means that module name must be equal to pattern respecting the case. + * If pattern contains '*' then to match pattern "*" module name must start with the and end with . + * denotes part of the module name between and . + * If module name can be matches with multiple patterns then pattern with the longest prefix will be picked. + * After selecting pattern we'll use list of substitutions to get candidate locations of the module and the try to load module + * from the candidate location. + * Substitution is a string that can contain zero or one '*'. To get candidate location from substitution we'll pick every + * substitution in the list and replace '*' with string. If candidate location is not rooted it + * will be converted to absolute using baseUrl. + * For example: + * baseUrl: /a/b/c + * "paths": { + * // match all module names + * "*": [ + * "*", // use matched name as is, + * // will be looked as /a/b/c/ + * + * "folder1/*" // substitution will convert matched name to 'folder1/', + * // since it is not rooted then final candidate location will be /a/b/c/folder1/ + * ], + * // match module names that start with 'components/' + * "components/*": [ "/root/components/*" ] // substitution will convert /components/folder1/ to '/root/components/folder1/', + * // it is rooted so it will be final candidate location + * } + * + * 'rootDirs' allows the project to be spreaded across multiple locations and resolve modules with relative names as if + * they were in the same location. For example lets say there are two files + * '/local/src/content/file1.ts' + * '/shared/components/contracts/src/content/protocols/file2.ts' + * After bundling content of '/shared/components/contracts/src' will be merged with '/local/src' so + * if file1 has the following import 'import {x} from "./protocols/file2"' it will be resolved successfully in runtime. + * 'rootDirs' provides the way to tell compiler that in order to get the whole project it should behave as if content of all + * root dirs were merged together. + * I.e. for the example above 'rootDirs' will have two entries: [ '/local/src', '/shared/components/contracts/src' ]. + * Compiler will first convert './protocols/file2' into absolute path relative to the location of containing file: + * '/local/src/content/protocols/file2' and try to load it - failure. + * Then it will search 'rootDirs' looking for a longest matching prefix of this absolute path and if such prefix is found - absolute path will + * be converted to a path relative to found rootDir entry './content/protocols/file2' (*). As a last step compiler will check all remaining + * entries in 'rootDirs', use them to build absolute path out of (*) and try to resolve module from this location. + */ + function tryLoadModuleUsingOptionalResolutionSettings(moduleName, containingDirectory, loader, failedLookupLocations, supportedExtensions, state) { + if (moduleHasNonRelativeName(moduleName)) { + return tryLoadModuleUsingBaseUrl(moduleName, loader, failedLookupLocations, supportedExtensions, state); } - function setCommonJsModuleIndicator(node) { - if (!file.commonJsModuleIndicator) { - file.commonJsModuleIndicator = node; - bindSourceFileAsExternalModule(); - } + else { + return tryLoadModuleUsingRootDirs(moduleName, containingDirectory, loader, failedLookupLocations, supportedExtensions, state); } - function bindExportsPropertyAssignment(node) { - // When we create a property via 'exports.foo = bar', the 'exports.foo' property access - // expression is the declaration - setCommonJsModuleIndicator(node); - declareSymbol(file.symbol.exports, file.symbol, node.left, 4 /* Property */ | 7340032 /* Export */, 0 /* None */); + } + function tryLoadModuleUsingRootDirs(moduleName, containingDirectory, loader, failedLookupLocations, supportedExtensions, state) { + if (!state.compilerOptions.rootDirs) { + return undefined; } - function bindModuleExportsAssignment(node) { - // 'module.exports = expr' assignment - setCommonJsModuleIndicator(node); - declareSymbol(file.symbol.exports, file.symbol, node, 4 /* Property */ | 7340032 /* Export */ | 512 /* ValueModule */, 0 /* None */); + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.rootDirs_option_is_set_using_it_to_resolve_relative_module_name_0, moduleName); } - function bindThisPropertyAssignment(node) { - ts.Debug.assert(ts.isInJavaScriptFile(node)); - // Declare a 'member' if the container is an ES5 class or ES6 constructor - if (container.kind === 220 /* FunctionDeclaration */ || container.kind === 179 /* FunctionExpression */) { - container.symbol.members = container.symbol.members || ts.createMap(); - // It's acceptable for multiple 'this' assignments of the same identifier to occur - declareSymbol(container.symbol.members, container.symbol, node, 4 /* Property */, 0 /* PropertyExcludes */ & ~4 /* Property */); - } - else if (container.kind === 148 /* Constructor */) { - // this.foo assignment in a JavaScript class - // Bind this property to the containing class - var saveContainer = container; - container = container.parent; - var symbol = bindPropertyOrMethodOrAccessor(node, 4 /* Property */, 0 /* None */); - if (symbol) { - // constructor-declared symbols can be overwritten by subsequent method declarations - symbol.isReplaceableByMethod = true; - } - container = saveContainer; + var candidate = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName)); + var matchedRootDir; + var matchedNormalizedPrefix; + for (var _i = 0, _a = state.compilerOptions.rootDirs; _i < _a.length; _i++) { + var rootDir = _a[_i]; + // rootDirs are expected to be absolute + // in case of tsconfig.json this will happen automatically - compiler will expand relative names + // using location of tsconfig.json as base location + var normalizedRoot = ts.normalizePath(rootDir); + if (!ts.endsWith(normalizedRoot, ts.directorySeparator)) { + normalizedRoot += ts.directorySeparator; } - } - function bindPrototypePropertyAssignment(node) { - // We saw a node of the form 'x.prototype.y = z'. Declare a 'member' y on x if x was a function. - // Look up the function in the local scope, since prototype assignments should - // follow the function declaration - var leftSideOfAssignment = node.left; - var classPrototype = leftSideOfAssignment.expression; - var constructorFunction = classPrototype.expression; - // Fix up parent pointers since we're going to use these nodes before we bind into them - leftSideOfAssignment.parent = node; - constructorFunction.parent = classPrototype; - classPrototype.parent = leftSideOfAssignment; - var funcSymbol = container.locals[constructorFunction.text]; - if (!funcSymbol || !(funcSymbol.flags & 16 /* Function */ || ts.isDeclarationOfFunctionExpression(funcSymbol))) { - return; + var isLongestMatchingPrefix = ts.startsWith(candidate, normalizedRoot) && + (matchedNormalizedPrefix === undefined || matchedNormalizedPrefix.length < normalizedRoot.length); + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Checking_if_0_is_the_longest_matching_prefix_for_1_2, normalizedRoot, candidate, isLongestMatchingPrefix); } - // Set up the members collection if it doesn't exist already - if (!funcSymbol.members) { - funcSymbol.members = ts.createMap(); + if (isLongestMatchingPrefix) { + matchedNormalizedPrefix = normalizedRoot; + matchedRootDir = rootDir; } - // Declare the method/property - declareSymbol(funcSymbol.members, funcSymbol, leftSideOfAssignment, 4 /* Property */, 0 /* PropertyExcludes */); } - function bindCallExpression(node) { - // We're only inspecting call expressions to detect CommonJS modules, so we can skip - // this check if we've already seen the module indicator - if (!file.commonJsModuleIndicator && ts.isRequireCall(node, /*checkArgumentIsStringLiteral*/ false)) { - setCommonJsModuleIndicator(node); + if (matchedNormalizedPrefix) { + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Longest_matching_prefix_for_0_is_1, candidate, matchedNormalizedPrefix); } - } - function bindClassLikeDeclaration(node) { - if (!ts.isDeclarationFile(file) && !ts.isInAmbientContext(node)) { - if (ts.getClassExtendsHeritageClauseElement(node) !== undefined) { - emitFlags |= 262144 /* HasClassExtends */; - } - if (ts.nodeIsDecorated(node)) { - emitFlags |= 524288 /* HasDecorators */; - } + var suffix = candidate.substr(matchedNormalizedPrefix.length); + // first - try to load from a initial location + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Loading_0_from_the_root_dir_1_candidate_location_2, suffix, matchedNormalizedPrefix, candidate); } - if (node.kind === 221 /* ClassDeclaration */) { - bindBlockScopedDeclaration(node, 32 /* Class */, 899519 /* ClassExcludes */); + var resolvedFileName = loader(candidate, supportedExtensions, failedLookupLocations, !directoryProbablyExists(containingDirectory, state.host), state); + if (resolvedFileName) { + return resolvedFileName; } - else { - var bindingName = node.name ? node.name.text : "__class"; - bindAnonymousDeclaration(node, 32 /* Class */, bindingName); - // Add name of class expression into the map for semantic classifier - if (node.name) { - classifiableNames[node.name.text] = node.name.text; - } + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Trying_other_entries_in_rootDirs); } - var symbol = node.symbol; - // TypeScript 1.0 spec (April 2014): 8.4 - // Every class automatically contains a static property member named 'prototype', the - // type of which is an instantiation of the class type with type Any supplied as a type - // argument for each type parameter. It is an error to explicitly declare a static - // property member with the name 'prototype'. - // - // Note: we check for this here because this class may be merging into a module. The - // module might have an exported variable called 'prototype'. We can't allow that as - // that would clash with the built-in 'prototype' for the class. - var prototypeSymbol = createSymbol(4 /* Property */ | 134217728 /* Prototype */, "prototype"); - if (symbol.exports[prototypeSymbol.name]) { - if (node.name) { - node.name.parent = node; + // then try to resolve using remaining entries in rootDirs + for (var _b = 0, _c = state.compilerOptions.rootDirs; _b < _c.length; _b++) { + var rootDir = _c[_b]; + if (rootDir === matchedRootDir) { + // skip the initially matched entry + continue; + } + var candidate_1 = ts.combinePaths(ts.normalizePath(rootDir), suffix); + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Loading_0_from_the_root_dir_1_candidate_location_2, suffix, rootDir, candidate_1); + } + var baseDirectory = ts.getDirectoryPath(candidate_1); + var resolvedFileName_1 = loader(candidate_1, supportedExtensions, failedLookupLocations, !directoryProbablyExists(baseDirectory, state.host), state); + if (resolvedFileName_1) { + return resolvedFileName_1; } - file.bindDiagnostics.push(ts.createDiagnosticForNode(symbol.exports[prototypeSymbol.name].declarations[0], ts.Diagnostics.Duplicate_identifier_0, prototypeSymbol.name)); } - symbol.exports[prototypeSymbol.name] = prototypeSymbol; - prototypeSymbol.parent = symbol; + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Module_resolution_using_rootDirs_has_failed); + } } - function bindEnumDeclaration(node) { - return ts.isConst(node) - ? bindBlockScopedDeclaration(node, 128 /* ConstEnum */, 899967 /* ConstEnumExcludes */) - : bindBlockScopedDeclaration(node, 256 /* RegularEnum */, 899327 /* RegularEnumExcludes */); + return undefined; + } + function tryLoadModuleUsingBaseUrl(moduleName, loader, failedLookupLocations, supportedExtensions, state) { + if (!state.compilerOptions.baseUrl) { + return undefined; } - function bindVariableDeclarationOrBindingElement(node) { - if (inStrictMode) { - checkStrictModeEvalOrArguments(node, node.name); + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.baseUrl_option_is_set_to_0_using_this_value_to_resolve_non_relative_module_name_1, state.compilerOptions.baseUrl, moduleName); + } + // string is for exact match + var matchedPattern = undefined; + if (state.compilerOptions.paths) { + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.paths_option_is_specified_looking_for_a_pattern_to_match_module_name_0, moduleName); } - if (!ts.isBindingPattern(node.name)) { - if (ts.isBlockOrCatchScoped(node)) { - bindBlockScopedVariableDeclaration(node); - } - else if (ts.isParameterDeclaration(node)) { - // It is safe to walk up parent chain to find whether the node is a destructing parameter declaration - // because its parent chain has already been set up, since parents are set before descending into children. - // - // If node is a binding element in parameter declaration, we need to use ParameterExcludes. - // Using ParameterExcludes flag allows the compiler to report an error on duplicate identifiers in Parameter Declaration - // For example: - // function foo([a,a]) {} // Duplicate Identifier error - // function bar(a,a) {} // Duplicate Identifier error, parameter declaration in this case is handled in bindParameter - // // which correctly set excluded symbols - declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 107455 /* ParameterExcludes */); + matchedPattern = ts.matchPatternOrExact(ts.getOwnKeys(state.compilerOptions.paths), moduleName); + } + if (matchedPattern) { + var matchedStar = typeof matchedPattern === "string" ? undefined : ts.matchedText(matchedPattern, moduleName); + var matchedPatternText = typeof matchedPattern === "string" ? matchedPattern : ts.patternText(matchedPattern); + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Module_name_0_matched_pattern_1, moduleName, matchedPatternText); + } + for (var _i = 0, _a = state.compilerOptions.paths[matchedPatternText]; _i < _a.length; _i++) { + var subst = _a[_i]; + var path = matchedStar ? subst.replace("*", matchedStar) : subst; + var candidate = ts.normalizePath(ts.combinePaths(state.compilerOptions.baseUrl, path)); + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Trying_substitution_0_candidate_module_location_Colon_1, subst, path); } - else { - declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 107454 /* FunctionScopedVariableExcludes */); + var resolvedFileName = loader(candidate, supportedExtensions, failedLookupLocations, !directoryProbablyExists(ts.getDirectoryPath(candidate), state.host), state); + if (resolvedFileName) { + return resolvedFileName; } } + return undefined; } - function bindParameter(node) { - if (!ts.isDeclarationFile(file) && - !ts.isInAmbientContext(node) && - ts.nodeIsDecorated(node)) { - emitFlags |= (524288 /* HasDecorators */ | 1048576 /* HasParamDecorators */); - } - if (inStrictMode) { - // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a - // strict mode FunctionLikeDeclaration or FunctionExpression(13.1) - checkStrictModeEvalOrArguments(node, node.name); + else { + var candidate = ts.normalizePath(ts.combinePaths(state.compilerOptions.baseUrl, moduleName)); + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Resolving_module_name_0_relative_to_base_url_1_2, moduleName, state.compilerOptions.baseUrl, candidate); } - if (ts.isBindingPattern(node.name)) { - bindAnonymousDeclaration(node, 1 /* FunctionScopedVariable */, getDestructuringParameterName(node)); + return loader(candidate, supportedExtensions, failedLookupLocations, !directoryProbablyExists(ts.getDirectoryPath(candidate), state.host), state); + } + } + function nodeModuleNameResolver(moduleName, containingFile, compilerOptions, host) { + var containingDirectory = ts.getDirectoryPath(containingFile); + var supportedExtensions = ts.getSupportedExtensions(compilerOptions); + var traceEnabled = isTraceEnabled(compilerOptions, host); + var failedLookupLocations = []; + var state = { compilerOptions: compilerOptions, host: host, traceEnabled: traceEnabled, skipTsx: false }; + var resolvedFileName = tryLoadModuleUsingOptionalResolutionSettings(moduleName, containingDirectory, nodeLoadModuleByRelativeName, failedLookupLocations, supportedExtensions, state); + var isExternalLibraryImport = false; + if (!resolvedFileName) { + if (moduleHasNonRelativeName(moduleName)) { + if (traceEnabled) { + trace(host, ts.Diagnostics.Loading_module_0_from_node_modules_folder, moduleName); + } + resolvedFileName = loadModuleFromNodeModules(moduleName, containingDirectory, failedLookupLocations, state, /*checkOneLevel*/ false); + isExternalLibraryImport = resolvedFileName !== undefined; } else { - declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 107455 /* ParameterExcludes */); - } - // If this is a property-parameter, then also declare the property symbol into the - // containing class. - if (ts.isParameterPropertyDeclaration(node)) { - var classDeclaration = node.parent.parent; - declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, 4 /* Property */ | (node.questionToken ? 536870912 /* Optional */ : 0 /* None */), 0 /* PropertyExcludes */); + var candidate = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName)); + resolvedFileName = nodeLoadModuleByRelativeName(candidate, supportedExtensions, failedLookupLocations, /*onlyRecordFailures*/ false, state); } } - function bindFunctionDeclaration(node) { - if (!ts.isDeclarationFile(file) && !ts.isInAmbientContext(node)) { - if (ts.isAsyncFunctionLike(node)) { - emitFlags |= 2097152 /* HasAsyncFunctions */; - } + if (resolvedFileName && host.realpath) { + var originalFileName = resolvedFileName; + resolvedFileName = ts.normalizePath(host.realpath(resolvedFileName)); + if (traceEnabled) { + trace(host, ts.Diagnostics.Resolving_real_path_for_0_result_1, originalFileName, resolvedFileName); } - checkStrictModeFunctionName(node); - if (inStrictMode) { - checkStrictModeFunctionDeclaration(node); - bindBlockScopedDeclaration(node, 16 /* Function */, 106927 /* FunctionExcludes */); + } + return createResolvedModule(resolvedFileName, isExternalLibraryImport, failedLookupLocations); + } + ts.nodeModuleNameResolver = nodeModuleNameResolver; + function nodeLoadModuleByRelativeName(candidate, supportedExtensions, failedLookupLocations, onlyRecordFailures, state) { + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Loading_module_as_file_Slash_folder_candidate_module_location_0, candidate); + } + var resolvedFileName = !ts.pathEndsWithDirectorySeparator(candidate) && loadModuleFromFile(candidate, supportedExtensions, failedLookupLocations, onlyRecordFailures, state); + return resolvedFileName || loadNodeModuleFromDirectory(supportedExtensions, candidate, failedLookupLocations, onlyRecordFailures, state); + } + /* @internal */ + function directoryProbablyExists(directoryName, host) { + // if host does not support 'directoryExists' assume that directory will exist + return !host.directoryExists || host.directoryExists(directoryName); + } + ts.directoryProbablyExists = directoryProbablyExists; + /** + * @param {boolean} onlyRecordFailures - if true then function won't try to actually load files but instead record all attempts as failures. This flag is necessary + * in cases when we know upfront that all load attempts will fail (because containing folder does not exists) however we still need to record all failed lookup locations. + */ + function loadModuleFromFile(candidate, extensions, failedLookupLocation, onlyRecordFailures, state) { + // First, try adding an extension. An import of "foo" could be matched by a file "foo.ts", or "foo.js" by "foo.js.ts" + var resolvedByAddingExtension = tryAddingExtensions(candidate, extensions, failedLookupLocation, onlyRecordFailures, state); + if (resolvedByAddingExtension) { + return resolvedByAddingExtension; + } + // If that didn't work, try stripping a ".js" or ".jsx" extension and replacing it with a TypeScript one; + // e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts" + if (ts.hasJavaScriptFileExtension(candidate)) { + var extensionless = ts.removeFileExtension(candidate); + if (state.traceEnabled) { + var extension = candidate.substring(extensionless.length); + trace(state.host, ts.Diagnostics.File_name_0_has_a_1_extension_stripping_it, candidate, extension); } - else { - declareSymbolAndAddToSymbolTable(node, 16 /* Function */, 106927 /* FunctionExcludes */); + return tryAddingExtensions(extensionless, extensions, failedLookupLocation, onlyRecordFailures, state); + } + } + /** Try to return an existing file that adds one of the `extensions` to `candidate`. */ + function tryAddingExtensions(candidate, extensions, failedLookupLocation, onlyRecordFailures, state) { + if (!onlyRecordFailures) { + // check if containing folder exists - if it doesn't then just record failures for all supported extensions without disk probing + var directory = ts.getDirectoryPath(candidate); + if (directory) { + onlyRecordFailures = !directoryProbablyExists(directory, state.host); } } - function bindFunctionExpression(node) { - if (!ts.isDeclarationFile(file) && !ts.isInAmbientContext(node)) { - if (ts.isAsyncFunctionLike(node)) { - emitFlags |= 2097152 /* HasAsyncFunctions */; - } + return ts.forEach(extensions, function (ext) { + return !(state.skipTsx && ts.isJsxOrTsxExtension(ext)) && tryFile(candidate + ext, failedLookupLocation, onlyRecordFailures, state); + }); + } + /** Return the file if it exists. */ + function tryFile(fileName, failedLookupLocation, onlyRecordFailures, state) { + if (!onlyRecordFailures && state.host.fileExists(fileName)) { + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.File_0_exist_use_it_as_a_name_resolution_result, fileName); } - if (currentFlow) { - node.flowNode = currentFlow; + return fileName; + } + else { + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.File_0_does_not_exist, fileName); } - checkStrictModeFunctionName(node); - var bindingName = node.name ? node.name.text : "__function"; - return bindAnonymousDeclaration(node, 16 /* Function */, bindingName); + failedLookupLocation.push(fileName); + return undefined; } - function bindPropertyOrMethodOrAccessor(node, symbolFlags, symbolExcludes) { - if (!ts.isDeclarationFile(file) && !ts.isInAmbientContext(node)) { - if (ts.isAsyncFunctionLike(node)) { - emitFlags |= 2097152 /* HasAsyncFunctions */; + } + function loadNodeModuleFromDirectory(extensions, candidate, failedLookupLocation, onlyRecordFailures, state) { + var packageJsonPath = pathToPackageJson(candidate); + var directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, state.host); + if (directoryExists && state.host.fileExists(packageJsonPath)) { + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Found_package_json_at_0, packageJsonPath); + } + var typesFile = tryReadTypesSection(packageJsonPath, candidate, state); + if (typesFile) { + var onlyRecordFailures_1 = !directoryProbablyExists(ts.getDirectoryPath(typesFile), state.host); + // A package.json "typings" may specify an exact filename, or may choose to omit an extension. + var result = tryFile(typesFile, failedLookupLocation, onlyRecordFailures_1, state) || + tryAddingExtensions(typesFile, extensions, failedLookupLocation, onlyRecordFailures_1, state); + if (result) { + return result; } - if (ts.nodeIsDecorated(node)) { - emitFlags |= 524288 /* HasDecorators */; + } + else { + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.package_json_does_not_have_types_field); } } - return ts.hasDynamicName(node) - ? bindAnonymousDeclaration(node, symbolFlags, "__computed") - : declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); } - function bindJSDocProperty(node) { - return declareSymbolAndAddToSymbolTable(node, 4 /* Property */, 0 /* PropertyExcludes */); + else { + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.File_0_does_not_exist, packageJsonPath); + } + // record package json as one of failed lookup locations - in the future if this file will appear it will invalidate resolution results + failedLookupLocation.push(packageJsonPath); } - // reachability checks - function shouldReportErrorOnModuleDeclaration(node) { - var instanceState = getModuleInstanceState(node); - return instanceState === 1 /* Instantiated */ || (instanceState === 2 /* ConstEnumOnly */ && options.preserveConstEnums); + return loadModuleFromFile(ts.combinePaths(candidate, "index"), extensions, failedLookupLocation, !directoryExists, state); + } + function pathToPackageJson(directory) { + return ts.combinePaths(directory, "package.json"); + } + function loadModuleFromNodeModulesFolder(moduleName, directory, failedLookupLocations, state) { + var nodeModulesFolder = ts.combinePaths(directory, "node_modules"); + var nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, state.host); + var candidate = ts.normalizePath(ts.combinePaths(nodeModulesFolder, moduleName)); + var supportedExtensions = ts.getSupportedExtensions(state.compilerOptions); + var result = loadModuleFromFile(candidate, supportedExtensions, failedLookupLocations, !nodeModulesFolderExists, state); + if (result) { + return result; } - function checkUnreachable(node) { - if (!(currentFlow.flags & 1 /* Unreachable */)) { - return false; - } - if (currentFlow === unreachableFlow) { - var reportError = - // report error on all statements except empty ones - (ts.isStatement(node) && node.kind !== 201 /* EmptyStatement */) || - // report error on class declarations - node.kind === 221 /* ClassDeclaration */ || - // report error on instantiated modules or const-enums only modules if preserveConstEnums is set - (node.kind === 225 /* ModuleDeclaration */ && shouldReportErrorOnModuleDeclaration(node)) || - // report error on regular enums and const enums if preserveConstEnums is set - (node.kind === 224 /* EnumDeclaration */ && (!ts.isConstEnumDeclaration(node) || options.preserveConstEnums)); - if (reportError) { - currentFlow = reportedUnreachableFlow; - // unreachable code is reported if - // - user has explicitly asked about it AND - // - statement is in not ambient context (statements in ambient context is already an error - // so we should not report extras) AND - // - node is not variable statement OR - // - node is block scoped variable statement OR - // - node is not block scoped variable statement and at least one variable declaration has initializer - // Rationale: we don't want to report errors on non-initialized var's since they are hoisted - // On the other side we do want to report errors on non-initialized 'lets' because of TDZ - var reportUnreachableCode = !options.allowUnreachableCode && - !ts.isInAmbientContext(node) && - (node.kind !== 200 /* VariableStatement */ || - ts.getCombinedNodeFlags(node.declarationList) & 3072 /* BlockScoped */ || - ts.forEach(node.declarationList.declarations, function (d) { return d.initializer; })); - if (reportUnreachableCode) { - errorOnFirstToken(node, ts.Diagnostics.Unreachable_code_detected); + result = loadNodeModuleFromDirectory(supportedExtensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state); + if (result) { + return result; + } + } + /* @internal */ + function loadModuleFromNodeModules(moduleName, directory, failedLookupLocations, state, checkOneLevel) { + directory = ts.normalizeSlashes(directory); + while (true) { + var baseName = ts.getBaseFileName(directory); + if (baseName !== "node_modules") { + // Try to load source from the package + var packageResult = loadModuleFromNodeModulesFolder(moduleName, directory, failedLookupLocations, state); + if (packageResult && ts.hasTypeScriptFileExtension(packageResult)) { + // Always prefer a TypeScript (.ts, .tsx, .d.ts) file shipped with the package + return packageResult; + } + else { + // Else prefer a types package over non-TypeScript results (e.g. JavaScript files) + var typesResult = loadModuleFromNodeModulesFolder(ts.combinePaths("@types", moduleName), directory, failedLookupLocations, state); + if (typesResult || packageResult) { + return typesResult || packageResult; } } } - return true; + var parentPath = ts.getDirectoryPath(directory); + if (parentPath === directory || checkOneLevel) { + break; + } + directory = parentPath; + } + return undefined; + } + ts.loadModuleFromNodeModules = loadModuleFromNodeModules; + function classicNameResolver(moduleName, containingFile, compilerOptions, host) { + var traceEnabled = isTraceEnabled(compilerOptions, host); + var state = { compilerOptions: compilerOptions, host: host, traceEnabled: traceEnabled, skipTsx: !compilerOptions.jsx }; + var failedLookupLocations = []; + var supportedExtensions = ts.getSupportedExtensions(compilerOptions); + var containingDirectory = ts.getDirectoryPath(containingFile); + var resolvedFileName = tryLoadModuleUsingOptionalResolutionSettings(moduleName, containingDirectory, loadModuleFromFile, failedLookupLocations, supportedExtensions, state); + if (resolvedFileName) { + return createResolvedModule(resolvedFileName, /*isExternalLibraryImport*/ false, failedLookupLocations); + } + var referencedSourceFile; + if (moduleHasNonRelativeName(moduleName)) { + while (true) { + var searchName = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName)); + referencedSourceFile = loadModuleFromFile(searchName, supportedExtensions, failedLookupLocations, /*onlyRecordFailures*/ false, state); + if (referencedSourceFile) { + break; + } + var parentPath = ts.getDirectoryPath(containingDirectory); + if (parentPath === containingDirectory) { + break; + } + containingDirectory = parentPath; + } } + else { + var candidate = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName)); + referencedSourceFile = loadModuleFromFile(candidate, supportedExtensions, failedLookupLocations, /*onlyRecordFailures*/ false, state); + } + return referencedSourceFile + ? { resolvedModule: { resolvedFileName: referencedSourceFile }, failedLookupLocations: failedLookupLocations } + : { resolvedModule: undefined, failedLookupLocations: failedLookupLocations }; } + ts.classicNameResolver = classicNameResolver; })(ts || (ts = {})); +/// /// /* @internal */ var ts; (function (ts) { + var ambientModuleSymbolRegex = /^".+"$/; var nextSymbolId = 1; var nextNodeId = 1; var nextMergeId = 1; @@ -16622,6 +22582,7 @@ var ts; getAliasedSymbol: resolveAlias, getEmitResolver: getEmitResolver, getExportsOfModule: getExportsOfModuleAsArray, + getAmbientModules: getAmbientModules, getJsxElementAttributesType: getJsxElementAttributesType, getJsxIntrinsicTagNames: getJsxIntrinsicTagNames, isOptionalParameter: isOptionalParameter @@ -16647,6 +22608,7 @@ var ts; var esSymbolType = createIntrinsicType(512 /* ESSymbol */, "symbol"); var voidType = createIntrinsicType(1024 /* Void */, "void"); var neverType = createIntrinsicType(8192 /* Never */, "never"); + var silentNeverType = createIntrinsicType(8192 /* Never */, "never"); var emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); var emptyGenericType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); emptyGenericType.instantiations = ts.createMap(); @@ -16658,6 +22620,7 @@ var ts; var anySignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); var unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, unknownType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); var resolvingSignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); + var silentNeverSignature = createSignature(undefined, undefined, undefined, emptyArray, silentNeverType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); var enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true); var globals = ts.createMap(); /** @@ -16668,6 +22631,7 @@ var ts; var patternAmbientModules; var getGlobalESSymbolConstructorSymbol; var getGlobalPromiseConstructorSymbol; + var tryGetGlobalPromiseConstructorSymbol; var globalObjectType; var globalFunctionType; var globalArrayType; @@ -16824,6 +22788,7 @@ var ts; var assignableRelation = ts.createMap(); var comparableRelation = ts.createMap(); var identityRelation = ts.createMap(); + var enumRelation = ts.createMap(); // This is for caching the result of getSymbolDisplayBuilder. Do not access directly. var _displayBuilder; var TypeSystemPropertyName; @@ -17117,7 +23082,7 @@ var ts; } var initializerOfNonStaticProperty = current.parent && current.parent.kind === 145 /* PropertyDeclaration */ && - (current.parent.flags & 32 /* Static */) === 0 && + (ts.getModifierFlags(current.parent) & 32 /* Static */) === 0 && current.parent.initializer === current; if (initializerOfNonStaticProperty) { return true; @@ -17226,7 +23191,7 @@ var ts; // local variables of the constructor. This effectively means that entities from outer scopes // by the same name as a constructor parameter or local variable are inaccessible // in initializer expressions for instance member variables. - if (ts.isClassLike(location.parent) && !(location.flags & 32 /* Static */)) { + if (ts.isClassLike(location.parent) && !(ts.getModifierFlags(location) & 32 /* Static */)) { var ctor = findConstructorDeclaration(location.parent); if (ctor && ctor.locals) { if (getSymbol(ctor.locals, name, meaning & 107455 /* Value */)) { @@ -17240,7 +23205,7 @@ var ts; case 192 /* ClassExpression */: case 222 /* InterfaceDeclaration */: if (result = getSymbol(getSymbolOfNode(location).members, name, meaning & 793064 /* Type */)) { - if (lastLocation && lastLocation.flags & 32 /* Static */) { + if (lastLocation && ts.getModifierFlags(lastLocation) & 32 /* Static */) { // TypeScript 1.0 spec (April 2014): 3.4.1 // The scope of a type parameter extends over the entire declaration with which the type // parameter list is associated, with the exception of static member declarations in classes. @@ -17336,7 +23301,8 @@ var ts; if (nameNotFoundMessage) { if (!errorLocation || !checkAndReportErrorForMissingPrefix(errorLocation, name, nameArg) && - !checkAndReportErrorForExtendingInterface(errorLocation)) { + !checkAndReportErrorForExtendingInterface(errorLocation) && + !checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning)) { error(errorLocation, nameNotFoundMessage, typeof nameArg === "string" ? nameArg : ts.declarationNameToString(nameArg)); } } @@ -17368,8 +23334,8 @@ var ts; checkResolvedBlockScopedVariable(exportOrLocalSymbol, errorLocation); } } - // If we're in an external module, we can't reference symbols created from UMD export declarations - if (result && isInExternalModule) { + // If we're in an external module, we can't reference value symbols created from UMD export declarations + if (result && isInExternalModule && (meaning & 107455 /* Value */) === 107455 /* Value */) { var decls = result.declarations; if (decls && decls.length === 1 && decls[0].kind === 228 /* NamespaceExportDeclaration */) { error(errorLocation, ts.Diagnostics.Identifier_0_must_be_imported_from_a_module, name); @@ -17398,7 +23364,7 @@ var ts; } // No static member is present. // Check if we're in an instance method and look for a relevant instance member. - if (location === container && !(location.flags & 32 /* Static */)) { + if (location === container && !(ts.getModifierFlags(location) & 32 /* Static */)) { var instanceType = getDeclaredTypeOfSymbol(classSymbol).thisType; if (getPropertyOfType(instanceType, name)) { error(errorLocation, ts.Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0, typeof nameArg === "string" ? nameArg : ts.declarationNameToString(nameArg)); @@ -17434,6 +23400,16 @@ var ts; return undefined; } } + function checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning) { + if (meaning & (107455 /* Value */ & ~1024 /* NamespaceModule */)) { + var symbol = resolveSymbol(resolveName(errorLocation, name, 793064 /* Type */ & ~107455 /* Value */, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined)); + if (symbol && !(symbol.flags & 1024 /* NamespaceModule */)) { + error(errorLocation, ts.Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, name); + return true; + } + } + return false; + } function checkResolvedBlockScopedVariable(result, errorLocation) { ts.Debug.assert((result.flags & 2 /* BlockScopedVariable */) !== 0); // Block-scoped variables cannot be used before their definition @@ -17481,7 +23457,7 @@ var ts; function getTargetOfImportClause(node) { var moduleSymbol = resolveExternalModuleName(node, node.parent.moduleSpecifier); if (moduleSymbol) { - var exportDefaultSymbol = ts.isShorthandAmbientModule(moduleSymbol.valueDeclaration) ? + var exportDefaultSymbol = ts.isShorthandAmbientModuleSymbol(moduleSymbol) ? moduleSymbol : moduleSymbol.exports["export="] ? getPropertyOfType(getTypeOfSymbol(moduleSymbol.exports["export="]), "default") : @@ -17552,31 +23528,31 @@ var ts; var moduleSymbol = resolveExternalModuleName(node, node.moduleSpecifier); var targetSymbol = resolveESModuleSymbol(moduleSymbol, node.moduleSpecifier); if (targetSymbol) { - var name_10 = specifier.propertyName || specifier.name; - if (name_10.text) { - if (ts.isShorthandAmbientModule(moduleSymbol.valueDeclaration)) { + var name_13 = specifier.propertyName || specifier.name; + if (name_13.text) { + if (ts.isShorthandAmbientModuleSymbol(moduleSymbol)) { return moduleSymbol; } var symbolFromVariable = void 0; // First check if module was specified with "export=". If so, get the member from the resolved type if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports["export="]) { - symbolFromVariable = getPropertyOfType(getTypeOfSymbol(targetSymbol), name_10.text); + symbolFromVariable = getPropertyOfType(getTypeOfSymbol(targetSymbol), name_13.text); } else { - symbolFromVariable = getPropertyOfVariable(targetSymbol, name_10.text); + symbolFromVariable = getPropertyOfVariable(targetSymbol, name_13.text); } // if symbolFromVariable is export - get its final target symbolFromVariable = resolveSymbol(symbolFromVariable); - var symbolFromModule = getExportOfModule(targetSymbol, name_10.text); + var symbolFromModule = getExportOfModule(targetSymbol, name_13.text); // If the export member we're looking for is default, and there is no real default but allowSyntheticDefaultImports is on, return the entire module as the default - if (!symbolFromModule && allowSyntheticDefaultImports && name_10.text === "default") { + if (!symbolFromModule && allowSyntheticDefaultImports && name_13.text === "default") { symbolFromModule = resolveExternalModuleSymbol(moduleSymbol) || resolveSymbol(moduleSymbol); } var symbol = symbolFromModule && symbolFromVariable ? combineValueAndTypeSymbols(symbolFromVariable, symbolFromModule) : symbolFromModule || symbolFromVariable; if (!symbol) { - error(name_10, ts.Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(moduleSymbol), ts.declarationNameToString(name_10)); + error(name_13, ts.Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(moduleSymbol), ts.declarationNameToString(name_13)); } return symbol; } @@ -17697,14 +23673,14 @@ var ts; return symbol.parent ? getFullyQualifiedName(symbol.parent) + "." + symbolToString(symbol) : symbolToString(symbol); } // Resolves a qualified name and any involved aliases - function resolveEntityName(name, meaning, ignoreErrors, dontResolveAlias) { + function resolveEntityName(name, meaning, ignoreErrors, dontResolveAlias, location) { if (ts.nodeIsMissing(name)) { return undefined; } var symbol; if (name.kind === 69 /* Identifier */) { var message = meaning === 1920 /* Namespace */ ? ts.Diagnostics.Cannot_find_namespace_0 : ts.Diagnostics.Cannot_find_name_0; - symbol = resolveName(name, name.text, meaning, ignoreErrors ? undefined : message, name); + symbol = resolveName(location || name, name.text, meaning, ignoreErrors ? undefined : message, name); if (!symbol) { return undefined; } @@ -17712,7 +23688,7 @@ var ts; else if (name.kind === 139 /* QualifiedName */ || name.kind === 172 /* PropertyAccessExpression */) { var left = name.kind === 139 /* QualifiedName */ ? name.left : name.expression; var right = name.kind === 139 /* QualifiedName */ ? name.right : name.name; - var namespace = resolveEntityName(left, 1920 /* Namespace */, ignoreErrors); + var namespace = resolveEntityName(left, 1920 /* Namespace */, ignoreErrors, /*dontResolveAlias*/ false, location); if (!namespace || ts.nodeIsMissing(right)) { return undefined; } @@ -17722,7 +23698,7 @@ var ts; symbol = getSymbol(getExportsOfSymbol(namespace), right.text, meaning); if (!symbol) { if (!ignoreErrors) { - error(right, ts.Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(namespace), ts.declarationNameToString(right)); + error(right, ts.Diagnostics.Namespace_0_has_no_exported_member_1, getFullyQualifiedName(namespace), ts.declarationNameToString(right)); } return undefined; } @@ -17741,9 +23717,12 @@ var ts; return; } var moduleReferenceLiteral = moduleReferenceExpression; + return resolveExternalModule(location, moduleReferenceLiteral.text, moduleNotFoundError, moduleReferenceLiteral); + } + function resolveExternalModule(location, moduleReference, moduleNotFoundError, errorNode) { // Module names are escaped in our symbol table. However, string literal values aren't. // Escape the name in the "require(...)" clause to ensure we find the right symbol. - var moduleName = ts.escapeIdentifier(moduleReferenceLiteral.text); + var moduleName = ts.escapeIdentifier(moduleReference); if (moduleName === undefined) { return; } @@ -17755,7 +23734,7 @@ var ts; return getMergedSymbol(symbol); } } - var resolvedModule = ts.getResolvedModule(ts.getSourceFileOfNode(location), moduleReferenceLiteral.text); + var resolvedModule = ts.getResolvedModule(ts.getSourceFileOfNode(location), moduleReference); var sourceFile = resolvedModule && host.getSourceFile(resolvedModule.resolvedFileName); if (sourceFile) { if (sourceFile.symbol) { @@ -17764,7 +23743,7 @@ var ts; } if (moduleNotFoundError) { // report errors only if it was requested - error(moduleReferenceLiteral, ts.Diagnostics.File_0_is_not_a_module, sourceFile.fileName); + error(errorNode, ts.Diagnostics.File_0_is_not_a_module, sourceFile.fileName); } return undefined; } @@ -17779,10 +23758,10 @@ var ts; var tsExtension = ts.tryExtractTypeScriptExtension(moduleName); if (tsExtension) { var diag = ts.Diagnostics.An_import_path_cannot_end_with_a_0_extension_Consider_importing_1_instead; - error(moduleReferenceLiteral, diag, tsExtension, ts.removeExtension(moduleName, tsExtension)); + error(errorNode, diag, tsExtension, ts.removeExtension(moduleName, tsExtension)); } else { - error(moduleReferenceLiteral, moduleNotFoundError, moduleName); + error(errorNode, moduleNotFoundError, moduleName); } } return undefined; @@ -18100,7 +24079,15 @@ var ts; } return false; } - function isSymbolAccessible(symbol, enclosingDeclaration, meaning) { + /** + * Check if the given symbol in given enclosing declaration is accessible and mark all associated alias to be visible if requested + * + * @param symbol a Symbol to check if accessible + * @param enclosingDeclaration a Node containing reference to the symbol + * @param meaning a SymbolFlags to check if such meaning of the symbol is accessible + * @param shouldComputeAliasToMakeVisible a boolean value to indicate whether to return aliases to be mark visible in case the symbol is accessible + */ + function isSymbolAccessible(symbol, enclosingDeclaration, meaning, shouldComputeAliasesToMakeVisible) { if (symbol && enclosingDeclaration && !(symbol.flags & 262144 /* TypeParameter */)) { var initialSymbol = symbol; var meaningToLook = meaning; @@ -18108,7 +24095,7 @@ var ts; // Symbol is accessible if it by itself is accessible var accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaningToLook, /*useOnlyExternalAliasing*/ false); if (accessibleSymbolChain) { - var hasAccessibleDeclarations = hasVisibleDeclarations(accessibleSymbolChain[0]); + var hasAccessibleDeclarations = hasVisibleDeclarations(accessibleSymbolChain[0], shouldComputeAliasesToMakeVisible); if (!hasAccessibleDeclarations) { return { accessibility: 1 /* NotAccessible */, @@ -18165,7 +24152,7 @@ var ts; function hasExternalModuleSymbol(declaration) { return ts.isAmbientModule(declaration) || (declaration.kind === 256 /* SourceFile */ && ts.isExternalOrCommonJsModule(declaration)); } - function hasVisibleDeclarations(symbol) { + function hasVisibleDeclarations(symbol, shouldComputeAliasToMakeVisible) { var aliasesToMakeVisible; if (ts.forEach(symbol.declarations, function (declaration) { return !getIsDeclarationVisible(declaration); })) { return undefined; @@ -18177,16 +24164,21 @@ var ts; // because these kind of aliases can be used to name types in declaration file var anyImportSyntax = getAnyImportSyntax(declaration); if (anyImportSyntax && - !(anyImportSyntax.flags & 1 /* Export */) && + !(ts.getModifierFlags(anyImportSyntax) & 1 /* Export */) && isDeclarationVisible(anyImportSyntax.parent)) { - getNodeLinks(declaration).isVisible = true; - if (aliasesToMakeVisible) { - if (!ts.contains(aliasesToMakeVisible, anyImportSyntax)) { - aliasesToMakeVisible.push(anyImportSyntax); + // In function "buildTypeDisplay" where we decide whether to write type-alias or serialize types, + // we want to just check if type- alias is accessible or not but we don't care about emitting those alias at that time + // since we will do the emitting later in trackSymbol. + if (shouldComputeAliasToMakeVisible) { + getNodeLinks(declaration).isVisible = true; + if (aliasesToMakeVisible) { + if (!ts.contains(aliasesToMakeVisible, anyImportSyntax)) { + aliasesToMakeVisible.push(anyImportSyntax); + } + } + else { + aliasesToMakeVisible = [anyImportSyntax]; } - } - else { - aliasesToMakeVisible = [anyImportSyntax]; } return true; } @@ -18216,7 +24208,7 @@ var ts; var firstIdentifier = getFirstIdentifier(entityName); var symbol = resolveName(enclosingDeclaration, firstIdentifier.text, meaning, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined); // Verify if the symbol is accessible - return (symbol && hasVisibleDeclarations(symbol)) || { + return (symbol && hasVisibleDeclarations(symbol, /*shouldComputeAliasToMakeVisible*/ true)) || { accessibility: 1 /* NotAccessible */, errorSymbolName: ts.getTextOfNode(firstIdentifier), errorNode: firstIdentifier @@ -18314,6 +24306,9 @@ var ts; node.parent.kind === 226 /* ModuleBlock */ && ts.isExternalModuleAugmentation(node.parent.parent); } + function literalTypeToString(type) { + return type.flags & 32 /* StringLiteral */ ? "\"" + ts.escapeString(type.text) + "\"" : type.text; + } function getSymbolDisplayBuilder() { function getNameOfSymbol(symbol) { if (symbol.declarations && symbol.declarations.length) { @@ -18386,7 +24381,7 @@ var ts; } parentSymbol = symbol; } - // const the writer know we just wrote out a symbol. The declaration emitter writer uses + // Let the writer know we just wrote out a symbol. The declaration emitter writer uses // this to determine if an import it has previously seen (and not written out) needs // to be written to the file once the walk of the tree is complete. // @@ -18394,32 +24389,32 @@ var ts; // up front (for example, during checking) could determine if we need to emit the imports // and we could then access that data during declaration emit. writer.trackSymbol(symbol, enclosingDeclaration, meaning); - function walkSymbol(symbol, meaning) { - if (symbol) { - var accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaning, !!(flags & 2 /* UseOnlyExternalAliasing */)); - if (!accessibleSymbolChain || - needsQualification(accessibleSymbolChain[0], enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning))) { - // Go up and add our parent. - walkSymbol(getParentOfSymbol(accessibleSymbolChain ? accessibleSymbolChain[0] : symbol), getQualifiedLeftMeaning(meaning)); + /** @param endOfChain Set to false for recursive calls; non-recursive calls should always output something. */ + function walkSymbol(symbol, meaning, endOfChain) { + var accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaning, !!(flags & 2 /* UseOnlyExternalAliasing */)); + if (!accessibleSymbolChain || + needsQualification(accessibleSymbolChain[0], enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning))) { + // Go up and add our parent. + var parent_8 = getParentOfSymbol(accessibleSymbolChain ? accessibleSymbolChain[0] : symbol); + if (parent_8) { + walkSymbol(parent_8, getQualifiedLeftMeaning(meaning), /*endOfChain*/ false); } - if (accessibleSymbolChain) { - for (var _i = 0, accessibleSymbolChain_1 = accessibleSymbolChain; _i < accessibleSymbolChain_1.length; _i++) { - var accessibleSymbol = accessibleSymbolChain_1[_i]; - appendParentTypeArgumentsAndSymbolName(accessibleSymbol); - } - } - else { - // If we didn't find accessible symbol chain for this symbol, break if this is external module - if (!parentSymbol && ts.forEach(symbol.declarations, hasExternalModuleSymbol)) { - return; - } - // if this is anonymous type break - if (symbol.flags & 2048 /* TypeLiteral */ || symbol.flags & 4096 /* ObjectLiteral */) { - return; - } - appendParentTypeArgumentsAndSymbolName(symbol); + } + if (accessibleSymbolChain) { + for (var _i = 0, accessibleSymbolChain_1 = accessibleSymbolChain; _i < accessibleSymbolChain_1.length; _i++) { + var accessibleSymbol = accessibleSymbolChain_1[_i]; + appendParentTypeArgumentsAndSymbolName(accessibleSymbol); } } + else if ( + // If this is the last part of outputting the symbol, always output. The cases apply only to parent symbols. + endOfChain || + // If a parent symbol is an external module, don't write it. (We prefer just `x` vs `"foo/bar".x`.) + !(!parentSymbol && ts.forEach(symbol.declarations, hasExternalModuleSymbol)) && + // If a parent symbol is an anonymous type, don't write it. + !(symbol.flags & (2048 /* TypeLiteral */ | 4096 /* ObjectLiteral */))) { + appendParentTypeArgumentsAndSymbolName(symbol); + } } // Get qualified name if the symbol is not a type parameter // and there is an enclosing declaration or we specifically @@ -18427,10 +24422,11 @@ var ts; var isTypeParameter = symbol.flags & 262144 /* TypeParameter */; var typeFormatFlag = 128 /* UseFullyQualifiedType */ & typeFlags; if (!isTypeParameter && (enclosingDeclaration || typeFormatFlag)) { - walkSymbol(symbol, meaning); - return; + walkSymbol(symbol, meaning, /*endOfChain*/ true); + } + else { + appendParentTypeArgumentsAndSymbolName(symbol); } - return appendParentTypeArgumentsAndSymbolName(symbol); } function buildTypeDisplay(type, writer, enclosingDeclaration, globalFlags, symbolStack) { var globalFlagsToPass = globalFlags & 16 /* WriteOwnNameForAnyLike */; @@ -18463,7 +24459,9 @@ var ts; // The specified symbol flags need to be reinterpreted as type flags buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, 793064 /* Type */, 0 /* None */, nextFlags); } - else if (!(flags & 512 /* InTypeAlias */) && type.flags & (2097152 /* Anonymous */ | 1572864 /* UnionOrIntersection */) && type.aliasSymbol) { + else if (!(flags & 512 /* InTypeAlias */) && type.flags & (2097152 /* Anonymous */ | 1572864 /* UnionOrIntersection */) && type.aliasSymbol && + isSymbolAccessible(type.aliasSymbol, enclosingDeclaration, 793064 /* Type */, /*shouldComputeAliasesToMakeVisible*/ false).accessibility === 0 /* Accessible */) { + // Only write out inferred type with its corresponding type-alias if type-alias is visible var typeArguments = type.aliasTypeArguments; writeSymbolTypeReference(type.aliasSymbol, typeArguments, 0, typeArguments ? typeArguments.length : 0, nextFlags); } @@ -18473,11 +24471,8 @@ var ts; else if (type.flags & 2097152 /* Anonymous */) { writeAnonymousType(type, nextFlags); } - else if (type.flags & 32 /* StringLiteral */) { - writer.writeStringLiteral("\"" + ts.escapeString(type.text) + "\""); - } - else if (type.flags & 64 /* NumberLiteral */) { - writer.writeStringLiteral(type.text); + else if (type.flags & 96 /* StringOrNumberLiteral */) { + writer.writeStringLiteral(literalTypeToString(type)); } else { // Should never get here @@ -18542,14 +24537,14 @@ var ts; while (i < length_1) { // Find group of type arguments for type parameters with the same declaring container. var start = i; - var parent_7 = getParentSymbolOfTypeParameter(outerTypeParameters[i]); + var parent_9 = getParentSymbolOfTypeParameter(outerTypeParameters[i]); do { i++; - } while (i < length_1 && getParentSymbolOfTypeParameter(outerTypeParameters[i]) === parent_7); + } while (i < length_1 && getParentSymbolOfTypeParameter(outerTypeParameters[i]) === parent_9); // When type parameters are their own type arguments for the whole group (i.e. we have // the default outer type arguments), we don't show the group. if (!ts.rangeEquals(outerTypeParameters, typeArguments, start, i)) { - writeSymbolTypeReference(parent_7, typeArguments, start, i, flags); + writeSymbolTypeReference(parent_9, typeArguments, start, i, flags); writePunctuation(writer, 21 /* DotToken */); } } @@ -18611,7 +24606,7 @@ var ts; } function shouldWriteTypeOfFunctionSymbol() { var isStaticMethodSymbol = !!(symbol.flags & 8192 /* Method */ && - ts.forEach(symbol.declarations, function (declaration) { return declaration.flags & 32 /* Static */; })); + ts.forEach(symbol.declarations, function (declaration) { return ts.getModifierFlags(declaration) & 32 /* Static */; })); var isNonLocalFunctionSymbol = !!(symbol.flags & 16 /* Function */) && (symbol.parent || ts.forEach(symbol.declarations, function (declaration) { @@ -18800,7 +24795,7 @@ var ts; } } function buildBindingElementDisplay(bindingElement, writer, enclosingDeclaration, flags, symbolStack) { - if (bindingElement.kind === 193 /* OmittedExpression */) { + if (ts.isOmittedExpression(bindingElement)) { return; } ts.Debug.assert(bindingElement.kind === 169 /* BindingElement */); @@ -18953,21 +24948,21 @@ var ts; if (ts.isExternalModuleAugmentation(node)) { return true; } - var parent_8 = getDeclarationContainer(node); + var parent_10 = getDeclarationContainer(node); // If the node is not exported or it is not ambient module element (except import declaration) - if (!(ts.getCombinedNodeFlags(node) & 1 /* Export */) && - !(node.kind !== 229 /* ImportEqualsDeclaration */ && parent_8.kind !== 256 /* SourceFile */ && ts.isInAmbientContext(parent_8))) { - return isGlobalSourceFile(parent_8); + if (!(ts.getCombinedModifierFlags(node) & 1 /* Export */) && + !(node.kind !== 229 /* ImportEqualsDeclaration */ && parent_10.kind !== 256 /* SourceFile */ && ts.isInAmbientContext(parent_10))) { + return isGlobalSourceFile(parent_10); } // Exported members/ambient module elements (exception import declaration) are visible if parent is visible - return isDeclarationVisible(parent_8); + return isDeclarationVisible(parent_10); case 145 /* PropertyDeclaration */: case 144 /* PropertySignature */: case 149 /* GetAccessor */: case 150 /* SetAccessor */: case 147 /* MethodDeclaration */: case 146 /* MethodSignature */: - if (node.flags & (8 /* Private */ | 16 /* Protected */)) { + if (ts.getModifierFlags(node) & (8 /* Private */ | 16 /* Protected */)) { // Private/protected properties/methods are not visible return false; } @@ -18996,8 +24991,9 @@ var ts; return false; // Type parameters are always visible case 141 /* TypeParameter */: - // Source file is always visible + // Source file and namespace export are always visible case 256 /* SourceFile */: + case 228 /* NamespaceExportDeclaration */: return true; // Export assignments do not create name bindings outside the module case 235 /* ExportAssignment */: @@ -19174,15 +25170,15 @@ var ts; // undefined or any type of the parent. if (!parentType || isTypeAny(parentType)) { if (declaration.initializer) { - return checkExpressionCached(declaration.initializer); + return checkDeclarationInitializer(declaration); } return parentType; } var type; if (pattern.kind === 167 /* ObjectBindingPattern */) { // Use explicitly specified property name ({ p: xxx } form), or otherwise the implied name ({ p } form) - var name_11 = declaration.propertyName || declaration.name; - if (isComputedNonLiteralName(name_11)) { + var name_14 = declaration.propertyName || declaration.name; + if (isComputedNonLiteralName(name_14)) { // computed properties with non-literal names are treated as 'any' return anyType; } @@ -19191,12 +25187,12 @@ var ts; } // Use type of the specified property, or otherwise, for a numeric name, the type of the numeric index signature, // or otherwise the type of the string index signature. - var text = getTextOfPropertyName(name_11); + var text = getTextOfPropertyName(name_14); type = getTypeOfPropertyOfType(parentType, text) || isNumericLiteralName(text) && getIndexTypeOfType(parentType, 1 /* Number */) || getIndexTypeOfType(parentType, 0 /* String */); if (!type) { - error(name_11, ts.Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(parentType), ts.declarationNameToString(name_11)); + error(name_14, ts.Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(parentType), ts.declarationNameToString(name_14)); return unknownType; } } @@ -19231,7 +25227,9 @@ var ts; if (strictNullChecks && declaration.initializer && !(getFalsyFlags(checkExpressionCached(declaration.initializer)) & 2048 /* Undefined */)) { type = getTypeWithFacts(type, 131072 /* NEUndefined */); } - return type; + return declaration.initializer ? + getUnionType([type, checkExpressionCached(declaration.initializer)], /*subtypeReduction*/ true) : + type; } function getTypeForVariableLikeDeclarationFromJSDocComment(declaration) { var jsDocType = getJSDocTypeForVariableLikeDeclarationFromJSDocComment(declaration); @@ -19269,7 +25267,7 @@ var ts; } // Return the inferred type for a variable, parameter, or property declaration function getTypeForVariableLikeDeclaration(declaration, includeOptionality) { - if (declaration.flags & 134217728 /* JavaScriptFile */) { + if (declaration.flags & 1048576 /* JavaScriptFile */) { // If this is a variable in a JavaScript file, then use the JSDoc type (if it has // one as its type), otherwise fallback to the below standard TS codepaths to // try to figure it out. @@ -19327,7 +25325,8 @@ var ts; } // Use the type of the initializer expression if one is present if (declaration.initializer) { - return addOptionality(checkExpressionCached(declaration.initializer), /*optional*/ declaration.questionToken && includeOptionality); + var type = checkDeclarationInitializer(declaration); + return addOptionality(type, /*optional*/ declaration.questionToken && includeOptionality); } // If it is a short-hand property assignment, use the type of the identifier if (declaration.kind === 254 /* ShorthandPropertyAssignment */) { @@ -19345,7 +25344,7 @@ var ts; // pattern. Otherwise, it is the type any. function getTypeFromBindingElement(element, includePatternInType, reportErrors) { if (element.initializer) { - return checkExpressionCached(element.initializer); + return checkDeclarationInitializer(element); } if (ts.isBindingPattern(element.name)) { return getTypeFromBindingPattern(element.name, includePatternInType, reportErrors); @@ -19385,11 +25384,12 @@ var ts; // Return the type implied by an array binding pattern function getTypeFromArrayBindingPattern(pattern, includePatternInType, reportErrors) { var elements = pattern.elements; - if (elements.length === 0 || elements[elements.length - 1].dotDotDotToken) { + var lastElement = ts.lastOrUndefined(elements); + if (elements.length === 0 || (!ts.isOmittedExpression(lastElement) && lastElement.dotDotDotToken)) { return languageVersion >= 2 /* ES6 */ ? createIterableType(anyType) : anyArrayType; } // If the pattern has at least one element, and no rest element, then it should imply a tuple type. - var elementTypes = ts.map(elements, function (e) { return e.kind === 193 /* OmittedExpression */ ? anyType : getTypeFromBindingElement(e, includePatternInType, reportErrors); }); + var elementTypes = ts.map(elements, function (e) { return ts.isOmittedExpression(e) ? anyType : getTypeFromBindingElement(e, includePatternInType, reportErrors); }); var result = createTupleType(elementTypes); if (includePatternInType) { result = cloneTypeReference(result); @@ -19463,7 +25463,7 @@ var ts; if (declaration.kind === 235 /* ExportAssignment */) { return links.type = checkExpression(declaration.expression); } - if (declaration.flags & 134217728 /* JavaScriptFile */ && declaration.kind === 280 /* JSDocPropertyTag */ && declaration.typeExpression) { + if (declaration.flags & 1048576 /* JavaScriptFile */ && declaration.kind === 280 /* JSDocPropertyTag */ && declaration.typeExpression) { return links.type = getTypeFromTypeNode(declaration.typeExpression.type); } // Handle variable, parameter or property @@ -19479,7 +25479,7 @@ var ts; if (declaration.kind === 187 /* BinaryExpression */ || declaration.kind === 172 /* PropertyAccessExpression */ && declaration.parent.kind === 187 /* BinaryExpression */) { // Use JS Doc type if present on parent expression statement - if (declaration.flags & 134217728 /* JavaScriptFile */) { + if (declaration.flags & 1048576 /* JavaScriptFile */) { var typeTag = ts.getJSDocTypeTag(declaration.parent); if (typeTag && typeTag.typeExpression) { return links.type = getTypeFromTypeNode(typeTag.typeExpression.type); @@ -19535,7 +25535,7 @@ var ts; if (!links.type) { var getter = ts.getDeclarationOfKind(symbol, 149 /* GetAccessor */); var setter = ts.getDeclarationOfKind(symbol, 150 /* SetAccessor */); - if (getter && getter.flags & 134217728 /* JavaScriptFile */) { + if (getter && getter.flags & 1048576 /* JavaScriptFile */) { var jsDocType = getTypeForVariableLikeDeclarationFromJSDocComment(getter); if (jsDocType) { return links.type = jsDocType; @@ -19589,7 +25589,7 @@ var ts; function getTypeOfFuncClassEnumModule(symbol) { var links = getSymbolLinks(symbol); if (!links.type) { - if (symbol.valueDeclaration.kind === 225 /* ModuleDeclaration */ && ts.isShorthandAmbientModule(symbol.valueDeclaration)) { + if (symbol.valueDeclaration.kind === 225 /* ModuleDeclaration */ && ts.isShorthandAmbientModuleSymbol(symbol)) { links.type = anyType; } else { @@ -19603,7 +25603,7 @@ var ts; function getTypeOfEnumMember(symbol) { var links = getSymbolLinks(symbol); if (!links.type) { - links.type = getDeclaredTypeOfEnum(getParentOfSymbol(symbol)); + links.type = getDeclaredTypeOfEnumMember(symbol); } return links.type; } @@ -19734,7 +25734,7 @@ var ts; function getInstantiatedConstructorsForTypeArguments(type, typeArgumentNodes) { var signatures = getConstructorsForTypeArguments(type, typeArgumentNodes); if (typeArgumentNodes) { - var typeArguments_1 = ts.map(typeArgumentNodes, getTypeFromTypeNode); + var typeArguments_1 = ts.map(typeArgumentNodes, getTypeFromTypeNodeNoAlias); signatures = ts.map(signatures, function (sig) { return getSignatureInstantiation(sig, typeArguments_1); }); } return signatures; @@ -19883,7 +25883,7 @@ var ts; for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var declaration = _a[_i]; if (declaration.kind === 222 /* InterfaceDeclaration */) { - if (declaration.flags & 16384 /* ContainsThis */) { + if (declaration.flags & 64 /* ContainsThis */) { return false; } var baseTypeNodes = ts.getInterfaceBaseTypeNodes(declaration); @@ -19994,6 +25994,13 @@ var ts; } return true; } + function createEnumLiteralType(symbol, baseType, text) { + var type = createType(256 /* EnumLiteral */); + type.symbol = symbol; + type.baseType = baseType; + type.text = text; + return type; + } function getDeclaredTypeOfEnum(symbol) { var links = getSymbolLinks(symbol); if (!links.declaredType) { @@ -20011,10 +26018,7 @@ var ts; var memberSymbol = getSymbolOfNode(member); var value = getEnumMemberValue(member); if (!memberTypes[value]) { - var memberType = memberTypes[value] = createType(256 /* EnumLiteral */); - memberType.symbol = memberSymbol; - memberType.baseType = enumType; - memberType.text = "" + value; + var memberType = memberTypes[value] = createEnumLiteralType(memberSymbol, enumType, "" + value); memberTypeList.push(memberType); } } @@ -20274,7 +26278,7 @@ var ts; return [createSignature(undefined, classType.localTypeParameters, undefined, emptyArray, classType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false)]; } var baseTypeNode = getBaseTypeNodeOfClass(classType); - var typeArguments = ts.map(baseTypeNode.typeArguments, getTypeFromTypeNode); + var typeArguments = ts.map(baseTypeNode.typeArguments, getTypeFromTypeNodeNoAlias); var typeArgCount = typeArguments ? typeArguments.length : 0; var result = []; for (var _i = 0, baseSignatures_1 = baseSignatures; _i < baseSignatures_1.length; _i++) { @@ -20493,7 +26497,7 @@ var ts; var current = _a[_i]; for (var _b = 0, _c = getPropertiesOfType(current); _b < _c.length; _b++) { var prop = _c[_b]; - getPropertyOfUnionOrIntersectionType(type, prop.name); + getUnionOrIntersectionProperty(type, prop.name); } // The properties of a union type are those that are present in all constituent types, so // we only need to check the properties of the first type @@ -20501,7 +26505,19 @@ var ts; break; } } - return type.resolvedProperties ? symbolsToArray(type.resolvedProperties) : emptyArray; + var props = type.resolvedProperties; + if (props) { + var result = []; + for (var key in props) { + var prop = props[key]; + // We need to filter out partial properties in union types + if (!(prop.flags & 268435456 /* SyntheticProperty */ && prop.isPartial)) { + result.push(prop); + } + } + return result; + } + return emptyArray; } function getPropertiesOfType(type) { type = getApparentType(type); @@ -20550,12 +26566,13 @@ var ts; // Flags we want to propagate to the result if they exist in all source symbols var commonFlags = (containingType.flags & 1048576 /* Intersection */) ? 536870912 /* Optional */ : 0 /* None */; var isReadonly = false; + var isPartial = false; for (var _i = 0, types_2 = types; _i < types_2.length; _i++) { var current = types_2[_i]; var type = getApparentType(current); if (type !== unknownType) { var prop = getPropertyOfType(type, name); - if (prop && !(getDeclarationFlagsFromSymbol(prop) & (8 /* Private */ | 16 /* Protected */))) { + if (prop && !(getDeclarationModifierFlagsFromSymbol(prop) & (8 /* Private */ | 16 /* Protected */))) { commonFlags &= prop.flags; if (!props) { props = [prop]; @@ -20568,21 +26585,20 @@ var ts; } } else if (containingType.flags & 524288 /* Union */) { - // A union type requires the property to be present in all constituent types - return undefined; + isPartial = true; } } } if (!props) { return undefined; } - if (props.length === 1) { + if (props.length === 1 && !isPartial) { return props[0]; } var propTypes = []; var declarations = []; var commonType = undefined; - var hasCommonType = true; + var hasNonUniformType = false; for (var _a = 0, props_1 = props; _a < props_1.length; _a++) { var prop = props_1[_a]; if (prop.declarations) { @@ -20593,22 +26609,25 @@ var ts; commonType = type; } else if (type !== commonType) { - hasCommonType = false; + hasNonUniformType = true; } - propTypes.push(getTypeOfSymbol(prop)); + propTypes.push(type); } - var result = createSymbol(4 /* Property */ | - 67108864 /* Transient */ | - 268435456 /* SyntheticProperty */ | - commonFlags, name); + var result = createSymbol(4 /* Property */ | 67108864 /* Transient */ | 268435456 /* SyntheticProperty */ | commonFlags, name); result.containingType = containingType; - result.hasCommonType = hasCommonType; + result.hasNonUniformType = hasNonUniformType; + result.isPartial = isPartial; result.declarations = declarations; result.isReadonly = isReadonly; result.type = containingType.flags & 524288 /* Union */ ? getUnionType(propTypes) : getIntersectionType(propTypes); return result; } - function getPropertyOfUnionOrIntersectionType(type, name) { + // Return the symbol for a given property in a union or intersection type, or undefined if the property + // does not exist in any constituent type. Note that the returned property may only be present in some + // constituents, in which case the isPartial flag is set when the containing type is union type. We need + // these partial properties when identifying discriminant properties, but otherwise they are filtered out + // and do not appear to be present in the union type. + function getUnionOrIntersectionProperty(type, name) { var properties = type.resolvedProperties || (type.resolvedProperties = ts.createMap()); var property = properties[name]; if (!property) { @@ -20619,6 +26638,11 @@ var ts; } return property; } + function getPropertyOfUnionOrIntersectionType(type, name) { + var property = getUnionOrIntersectionProperty(type, name); + // We need to filter out partial properties in union types + return property && !(property.flags & 268435456 /* SyntheticProperty */ && property.isPartial) ? property : undefined; + } /** * Return the symbol for the property with the given name in the given type. Creates synthetic union properties when * necessary, maps primitive types and type parameters are to their apparent types, and augments with properties from @@ -20698,7 +26722,7 @@ var ts; return undefined; } function getTypeParametersFromJSDocTemplate(declaration) { - if (declaration.flags & 134217728 /* JavaScriptFile */) { + if (declaration.flags & 1048576 /* JavaScriptFile */) { var templateTag = ts.getJSDocTemplateTag(declaration); if (templateTag) { return getTypeParametersFromDeclaration(templateTag.typeParameters); @@ -20728,7 +26752,7 @@ var ts; return result; } function isJSDocOptionalParameter(node) { - if (node.flags & 134217728 /* JavaScriptFile */) { + if (node.flags & 1048576 /* JavaScriptFile */) { if (node.type && node.type.kind === 268 /* JSDocOptionalType */) { return true; } @@ -20856,7 +26880,7 @@ var ts; else if (declaration.type) { return getTypeFromTypeNode(declaration.type); } - if (declaration.flags & 134217728 /* JavaScriptFile */) { + if (declaration.flags & 1048576 /* JavaScriptFile */) { var type = getReturnTypeFromJSDocComment(declaration); if (type && type !== unknownType) { return type; @@ -21015,7 +27039,7 @@ var ts; function getIndexInfoOfSymbol(symbol, kind) { var declaration = getIndexDeclarationOfSymbol(symbol, kind); if (declaration) { - return createIndexInfo(declaration.type ? getTypeFromTypeNode(declaration.type) : anyType, (declaration.flags & 64 /* Readonly */) !== 0, declaration); + return createIndexInfo(declaration.type ? getTypeFromTypeNode(declaration.type) : anyType, (ts.getModifierFlags(declaration) & 64 /* Readonly */) !== 0, declaration); } return undefined; } @@ -21125,7 +27149,7 @@ var ts; // In a type reference, the outer type parameters of the referenced class or interface are automatically // supplied as type arguments and the type reference only specifies arguments for the local type parameters // of the class or interface. - return createTypeReference(type, ts.concatenate(type.outerTypeParameters, ts.map(node.typeArguments, getTypeFromTypeNode))); + return createTypeReference(type, ts.concatenate(type.outerTypeParameters, ts.map(node.typeArguments, getTypeFromTypeNodeNoAlias))); } if (node.typeArguments) { error(node, ts.Diagnostics.Type_0_is_not_generic, typeToString(type)); @@ -21145,7 +27169,7 @@ var ts; error(node, ts.Diagnostics.Generic_type_0_requires_1_type_argument_s, symbolToString(symbol), typeParameters.length); return unknownType; } - var typeArguments = ts.map(node.typeArguments, getTypeFromTypeNode); + var typeArguments = ts.map(node.typeArguments, getTypeFromTypeNodeNoAlias); var id = getTypeListId(typeArguments); return links.instantiations[id] || (links.instantiations[id] = instantiateType(type, createTypeMapper(typeParameters, typeArguments))); } @@ -21367,7 +27391,7 @@ var ts; function getTypeFromTupleTypeNode(node) { var links = getNodeLinks(node); if (!links.resolvedType) { - links.resolvedType = createTupleType(ts.map(node.elementTypes, getTypeFromTypeNode)); + links.resolvedType = createTupleType(ts.map(node.elementTypes, getTypeFromTypeNodeNoAlias)); } return links.resolvedType; } @@ -21394,25 +27418,32 @@ var ts; return binarySearchTypes(types, type) >= 0; } function addTypeToUnion(typeSet, type) { - if (type.flags & 524288 /* Union */) { + var flags = type.flags; + if (flags & 524288 /* Union */) { addTypesToUnion(typeSet, type.types); } - else if (type.flags & 1 /* Any */) { + else if (flags & 1 /* Any */) { typeSet.containsAny = true; } - else if (!strictNullChecks && type.flags & 6144 /* Nullable */) { - if (type.flags & 2048 /* Undefined */) + else if (!strictNullChecks && flags & 6144 /* Nullable */) { + if (flags & 2048 /* Undefined */) typeSet.containsUndefined = true; - if (type.flags & 4096 /* Null */) + if (flags & 4096 /* Null */) typeSet.containsNull = true; - if (!(type.flags & 33554432 /* ContainsWideningType */)) + if (!(flags & 33554432 /* ContainsWideningType */)) typeSet.containsNonWideningType = true; } - else if (!(type.flags & 8192 /* Never */)) { + else if (!(flags & 8192 /* Never */)) { + if (flags & 2 /* String */) + typeSet.containsString = true; + if (flags & 4 /* Number */) + typeSet.containsNumber = true; + if (flags & 96 /* StringOrNumberLiteral */) + typeSet.containsStringOrNumberLiteral = true; var len = typeSet.length; var index = len && type.id > typeSet[len - 1].id ? ~len : binarySearchTypes(typeSet, type); if (index < 0) { - if (!(type.flags & 2097152 /* Anonymous */ && type.symbol && type.symbol.flags & (16 /* Function */ | 8192 /* Method */) && containsIdenticalType(typeSet, type))) { + if (!(flags & 2097152 /* Anonymous */ && type.symbol && type.symbol.flags & (16 /* Function */ | 8192 /* Method */) && containsIdenticalType(typeSet, type))) { typeSet.splice(~index, 0, type); } } @@ -21452,6 +27483,19 @@ var ts; } } } + function removeRedundantLiteralTypes(types) { + var i = types.length; + while (i > 0) { + i--; + var t = types[i]; + var remove = t.flags & 32 /* StringLiteral */ && types.containsString || + t.flags & 64 /* NumberLiteral */ && types.containsNumber || + t.flags & 96 /* StringOrNumberLiteral */ && t.flags & 16777216 /* FreshLiteral */ && containsType(types, t.regularType); + if (remove) { + ts.orderedRemoveItemAt(types, i); + } + } + } // We sort and deduplicate the constituent types based on object identity. If the subtypeReduction // flag is specified we also reduce the constituent type set to only include types that aren't subtypes // of other types. Subtype reduction is expensive for large union types and is possible only when union @@ -21474,6 +27518,9 @@ var ts; if (subtypeReduction) { removeSubtypes(typeSet); } + else if (typeSet.containsStringOrNumberLiteral) { + removeRedundantLiteralTypes(typeSet); + } if (typeSet.length === 0) { return typeSet.containsNull ? typeSet.containsNonWideningType ? nullType : nullWideningType : typeSet.containsUndefined ? typeSet.containsNonWideningType ? undefinedType : undefinedWideningType : @@ -21503,7 +27550,7 @@ var ts; function getTypeFromUnionTypeNode(node, aliasSymbol, aliasTypeArguments) { var links = getNodeLinks(node); if (!links.resolvedType) { - links.resolvedType = getUnionType(ts.map(node.types, getTypeFromTypeNode), /*subtypeReduction*/ false, aliasSymbol, aliasTypeArguments); + links.resolvedType = getUnionType(ts.map(node.types, getTypeFromTypeNodeNoAlias), /*subtypeReduction*/ false, aliasSymbol, aliasTypeArguments); } return links.resolvedType; } @@ -21557,7 +27604,7 @@ var ts; function getTypeFromIntersectionTypeNode(node, aliasSymbol, aliasTypeArguments) { var links = getNodeLinks(node); if (!links.resolvedType) { - links.resolvedType = getIntersectionType(ts.map(node.types, getTypeFromTypeNode), aliasSymbol, aliasTypeArguments); + links.resolvedType = getIntersectionType(ts.map(node.types, getTypeFromTypeNodeNoAlias), aliasSymbol, aliasTypeArguments); } return links.resolvedType; } @@ -21577,6 +27624,20 @@ var ts; type.text = text; return type; } + function getFreshTypeOfLiteralType(type) { + if (type.flags & 96 /* StringOrNumberLiteral */ && !(type.flags & 16777216 /* FreshLiteral */)) { + if (!type.freshType) { + var freshType = createLiteralType(type.flags | 16777216 /* FreshLiteral */, type.text); + freshType.regularType = type; + type.freshType = freshType; + } + return type.freshType; + } + return type; + } + function getRegularTypeOfLiteralType(type) { + return type.flags & 96 /* StringOrNumberLiteral */ && type.flags & 16777216 /* FreshLiteral */ ? type.regularType : type; + } function getLiteralTypeForText(flags, text) { var map = flags & 32 /* StringLiteral */ ? stringLiteralTypes : numericLiteralTypes; return map[text] || (map[text] = createLiteralType(flags, text)); @@ -21584,7 +27645,7 @@ var ts; function getTypeFromLiteralTypeNode(node) { var links = getNodeLinks(node); if (!links.resolvedType) { - links.resolvedType = checkExpression(node.literal); + links.resolvedType = getRegularTypeOfLiteralType(checkExpression(node.literal)); } return links.resolvedType; } @@ -21599,7 +27660,7 @@ var ts; function getTypeFromJSDocTupleType(node) { var links = getNodeLinks(node); if (!links.resolvedType) { - var types = ts.map(node.types, getTypeFromTypeNode); + var types = ts.map(node.types, getTypeFromTypeNodeNoAlias); links.resolvedType = createTupleType(types); } return links.resolvedType; @@ -21608,8 +27669,8 @@ var ts; var container = ts.getThisContainer(node, /*includeArrowFunctions*/ false); var parent = container && container.parent; if (parent && (ts.isClassLike(parent) || parent.kind === 222 /* InterfaceDeclaration */)) { - if (!(container.flags & 32 /* Static */) && - (container.kind !== 148 /* Constructor */ || ts.isNodeDescendentOf(node, container.body))) { + if (!(ts.getModifierFlags(container) & 32 /* Static */) && + (container.kind !== 148 /* Constructor */ || ts.isNodeDescendantOf(node, container.body))) { return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(parent)).thisType; } } @@ -21623,6 +27684,9 @@ var ts; } return links.resolvedType; } + function getTypeFromTypeNodeNoAlias(type) { + return getTypeFromTypeNode(type, /*aliasSymbol*/ undefined, /*aliasTypeArguments*/ undefined); + } function getTypeFromTypeNode(node, aliasSymbol, aliasTypeArguments) { switch (node.kind) { case 117 /* AnyKeyword */: @@ -21684,12 +27748,13 @@ var ts; case 272 /* JSDocThisType */: case 268 /* JSDocOptionalType */: return getTypeFromTypeNode(node.type); + case 265 /* JSDocRecordType */: + return getTypeFromTypeNode(node.literal); case 156 /* FunctionType */: case 157 /* ConstructorType */: case 159 /* TypeLiteral */: case 281 /* JSDocTypeLiteral */: case 269 /* JSDocFunctionType */: - case 265 /* JSDocRecordType */: return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node, aliasSymbol, aliasTypeArguments); // This function assumes that an identifier or qualified name is a type expression // Callers should first ensure this by calling isTypeNode @@ -21747,7 +27812,7 @@ var ts; function getInferenceMapper(context) { if (!context.mapper) { var mapper = function (t) { - var typeParameters = context.typeParameters; + var typeParameters = context.signature.typeParameters; for (var i = 0; i < typeParameters.length; i++) { if (t === typeParameters[i]) { context.inferences[i].isFixed = true; @@ -21756,7 +27821,7 @@ var ts; } return t; }; - mapper.mappedTypes = context.typeParameters; + mapper.mappedTypes = context.signature.typeParameters; mapper.context = context; context.mapper = mapper; } @@ -22172,8 +28237,14 @@ var ts; if (source === target) { return true; } - if (source.symbol.name !== target.symbol.name || !(source.symbol.flags & 256 /* RegularEnum */) || !(target.symbol.flags & 256 /* RegularEnum */)) { - return false; + var id = source.id + "," + target.id; + if (enumRelation[id] !== undefined) { + return enumRelation[id]; + } + if (source.symbol.name !== target.symbol.name || + !(source.symbol.flags & 256 /* RegularEnum */) || !(target.symbol.flags & 256 /* RegularEnum */) || + (source.flags & 524288 /* Union */) !== (target.flags & 524288 /* Union */)) { + return enumRelation[id] = false; } var targetEnumType = getTypeOfSymbol(target.symbol); for (var _i = 0, _a = getPropertiesOfType(getTypeOfSymbol(source.symbol)); _i < _a.length; _i++) { @@ -22184,11 +28255,11 @@ var ts; if (errorReporter) { errorReporter(ts.Diagnostics.Property_0_is_missing_in_type_1, property.name, typeToString(target, /*enclosingDeclaration*/ undefined, 128 /* UseFullyQualifiedType */)); } - return false; + return enumRelation[id] = false; } } } - return true; + return enumRelation[id] = true; } function isSimpleTypeRelatedTo(source, target, relation, errorReporter) { if (target.flags & 8192 /* Never */) @@ -22212,14 +28283,29 @@ var ts; if (relation === assignableRelation || relation === comparableRelation) { if (source.flags & 1 /* Any */) return true; - if (source.flags & (4 /* Number */ | 64 /* NumberLiteral */) && target.flags & 16 /* Enum */) + if ((source.flags & 4 /* Number */ | source.flags & 64 /* NumberLiteral */) && target.flags & 272 /* EnumLike */) + return true; + if (source.flags & 256 /* EnumLiteral */ && + target.flags & 256 /* EnumLiteral */ && + source.text === target.text && + isEnumTypeRelatedTo(source.baseType, target.baseType, errorReporter)) { return true; - if (source.flags & 64 /* NumberLiteral */ && target.flags & 256 /* EnumLiteral */ && source.text === target.text) + } + if (source.flags & 256 /* EnumLiteral */ && + target.flags & 16 /* Enum */ && + isEnumTypeRelatedTo(target, source.baseType, errorReporter)) { return true; + } } return false; } function isTypeRelatedTo(source, target, relation) { + if (source.flags & 96 /* StringOrNumberLiteral */ && source.flags & 16777216 /* FreshLiteral */) { + source = source.regularType; + } + if (target.flags & 96 /* StringOrNumberLiteral */ && target.flags & 16777216 /* FreshLiteral */) { + target = target.regularType; + } if (source === target || relation !== identityRelation && isSimpleTypeRelatedTo(source, target, relation)) { return true; } @@ -22299,6 +28385,12 @@ var ts; // Ternary.False if they are not related. function isRelatedTo(source, target, reportErrors, headMessage) { var result; + if (source.flags & 96 /* StringOrNumberLiteral */ && source.flags & 16777216 /* FreshLiteral */) { + source = source.regularType; + } + if (target.flags & 96 /* StringOrNumberLiteral */ && target.flags & 16777216 /* FreshLiteral */) { + target = target.regularType; + } // both types are the same - covers 'they are the same primitive type or both are Any' or the same type parameter cases if (source === target) return -1 /* True */; @@ -22307,7 +28399,7 @@ var ts; } if (isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) return -1 /* True */; - if (source.flags & 16777216 /* FreshObjectLiteral */) { + if (source.flags & 8388608 /* ObjectLiteral */ && source.flags & 16777216 /* FreshLiteral */) { if (hasExcessProperties(source, target, reportErrors)) { if (reportErrors) { reportRelationError(headMessage, source, target); @@ -22409,6 +28501,9 @@ var ts; if (source.flags & 2588672 /* ObjectType */ && target.flags & 8190 /* Primitive */) { tryElaborateErrorsForPrimitivesAndObjects(source, target); } + else if (source.symbol && source.flags & 2588672 /* ObjectType */ && globalObjectType === source) { + reportError(ts.Diagnostics.The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead); + } reportRelationError(headMessage, source, target); } return 0 /* False */; @@ -22658,8 +28753,8 @@ var ts; var result = -1 /* True */; var properties = getPropertiesOfObjectType(target); var requireOptionalProperties = relation === subtypeRelation && !(source.flags & 8388608 /* ObjectLiteral */); - for (var _i = 0, properties_1 = properties; _i < properties_1.length; _i++) { - var targetProp = properties_1[_i]; + for (var _i = 0, properties_2 = properties; _i < properties_2.length; _i++) { + var targetProp = properties_2[_i]; var sourceProp = getPropertyOfType(source, targetProp.name); if (sourceProp !== targetProp) { if (!sourceProp) { @@ -22671,8 +28766,8 @@ var ts; } } else if (!(targetProp.flags & 134217728 /* Prototype */)) { - var sourcePropFlags = getDeclarationFlagsFromSymbol(sourceProp); - var targetPropFlags = getDeclarationFlagsFromSymbol(targetProp); + var sourcePropFlags = getDeclarationModifierFlagsFromSymbol(sourceProp); + var targetPropFlags = getDeclarationModifierFlagsFromSymbol(targetProp); if (sourcePropFlags & 8 /* Private */ || targetPropFlags & 8 /* Private */) { if (sourceProp.valueDeclaration !== targetProp.valueDeclaration) { if (reportErrors) { @@ -22893,8 +28988,8 @@ var ts; if (!sourceSignature.declaration || !targetSignature.declaration) { return true; } - var sourceAccessibility = sourceSignature.declaration.flags & (8 /* Private */ | 16 /* Protected */); - var targetAccessibility = targetSignature.declaration.flags & (8 /* Private */ | 16 /* Protected */); + var sourceAccessibility = ts.getModifierFlags(sourceSignature.declaration) & 24 /* NonPublicAccessibilityModifier */; + var targetAccessibility = ts.getModifierFlags(targetSignature.declaration) & 24 /* NonPublicAccessibilityModifier */; // A public, protected and private signature is assignable to a private signature. if (targetAccessibility === 8 /* Private */) { return true; @@ -22919,7 +29014,7 @@ var ts; var symbol = type.symbol; if (symbol && symbol.flags & 32 /* Class */) { var declaration = getClassLikeDeclarationOfSymbol(symbol); - if (declaration && declaration.flags & 128 /* Abstract */) { + if (declaration && ts.getModifierFlags(declaration) & 128 /* Abstract */) { return true; } } @@ -22957,8 +29052,8 @@ var ts; if (sourceProp === targetProp) { return -1 /* True */; } - var sourcePropAccessibility = getDeclarationFlagsFromSymbol(sourceProp) & (8 /* Private */ | 16 /* Protected */); - var targetPropAccessibility = getDeclarationFlagsFromSymbol(targetProp) & (8 /* Private */ | 16 /* Protected */); + var sourcePropAccessibility = getDeclarationModifierFlagsFromSymbol(sourceProp) & 24 /* NonPublicAccessibilityModifier */; + var targetPropAccessibility = getDeclarationModifierFlagsFromSymbol(targetProp) & 24 /* NonPublicAccessibilityModifier */; if (sourcePropAccessibility !== targetPropAccessibility) { return 0 /* False */; } @@ -23059,15 +29154,35 @@ var ts; } return true; } + function literalTypesWithSameBaseType(types) { + var commonBaseType; + for (var _i = 0, types_8 = types; _i < types_8.length; _i++) { + var t = types_8[_i]; + var baseType = getBaseTypeOfLiteralType(t); + if (!commonBaseType) { + commonBaseType = baseType; + } + if (baseType === t || baseType !== commonBaseType) { + return false; + } + } + return true; + } + // When the candidate types are all literal types with the same base type, the common + // supertype is a union of those literal types. Otherwise, the common supertype is the + // first type that is a supertype of each of the other types. + function getSupertypeOrUnion(types) { + return literalTypesWithSameBaseType(types) ? getUnionType(types) : ts.forEach(types, function (t) { return isSupertypeOfEach(t, types) ? t : undefined; }); + } function getCommonSupertype(types) { if (!strictNullChecks) { - return ts.forEach(types, function (t) { return isSupertypeOfEach(t, types) ? t : undefined; }); + return getSupertypeOrUnion(types); } var primaryTypes = ts.filter(types, function (t) { return !(t.flags & 6144 /* Nullable */); }); if (!primaryTypes.length) { return getUnionType(types, /*subtypeReduction*/ true); } - var supertype = ts.forEach(primaryTypes, function (t) { return isSupertypeOfEach(t, primaryTypes) ? t : undefined; }); + var supertype = getSupertypeOrUnion(primaryTypes); return supertype && includeFalsyTypes(supertype, getFalsyFlagsOfTypes(types) & 6144 /* Nullable */); } function reportNoCommonSupertypeError(types, errorLocation, errorMessageChainHead) { @@ -23118,17 +29233,25 @@ var ts; function isUnitType(type) { return (type.flags & (480 /* Literal */ | 2048 /* Undefined */ | 4096 /* Null */)) !== 0; } - function isUnitUnionType(type) { + function isLiteralType(type) { return type.flags & 8 /* Boolean */ ? true : type.flags & 524288 /* Union */ ? type.flags & 16 /* Enum */ ? true : !ts.forEach(type.types, function (t) { return !isUnitType(t); }) : isUnitType(type); } - function getBaseTypeOfUnitType(type) { + function getBaseTypeOfLiteralType(type) { return type.flags & 32 /* StringLiteral */ ? stringType : type.flags & 64 /* NumberLiteral */ ? numberType : type.flags & 128 /* BooleanLiteral */ ? booleanType : type.flags & 256 /* EnumLiteral */ ? type.baseType : - type.flags & 524288 /* Union */ && !(type.flags & 16 /* Enum */) ? getUnionType(ts.map(type.types, getBaseTypeOfUnitType)) : + type.flags & 524288 /* Union */ && !(type.flags & 16 /* Enum */) ? getUnionType(ts.map(type.types, getBaseTypeOfLiteralType)) : + type; + } + function getWidenedLiteralType(type) { + return type.flags & 32 /* StringLiteral */ && type.flags & 16777216 /* FreshLiteral */ ? stringType : + type.flags & 64 /* NumberLiteral */ && type.flags & 16777216 /* FreshLiteral */ ? numberType : + type.flags & 128 /* BooleanLiteral */ ? booleanType : + type.flags & 256 /* EnumLiteral */ ? type.baseType : + type.flags & 524288 /* Union */ && !(type.flags & 16 /* Enum */) ? getUnionType(ts.map(type.types, getWidenedLiteralType)) : type; } /** @@ -23140,8 +29263,8 @@ var ts; } function getFalsyFlagsOfTypes(types) { var result = 0; - for (var _i = 0, types_8 = types; _i < types_8.length; _i++) { - var t = types_8[_i]; + for (var _i = 0, types_9 = types; _i < types_9.length; _i++) { + var t = types_9[_i]; result |= getFalsyFlags(t); } return result; @@ -23151,8 +29274,8 @@ var ts; // no flags for all other types (including non-falsy literal types). function getFalsyFlags(type) { return type.flags & 524288 /* Union */ ? getFalsyFlagsOfTypes(type.types) : - type.flags & 32 /* StringLiteral */ ? type === emptyStringType ? 32 /* StringLiteral */ : 0 : - type.flags & 64 /* NumberLiteral */ ? type === zeroType ? 64 /* NumberLiteral */ : 0 : + type.flags & 32 /* StringLiteral */ ? type.text === "" ? 32 /* StringLiteral */ : 0 : + type.flags & 64 /* NumberLiteral */ ? type.text === "0" ? 64 /* NumberLiteral */ : 0 : type.flags & 128 /* BooleanLiteral */ ? type === falseType ? 128 /* BooleanLiteral */ : 0 : type.flags & 7406 /* PossiblyFalsy */; } @@ -23220,7 +29343,7 @@ var ts; * Leave signatures alone since they are not subject to the check. */ function getRegularTypeOfObjectLiteral(type) { - if (!(type.flags & 16777216 /* FreshObjectLiteral */)) { + if (!(type.flags & 8388608 /* ObjectLiteral */ && type.flags & 16777216 /* FreshLiteral */)) { return type; } var regularType = type.regularType; @@ -23230,7 +29353,7 @@ var ts; var resolved = type; var members = transformTypeOfMembers(type, getRegularTypeOfObjectLiteral); var regularNew = createAnonymousType(resolved.symbol, members, resolved.callSignatures, resolved.constructSignatures, resolved.stringIndexInfo, resolved.numberIndexInfo); - regularNew.flags = resolved.flags & ~16777216 /* FreshObjectLiteral */; + regularNew.flags = resolved.flags & ~16777216 /* FreshLiteral */; type.regularType = regularNew; return regularNew; } @@ -23368,19 +29491,20 @@ var ts; callback(getTypeAtPosition(source, i), getTypeAtPosition(target, i)); } } - function createInferenceContext(typeParameters, inferUnionTypes) { - var inferences = ts.map(typeParameters, createTypeInferencesObject); + function createInferenceContext(signature, inferUnionTypes) { + var inferences = ts.map(signature.typeParameters, createTypeInferencesObject); return { - typeParameters: typeParameters, + signature: signature, inferUnionTypes: inferUnionTypes, inferences: inferences, - inferredTypes: new Array(typeParameters.length), + inferredTypes: new Array(signature.typeParameters.length), }; } function createTypeInferencesObject() { return { primary: undefined, secondary: undefined, + topLevel: true, isFixed: false, }; } @@ -23399,13 +29523,17 @@ var ts; } return type.couldContainTypeParameters; } - function inferTypes(context, source, target) { + function isTypeParameterAtTopLevel(type, typeParameter) { + return type === typeParameter || type.flags & 1572864 /* UnionOrIntersection */ && ts.forEach(type.types, function (t) { return isTypeParameterAtTopLevel(t, typeParameter); }); + } + function inferTypes(context, originalSource, originalTarget) { + var typeParameters = context.signature.typeParameters; var sourceStack; var targetStack; var depth = 0; var inferiority = 0; var visited = ts.createMap(); - inferFromTypes(source, target); + inferFromTypes(originalSource, originalTarget); function isInProcess(source, target) { for (var i = 0; i < depth; i++) { if (source === sourceStack[i] && target === targetStack[i]) { @@ -23429,17 +29557,25 @@ var ts; } return; } - // Find each target constituent type that has an identically matching source - // constituent type, and for each such target constituent type infer from the type to - // itself. When inferring from a type to itself we effectively find all type parameter - // occurrences within that type and infer themselves as their type arguments. + // Find each source constituent type that has an identically matching target constituent + // type, and for each such type infer from the type to itself. When inferring from a + // type to itself we effectively find all type parameter occurrences within that type + // and infer themselves as their type arguments. We have special handling for numeric + // and string literals because the number and string types are not represented as unions + // of all their possible values. var matchingTypes = void 0; - for (var _b = 0, _c = target.types; _b < _c.length; _b++) { + for (var _b = 0, _c = source.types; _b < _c.length; _b++) { var t = _c[_b]; - if (typeIdenticalToSomeType(t, source.types)) { + if (typeIdenticalToSomeType(t, target.types)) { (matchingTypes || (matchingTypes = [])).push(t); inferFromTypes(t, t); } + else if (t.flags & (64 /* NumberLiteral */ | 32 /* StringLiteral */)) { + var b = getBaseTypeOfLiteralType(t); + if (typeIdenticalToSomeType(b, target.types)) { + (matchingTypes || (matchingTypes = [])).push(t, b); + } + } } // Next, to improve the quality of inferences, reduce the source and target types by // removing the identically matched constituents. For example, when inferring from @@ -23459,7 +29595,6 @@ var ts; if (source.flags & 134217728 /* ContainsAnyFunctionType */) { return; } - var typeParameters = context.typeParameters; for (var i = 0; i < typeParameters.length; i++) { if (target === typeParameters[i]) { var inferences = context.inferences[i]; @@ -23476,6 +29611,9 @@ var ts; if (!ts.contains(candidates, source)) { candidates.push(source); } + if (!isTypeParameterAtTopLevel(originalTarget, target)) { + inferences.topLevel = false; + } } return; } @@ -23497,7 +29635,7 @@ var ts; // First infer to each type in union or intersection that isn't a type parameter for (var _d = 0, targetTypes_2 = targetTypes; _d < targetTypes_2.length; _d++) { var t = targetTypes_2[_d]; - if (t.flags & 16384 /* TypeParameter */ && ts.contains(context.typeParameters, t)) { + if (t.flags & 16384 /* TypeParameter */ && ts.contains(typeParameters, t)) { typeParameter = t; typeParameterCount++; } @@ -23553,8 +29691,8 @@ var ts; } function inferFromProperties(source, target) { var properties = getPropertiesOfObjectType(target); - for (var _i = 0, properties_2 = properties; _i < properties_2.length; _i++) { - var targetProp = properties_2[_i]; + for (var _i = 0, properties_3 = properties; _i < properties_3.length; _i++) { + var targetProp = properties_3[_i]; var sourceProp = getPropertyOfObjectType(source, targetProp.name); if (sourceProp) { inferFromTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp)); @@ -23571,8 +29709,11 @@ var ts; inferFromSignature(getErasedSignature(sourceSignatures[sourceLen - len + i]), getErasedSignature(targetSignatures[targetLen - len + i])); } } + function inferFromParameterTypes(source, target) { + return inferFromTypes(source, target); + } function inferFromSignature(source, target) { - forEachMatchingParameterType(source, target, inferFromTypes); + forEachMatchingParameterType(source, target, inferFromParameterTypes); if (source.typePredicate && target.typePredicate && source.typePredicate.kind === target.typePredicate.kind) { inferFromTypes(source.typePredicate.type, target.typePredicate.type); } @@ -23601,8 +29742,8 @@ var ts; } } function typeIdenticalToSomeType(type, types) { - for (var _i = 0, types_9 = types; _i < types_9.length; _i++) { - var t = types_9[_i]; + for (var _i = 0, types_10 = types; _i < types_10.length; _i++) { + var t = types_10[_i]; if (isTypeIdenticalTo(t, type)) { return true; } @@ -23627,14 +29768,27 @@ var ts; var inferences = context.inferences[index]; return inferences.primary || inferences.secondary || emptyArray; } + function hasPrimitiveConstraint(type) { + var constraint = getConstraintOfTypeParameter(type); + return constraint && maybeTypeOfKind(constraint, 8190 /* Primitive */); + } function getInferredType(context, index) { var inferredType = context.inferredTypes[index]; var inferenceSucceeded; if (!inferredType) { var inferences = getInferenceCandidates(context, index); if (inferences.length) { + // We widen inferred literal types if + // all inferences were made to top-level ocurrences of the type parameter, and + // the type parameter has no constraint or its constraint includes no primitive or literal types, and + // the type parameter was fixed during inference or does not occur at top-level in the return type. + var signature = context.signature; + var widenLiteralTypes = context.inferences[index].topLevel && + !hasPrimitiveConstraint(signature.typeParameters[index]) && + (context.inferences[index].isFixed || !isTypeParameterAtTopLevel(getReturnTypeOfSignature(signature), signature.typeParameters[index])); + var baseInferences = widenLiteralTypes ? ts.map(inferences, getWidenedLiteralType) : inferences; // Infer widened union or supertype, or the unknown type for no common supertype - var unionOrSuperType = context.inferUnionTypes ? getUnionType(inferences, /*subtypeReduction*/ true) : getCommonSupertype(inferences); + var unionOrSuperType = context.inferUnionTypes ? getUnionType(baseInferences, /*subtypeReduction*/ true) : getCommonSupertype(baseInferences); inferredType = unionOrSuperType ? getWidenedType(unionOrSuperType) : unknownType; inferenceSucceeded = !!unionOrSuperType; } @@ -23649,7 +29803,7 @@ var ts; context.inferredTypes[index] = inferredType; // Only do the constraint check if inference succeeded (to prevent cascading errors) if (inferenceSucceeded) { - var constraint = getConstraintOfTypeParameter(context.typeParameters[index]); + var constraint = getConstraintOfTypeParameter(context.signature.typeParameters[index]); if (constraint) { var instantiatedConstraint = instantiateType(constraint, getInferenceMapper(context)); if (!isTypeAssignableTo(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) { @@ -23771,21 +29925,10 @@ var ts; } function isDiscriminantProperty(type, name) { if (type && type.flags & 524288 /* Union */) { - var prop = getPropertyOfType(type, name); - if (!prop) { - // The type may be a union that includes nullable or primitive types. If filtering - // those out produces a different type, get the property from that type instead. - // Effectively, we're checking if this *could* be a discriminant property once nullable - // and primitive types are removed by other type guards. - var filteredType = getTypeWithFacts(type, 4194304 /* Discriminatable */); - if (filteredType !== type && filteredType.flags & 524288 /* Union */) { - prop = getPropertyOfType(filteredType, name); - } - } + var prop = getUnionOrIntersectionProperty(type, name); if (prop && prop.flags & 268435456 /* SyntheticProperty */) { if (prop.isDiscriminantProperty === undefined) { - prop.isDiscriminantProperty = !prop.hasCommonType && - isUnitUnionType(getTypeOfSymbol(prop)); + prop.isDiscriminantProperty = prop.hasNonUniformType && isLiteralType(getTypeOfSymbol(prop)); } return prop.isDiscriminantProperty; } @@ -23834,8 +29977,11 @@ var ts; // we remove type string. function getAssignmentReducedType(declaredType, assignedType) { if (declaredType !== assignedType) { + if (assignedType.flags & 8192 /* Never */) { + return assignedType; + } var reducedType = filterType(declaredType, function (t) { return typeMaybeAssignableTo(assignedType, t); }); - if (reducedType !== neverType) { + if (!(reducedType.flags & 8192 /* Never */)) { return reducedType; } } @@ -23843,8 +29989,8 @@ var ts; } function getTypeFactsOfTypes(types) { var result = 0 /* None */; - for (var _i = 0, types_10 = types; _i < types_10.length; _i++) { - var t = types_10[_i]; + for (var _i = 0, types_11 = types; _i < types_11.length; _i++) { + var t = types_11[_i]; result |= getTypeFacts(t); } return result; @@ -23863,14 +30009,14 @@ var ts; } if (flags & 32 /* StringLiteral */) { return strictNullChecks ? - type === emptyStringType ? 3030785 /* EmptyStringStrictFacts */ : 1982209 /* NonEmptyStringStrictFacts */ : - type === emptyStringType ? 3145473 /* EmptyStringFacts */ : 4194049 /* NonEmptyStringFacts */; + type.text === "" ? 3030785 /* EmptyStringStrictFacts */ : 1982209 /* NonEmptyStringStrictFacts */ : + type.text === "" ? 3145473 /* EmptyStringFacts */ : 4194049 /* NonEmptyStringFacts */; } if (flags & (4 /* Number */ | 16 /* Enum */)) { return strictNullChecks ? 4079234 /* NumberStrictFacts */ : 4193922 /* NumberFacts */; } if (flags & (64 /* NumberLiteral */ | 256 /* EnumLiteral */)) { - var isZero = type === zeroType || type.flags & 256 /* EnumLiteral */ && type.text === "0"; + var isZero = type.text === "0"; return strictNullChecks ? isZero ? 3030658 /* ZeroStrictFacts */ : 1982082 /* NonZeroStrictFacts */ : isZero ? 3145346 /* ZeroFacts */ : 4193922 /* NonZeroFacts */; @@ -24025,7 +30171,7 @@ var ts; } function getTypeOfSwitchClause(clause) { if (clause.kind === 249 /* CaseClause */) { - var caseType = checkExpression(clause.expression); + var caseType = getRegularTypeOfLiteralType(checkExpression(clause.expression)); return isUnitType(caseType) ? caseType : undefined; } return neverType; @@ -24087,7 +30233,7 @@ var ts; var visitedFlowStart = visitedFlowCount; var result = getTypeFromFlowType(getTypeAtFlowNode(reference.flowNode)); visitedFlowCount = visitedFlowStart; - if (reference.parent.kind === 196 /* NonNullExpression */ && getTypeWithFacts(result, 524288 /* NEUndefinedOrNull */) === neverType) { + if (reference.parent.kind === 196 /* NonNullExpression */ && getTypeWithFacts(result, 524288 /* NEUndefinedOrNull */).flags & 8192 /* Never */) { return declaredType; } return result; @@ -24155,7 +30301,8 @@ var ts; // Assignments only narrow the computed type if the declared type is a union type. Thus, we // only need to evaluate the assigned type if the declared type is a union type. if (isMatchingReference(reference, node)) { - return declaredType.flags & 524288 /* Union */ ? + var isIncrementOrDecrement = node.parent.kind === 185 /* PrefixUnaryExpression */ || node.parent.kind === 186 /* PostfixUnaryExpression */; + return declaredType.flags & 524288 /* Union */ && !isIncrementOrDecrement ? getAssignmentReducedType(declaredType, getInitialOrAssignedType(node)) : declaredType; } @@ -24172,17 +30319,18 @@ var ts; function getTypeAtFlowCondition(flow) { var flowType = getTypeAtFlowNode(flow.antecedent); var type = getTypeFromFlowType(flowType); - if (type !== neverType) { + if (!(type.flags & 8192 /* Never */)) { // If we have an antecedent type (meaning we're reachable in some way), we first // attempt to narrow the antecedent type. If that produces the never type, and if // the antecedent type is incomplete (i.e. a transient type in a loop), then we // take the type guard as an indication that control *could* reach here once we - // have the complete type. We proceed by reverting to the declared type and then - // narrow that. + // have the complete type. We proceed by switching to the silent never type which + // doesn't report errors when operators are applied to it. Note that this is the + // *only* place a silent never type is ever generated. var assumeTrue = (flow.flags & 32 /* TrueCondition */) !== 0; type = narrowType(type, flow.expression, assumeTrue); - if (type === neverType && isIncomplete(flowType)) { - type = narrowType(declaredType, flow.expression, assumeTrue); + if (type.flags & 8192 /* Never */ && isIncomplete(flowType)) { + type = silentNeverType; } } return createFlowType(type, isIncomplete(flowType)); @@ -24361,6 +30509,9 @@ var ts; return type; } function narrowTypeByEquality(type, operator, value, assumeTrue) { + if (type.flags & 1 /* Any */) { + return type; + } if (operator === 31 /* ExclamationEqualsToken */ || operator === 33 /* ExclamationEqualsEqualsToken */) { assumeTrue = !assumeTrue; } @@ -24382,9 +30533,13 @@ var ts; } if (assumeTrue) { var narrowedType = filterType(type, function (t) { return areTypesComparable(t, valueType); }); - return narrowedType !== neverType ? narrowedType : type; + return narrowedType.flags & 8192 /* Never */ ? type : narrowedType; } - return isUnitType(valueType) ? filterType(type, function (t) { return t !== valueType; }) : type; + if (isUnitType(valueType)) { + var regularType_1 = getRegularTypeOfLiteralType(valueType); + return filterType(type, function (t) { return getRegularTypeOfLiteralType(t) !== regularType_1; }); + } + return type; } function narrowTypeByTypeof(type, typeOfExpr, operator, literal, assumeTrue) { // We have '==', '!=', '====', or !==' operator with 'typeof xxx' and string literal operands @@ -24423,12 +30578,12 @@ var ts; var clauseTypes = switchTypes.slice(clauseStart, clauseEnd); var hasDefaultClause = clauseStart === clauseEnd || ts.contains(clauseTypes, neverType); var discriminantType = getUnionType(clauseTypes); - var caseType = discriminantType === neverType ? neverType : filterType(type, function (t) { return isTypeComparableTo(discriminantType, t); }); + var caseType = discriminantType.flags & 8192 /* Never */ ? neverType : filterType(type, function (t) { return isTypeComparableTo(discriminantType, t); }); if (!hasDefaultClause) { return caseType; } - var defaultType = filterType(type, function (t) { return !(isUnitType(t) && ts.contains(switchTypes, t)); }); - return caseType === neverType ? defaultType : getUnionType([caseType, defaultType]); + var defaultType = filterType(type, function (t) { return !(isUnitType(t) && ts.contains(switchTypes, getRegularTypeOfLiteralType(t))); }); + return caseType.flags & 8192 /* Never */ ? defaultType : getUnionType([caseType, defaultType]); } function narrowTypeByInstanceof(type, expr, assumeTrue) { var left = getReferenceCandidate(expr.left); @@ -24484,7 +30639,7 @@ var ts; // the candidate type. If one or more constituents remain, return a union of those. if (type.flags & 524288 /* Union */) { var assignableType = filterType(type, function (t) { return isTypeInstanceOf(t, candidate); }); - if (assignableType !== neverType) { + if (!(assignableType.flags & 8192 /* Never */)) { return assignableType; } } @@ -24494,7 +30649,7 @@ var ts; // type. Otherwise, the types are completely unrelated, so narrow to an intersection of the // two types. var targetType = type.flags & 16384 /* TypeParameter */ ? getApparentType(type) : type; - return isTypeSubtypeOf(candidate, targetType) ? candidate : + return isTypeSubtypeOf(candidate, type) ? candidate : isTypeAssignableTo(type, candidate) ? type : isTypeAssignableTo(candidate, targetType) ? candidate : getIntersectionType([type, candidate]); @@ -24647,12 +30802,15 @@ var ts; // can explicitly bound arguments objects if (symbol === argumentsSymbol) { var container = ts.getContainingFunction(node); - if (container.kind === 180 /* ArrowFunction */) { - if (languageVersion < 2 /* ES6 */) { + if (languageVersion < 2 /* ES6 */) { + if (container.kind === 180 /* ArrowFunction */) { error(node, ts.Diagnostics.The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression); } + else if (ts.hasModifier(container, 256 /* Async */)) { + error(node, ts.Diagnostics.The_arguments_object_cannot_be_referenced_in_an_async_function_or_method_in_ES3_and_ES5_Consider_using_a_standard_function_or_method); + } } - if (node.flags & 33554432 /* AwaitContext */) { + if (node.flags & 262144 /* AwaitContext */) { getNodeLinks(container).flags |= 8192 /* CaptureArguments */; } } @@ -24660,21 +30818,39 @@ var ts; markAliasSymbolAsReferenced(symbol); } var localOrExportSymbol = getExportSymbolOfValueSymbolIfExported(symbol); - // Due to the emit for class decorators, any reference to the class from inside of the class body - // must instead be rewritten to point to a temporary variable to avoid issues with the double-bind - // behavior of class names in ES6. - if (languageVersion === 2 /* ES6 */ - && localOrExportSymbol.flags & 32 /* Class */ - && localOrExportSymbol.valueDeclaration.kind === 221 /* ClassDeclaration */ - && ts.nodeIsDecorated(localOrExportSymbol.valueDeclaration)) { - var container = ts.getContainingClass(node); - while (container !== undefined) { - if (container === localOrExportSymbol.valueDeclaration && container.name !== node) { - getNodeLinks(container).flags |= 524288 /* ClassWithBodyScopedClassBinding */; - getNodeLinks(node).flags |= 1048576 /* BodyScopedClassBinding */; - break; + if (localOrExportSymbol.flags & 32 /* Class */) { + var declaration_1 = localOrExportSymbol.valueDeclaration; + // Due to the emit for class decorators, any reference to the class from inside of the class body + // must instead be rewritten to point to a temporary variable to avoid issues with the double-bind + // behavior of class names in ES6. + if (languageVersion === 2 /* ES6 */ + && declaration_1.kind === 221 /* ClassDeclaration */ + && ts.nodeIsDecorated(declaration_1)) { + var container = ts.getContainingClass(node); + while (container !== undefined) { + if (container === declaration_1 && container.name !== node) { + getNodeLinks(declaration_1).flags |= 8388608 /* ClassWithConstructorReference */; + getNodeLinks(node).flags |= 16777216 /* ConstructorReferenceInClass */; + break; + } + container = ts.getContainingClass(container); + } + } + else if (declaration_1.kind === 192 /* ClassExpression */) { + // When we emit a class expression with static members that contain a reference + // to the constructor in the initializer, we will need to substitute that + // binding with an alias as the class name is not in scope. + var container = ts.getThisContainer(node, /*includeArrowFunctions*/ false); + while (container !== undefined) { + if (container.parent === declaration_1) { + if (container.kind === 145 /* PropertyDeclaration */ && ts.hasModifier(container, 32 /* Static */)) { + getNodeLinks(declaration_1).flags |= 8388608 /* ClassWithConstructorReference */; + getNodeLinks(node).flags |= 16777216 /* ConstructorReferenceInClass */; + } + break; + } + container = ts.getThisContainer(container, /*includeArrowFunctions*/ false); } - container = ts.getContainingClass(container); } } checkCollisionWithCapturedSuperVariable(node, node); @@ -24693,6 +30869,7 @@ var ts; var isParameter = ts.getRootDeclaration(declaration).kind === 142 /* Parameter */; var declarationContainer = getControlFlowContainer(declaration); var flowContainer = getControlFlowContainer(node); + var isOuterVariable = flowContainer !== declarationContainer; // When the control flow originates in a function expression or arrow function and we are referencing // a const variable or parameter from an outer function, we extend the origin of the control flow // analysis to include the immediately enclosing function. @@ -24705,7 +30882,7 @@ var ts; // the entire control flow graph from the variable's declaration (i.e. when the flow container and // declaration container are the same). var assumeInitialized = !strictNullChecks || (type.flags & 1 /* Any */) !== 0 || isParameter || - flowContainer !== declarationContainer || ts.isInAmbientContext(declaration); + isOuterVariable || ts.isInAmbientContext(declaration); var flowType = getFlowTypeOfReference(node, type, assumeInitialized, flowContainer); // A variable is considered uninitialized when it is possible to analyze the entire control flow graph // from declaration to use, and when the variable's declared type doesn't include undefined but the @@ -24889,7 +31066,7 @@ var ts; break; case 145 /* PropertyDeclaration */: case 144 /* PropertySignature */: - if (container.flags & 32 /* Static */) { + if (ts.getModifierFlags(container) & 32 /* Static */) { error(node, ts.Diagnostics.this_cannot_be_referenced_in_a_static_property_initializer); } break; @@ -24925,7 +31102,7 @@ var ts; } if (ts.isClassLike(container.parent)) { var symbol = getSymbolOfNode(container.parent); - var type = container.flags & 32 /* Static */ ? getTypeOfSymbol(symbol) : getDeclaredTypeOfSymbol(symbol).thisType; + var type = ts.hasModifier(container, 32 /* Static */) ? getTypeOfSymbol(symbol) : getDeclaredTypeOfSymbol(symbol).thisType; return getFlowTypeOfReference(node, type, /*assumeInitialized*/ true, /*flowContainer*/ undefined); } if (ts.isInJavaScriptFile(node)) { @@ -24961,8 +31138,8 @@ var ts; var isCallExpression = node.parent.kind === 174 /* CallExpression */ && node.parent.expression === node; var container = ts.getSuperContainer(node, /*stopOnFunctions*/ true); var needToCaptureLexicalThis = false; + // adjust the container reference in case if super is used inside arrow functions with arbitrarily deep nesting if (!isCallExpression) { - // adjust the container reference in case if super is used inside arrow functions with arbitrary deep nesting while (container && container.kind === 180 /* ArrowFunction */) { container = ts.getSuperContainer(container, /*stopOnFunctions*/ true); needToCaptureLexicalThis = languageVersion < 2 /* ES6 */; @@ -24994,7 +31171,7 @@ var ts; } return unknownType; } - if ((container.flags & 32 /* Static */) || isCallExpression) { + if ((ts.getModifierFlags(container) & 32 /* Static */) || isCallExpression) { nodeCheckFlag = 512 /* SuperStatic */; } else { @@ -25057,8 +31234,8 @@ var ts; // This helper creates an object with a "value" property that wraps the `super` property or indexed access for both get and set. // This is required for destructuring assignments, as a call expression cannot be used as the target of a destructuring assignment // while a property access can. - if (container.kind === 147 /* MethodDeclaration */ && container.flags & 256 /* Async */) { - if (ts.isSuperPropertyOrElementAccess(node.parent) && ts.isAssignmentTarget(node.parent)) { + if (container.kind === 147 /* MethodDeclaration */ && ts.getModifierFlags(container) & 256 /* Async */) { + if (ts.isSuperProperty(node.parent) && ts.isAssignmentTarget(node.parent)) { getNodeLinks(container).flags |= 4096 /* AsyncMethodWithSuperBinding */; } else { @@ -25115,7 +31292,7 @@ var ts; // - In a static member function or static member accessor // topmost container must be something that is directly nested in the class declaration\object literal expression if (ts.isClassLike(container.parent) || container.parent.kind === 171 /* ObjectLiteralExpression */) { - if (container.flags & 32 /* Static */) { + if (ts.getModifierFlags(container) & 32 /* Static */) { return container.kind === 147 /* MethodDeclaration */ || container.kind === 146 /* MethodSignature */ || container.kind === 149 /* GetAccessor */ || @@ -25155,14 +31332,14 @@ var ts; if (parameter.dotDotDotToken) { var restTypes = []; for (var i = indexOfParameter; i < iife.arguments.length; i++) { - restTypes.push(getTypeOfExpression(iife.arguments[i])); + restTypes.push(getWidenedLiteralType(checkExpression(iife.arguments[i]))); } return createArrayType(getUnionType(restTypes)); } var links = getNodeLinks(iife); var cached = links.resolvedSignature; links.resolvedSignature = anySignature; - var type = checkExpression(iife.arguments[indexOfParameter]); + var type = getWidenedLiteralType(checkExpression(iife.arguments[indexOfParameter])); links.resolvedSignature = cached; return type; } @@ -25210,11 +31387,11 @@ var ts; } if (ts.isBindingPattern(declaration.parent)) { var parentDeclaration = declaration.parent.parent; - var name_12 = declaration.propertyName || declaration.name; + var name_15 = declaration.propertyName || declaration.name; if (ts.isVariableLike(parentDeclaration) && parentDeclaration.type && - !ts.isBindingPattern(name_12)) { - var text = getTextOfPropertyName(name_12); + !ts.isBindingPattern(name_15)) { + var text = getTextOfPropertyName(name_15); if (text) { return getTypeOfPropertyOfType(getTypeFromTypeNode(parentDeclaration.type), text); } @@ -25329,8 +31506,8 @@ var ts; var types = type.types; var mappedType; var mappedTypes; - for (var _i = 0, types_11 = types; _i < types_11.length; _i++) { - var current = types_11[_i]; + for (var _i = 0, types_12 = types; _i < types_12.length; _i++) { + var current = types_12[_i]; var t = mapper(current); if (t) { if (!mappedType) { @@ -25477,6 +31654,7 @@ var ts; case 187 /* BinaryExpression */: return getContextualTypeForBinaryOperand(node); case 253 /* PropertyAssignment */: + case 254 /* ShorthandPropertyAssignment */: return getContextualTypeForObjectLiteralElement(parent); case 170 /* ArrayLiteralExpression */: return getContextualTypeForElementExpression(node); @@ -25495,30 +31673,6 @@ var ts; } return undefined; } - function isLiteralTypeLocation(node) { - var parent = node.parent; - switch (parent.kind) { - case 187 /* BinaryExpression */: - switch (parent.operatorToken.kind) { - case 32 /* EqualsEqualsEqualsToken */: - case 33 /* ExclamationEqualsEqualsToken */: - case 30 /* EqualsEqualsToken */: - case 31 /* ExclamationEqualsToken */: - return true; - } - break; - case 188 /* ConditionalExpression */: - return (node === parent.whenTrue || - node === parent.whenFalse) && - isLiteralTypeLocation(parent); - case 178 /* ParenthesizedExpression */: - return isLiteralTypeLocation(parent); - case 249 /* CaseClause */: - case 166 /* LiteralType */: - return true; - } - return false; - } // If the given type is an object or union type, if that type has a single signature, and if // that signature is non-generic, return the signature. Otherwise return undefined. function getNonGenericSignature(type) { @@ -25560,8 +31714,8 @@ var ts; } var signatureList; var types = type.types; - for (var _i = 0, types_12 = types; _i < types_12.length; _i++) { - var current = types_12[_i]; + for (var _i = 0, types_13 = types; _i < types_13.length; _i++) { + var current = types_13[_i]; var signature = getNonGenericSignature(current); if (signature) { if (!signatureList) { @@ -25648,7 +31802,7 @@ var ts; } } else { - var type = checkExpression(e, contextualMapper); + var type = checkExpressionForMutableLocation(e, contextualMapper); elementTypes.push(type); } hasSpreadElement = hasSpreadElement || e.kind === 191 /* SpreadElementExpression */; @@ -25701,6 +31855,9 @@ var ts; function isTypeAnyOrAllConstituentTypesHaveKind(type, kind) { return isTypeAny(type) || isTypeOfKind(type, kind); } + function isInfinityOrNaNString(name) { + return name === "Infinity" || name === "-Infinity" || name === "NaN"; + } function isNumericLiteralName(name) { // The intent of numeric names is that // - they are names with text in a numeric form, and that @@ -25778,7 +31935,7 @@ var ts; } else { ts.Debug.assert(memberDecl.kind === 254 /* ShorthandPropertyAssignment */); - type = checkExpression(memberDecl.name, contextualMapper); + type = checkExpressionForMutableLocation(memberDecl.name, contextualMapper); } typeFlags |= type.flags; var prop = createSymbol(4 /* Property */ | 67108864 /* Transient */ | member.flags, member.name); @@ -25853,7 +32010,7 @@ var ts; var stringIndexInfo = hasComputedStringProperty ? getObjectLiteralIndexInfo(node, propertiesArray, 0 /* String */) : undefined; var numberIndexInfo = hasComputedNumberProperty ? getObjectLiteralIndexInfo(node, propertiesArray, 1 /* Number */) : undefined; var result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo); - var freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : 16777216 /* FreshObjectLiteral */; + var freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : 16777216 /* FreshLiteral */; result.flags |= 8388608 /* ObjectLiteral */ | 67108864 /* ContainsObjectLiteral */ | freshObjectLiteralFlag | (typeFlags & 234881024 /* PropagatingFlags */) | (patternWithComputedProperties ? 536870912 /* ObjectLiteralPatternWithComputedProperties */ : 0); if (inDestructuringPattern) { result.pattern = node; @@ -26286,8 +32443,11 @@ var ts; function getDeclarationKindFromSymbol(s) { return s.valueDeclaration ? s.valueDeclaration.kind : 145 /* PropertyDeclaration */; } - function getDeclarationFlagsFromSymbol(s) { - return s.valueDeclaration ? ts.getCombinedNodeFlags(s.valueDeclaration) : s.flags & 134217728 /* Prototype */ ? 4 /* Public */ | 32 /* Static */ : 0; + function getDeclarationModifierFlagsFromSymbol(s) { + return s.valueDeclaration ? ts.getCombinedModifierFlags(s.valueDeclaration) : s.flags & 134217728 /* Prototype */ ? 4 /* Public */ | 32 /* Static */ : 0; + } + function getDeclarationNodeFlagsFromSymbol(s) { + return s.valueDeclaration ? ts.getCombinedNodeFlags(s.valueDeclaration) : 0; } /** * Check whether the requested property access is valid. @@ -26298,7 +32458,7 @@ var ts; * @param prop The symbol for the right hand side of the property access. */ function checkClassPropertyAccess(node, left, type, prop) { - var flags = getDeclarationFlagsFromSymbol(prop); + var flags = getDeclarationModifierFlagsFromSymbol(prop); var declaringClass = getDeclaredTypeOfSymbol(getParentOfSymbol(prop)); var errorNode = node.kind === 172 /* PropertyAccessExpression */ || node.kind === 218 /* VariableDeclaration */ ? node.name : @@ -26327,7 +32487,7 @@ var ts; } } // Public properties are otherwise accessible. - if (!(flags & (8 /* Private */ | 16 /* Protected */))) { + if (!(flags & 24 /* NonPublicAccessibilityModifier */)) { return true; } // Property is known to be private or protected at this point @@ -26393,7 +32553,7 @@ var ts; } function checkPropertyAccessExpressionOrQualifiedName(node, left, right) { var type = checkNonNullExpression(left); - if (isTypeAny(type)) { + if (isTypeAny(type) || type === silentNeverType) { return type; } var apparentType = getApparentType(getWidenedType(type)); @@ -26404,13 +32564,13 @@ var ts; var prop = getPropertyOfType(apparentType, right.text); if (!prop) { if (right.text && !checkAndReportErrorForExtendingInterface(node)) { - error(right, ts.Diagnostics.Property_0_does_not_exist_on_type_1, ts.declarationNameToString(right), typeToString(type.flags & 268435456 /* ThisType */ ? apparentType : type)); + reportNonexistentProperty(right, type.flags & 268435456 /* ThisType */ ? apparentType : type); } return unknownType; } if (noUnusedIdentifiers && (prop.flags & 106500 /* ClassMember */) && - prop.valueDeclaration && (prop.valueDeclaration.flags & 8 /* Private */)) { + prop.valueDeclaration && (ts.getModifierFlags(prop.valueDeclaration) & 8 /* Private */)) { if (prop.flags & 16777216 /* Instantiated */) { getSymbolLinks(prop).target.isReferenced = true; } @@ -26423,9 +32583,6 @@ var ts; checkClassPropertyAccess(node, left, apparentType, prop); } var propType = getTypeOfSymbol(prop); - if (prop.flags & 8 /* EnumMember */ && isLiteralContextForType(node, propType)) { - propType = getDeclaredTypeOfSymbol(prop); - } // Only compute control flow type if this is a property access expression that isn't an // assignment target, and the referenced property was declared as a variable, property, // accessor, or optional method. @@ -26435,6 +32592,20 @@ var ts; return propType; } return getFlowTypeOfReference(node, propType, /*assumeInitialized*/ true, /*flowContainer*/ undefined); + function reportNonexistentProperty(propNode, containingType) { + var errorInfo; + if (containingType.flags & 524288 /* Union */ && !(containingType.flags & 8190 /* Primitive */)) { + for (var _i = 0, _a = containingType.types; _i < _a.length; _i++) { + var subtype = _a[_i]; + if (!getPropertyOfType(subtype, propNode.text)) { + errorInfo = ts.chainDiagnosticMessages(errorInfo, ts.Diagnostics.Property_0_does_not_exist_on_type_1, ts.declarationNameToString(propNode), typeToString(subtype)); + break; + } + } + } + errorInfo = ts.chainDiagnosticMessages(errorInfo, ts.Diagnostics.Property_0_does_not_exist_on_type_1, ts.declarationNameToString(propNode), typeToString(containingType)); + diagnostics.add(ts.createDiagnosticForNodeFromMessageChain(propNode, errorInfo)); + } } function isValidPropertyAccess(node, propertyName) { var left = node.kind === 172 /* PropertyAccessExpression */ @@ -26514,8 +32685,8 @@ var ts; // Obtain base constraint such that we can bail out if the constraint is an unknown type var objectType = getApparentType(checkNonNullExpression(node.expression)); var indexType = node.argumentExpression ? checkExpression(node.argumentExpression) : unknownType; - if (objectType === unknownType) { - return unknownType; + if (objectType === unknownType || objectType === silentNeverType) { + return objectType; } var isConstEnum = isConstEnumObjectType(objectType); if (isConstEnum && @@ -26533,15 +32704,15 @@ var ts; // - Otherwise, if IndexExpr is of type Any, the String or Number primitive type, or an enum type, the property access is of type Any. // See if we can index as a property. if (node.argumentExpression) { - var name_13 = getPropertyNameForIndexedAccess(node.argumentExpression, indexType); - if (name_13 !== undefined) { - var prop = getPropertyOfType(objectType, name_13); + var name_16 = getPropertyNameForIndexedAccess(node.argumentExpression, indexType); + if (name_16 !== undefined) { + var prop = getPropertyOfType(objectType, name_16); if (prop) { getNodeLinks(node).resolvedSymbol = prop; return getTypeOfSymbol(prop); } else if (isConstEnum) { - error(node.argumentExpression, ts.Diagnostics.Property_0_does_not_exist_on_const_enum_1, name_13, symbolToString(objectType.symbol)); + error(node.argumentExpression, ts.Diagnostics.Property_0_does_not_exist_on_const_enum_1, name_16, symbolToString(objectType.symbol)); return unknownType; } } @@ -26674,13 +32845,13 @@ var ts; for (var _i = 0, signatures_2 = signatures; _i < signatures_2.length; _i++) { var signature = signatures_2[_i]; var symbol = signature.declaration && getSymbolOfNode(signature.declaration); - var parent_9 = signature.declaration && signature.declaration.parent; + var parent_11 = signature.declaration && signature.declaration.parent; if (!lastSymbol || symbol === lastSymbol) { - if (lastParent && parent_9 === lastParent) { + if (lastParent && parent_11 === lastParent) { index++; } else { - lastParent = parent_9; + lastParent = parent_11; index = cutoffIndex; } } @@ -26688,7 +32859,7 @@ var ts; // current declaration belongs to a different symbol // set cutoffIndex so re-orderings in the future won't change result set from 0 to cutoffIndex index = cutoffIndex = result.length; - lastParent = parent_9; + lastParent = parent_11; } lastSymbol = symbol; // specialized signatures always need to be placed before non-specialized signatures regardless @@ -26797,7 +32968,7 @@ var ts; } // Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec) function instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper) { - var context = createInferenceContext(signature.typeParameters, /*inferUnionTypes*/ true); + var context = createInferenceContext(signature, /*inferUnionTypes*/ true); forEachMatchingParameterType(contextualSignature, signature, function (source, target) { // Type parameters from outer context referenced by source type are fixed by instantiation of the source type inferTypes(context, instantiateType(source, contextualMapper), target); @@ -27327,7 +33498,7 @@ var ts; else if (candidateForTypeArgumentError) { if (!isTaggedTemplate && !isDecorator && typeArguments) { var typeArguments_2 = node.typeArguments; - checkTypeArguments(candidateForTypeArgumentError, typeArguments_2, ts.map(typeArguments_2, getTypeFromTypeNode), /*reportErrors*/ true, headMessage); + checkTypeArguments(candidateForTypeArgumentError, typeArguments_2, ts.map(typeArguments_2, getTypeFromTypeNodeNoAlias), /*reportErrors*/ true, headMessage); } else { ts.Debug.assert(resultOfFailedInference.failedTypeParameterIndex >= 0); @@ -27354,7 +33525,7 @@ var ts; var candidate = candidates_1[_i]; if (hasCorrectArity(node, args, candidate)) { if (candidate.typeParameters && typeArguments) { - candidate = getSignatureInstantiation(candidate, ts.map(typeArguments, getTypeFromTypeNode)); + candidate = getSignatureInstantiation(candidate, ts.map(typeArguments, getTypeFromTypeNodeNoAlias)); } return candidate; } @@ -27379,14 +33550,14 @@ var ts; var candidate = void 0; var typeArgumentsAreValid = void 0; var inferenceContext = originalCandidate.typeParameters - ? createInferenceContext(originalCandidate.typeParameters, /*inferUnionTypes*/ false) + ? createInferenceContext(originalCandidate, /*inferUnionTypes*/ false) : undefined; while (true) { candidate = originalCandidate; if (candidate.typeParameters) { var typeArgumentTypes = void 0; if (typeArguments) { - typeArgumentTypes = ts.map(typeArguments, getTypeFromTypeNode); + typeArgumentTypes = ts.map(typeArguments, getTypeFromTypeNodeNoAlias); typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false); } else { @@ -27448,6 +33619,9 @@ var ts; return resolveUntypedCall(node); } var funcType = checkNonNullExpression(node.expression); + if (funcType === silentNeverType) { + return silentNeverSignature; + } var apparentType = getApparentType(funcType); if (apparentType === unknownType) { // Another error has already been reported @@ -27478,7 +33652,7 @@ var ts; error(node, ts.Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType)); } else { - error(node, ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature); + error(node, ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType)); } return resolveErrorCall(node); } @@ -27514,6 +33688,9 @@ var ts; } } var expressionType = checkNonNullExpression(node.expression); + if (expressionType === silentNeverType) { + return silentNeverSignature; + } // If expressionType's apparent type(section 3.8.1) is an object type with one or // more construct signatures, the expression is processed in the same manner as a // function call, but using the construct signatures as the initial set of candidate @@ -27529,7 +33706,7 @@ var ts; // In the case of a merged class-module or class-interface declaration, // only the class declaration node will have the Abstract flag set. var valueDecl = expressionType.symbol && getClassLikeDeclarationOfSymbol(expressionType.symbol); - if (valueDecl && valueDecl.flags & 128 /* Abstract */) { + if (valueDecl && ts.getModifierFlags(valueDecl) & 128 /* Abstract */) { error(node, ts.Diagnostics.Cannot_create_an_instance_of_the_abstract_class_0, ts.declarationNameToString(valueDecl.name)); return resolveErrorCall(node); } @@ -27576,9 +33753,9 @@ var ts; return true; } var declaration = signature.declaration; - var flags = declaration.flags; + var modifiers = ts.getModifierFlags(declaration); // Public constructor is accessible. - if (!(flags & (8 /* Private */ | 16 /* Protected */))) { + if (!(modifiers & 24 /* NonPublicAccessibilityModifier */)) { return true; } var declaringClassDeclaration = getClassLikeDeclarationOfSymbol(declaration.parent.symbol); @@ -27591,16 +33768,16 @@ var ts; var baseTypes = getBaseTypes(containingType); if (baseTypes.length) { var baseType = baseTypes[0]; - if (flags & 16 /* Protected */ && + if (modifiers & 16 /* Protected */ && baseType.symbol === declaration.parent.symbol) { return true; } } } - if (flags & 8 /* Private */) { + if (modifiers & 8 /* Private */) { error(node, ts.Diagnostics.Constructor_of_class_0_is_private_and_only_accessible_within_the_class_declaration, typeToString(declaringClass)); } - if (flags & 16 /* Protected */) { + if (modifiers & 16 /* Protected */) { error(node, ts.Diagnostics.Constructor_of_class_0_is_protected_and_only_accessible_within_the_class_declaration, typeToString(declaringClass)); } return false; @@ -27620,7 +33797,7 @@ var ts; return resolveUntypedCall(node); } if (!callSignatures.length) { - error(node, ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature); + error(node, ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType)); return resolveErrorCall(node); } return resolveCall(node, callSignatures, candidatesOutArray); @@ -27660,7 +33837,7 @@ var ts; var headMessage = getDiagnosticHeadMessageForDecoratorResolution(node); if (!callSignatures.length) { var errorInfo = void 0; - errorInfo = ts.chainDiagnosticMessages(errorInfo, ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature); + errorInfo = ts.chainDiagnosticMessages(errorInfo, ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType)); errorInfo = ts.chainDiagnosticMessages(errorInfo, headMessage); diagnostics.add(ts.createDiagnosticForNodeFromMessageChain(node, errorInfo)); return resolveErrorCall(node); @@ -27758,7 +33935,7 @@ var ts; return getReturnTypeOfSignature(getResolvedSignature(node)); } function checkAssertion(node) { - var exprType = getRegularTypeOfObjectLiteral(checkExpression(node.expression)); + var exprType = getRegularTypeOfObjectLiteral(getBaseTypeOfLiteralType(checkExpression(node.expression))); checkSourceElement(node.type); var targetType = getTypeFromTypeNode(node.type); if (produceDiagnostics && targetType !== unknownType) { @@ -27812,7 +33989,7 @@ var ts; if (ts.isBindingPattern(node.name)) { for (var _i = 0, _a = node.name.elements; _i < _a.length; _i++) { var element = _a[_i]; - if (element.kind !== 193 /* OmittedExpression */) { + if (!ts.isOmittedExpression(element)) { if (element.name.kind === 69 /* Identifier */) { getSymbolLinks(getSymbolOfNode(element)).type = getTypeForBindingElement(element); } @@ -27932,20 +34109,8 @@ var ts; return isAsync ? createPromiseReturnType(func, voidType) : voidType; } } - // When yield/return statements are contextually typed we allow the return type to be a union type. - // Otherwise we require the yield/return expressions to have a best common supertype. - type = contextualSignature ? getUnionType(types, /*subtypeReduction*/ true) : getCommonSupertype(types); - if (!type) { - if (funcIsGenerator) { - error(func, ts.Diagnostics.No_best_common_type_exists_among_yield_expressions); - return createIterableIteratorType(unknownType); - } - else { - error(func, ts.Diagnostics.No_best_common_type_exists_among_return_expressions); - // Defer to unioning the return types so we get a) downstream errors earlier and b) better Salsa experience - return isAsync ? createPromiseReturnType(func, getUnionType(types, /*subtypeReduction*/ true)) : getUnionType(types, /*subtypeReduction*/ true); - } - } + // Return a union of the return expression types. + type = getUnionType(types, /*subtypeReduction*/ true); if (funcIsGenerator) { type = createIterableIteratorType(type); } @@ -27953,6 +34118,9 @@ var ts; if (!contextualSignature) { reportErrorsFromWidening(func, type); } + if (isUnitType(type) && !(contextualSignature && isLiteralContextualType(getReturnTypeOfSignature(contextualSignature)))) { + type = getWidenedLiteralType(type); + } var widenedType = getWidenedType(type); // From within an async function you can return either a non-promise value or a promise. Any // Promise/A+ compatible implementation will always assimilate any foreign promise, so the @@ -27981,7 +34149,7 @@ var ts; return false; } var type = checkExpression(node.expression); - if (!isUnitUnionType(type)) { + if (!isLiteralType(type)) { return false; } var switchTypes = getSwitchClauseTypes(node); @@ -27991,7 +34159,7 @@ var ts; return eachTypeContainedIn(type, switchTypes); } function functionHasImplicitReturn(func) { - if (!(func.flags & 32768 /* HasImplicitReturn */)) { + if (!(func.flags & 128 /* HasImplicitReturn */)) { return false; } var lastStatement = ts.lastOrUndefined(func.body.statements); @@ -28016,7 +34184,7 @@ var ts; // the native Promise type by the caller. type = checkAwaitedType(type, func, ts.Diagnostics.Return_expression_in_async_function_does_not_have_a_valid_callable_then_member); } - if (type === neverType) { + if (type.flags & 8192 /* Never */) { hasReturnOfTypeNever = true; } else if (!ts.contains(aggregatedTypes, type)) { @@ -28060,8 +34228,8 @@ var ts; if (ts.nodeIsMissing(func.body) || func.body.kind !== 199 /* Block */ || !functionHasImplicitReturn(func)) { return; } - var hasExplicitReturn = func.flags & 65536 /* HasExplicitReturn */; - if (returnType === neverType) { + var hasExplicitReturn = func.flags & 256 /* HasExplicitReturn */; + if (returnType && returnType.flags & 8192 /* Never */) { error(func.type, ts.Diagnostics.A_function_returning_never_cannot_have_a_reachable_end_point); } else if (returnType && !hasExplicitReturn) { @@ -28195,8 +34363,8 @@ var ts; // Enum members // Unions and intersections of the above (unions and intersections eagerly set isReadonly on creation) return symbol.isReadonly || - symbol.flags & 4 /* Property */ && (getDeclarationFlagsFromSymbol(symbol) & 64 /* Readonly */) !== 0 || - symbol.flags & 3 /* Variable */ && (getDeclarationFlagsFromSymbol(symbol) & 2048 /* Const */) !== 0 || + symbol.flags & 4 /* Property */ && (getDeclarationModifierFlagsFromSymbol(symbol) & 64 /* Readonly */) !== 0 || + symbol.flags & 3 /* Variable */ && (getDeclarationNodeFlagsFromSymbol(symbol) & 2 /* Const */) !== 0 || symbol.flags & 98304 /* Accessor */ && !(symbol.flags & 65536 /* SetAccessor */) || (symbol.flags & 8 /* EnumMember */) !== 0; } @@ -28281,7 +34449,7 @@ var ts; function checkAwaitExpression(node) { // Grammar checking if (produceDiagnostics) { - if (!(node.flags & 33554432 /* AwaitContext */)) { + if (!(node.flags & 262144 /* AwaitContext */)) { grammarErrorOnFirstToken(node, ts.Diagnostics.await_expression_is_only_allowed_within_an_async_function); } if (isInParameterInitializerBeforeContainingFunction(node)) { @@ -28293,8 +34461,11 @@ var ts; } function checkPrefixUnaryExpression(node) { var operandType = checkExpression(node.operand); - if (node.operator === 36 /* MinusToken */ && node.operand.kind === 8 /* NumericLiteral */ && isLiteralContextForType(node, numberType)) { - return getLiteralTypeForText(64 /* NumberLiteral */, "" + -node.operand.text); + if (operandType === silentNeverType) { + return silentNeverType; + } + if (node.operator === 36 /* MinusToken */ && node.operand.kind === 8 /* NumericLiteral */) { + return getFreshTypeOfLiteralType(getLiteralTypeForText(64 /* NumberLiteral */, "" + -node.operand.text)); } switch (node.operator) { case 35 /* PlusToken */: @@ -28322,6 +34493,9 @@ var ts; } function checkPostfixUnaryExpression(node) { var operandType = checkExpression(node.operand); + if (operandType === silentNeverType) { + return silentNeverType; + } var ok = checkArithmeticOperandType(node.operand, getNonNullableType(operandType), ts.Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type); if (ok) { // run check only if former checks succeeded to avoid reporting cascading errors @@ -28337,8 +34511,8 @@ var ts; } if (type.flags & 1572864 /* UnionOrIntersection */) { var types = type.types; - for (var _i = 0, types_13 = types; _i < types_13.length; _i++) { - var t = types_13[_i]; + for (var _i = 0, types_14 = types; _i < types_14.length; _i++) { + var t = types_14[_i]; if (maybeTypeOfKind(t, kind)) { return true; } @@ -28355,8 +34529,8 @@ var ts; } if (type.flags & 524288 /* Union */) { var types = type.types; - for (var _i = 0, types_14 = types; _i < types_14.length; _i++) { - var t = types_14[_i]; + for (var _i = 0, types_15 = types; _i < types_15.length; _i++) { + var t = types_15[_i]; if (!isTypeOfKind(t, kind)) { return false; } @@ -28365,8 +34539,8 @@ var ts; } if (type.flags & 1048576 /* Intersection */) { var types = type.types; - for (var _a = 0, types_15 = types; _a < types_15.length; _a++) { - var t = types_15[_a]; + for (var _a = 0, types_16 = types; _a < types_16.length; _a++) { + var t = types_16[_a]; if (isTypeOfKind(t, kind)) { return true; } @@ -28381,6 +34555,9 @@ var ts; return (symbol.flags & 128 /* ConstEnum */) !== 0; } function checkInstanceOfExpression(left, right, leftType, rightType) { + if (leftType === silentNeverType || rightType === silentNeverType) { + return silentNeverType; + } // TypeScript 1.0 spec (April 2014): 4.15.4 // The instanceof operator requires the left operand to be of type Any, an object type, or a type parameter type, // and the right operand to be of type Any or a subtype of the 'Function' interface type. @@ -28396,6 +34573,9 @@ var ts; return booleanType; } function checkInExpression(left, right, leftType, rightType) { + if (leftType === silentNeverType || rightType === silentNeverType) { + return silentNeverType; + } // TypeScript 1.0 spec (April 2014): 4.15.5 // The in operator requires the left operand to be of type Any, the String primitive type, or the Number primitive type, // and the right operand to be of type Any, an object type, or a type parameter type. @@ -28410,22 +34590,22 @@ var ts; } function checkObjectLiteralAssignment(node, sourceType, contextualMapper) { var properties = node.properties; - for (var _i = 0, properties_3 = properties; _i < properties_3.length; _i++) { - var p = properties_3[_i]; + for (var _i = 0, properties_4 = properties; _i < properties_4.length; _i++) { + var p = properties_4[_i]; checkObjectLiteralDestructuringPropertyAssignment(sourceType, p, contextualMapper); } return sourceType; } function checkObjectLiteralDestructuringPropertyAssignment(objectLiteralType, property, contextualMapper) { if (property.kind === 253 /* PropertyAssignment */ || property.kind === 254 /* ShorthandPropertyAssignment */) { - var name_14 = property.name; - if (name_14.kind === 140 /* ComputedPropertyName */) { - checkComputedPropertyName(name_14); + var name_17 = property.name; + if (name_17.kind === 140 /* ComputedPropertyName */) { + checkComputedPropertyName(name_17); } - if (isComputedNonLiteralName(name_14)) { + if (isComputedNonLiteralName(name_17)) { return undefined; } - var text = getTextOfPropertyName(name_14); + var text = getTextOfPropertyName(name_17); var type = isTypeAny(objectLiteralType) ? objectLiteralType : getTypeOfPropertyOfType(objectLiteralType, text) || @@ -28441,7 +34621,7 @@ var ts; } } else { - error(name_14, ts.Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(objectLiteralType), ts.declarationNameToString(name_14)); + error(name_17, ts.Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(objectLiteralType), ts.declarationNameToString(name_17)); } } else { @@ -28539,6 +34719,67 @@ var ts; } return sourceType; } + /** + * This is a *shallow* check: An expression is side-effect-free if the + * evaluation of the expression *itself* cannot produce side effects. + * For example, x++ / 3 is side-effect free because the / operator + * does not have side effects. + * The intent is to "smell test" an expression for correctness in positions where + * its value is discarded (e.g. the left side of the comma operator). + */ + function isSideEffectFree(node) { + node = ts.skipParentheses(node); + switch (node.kind) { + case 69 /* Identifier */: + case 9 /* StringLiteral */: + case 10 /* RegularExpressionLiteral */: + case 176 /* TaggedTemplateExpression */: + case 189 /* TemplateExpression */: + case 11 /* NoSubstitutionTemplateLiteral */: + case 8 /* NumericLiteral */: + case 99 /* TrueKeyword */: + case 84 /* FalseKeyword */: + case 93 /* NullKeyword */: + case 135 /* UndefinedKeyword */: + case 179 /* FunctionExpression */: + case 192 /* ClassExpression */: + case 180 /* ArrowFunction */: + case 170 /* ArrayLiteralExpression */: + case 171 /* ObjectLiteralExpression */: + case 182 /* TypeOfExpression */: + case 196 /* NonNullExpression */: + case 242 /* JsxSelfClosingElement */: + case 241 /* JsxElement */: + return true; + case 188 /* ConditionalExpression */: + return isSideEffectFree(node.whenTrue) && + isSideEffectFree(node.whenFalse); + case 187 /* BinaryExpression */: + if (ts.isAssignmentOperator(node.operatorToken.kind)) { + return false; + } + return isSideEffectFree(node.left) && + isSideEffectFree(node.right); + case 185 /* PrefixUnaryExpression */: + case 186 /* PostfixUnaryExpression */: + // Unary operators ~, !, +, and - have no side effects. + // The rest do. + switch (node.operator) { + case 49 /* ExclamationToken */: + case 35 /* PlusToken */: + case 36 /* MinusToken */: + case 50 /* TildeToken */: + return true; + } + return false; + // Some forms listed here for clarity + case 183 /* VoidExpression */: // Explicit opt-out + case 177 /* TypeAssertionExpression */: // Not SEF, but can produce useful type warnings + case 195 /* AsExpression */: // Not SEF, but can produce useful type warnings + default: + return false; + } + } function isTypeEqualityComparableTo(source, target) { return (target.flags & 6144 /* Nullable */) !== 0 || isTypeComparableTo(source, target); } @@ -28582,6 +34823,9 @@ var ts; case 68 /* CaretEqualsToken */: case 46 /* AmpersandToken */: case 66 /* AmpersandEqualsToken */: + if (leftType === silentNeverType || rightType === silentNeverType) { + return silentNeverType; + } // TypeScript 1.0 spec (April 2014): 4.19.1 // These operators require their operands to be of type Any, the Number primitive type, // or an enum type. Operands of an enum type are treated @@ -28613,6 +34857,9 @@ var ts; return numberType; case 35 /* PlusToken */: case 57 /* PlusEqualsToken */: + if (leftType === silentNeverType || rightType === silentNeverType) { + return silentNeverType; + } // TypeScript 1.0 spec (April 2014): 4.19.2 // The binary + operator requires both operands to be of the Number primitive type or an enum type, // or at least one of the operands to be of type Any or the String primitive type. @@ -28666,11 +34913,11 @@ var ts; case 31 /* ExclamationEqualsToken */: case 32 /* EqualsEqualsEqualsToken */: case 33 /* ExclamationEqualsEqualsToken */: - var leftIsUnit = isUnitUnionType(leftType); - var rightIsUnit = isUnitUnionType(rightType); - if (!leftIsUnit || !rightIsUnit) { - leftType = leftIsUnit ? getBaseTypeOfUnitType(leftType) : leftType; - rightType = rightIsUnit ? getBaseTypeOfUnitType(rightType) : rightType; + var leftIsLiteral = isLiteralType(leftType); + var rightIsLiteral = isLiteralType(rightType); + if (!leftIsLiteral || !rightIsLiteral) { + leftType = leftIsLiteral ? getBaseTypeOfLiteralType(leftType) : leftType; + rightType = rightIsLiteral ? getBaseTypeOfLiteralType(rightType) : rightType; } if (!isTypeEqualityComparableTo(leftType, rightType) && !isTypeEqualityComparableTo(rightType, leftType)) { reportOperatorError(); @@ -28682,7 +34929,7 @@ var ts; return checkInExpression(left, right, leftType, rightType); case 51 /* AmpersandAmpersandToken */: return getTypeFacts(leftType) & 1048576 /* Truthy */ ? - includeFalsyTypes(rightType, getFalsyFlags(strictNullChecks ? leftType : getBaseTypeOfUnitType(rightType))) : + includeFalsyTypes(rightType, getFalsyFlags(strictNullChecks ? leftType : getBaseTypeOfLiteralType(rightType))) : leftType; case 52 /* BarBarToken */: return getTypeFacts(leftType) & 2097152 /* Falsy */ ? @@ -28692,6 +34939,9 @@ var ts; checkAssignmentOperator(rightType); return getRegularTypeOfObjectLiteral(rightType); case 24 /* CommaToken */: + if (!compilerOptions.allowUnreachableCode && isSideEffectFree(left)) { + error(left, ts.Diagnostics.Left_side_of_comma_operator_is_unused_and_has_no_side_effects); + } return rightType; } // Return true if there was no error, false if there was an error. @@ -28758,7 +35008,7 @@ var ts; function checkYieldExpression(node) { // Grammar checking if (produceDiagnostics) { - if (!(node.flags & 8388608 /* YieldContext */) || isYieldExpressionInClass(node)) { + if (!(node.flags & 65536 /* YieldContext */) || isYieldExpressionInClass(node)) { grammarErrorOnFirstToken(node, ts.Diagnostics.A_yield_expression_is_only_allowed_in_a_generator_body); } if (isInParameterInitializerBeforeContainingFunction(node)) { @@ -28799,63 +35049,19 @@ var ts; var type2 = checkExpression(node.whenFalse, contextualMapper); return getBestChoiceType(type1, type2); } - function typeContainsLiteralFromEnum(type, enumType) { - if (type.flags & 524288 /* Union */) { - for (var _i = 0, _a = type.types; _i < _a.length; _i++) { - var t = _a[_i]; - if (t.flags & 256 /* EnumLiteral */ && t.baseType === enumType) { - return true; - } - } - } - if (type.flags & 256 /* EnumLiteral */) { - return type.baseType === enumType; - } - return false; - } - function isLiteralContextForType(node, type) { - if (isLiteralTypeLocation(node)) { - return true; - } - var contextualType = getContextualType(node); - if (contextualType) { - if (contextualType.flags & 16384 /* TypeParameter */) { - var apparentType = getApparentTypeOfTypeParameter(contextualType); - // If the type parameter is constrained to the base primitive type we're checking for, - // consider this a literal context. For example, given a type parameter 'T extends string', - // this causes us to infer string literal types for T. - if (type === apparentType) { - return true; - } - contextualType = apparentType; - } - if (type.flags & 2 /* String */) { - return maybeTypeOfKind(contextualType, 32 /* StringLiteral */); - } - if (type.flags & 4 /* Number */) { - return maybeTypeOfKind(contextualType, (64 /* NumberLiteral */ | 256 /* EnumLiteral */)); - } - if (type.flags & 8 /* Boolean */) { - return maybeTypeOfKind(contextualType, 128 /* BooleanLiteral */) && !isTypeAssignableTo(booleanType, contextualType); - } - if (type.flags & 16 /* Enum */) { - return typeContainsLiteralFromEnum(contextualType, type); - } - } - return false; - } function checkLiteralExpression(node) { if (node.kind === 8 /* NumericLiteral */) { checkGrammarNumericLiteral(node); } switch (node.kind) { case 9 /* StringLiteral */: - return isLiteralContextForType(node, stringType) ? getLiteralTypeForText(32 /* StringLiteral */, node.text) : stringType; + return getFreshTypeOfLiteralType(getLiteralTypeForText(32 /* StringLiteral */, node.text)); case 8 /* NumericLiteral */: - return isLiteralContextForType(node, numberType) ? getLiteralTypeForText(64 /* NumberLiteral */, node.text) : numberType; + return getFreshTypeOfLiteralType(getLiteralTypeForText(64 /* NumberLiteral */, node.text)); case 99 /* TrueKeyword */: + return trueType; case 84 /* FalseKeyword */: - return isLiteralContextForType(node, booleanType) ? node.kind === 99 /* TrueKeyword */ ? trueType : falseType : booleanType; + return falseType; } } function checkTemplateExpression(node) { @@ -28889,6 +35095,36 @@ var ts; } return links.resolvedType; } + function isTypeAssertion(node) { + node = skipParenthesizedNodes(node); + return node.kind === 177 /* TypeAssertionExpression */ || node.kind === 195 /* AsExpression */; + } + function checkDeclarationInitializer(declaration) { + var type = checkExpressionCached(declaration.initializer); + return ts.getCombinedNodeFlags(declaration) & 2 /* Const */ || + ts.getCombinedModifierFlags(declaration) & 64 /* Readonly */ || + isTypeAssertion(declaration.initializer) ? type : getWidenedLiteralType(type); + } + function isLiteralContextualType(contextualType) { + if (contextualType) { + if (contextualType.flags & 16384 /* TypeParameter */) { + var apparentType = getApparentTypeOfTypeParameter(contextualType); + // If the type parameter is constrained to the base primitive type we're checking for, + // consider this a literal context. For example, given a type parameter 'T extends string', + // this causes us to infer string literal types for T. + if (apparentType.flags & (2 /* String */ | 4 /* Number */ | 8 /* Boolean */ | 16 /* Enum */)) { + return true; + } + contextualType = apparentType; + } + return maybeTypeOfKind(contextualType, 480 /* Literal */); + } + return false; + } + function checkExpressionForMutableLocation(node, contextualMapper) { + var type = checkExpression(node, contextualMapper); + return isTypeAssertion(node) || isLiteralContextualType(getContextualType(node)) ? type : getWidenedLiteralType(type); + } function checkPropertyAssignment(node, contextualMapper) { // Do not use hasDynamicName here, because that returns false for well known symbols. // We want to perform checkComputedPropertyName for all computed properties, including @@ -28896,7 +35132,7 @@ var ts; if (node.name.kind === 140 /* ComputedPropertyName */) { checkComputedPropertyName(node.name); } - return checkExpression(node.initializer, contextualMapper); + return checkExpressionForMutableLocation(node.initializer, contextualMapper); } function checkObjectLiteralMethod(node, contextualMapper) { // Grammar checking @@ -29055,7 +35291,7 @@ var ts; checkGrammarDecorators(node) || checkGrammarModifiers(node); checkVariableLikeDeclaration(node); var func = ts.getContainingFunction(node); - if (node.flags & 92 /* ParameterPropertyModifier */) { + if (ts.getModifierFlags(node) & 92 /* ParameterPropertyModifier */) { func = ts.getContainingFunction(node); if (!(func.kind === 148 /* Constructor */ && ts.nodeIsPresent(func.body))) { error(node, ts.Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation); @@ -29127,9 +35363,9 @@ var ts; else if (parameterName) { var hasReportedError = false; for (var _i = 0, _a = parent.parameters; _i < _a.length; _i++) { - var name_15 = _a[_i].name; - if (ts.isBindingPattern(name_15) && - checkIfTypePredicateVariableIsDeclaredInBindingPattern(name_15, parameterName, typePredicate.parameterName)) { + var name_18 = _a[_i].name; + if (ts.isBindingPattern(name_18) && + checkIfTypePredicateVariableIsDeclaredInBindingPattern(name_18, parameterName, typePredicate.parameterName)) { hasReportedError = true; break; } @@ -29149,23 +35385,27 @@ var ts; case 156 /* FunctionType */: case 147 /* MethodDeclaration */: case 146 /* MethodSignature */: - var parent_10 = node.parent; - if (node === parent_10.type) { - return parent_10; + var parent_12 = node.parent; + if (node === parent_12.type) { + return parent_12; } } } function checkIfTypePredicateVariableIsDeclaredInBindingPattern(pattern, predicateVariableNode, predicateVariableName) { for (var _i = 0, _a = pattern.elements; _i < _a.length; _i++) { - var name_16 = _a[_i].name; - if (name_16.kind === 69 /* Identifier */ && - name_16.text === predicateVariableName) { + var element = _a[_i]; + if (ts.isOmittedExpression(element)) { + continue; + } + var name_19 = element.name; + if (name_19.kind === 69 /* Identifier */ && + name_19.text === predicateVariableName) { error(predicateVariableNode, ts.Diagnostics.A_type_predicate_cannot_reference_element_0_in_a_binding_pattern, predicateVariableName); return true; } - else if (name_16.kind === 168 /* ArrayBindingPattern */ || - name_16.kind === 167 /* ObjectBindingPattern */) { - if (checkIfTypePredicateVariableIsDeclaredInBindingPattern(name_16, predicateVariableNode, predicateVariableName)) { + else if (name_19.kind === 168 /* ArrayBindingPattern */ || + name_19.kind === 167 /* ObjectBindingPattern */) { + if (checkIfTypePredicateVariableIsDeclaredInBindingPattern(name_19, predicateVariableNode, predicateVariableName)) { return true; } } @@ -29357,7 +35597,7 @@ var ts; checkFunctionOrMethodDeclaration(node); // Abstract methods cannot have an implementation. // Extra checks are to avoid reporting multiple errors relating to the "abstractness" of the node. - if (node.flags & 128 /* Abstract */ && node.body) { + if (ts.getModifierFlags(node) & 128 /* Abstract */ && node.body) { error(node, ts.Diagnostics.Method_0_cannot_have_an_implementation_because_it_is_marked_abstract, ts.declarationNameToString(node.name)); } } @@ -29406,7 +35646,7 @@ var ts; } function isInstancePropertyWithInitializer(n) { return n.kind === 145 /* PropertyDeclaration */ && - !(n.flags & 32 /* Static */) && + !(ts.getModifierFlags(n) & 32 /* Static */) && !!n.initializer; } // TS 1.0 spec (April 2014): 8.3.2 @@ -29414,6 +35654,7 @@ var ts; // constructors of derived classes must contain at least one super call somewhere in their function body. var containingClassDecl = node.parent; if (ts.getClassExtendsHeritageClauseElement(containingClassDecl)) { + captureLexicalThis(node.parent, containingClassDecl); var classExtendsNull = classDeclarationExtendsNull(containingClassDecl); var superCall = getSuperCallInConstructor(node); if (superCall) { @@ -29426,7 +35667,7 @@ var ts; // - The constructor declares parameter properties // or the containing class declares instance member variables with initializers. var superCallShouldBeFirst = ts.forEach(node.parent.members, isInstancePropertyWithInitializer) || - ts.forEach(node.parameters, function (p) { return p.flags & 92 /* ParameterPropertyModifier */; }); + ts.forEach(node.parameters, function (p) { return ts.getModifierFlags(p) & 92 /* ParameterPropertyModifier */; }); // Skip past any prologue directives to find the first statement // to ensure that it was a super call. if (superCallShouldBeFirst) { @@ -29459,8 +35700,8 @@ var ts; checkDecorators(node); checkSignatureDeclaration(node); if (node.kind === 149 /* GetAccessor */) { - if (!ts.isInAmbientContext(node) && ts.nodeIsPresent(node.body) && (node.flags & 32768 /* HasImplicitReturn */)) { - if (!(node.flags & 65536 /* HasExplicitReturn */)) { + if (!ts.isInAmbientContext(node) && ts.nodeIsPresent(node.body) && (node.flags & 128 /* HasImplicitReturn */)) { + if (!(node.flags & 256 /* HasExplicitReturn */)) { error(node.name, ts.Diagnostics.A_get_accessor_must_return_a_value); } } @@ -29477,10 +35718,10 @@ var ts; var otherKind = node.kind === 149 /* GetAccessor */ ? 150 /* SetAccessor */ : 149 /* GetAccessor */; var otherAccessor = ts.getDeclarationOfKind(node.symbol, otherKind); if (otherAccessor) { - if (((node.flags & 28 /* AccessibilityModifier */) !== (otherAccessor.flags & 28 /* AccessibilityModifier */))) { + if ((ts.getModifierFlags(node) & 28 /* AccessibilityModifier */) !== (ts.getModifierFlags(otherAccessor) & 28 /* AccessibilityModifier */)) { error(node.name, ts.Diagnostics.Getter_and_setter_accessors_do_not_agree_in_visibility); } - if (((node.flags & 128 /* Abstract */) !== (otherAccessor.flags & 128 /* Abstract */))) { + if (ts.hasModifier(node, 128 /* Abstract */) !== ts.hasModifier(otherAccessor, 128 /* Abstract */)) { error(node.name, ts.Diagnostics.Accessors_must_both_be_abstract_or_non_abstract); } // TypeScript 1.0 spec (April 2014): 4.5 @@ -29524,7 +35765,7 @@ var ts; var constraint = getConstraintOfTypeParameter(typeParameters[i]); if (constraint) { if (!typeArguments) { - typeArguments = ts.map(typeArgumentNodes, getTypeFromTypeNode); + typeArguments = ts.map(typeArgumentNodes, getTypeFromTypeNodeNoAlias); mapper = createTypeMapper(typeParameters, typeArguments); } var typeArgument = typeArguments[i]; @@ -29578,10 +35819,10 @@ var ts; ts.forEach(node.types, checkSourceElement); } function isPrivateWithinAmbient(node) { - return (node.flags & 8 /* Private */) && ts.isInAmbientContext(node); + return (ts.getModifierFlags(node) & 8 /* Private */) && ts.isInAmbientContext(node); } function getEffectiveDeclarationFlags(n, flagsToCheck) { - var flags = ts.getCombinedNodeFlags(n); + var flags = ts.getCombinedModifierFlags(n); // children of classes (even ambient classes) should not be marked as ambient or export // because those flags have no useful semantics there. if (n.parent.kind !== 222 /* InterfaceDeclaration */ && @@ -29644,7 +35885,7 @@ var ts; } } var flagsToCheck = 1 /* Export */ | 2 /* Ambient */ | 8 /* Private */ | 16 /* Protected */ | 128 /* Abstract */; - var someNodeFlags = 0; + var someNodeFlags = 0 /* None */; var allNodeFlags = flagsToCheck; var someHaveQuestionToken = false; var allHaveQuestionToken = true; @@ -29675,13 +35916,13 @@ var ts; // TODO(jfreeman): These are methods, so handle computed name case if (node.name && subsequentNode.name && node.name.text === subsequentNode.name.text) { var reportError = (node.kind === 147 /* MethodDeclaration */ || node.kind === 146 /* MethodSignature */) && - (node.flags & 32 /* Static */) !== (subsequentNode.flags & 32 /* Static */); + (ts.getModifierFlags(node) & 32 /* Static */) !== (ts.getModifierFlags(subsequentNode) & 32 /* Static */); // we can get here in two cases // 1. mixed static and instance class members // 2. something with the same name was defined before the set of overloads that prevents them from merging // here we'll report error only for the first case since for second we should already report error in binder if (reportError) { - var diagnostic = node.flags & 32 /* Static */ ? ts.Diagnostics.Function_overload_must_be_static : ts.Diagnostics.Function_overload_must_not_be_static; + var diagnostic = ts.getModifierFlags(node) & 32 /* Static */ ? ts.Diagnostics.Function_overload_must_be_static : ts.Diagnostics.Function_overload_must_not_be_static; error(errorNode_1, diagnostic); } return; @@ -29699,7 +35940,7 @@ var ts; else { // Report different errors regarding non-consecutive blocks of declarations depending on whether // the node in question is abstract. - if (node.flags & 128 /* Abstract */) { + if (ts.getModifierFlags(node) & 128 /* Abstract */) { error(errorNode, ts.Diagnostics.All_declarations_of_an_abstract_method_must_be_consecutive); } else { @@ -29767,7 +36008,7 @@ var ts; } // Abstract methods can't have an implementation -- in particular, they don't need one. if (lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body && - !(lastSeenNonAmbientDeclaration.flags & 128 /* Abstract */) && !lastSeenNonAmbientDeclaration.questionToken) { + !(ts.getModifierFlags(lastSeenNonAmbientDeclaration) & 128 /* Abstract */) && !lastSeenNonAmbientDeclaration.questionToken) { reportImplementationExpectedError(lastSeenNonAmbientDeclaration); } if (hasOverloads) { @@ -30025,7 +36266,7 @@ var ts; * @param returnType The return type of a FunctionLikeDeclaration * @param location The node on which to report the error. */ - function checkCorrectPromiseType(returnType, location) { + function checkCorrectPromiseType(returnType, location, diagnostic, typeName) { if (returnType === unknownType) { // The return type already had some other error, so we ignore and return // the unknown type. @@ -30042,7 +36283,7 @@ var ts; } // The promise type was not a valid type reference to the global promise type, so we // report an error and return the unknown type. - error(location, ts.Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type); + error(location, diagnostic, typeName); return unknownType; } /** @@ -30061,7 +36302,7 @@ var ts; function checkAsyncFunctionReturnType(node) { if (languageVersion >= 2 /* ES6 */) { var returnType = getTypeFromTypeNode(node.type); - return checkCorrectPromiseType(returnType, node.type); + return checkCorrectPromiseType(returnType, node.type, ts.Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type); } var globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType(); if (globalPromiseConstructorLikeType === emptyObjectType) { @@ -30103,17 +36344,17 @@ var ts; } var promiseConstructor = getNodeLinks(node.type).resolvedSymbol; if (!promiseConstructor || !symbolIsValue(promiseConstructor)) { + // try to fall back to global promise type. var typeName = promiseConstructor ? symbolToString(promiseConstructor) : typeToString(promiseType); - error(node, ts.Diagnostics.Type_0_is_not_a_valid_async_function_return_type, typeName); - return unknownType; + return checkCorrectPromiseType(promiseType, node.type, ts.Diagnostics.Type_0_is_not_a_valid_async_function_return_type, typeName); } // If the Promise constructor, resolved locally, is an alias symbol we should mark it as referenced. checkReturnTypeAnnotationAsExpression(node); // Validate the promise constructor type. var promiseConstructorType = getTypeOfSymbol(promiseConstructor); - if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node, ts.Diagnostics.Type_0_is_not_a_valid_async_function_return_type)) { + if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node.type, ts.Diagnostics.Type_0_is_not_a_valid_async_function_return_type)) { return unknownType; } // Verify there is no local declaration that could collide with the promise constructor. @@ -30357,7 +36598,7 @@ var ts; } function checkUnusedLocalsAndParameters(node) { if (node.parent.kind !== 222 /* InterfaceDeclaration */ && noUnusedIdentifiers && !ts.isInAmbientContext(node)) { - var _loop_1 = function(key) { + var _loop_1 = function (key) { var local = node.locals[key]; if (!local.isReferenced) { if (local.valueDeclaration && local.valueDeclaration.kind === 142 /* Parameter */) { @@ -30391,14 +36632,14 @@ var ts; for (var _i = 0, _a = node.members; _i < _a.length; _i++) { var member = _a[_i]; if (member.kind === 147 /* MethodDeclaration */ || member.kind === 145 /* PropertyDeclaration */) { - if (!member.symbol.isReferenced && member.flags & 8 /* Private */) { + if (!member.symbol.isReferenced && ts.getModifierFlags(member) & 8 /* Private */) { error(member.name, ts.Diagnostics._0_is_declared_but_never_used, member.symbol.name); } } else if (member.kind === 148 /* Constructor */) { for (var _b = 0, _c = member.parameters; _b < _c.length; _b++) { var parameter = _c[_b]; - if (!parameter.symbol.isReferenced && parameter.flags & 8 /* Private */) { + if (!parameter.symbol.isReferenced && ts.getModifierFlags(parameter) & 8 /* Private */) { error(parameter.name, ts.Diagnostics.Property_0_is_declared_but_never_used, parameter.symbol.name); } } @@ -30529,6 +36770,10 @@ var ts; } } function checkCollisionWithRequireExportsInGeneratedCode(node, name) { + // No need to check for require or exports for ES6 modules and later + if (modulekind >= ts.ModuleKind.ES6) { + return; + } if (!needCollisionCheckForIdentifier(node, name, "require") && !needCollisionCheckForIdentifier(node, name, "exports")) { return; } @@ -30553,7 +36798,7 @@ var ts; } // In case of variable declaration, node.parent is variable statement so look at the variable statement's parent var parent = getDeclarationContainer(node); - if (parent.kind === 256 /* SourceFile */ && ts.isExternalOrCommonJsModule(parent) && parent.flags & 2097152 /* HasAsyncFunctions */) { + if (parent.kind === 256 /* SourceFile */ && ts.isExternalOrCommonJsModule(parent) && parent.flags & 8192 /* HasAsyncFunctions */) { // If the declaration happens to be in external module, report error that Promise is a reserved identifier. error(name, ts.Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_a_module_containing_async_functions, ts.declarationNameToString(name), ts.declarationNameToString(name)); } @@ -30582,7 +36827,7 @@ var ts; // const x = 0; // symbol for this declaration will be 'symbol' // } // skip block-scoped variables and parameters - if ((ts.getCombinedNodeFlags(node) & 3072 /* BlockScoped */) !== 0 || ts.isParameterDeclaration(node)) { + if ((ts.getCombinedNodeFlags(node) & 3 /* BlockScoped */) !== 0 || ts.isParameterDeclaration(node)) { return; } // skip variable declarations that don't have initializers @@ -30597,7 +36842,7 @@ var ts; if (localDeclarationSymbol && localDeclarationSymbol !== symbol && localDeclarationSymbol.flags & 2 /* BlockScopedVariable */) { - if (getDeclarationFlagsFromSymbol(localDeclarationSymbol) & 3072 /* BlockScoped */) { + if (getDeclarationNodeFlagsFromSymbol(localDeclarationSymbol) & 3 /* BlockScoped */) { var varDeclList = ts.getAncestor(localDeclarationSymbol.valueDeclaration, 219 /* VariableDeclarationList */); var container = varDeclList.parent.kind === 200 /* VariableStatement */ && varDeclList.parent.parent ? varDeclList.parent.parent @@ -30614,8 +36859,8 @@ var ts; // otherwise if variable has an initializer - show error that initialization will fail // since LHS will be block scoped name instead of function scoped if (!namesShareScope) { - var name_17 = symbolToString(localDeclarationSymbol); - error(node, ts.Diagnostics.Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1, name_17, name_17); + var name_20 = symbolToString(localDeclarationSymbol); + error(node, ts.Diagnostics.Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1, name_20, name_20); } } } @@ -30668,7 +36913,7 @@ var ts; // computed property names/initializers in instance property declaration of class like entities // are executed in constructor and thus deferred if (current.parent.kind === 145 /* PropertyDeclaration */ && - !(current.parent.flags & 32 /* Static */) && + !(ts.hasModifier(current.parent, 32 /* Static */)) && ts.isClassLike(current.parent.parent)) { return; } @@ -30703,12 +36948,12 @@ var ts; checkComputedPropertyName(node.propertyName); } // check private/protected variable access - var parent_11 = node.parent.parent; - var parentType = getTypeForBindingElementParent(parent_11); - var name_18 = node.propertyName || node.name; - var property = getPropertyOfType(parentType, getTextOfPropertyName(name_18)); - if (parent_11.initializer && property && getParentOfSymbol(property)) { - checkClassPropertyAccess(parent_11, parent_11.initializer, parentType, property); + var parent_13 = node.parent.parent; + var parentType = getTypeForBindingElementParent(parent_13); + var name_21 = node.propertyName || node.name; + var property = getPropertyOfType(parentType, getTextOfPropertyName(name_21)); + if (parent_13.initializer && property && getParentOfSymbol(property)) { + checkClassPropertyAccess(parent_13, parent_13.initializer, parentType, property); } } // For a binding pattern, check contained binding elements @@ -30781,7 +37026,7 @@ var ts; 128 /* Abstract */ | 64 /* Readonly */ | 32 /* Static */; - return (left.flags & interestingFlags) === (right.flags & interestingFlags); + return (ts.getModifierFlags(left) & interestingFlags) === (ts.getModifierFlags(right) & interestingFlags); } function checkVariableDeclaration(node) { checkGrammarVariableDeclaration(node); @@ -31137,7 +37382,7 @@ var ts; } // Now that we've removed all the StringLike types, if no constituents remain, then the entire // arrayOrStringType was a string. - if (arrayType === neverType) { + if (arrayType.flags & 8192 /* Never */) { return stringType; } } @@ -31188,7 +37433,7 @@ var ts; if (func) { var signature = getSignatureFromDeclaration(func); var returnType = getReturnTypeOfSignature(signature); - if (strictNullChecks || node.expression || returnType === neverType) { + if (strictNullChecks || node.expression || returnType.flags & 8192 /* Never */) { var exprType = node.expression ? checkExpressionCached(node.expression) : undefinedType; if (func.asteriskToken) { // A generator does not need its return expressions checked against its return type. @@ -31232,12 +37477,17 @@ var ts; function checkWithStatement(node) { // Grammar checking for withStatement if (!checkGrammarStatementInAmbientContext(node)) { - if (node.flags & 33554432 /* AwaitContext */) { + if (node.flags & 262144 /* AwaitContext */) { grammarErrorOnFirstToken(node, ts.Diagnostics.with_statements_are_not_allowed_in_an_async_function_block); } } checkExpression(node.expression); - error(node.expression, ts.Diagnostics.All_symbols_within_a_with_block_will_be_resolved_to_any); + var sourceFile = ts.getSourceFileOfNode(node); + if (!hasParseDiagnostics(sourceFile)) { + var start = ts.getSpanOfTokenAtPosition(sourceFile, node.pos).start; + var end = node.statement.pos; + grammarErrorAtPos(sourceFile, start, end - start, ts.Diagnostics.The_with_statement_is_not_supported_All_symbols_in_a_with_block_will_have_type_any); + } } function checkSwitchStatement(node) { // Grammar checking @@ -31358,7 +37608,7 @@ var ts; // Only process instance properties with computed names here. // Static properties cannot be in conflict with indexers, // and properties with literal names were already checked. - if (!(member.flags & 32 /* Static */) && ts.hasDynamicName(member)) { + if (!(ts.getModifierFlags(member) & 32 /* Static */) && ts.hasDynamicName(member)) { var propType = getTypeOfSymbol(member.symbol); checkIndexConstraintForProperty(member.symbol, propType, type, declaredStringIndexer, stringIndexType, 0 /* String */); checkIndexConstraintForProperty(member.symbol, propType, type, declaredNumberIndexer, numberIndexType, 1 /* Number */); @@ -31467,7 +37717,7 @@ var ts; registerForUnusedIdentifiersCheck(node); } function checkClassDeclaration(node) { - if (!node.name && !(node.flags & 512 /* Default */)) { + if (!node.name && !(ts.getModifierFlags(node) & 512 /* Default */)) { grammarErrorOnFirstToken(node, ts.Diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name); } checkClassLikeDeclaration(node); @@ -31559,7 +37809,7 @@ var ts; var signatures = getSignaturesOfType(type, 1 /* Construct */); if (signatures.length) { var declaration = signatures[0].declaration; - if (declaration && declaration.flags & 8 /* Private */) { + if (declaration && ts.getModifierFlags(declaration) & 8 /* Private */) { var typeClassDeclaration = getClassLikeDeclarationOfSymbol(type.symbol); if (!isNodeWithinClass(node, typeClassDeclaration)) { error(node, ts.Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, node.expression.text); @@ -31598,7 +37848,7 @@ var ts; continue; } var derived = getTargetSymbol(getPropertyOfObjectType(type, base.name)); - var baseDeclarationFlags = getDeclarationFlagsFromSymbol(base); + var baseDeclarationFlags = getDeclarationModifierFlagsFromSymbol(base); ts.Debug.assert(!!derived, "derived should point to something, even if it is the base class' declaration."); if (derived) { // In order to resolve whether the inherited method was overridden in the base class or not, @@ -31610,7 +37860,7 @@ var ts; // It is an error to inherit an abstract member without implementing it or being declared abstract. // If there is no declaration for the derived class (as in the case of class expressions), // then the class cannot be declared abstract. - if (baseDeclarationFlags & 128 /* Abstract */ && (!derivedClassDecl || !(derivedClassDecl.flags & 128 /* Abstract */))) { + if (baseDeclarationFlags & 128 /* Abstract */ && (!derivedClassDecl || !(ts.getModifierFlags(derivedClassDecl) & 128 /* Abstract */))) { if (derivedClassDecl.kind === 192 /* ClassExpression */) { error(derivedClassDecl, ts.Diagnostics.Non_abstract_class_expression_does_not_implement_inherited_abstract_member_0_from_class_1, symbolToString(baseProperty), typeToString(baseType)); } @@ -31621,7 +37871,7 @@ var ts; } else { // derived overrides base. - var derivedDeclarationFlags = getDeclarationFlagsFromSymbol(derived); + var derivedDeclarationFlags = getDeclarationModifierFlagsFromSymbol(derived); if ((baseDeclarationFlags & 8 /* Private */) || (derivedDeclarationFlags & 8 /* Private */)) { // either base or derived property is private - not override, skip it continue; @@ -31700,8 +37950,8 @@ var ts; for (var _i = 0, baseTypes_2 = baseTypes; _i < baseTypes_2.length; _i++) { var base = baseTypes_2[_i]; var properties = getPropertiesOfObjectType(getTypeWithThisArgument(base, type.thisType)); - for (var _a = 0, properties_4 = properties; _a < properties_4.length; _a++) { - var prop = properties_4[_a]; + for (var _a = 0, properties_5 = properties; _a < properties_5.length; _a++) { + var prop = properties_5[_a]; var existing = seen[prop.name]; if (!existing) { seen[prop.name] = { prop: prop, containingType: base }; @@ -31779,7 +38029,7 @@ var ts; } else { var text = getTextOfPropertyName(member.name); - if (isNumericLiteralName(text)) { + if (isNumericLiteralName(text) && !isInfinityOrNaNString(text)) { error(member.name, ts.Diagnostics.An_enum_member_cannot_have_a_numeric_name); } } @@ -32134,9 +38384,9 @@ var ts; break; case 169 /* BindingElement */: case 218 /* VariableDeclaration */: - var name_19 = node.name; - if (ts.isBindingPattern(name_19)) { - for (var _b = 0, _c = name_19.elements; _b < _c.length; _b++) { + var name_22 = node.name; + if (ts.isBindingPattern(name_22)) { + for (var _b = 0, _c = name_22.elements; _b < _c.length; _b++) { var el = _c[_b]; // mark individual names in binding pattern checkModuleAugmentationElement(el, isGlobalAugmentation); @@ -32243,7 +38493,7 @@ var ts; // If we hit an import declaration in an illegal context, just bail out to avoid cascading errors. return; } - if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && (node.flags & 1023 /* Modifier */)) { + if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && ts.getModifierFlags(node) !== 0) { grammarErrorOnFirstToken(node, ts.Diagnostics.An_import_declaration_cannot_have_modifiers); } if (checkExternalImportOrExportDeclaration(node)) { @@ -32271,7 +38521,7 @@ var ts; checkGrammarDecorators(node) || checkGrammarModifiers(node); if (ts.isInternalModuleImportEqualsDeclaration(node) || checkExternalImportOrExportDeclaration(node)) { checkImportBinding(node); - if (node.flags & 1 /* Export */) { + if (ts.getModifierFlags(node) & 1 /* Export */) { markExportAsReferenced(node); } if (ts.isInternalModuleImportEqualsDeclaration(node)) { @@ -32302,7 +38552,7 @@ var ts; // If we hit an export in an illegal context, just bail out to avoid cascading errors. return; } - if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && (node.flags & 1023 /* Modifier */)) { + if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && ts.getModifierFlags(node) !== 0) { grammarErrorOnFirstToken(node, ts.Diagnostics.An_export_declaration_cannot_have_modifiers); } if (!node.moduleSpecifier || checkExternalImportOrExportDeclaration(node)) { @@ -32325,9 +38575,11 @@ var ts; } } function checkGrammarModuleElementContext(node, errorMessage) { - if (node.parent.kind !== 256 /* SourceFile */ && node.parent.kind !== 226 /* ModuleBlock */ && node.parent.kind !== 225 /* ModuleDeclaration */) { - return grammarErrorOnFirstToken(node, errorMessage); + var isInAppropriateContext = node.parent.kind === 256 /* SourceFile */ || node.parent.kind === 226 /* ModuleBlock */ || node.parent.kind === 225 /* ModuleDeclaration */; + if (!isInAppropriateContext) { + grammarErrorOnFirstToken(node, errorMessage); } + return !isInAppropriateContext; } function checkExportSpecifier(node) { checkAliasSymbol(node); @@ -32355,7 +38607,7 @@ var ts; return; } // Grammar checking - if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && (node.flags & 1023 /* Modifier */)) { + if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && ts.getModifierFlags(node) !== 0) { grammarErrorOnFirstToken(node, ts.Diagnostics.An_export_assignment_cannot_have_modifiers); } if (node.expression.kind === 69 /* Identifier */) { @@ -32671,7 +38923,7 @@ var ts; } function getSymbolsInScope(location, meaning) { var symbols = ts.createMap(); - var memberFlags = 0; + var memberFlags = 0 /* None */; if (isInsideWithStatementBody(location)) { // We cannot answer semantic questions within a with block, do not proceed any further return []; @@ -32721,7 +38973,7 @@ var ts; if (ts.introducesArgumentsExoticObject(location)) { copySymbol(argumentsSymbol, meaning); } - memberFlags = location.flags; + memberFlags = ts.getModifierFlags(location); location = location.parent; } copySymbols(globals, meaning); @@ -32857,7 +39109,7 @@ var ts; meaning |= 8388608 /* Alias */; return resolveEntityName(entityName, meaning); } - else if (ts.isExpression(entityName)) { + else if (ts.isPartOfExpression(entityName)) { if (ts.nodeIsMissing(entityName)) { // Missing entity name. return undefined; @@ -32940,7 +39192,7 @@ var ts; } // fallthrough case 95 /* SuperKeyword */: - var type = ts.isExpression(node) ? checkExpression(node) : getTypeFromTypeNode(node); + var type = ts.isPartOfExpression(node) ? checkExpression(node) : getTypeFromTypeNode(node); return type.symbol; case 165 /* ThisType */: return getTypeFromTypeNode(node).symbol; @@ -32995,10 +39247,10 @@ var ts; // We cannot answer semantic questions within a with block, do not proceed any further return unknownType; } - if (ts.isTypeNode(node)) { + if (ts.isPartOfTypeNode(node)) { return getTypeFromTypeNode(node); } - if (ts.isExpression(node)) { + if (ts.isPartOfExpression(node)) { return getTypeOfExpression(node); } if (ts.isExpressionWithTypeArgumentsInClassExtendsClause(node)) { @@ -33083,7 +39335,7 @@ var ts; if (ts.isRightSideOfQualifiedNameOrPropertyAccess(expr)) { expr = expr.parent; } - return checkExpression(expr); + return getRegularTypeOfLiteralType(checkExpression(expr)); } /** * Gets either the static or instance type of a class element, based on @@ -33091,7 +39343,7 @@ var ts; */ function getParentTypeOfClassElement(node) { var classSymbol = getSymbolOfNode(node.parent); - return node.flags & 32 /* Static */ + return ts.getModifierFlags(node) & 32 /* Static */ ? getTypeOfSymbol(classSymbol) : getDeclaredTypeOfSymbol(classSymbol); } @@ -33112,9 +39364,9 @@ var ts; function getRootSymbols(symbol) { if (symbol.flags & 268435456 /* SyntheticProperty */) { var symbols_3 = []; - var name_20 = symbol.name; + var name_23 = symbol.name; ts.forEach(getSymbolLinks(symbol).containingType.types, function (t) { - var symbol = getPropertyOfType(t, name_20); + var symbol = getPropertyOfType(t, name_23); if (symbol) { symbols_3.push(symbol); } @@ -33135,12 +39387,18 @@ var ts; } // Emitter support function isArgumentsLocalBinding(node) { - return getReferencedValueSymbol(node) === argumentsSymbol; + if (!ts.isGeneratedIdentifier(node)) { + node = ts.getParseTreeNode(node, ts.isIdentifier); + if (node) { + return getReferencedValueSymbol(node) === argumentsSymbol; + } + } + return false; } function moduleExportsSomeValue(moduleReferenceExpression) { var moduleSymbol = resolveExternalModuleName(moduleReferenceExpression.parent, moduleReferenceExpression); - if (!moduleSymbol) { - // module not found - be conservative + if (!moduleSymbol || ts.isShorthandAmbientModuleSymbol(moduleSymbol)) { + // If the module is not found or is shorthand, assume that it may export a value. return true; } var hasExportAssignment = hasExportAssignmentSymbol(moduleSymbol); @@ -33161,32 +39419,44 @@ var ts; return s && !!(s.flags & 107455 /* Value */); } } + function isNameOfModuleOrEnumDeclaration(node) { + var parent = node.parent; + return ts.isModuleOrEnumDeclaration(parent) && node === parent.name; + } // When resolved as an expression identifier, if the given node references an exported entity, return the declaration // node of the exported entity's container. Otherwise, return undefined. - function getReferencedExportContainer(node) { - var symbol = getReferencedValueSymbol(node); - if (symbol) { - if (symbol.flags & 1048576 /* ExportValue */) { - // If we reference an exported entity within the same module declaration, then whether - // we prefix depends on the kind of entity. SymbolFlags.ExportHasLocal encompasses all the - // kinds that we do NOT prefix. - var exportSymbol = getMergedSymbol(symbol.exportSymbol); - if (exportSymbol.flags & 944 /* ExportHasLocal */) { - return undefined; - } - symbol = exportSymbol; - } - var parentSymbol = getParentOfSymbol(symbol); - if (parentSymbol) { - if (parentSymbol.flags & 512 /* ValueModule */ && parentSymbol.valueDeclaration.kind === 256 /* SourceFile */) { - // If `node` accesses an export and that export isn't in the same file, then symbol is a namespace export, so return undefined. - if (parentSymbol.valueDeclaration === ts.getSourceFileOfNode(node)) { - return parentSymbol.valueDeclaration; + function getReferencedExportContainer(node, prefixLocals) { + node = ts.getParseTreeNode(node, ts.isIdentifier); + if (node) { + // When resolving the export container for the name of a module or enum + // declaration, we need to start resolution at the declaration's container. + // Otherwise, we could incorrectly resolve the export container as the + // declaration if it contains an exported member with the same name. + var symbol = getReferencedValueSymbol(node, /*startInDeclarationContainer*/ isNameOfModuleOrEnumDeclaration(node)); + if (symbol) { + if (symbol.flags & 1048576 /* ExportValue */) { + // If we reference an exported entity within the same module declaration, then whether + // we prefix depends on the kind of entity. SymbolFlags.ExportHasLocal encompasses all the + // kinds that we do NOT prefix. + var exportSymbol = getMergedSymbol(symbol.exportSymbol); + if (!prefixLocals && exportSymbol.flags & 944 /* ExportHasLocal */) { + return undefined; } + symbol = exportSymbol; } - for (var n = node.parent; n; n = n.parent) { - if ((n.kind === 225 /* ModuleDeclaration */ || n.kind === 224 /* EnumDeclaration */) && getSymbolOfNode(n) === parentSymbol) { - return n; + var parentSymbol = getParentOfSymbol(symbol); + if (parentSymbol) { + if (parentSymbol.flags & 512 /* ValueModule */ && parentSymbol.valueDeclaration.kind === 256 /* SourceFile */) { + var symbolFile = parentSymbol.valueDeclaration; + var referenceFile = ts.getSourceFileOfNode(node); + // If `node` accesses an export and that export isn't in the same file, then symbol is a namespace export, so return undefined. + var symbolIsUmdExport = symbolFile !== referenceFile; + return symbolIsUmdExport ? undefined : symbolFile; + } + for (var n = node.parent; n; n = n.parent) { + if (ts.isModuleOrEnumDeclaration(n) && getSymbolOfNode(n) === parentSymbol) { + return n; + } } } } @@ -33195,8 +39465,14 @@ var ts; // When resolved as an expression identifier, if the given node references an import, return the declaration of // that import. Otherwise, return undefined. function getReferencedImportDeclaration(node) { - var symbol = getReferencedValueSymbol(node); - return symbol && symbol.flags & 8388608 /* Alias */ ? getDeclarationOfAliasSymbol(symbol) : undefined; + node = ts.getParseTreeNode(node, ts.isIdentifier); + if (node) { + var symbol = getReferencedValueSymbol(node); + if (symbol && symbol.flags & 8388608 /* Alias */) { + return getDeclarationOfAliasSymbol(symbol); + } + } + return undefined; } function isSymbolOfDeclarationWithCollidingName(symbol) { if (symbol.flags & 418 /* BlockScoped */) { @@ -33243,32 +39519,56 @@ var ts; // a name that either hides an existing name or might hide it when compiled downlevel, // return the declaration of that entity. Otherwise, return undefined. function getReferencedDeclarationWithCollidingName(node) { - var symbol = getReferencedValueSymbol(node); - return symbol && isSymbolOfDeclarationWithCollidingName(symbol) ? symbol.valueDeclaration : undefined; + if (!ts.isGeneratedIdentifier(node)) { + node = ts.getParseTreeNode(node, ts.isIdentifier); + if (node) { + var symbol = getReferencedValueSymbol(node); + if (symbol && isSymbolOfDeclarationWithCollidingName(symbol)) { + return symbol.valueDeclaration; + } + } + } + return undefined; } // Return true if the given node is a declaration of a nested block scoped entity with a name that either hides an // existing name or might hide a name when compiled downlevel function isDeclarationWithCollidingName(node) { - return isSymbolOfDeclarationWithCollidingName(getSymbolOfNode(node)); + node = ts.getParseTreeNode(node, ts.isDeclaration); + if (node) { + var symbol = getSymbolOfNode(node); + if (symbol) { + return isSymbolOfDeclarationWithCollidingName(symbol); + } + } + return false; } function isValueAliasDeclaration(node) { + node = ts.getParseTreeNode(node); + if (node === undefined) { + // A synthesized node comes from an emit transformation and is always a value. + return true; + } switch (node.kind) { case 229 /* ImportEqualsDeclaration */: case 231 /* ImportClause */: case 232 /* NamespaceImport */: case 234 /* ImportSpecifier */: case 238 /* ExportSpecifier */: - return isAliasResolvedToValue(getSymbolOfNode(node)); + return isAliasResolvedToValue(getSymbolOfNode(node) || unknownSymbol); case 236 /* ExportDeclaration */: var exportClause = node.exportClause; return exportClause && ts.forEach(exportClause.elements, isValueAliasDeclaration); case 235 /* ExportAssignment */: - return node.expression && node.expression.kind === 69 /* Identifier */ ? isAliasResolvedToValue(getSymbolOfNode(node)) : true; + return node.expression + && node.expression.kind === 69 /* Identifier */ + ? isAliasResolvedToValue(getSymbolOfNode(node) || unknownSymbol) + : true; } return false; } function isTopLevelValueImportEqualsWithEntityName(node) { - if (node.parent.kind !== 256 /* SourceFile */ || !ts.isInternalModuleImportEqualsDeclaration(node)) { + node = ts.getParseTreeNode(node, ts.isImportEqualsDeclaration); + if (node === undefined || node.parent.kind !== 256 /* SourceFile */ || !ts.isInternalModuleImportEqualsDeclaration(node)) { // parent is not source file or it is not reference to internal module return false; } @@ -33289,9 +39589,14 @@ var ts; return isConstEnumSymbol(s) || s.constEnumOnlyModule; } function isReferencedAliasDeclaration(node, checkChildren) { + node = ts.getParseTreeNode(node); + // Purely synthesized nodes are always emitted. + if (node === undefined) { + return true; + } if (ts.isAliasSymbolDeclaration(node)) { var symbol = getSymbolOfNode(node); - if (getSymbolLinks(symbol).referenced) { + if (symbol && getSymbolLinks(symbol).referenced) { return true; } } @@ -33321,7 +39626,8 @@ var ts; return false; } function getNodeCheckFlags(node) { - return getNodeLinks(node).flags; + node = ts.getParseTreeNode(node); + return node ? getNodeLinks(node).flags : undefined; } function getEnumMemberValue(node) { computeEnumMemberValues(node.parent); @@ -33343,15 +39649,19 @@ var ts; function isFunctionType(type) { return type.flags & 2588672 /* ObjectType */ && getSignaturesOfType(type, 0 /* Call */).length > 0; } - function getTypeReferenceSerializationKind(typeName) { + function getTypeReferenceSerializationKind(typeName, location) { // Resolve the symbol as a value to ensure the type can be reached at runtime during emit. - var valueSymbol = resolveEntityName(typeName, 107455 /* Value */, /*ignoreErrors*/ true); + var valueSymbol = resolveEntityName(typeName, 107455 /* Value */, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, location); + var globalPromiseSymbol = tryGetGlobalPromiseConstructorSymbol(); + if (globalPromiseSymbol && valueSymbol === globalPromiseSymbol) { + return ts.TypeReferenceSerializationKind.Promise; + } var constructorType = valueSymbol ? getTypeOfSymbol(valueSymbol) : undefined; if (constructorType && isConstructorType(constructorType)) { return ts.TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue; } // Resolve the symbol as a type so that we can provide a more useful hint for the type serializer. - var typeSymbol = resolveEntityName(typeName, 793064 /* Type */, /*ignoreErrors*/ true); + var typeSymbol = resolveEntityName(typeName, 793064 /* Type */, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, location); // We might not be able to resolve type symbol so use unknown type in that case (eg error case) if (!typeSymbol) { return ts.TypeReferenceSerializationKind.ObjectType; @@ -33363,8 +39673,8 @@ var ts; else if (type.flags & 1 /* Any */) { return ts.TypeReferenceSerializationKind.ObjectType; } - else if (isTypeOfKind(type, 1024 /* Void */)) { - return ts.TypeReferenceSerializationKind.VoidType; + else if (isTypeOfKind(type, 1024 /* Void */ | 6144 /* Nullable */ | 8192 /* Never */)) { + return ts.TypeReferenceSerializationKind.VoidNullableOrNeverType; } else if (isTypeOfKind(type, 136 /* BooleanLike */)) { return ts.TypeReferenceSerializationKind.BooleanType; @@ -33395,7 +39705,7 @@ var ts; // Get type of the symbol if this is the valid symbol otherwise get type at location var symbol = getSymbolOfNode(declaration); var type = symbol && !(symbol.flags & (2048 /* TypeLiteral */ | 131072 /* Signature */)) - ? getTypeOfSymbol(symbol) + ? getWidenedLiteralType(getTypeOfSymbol(symbol)) : unknownType; getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags); } @@ -33416,15 +39726,44 @@ var ts; function hasGlobalName(name) { return !!globals[name]; } - function getReferencedValueSymbol(reference) { - return getNodeLinks(reference).resolvedSymbol || - resolveName(reference, reference.text, 107455 /* Value */ | 1048576 /* ExportValue */ | 8388608 /* Alias */, - /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined); + function getReferencedValueSymbol(reference, startInDeclarationContainer) { + var resolvedSymbol = getNodeLinks(reference).resolvedSymbol; + if (resolvedSymbol) { + return resolvedSymbol; + } + var location = reference; + if (startInDeclarationContainer) { + // When resolving the name of a declaration as a value, we need to start resolution + // at a point outside of the declaration. + var parent_14 = reference.parent; + if (ts.isDeclaration(parent_14) && reference === parent_14.name) { + location = getDeclarationContainer(parent_14); + } + } + return resolveName(location, reference.text, 107455 /* Value */ | 1048576 /* ExportValue */ | 8388608 /* Alias */, /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined); } function getReferencedValueDeclaration(reference) { - ts.Debug.assert(!ts.nodeIsSynthesized(reference)); - var symbol = getReferencedValueSymbol(reference); - return symbol && getExportSymbolOfValueSymbolIfExported(symbol).valueDeclaration; + if (!ts.isGeneratedIdentifier(reference)) { + reference = ts.getParseTreeNode(reference, ts.isIdentifier); + if (reference) { + var symbol = getReferencedValueSymbol(reference); + if (symbol) { + return getExportSymbolOfValueSymbolIfExported(symbol).valueDeclaration; + } + } + } + return undefined; + } + function isLiteralConstDeclaration(node) { + if (ts.isConst(node)) { + var type = getTypeOfSymbol(getSymbolOfNode(node)); + return !!(type.flags & 96 /* StringOrNumberLiteral */ && type.flags & 16777216 /* FreshLiteral */); + } + return false; + } + function writeLiteralConstValue(node, writer) { + var type = getTypeOfSymbol(getSymbolOfNode(node)); + writer.writeStringLiteral(literalTypeToString(type)); } function createResolver() { // this variable and functions that use it are deliberately moved here from the outer scope @@ -33470,7 +39809,9 @@ var ts; isArgumentsLocalBinding: isArgumentsLocalBinding, getExternalModuleFileFromDeclaration: getExternalModuleFileFromDeclaration, getTypeReferenceDirectivesForEntityName: getTypeReferenceDirectivesForEntityName, - getTypeReferenceDirectivesForSymbol: getTypeReferenceDirectivesForSymbol + getTypeReferenceDirectivesForSymbol: getTypeReferenceDirectivesForSymbol, + isLiteralConstDeclaration: isLiteralConstDeclaration, + writeLiteralConstValue: writeLiteralConstValue }; // defined here to avoid outer scope pollution function getTypeReferenceDirectivesForEntityName(node) { @@ -33520,9 +39861,9 @@ var ts; // external modules cannot define or contribute to type declaration files var current = symbol; while (true) { - var parent_12 = getParentOfSymbol(current); - if (parent_12) { - current = parent_12; + var parent_15 = getParentOfSymbol(current); + if (parent_15) { + current = parent_15; } else { break; @@ -33552,12 +39893,16 @@ var ts; } function initializeTypeChecker() { // Bind all source files and propagate errors - ts.forEach(host.getSourceFiles(), function (file) { + for (var _i = 0, _a = host.getSourceFiles(); _i < _a.length; _i++) { + var file = _a[_i]; ts.bindSourceFile(file, compilerOptions); - }); - var augmentations; + } // Initialize global symbol table - ts.forEach(host.getSourceFiles(), function (file) { + var augmentations; + var requestedExternalEmitHelpers = 0; + var firstFileRequestingExternalHelpers; + for (var _b = 0, _c = host.getSourceFiles(); _b < _c.length; _b++) { + var file = _c[_b]; if (!ts.isExternalOrCommonJsModule(file)) { mergeSymbolTable(globals, file.locals); } @@ -33576,14 +39921,23 @@ var ts; } } } - }); + if ((compilerOptions.isolatedModules || ts.isExternalModule(file)) && !file.isDeclarationFile) { + var fileRequestedExternalEmitHelpers = file.flags & 31744 /* EmitHelperFlags */; + if (fileRequestedExternalEmitHelpers) { + requestedExternalEmitHelpers |= fileRequestedExternalEmitHelpers; + if (firstFileRequestingExternalHelpers === undefined) { + firstFileRequestingExternalHelpers = file; + } + } + } + } if (augmentations) { // merge module augmentations. // this needs to be done after global symbol table is initialized to make sure that all ambient modules are indexed - for (var _i = 0, augmentations_1 = augmentations; _i < augmentations_1.length; _i++) { - var list = augmentations_1[_i]; - for (var _a = 0, list_1 = list; _a < list_1.length; _a++) { - var augmentation = list_1[_a]; + for (var _d = 0, augmentations_1 = augmentations; _d < augmentations_1.length; _d++) { + var list = augmentations_1[_d]; + for (var _e = 0, list_1 = list; _e < list_1.length; _e++) { + var augmentation = list_1[_e]; mergeModuleAugmentation(augmentation); } } @@ -33613,6 +39967,7 @@ var ts; getGlobalPromiseLikeType = ts.memoize(function () { return getGlobalType("PromiseLike", /*arity*/ 1); }); getInstantiatedGlobalPromiseLikeType = ts.memoize(createInstantiatedPromiseLikeType); getGlobalPromiseConstructorSymbol = ts.memoize(function () { return getGlobalValueSymbol("Promise"); }); + tryGetGlobalPromiseConstructorSymbol = ts.memoize(function () { return getGlobalSymbol("Promise", 107455 /* Value */, /*diagnostic*/ undefined) && getGlobalPromiseConstructorSymbol(); }); getGlobalPromiseConstructorLikeType = ts.memoize(function () { return getGlobalType("PromiseConstructorLike"); }); getGlobalThenableType = ts.memoize(createThenableType); getGlobalTemplateStringsArrayType = ts.memoize(function () { return getGlobalType("TemplateStringsArray"); }); @@ -33632,6 +39987,45 @@ var ts; var symbol = getGlobalSymbol("ReadonlyArray", 793064 /* Type */, /*diagnostic*/ undefined); globalReadonlyArrayType = symbol && getTypeOfGlobalSymbol(symbol, /*arity*/ 1); anyReadonlyArrayType = globalReadonlyArrayType ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType; + // If we have specified that we are importing helpers, we should report global + // errors if we cannot resolve the helpers external module, or if it does not have + // the necessary helpers exported. + if (compilerOptions.importHelpers && firstFileRequestingExternalHelpers) { + // Find the first reference to the helpers module. + var helpersModule = resolveExternalModule(firstFileRequestingExternalHelpers, ts.externalHelpersModuleNameText, ts.Diagnostics.Cannot_find_module_0, + /*errorNode*/ undefined); + // If we found the module, report errors if it does not have the necessary exports. + if (helpersModule) { + var exports = helpersModule.exports; + if (requestedExternalEmitHelpers & 1024 /* HasClassExtends */ && languageVersion < 2 /* ES6 */) { + verifyHelperSymbol(exports, "__extends", 107455 /* Value */); + } + if (requestedExternalEmitHelpers & 16384 /* HasJsxSpreadAttributes */ && compilerOptions.jsx !== 1 /* Preserve */) { + verifyHelperSymbol(exports, "__assign", 107455 /* Value */); + } + if (requestedExternalEmitHelpers & 2048 /* HasDecorators */) { + verifyHelperSymbol(exports, "__decorate", 107455 /* Value */); + if (compilerOptions.emitDecoratorMetadata) { + verifyHelperSymbol(exports, "__metadata", 107455 /* Value */); + } + } + if (requestedExternalEmitHelpers & 4096 /* HasParamDecorators */) { + verifyHelperSymbol(exports, "__param", 107455 /* Value */); + } + if (requestedExternalEmitHelpers & 8192 /* HasAsyncFunctions */) { + verifyHelperSymbol(exports, "__awaiter", 107455 /* Value */); + if (languageVersion < 2 /* ES6 */) { + verifyHelperSymbol(exports, "__generator", 107455 /* Value */); + } + } + } + } + } + function verifyHelperSymbol(symbols, name, meaning) { + var symbol = getSymbol(symbols, ts.escapeIdentifier(name), meaning); + if (!symbol) { + error(/*location*/ undefined, ts.Diagnostics.Module_0_has_no_exported_member_1, ts.externalHelpersModuleNameText, name); + } } function createInstantiatedPromiseLikeType() { var promiseLikeType = getGlobalPromiseLikeType(); @@ -33678,7 +40072,7 @@ var ts; return quickResult; } var lastStatic, lastPrivate, lastProtected, lastDeclare, lastAsync, lastReadonly; - var flags = 0; + var flags = 0 /* None */; for (var _i = 0, _a = node.modifiers; _i < _a.length; _i++) { var modifier = _a[_i]; if (modifier.kind !== 128 /* ReadonlyKeyword */) { @@ -33814,7 +40208,7 @@ var ts; node.kind !== 150 /* SetAccessor */) { return grammarErrorOnNode(modifier, ts.Diagnostics.abstract_modifier_can_only_appear_on_a_class_method_or_property_declaration); } - if (!(node.parent.kind === 221 /* ClassDeclaration */ && node.parent.flags & 128 /* Abstract */)) { + if (!(node.parent.kind === 221 /* ClassDeclaration */ && ts.getModifierFlags(node.parent) & 128 /* Abstract */)) { return grammarErrorOnNode(modifier, ts.Diagnostics.Abstract_methods_can_only_appear_within_an_abstract_class); } if (flags & 32 /* Static */) { @@ -33924,9 +40318,6 @@ var ts; return node.modifiers.length > 1 || node.modifiers[0].kind !== allowedModifier; } function checkGrammarAsyncModifier(node, asyncModifier) { - if (languageVersion < 2 /* ES6 */) { - return grammarErrorOnNode(asyncModifier, ts.Diagnostics.Async_functions_are_only_available_when_targeting_ECMAScript_2015_or_higher); - } switch (node.kind) { case 147 /* MethodDeclaration */: case 220 /* FunctionDeclaration */: @@ -34017,7 +40408,7 @@ var ts; if (parameter.dotDotDotToken) { return grammarErrorOnNode(parameter.dotDotDotToken, ts.Diagnostics.An_index_signature_cannot_have_a_rest_parameter); } - if (parameter.flags & 1023 /* Modifier */) { + if (ts.getModifierFlags(parameter) !== 0) { return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_cannot_have_an_accessibility_modifier); } if (parameter.questionToken) { @@ -34055,8 +40446,8 @@ var ts; function checkGrammarForOmittedArgument(node, args) { if (args) { var sourceFile = ts.getSourceFileOfNode(node); - for (var _i = 0, args_1 = args; _i < args_1.length; _i++) { - var arg = args_1[_i]; + for (var _i = 0, args_4 = args; _i < args_4.length; _i++) { + var arg = args_4[_i]; if (arg.kind === 193 /* OmittedExpression */) { return grammarErrorAtPos(sourceFile, arg.pos, 0, ts.Diagnostics.Argument_expression_expected); } @@ -34165,24 +40556,28 @@ var ts; var GetAccessor = 2; var SetAccessor = 4; var GetOrSetAccessor = GetAccessor | SetAccessor; - var _loop_2 = function(prop) { - var name_21 = prop.name; + for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { + var prop = _a[_i]; + var name_24 = prop.name; if (prop.kind === 193 /* OmittedExpression */ || - name_21.kind === 140 /* ComputedPropertyName */) { + name_24.kind === 140 /* ComputedPropertyName */) { // If the name is not a ComputedPropertyName, the grammar checking will skip it - checkGrammarComputedPropertyName(name_21); + checkGrammarComputedPropertyName(name_24); } if (prop.kind === 254 /* ShorthandPropertyAssignment */ && !inDestructuring && prop.objectAssignmentInitializer) { // having objectAssignmentInitializer is only valid in ObjectAssignmentPattern // outside of destructuring it is a syntax error - return { value: grammarErrorOnNode(prop.equalsToken, ts.Diagnostics.can_only_be_used_in_an_object_literal_property_inside_a_destructuring_assignment) }; + return grammarErrorOnNode(prop.equalsToken, ts.Diagnostics.can_only_be_used_in_an_object_literal_property_inside_a_destructuring_assignment); } // Modifiers are never allowed on properties except for 'async' on a method declaration - ts.forEach(prop.modifiers, function (mod) { - if (mod.kind !== 118 /* AsyncKeyword */ || prop.kind !== 147 /* MethodDeclaration */) { - grammarErrorOnNode(mod, ts.Diagnostics._0_modifier_cannot_be_used_here, ts.getTextOfNode(mod)); + if (prop.modifiers) { + for (var _b = 0, _c = prop.modifiers; _b < _c.length; _b++) { + var mod = _c[_b]; + if (mod.kind !== 118 /* AsyncKeyword */ || prop.kind !== 147 /* MethodDeclaration */) { + grammarErrorOnNode(mod, ts.Diagnostics._0_modifier_cannot_be_used_here, ts.getTextOfNode(mod)); + } } - }); + } // ECMA-262 11.1.5 Object Initializer // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true // a.This production is contained in strict code and IsDataDescriptor(previous) is true and @@ -34195,8 +40590,8 @@ var ts; if (prop.kind === 253 /* PropertyAssignment */ || prop.kind === 254 /* ShorthandPropertyAssignment */) { // Grammar checking for computedPropertyName and shorthandPropertyAssignment checkGrammarForInvalidQuestionMark(prop, prop.questionToken, ts.Diagnostics.An_object_member_cannot_be_declared_optional); - if (name_21.kind === 8 /* NumericLiteral */) { - checkGrammarNumericLiteral(name_21); + if (name_24.kind === 8 /* NumericLiteral */) { + checkGrammarNumericLiteral(name_24); } currentKind = Property; } @@ -34212,9 +40607,9 @@ var ts; else { ts.Debug.fail("Unexpected syntax kind:" + prop.kind); } - var effectiveName = ts.getPropertyNameForPropertyNameNode(name_21); + var effectiveName = ts.getPropertyNameForPropertyNameNode(name_24); if (effectiveName === undefined) { - return "continue"; + continue; } if (!seen[effectiveName]) { seen[effectiveName] = currentKind; @@ -34222,25 +40617,20 @@ var ts; else { var existingKind = seen[effectiveName]; if (currentKind === Property && existingKind === Property) { - grammarErrorOnNode(name_21, ts.Diagnostics.Duplicate_identifier_0, ts.getTextOfNode(name_21)); + grammarErrorOnNode(name_24, ts.Diagnostics.Duplicate_identifier_0, ts.getTextOfNode(name_24)); } else if ((currentKind & GetOrSetAccessor) && (existingKind & GetOrSetAccessor)) { if (existingKind !== GetOrSetAccessor && currentKind !== existingKind) { seen[effectiveName] = currentKind | existingKind; } else { - return { value: grammarErrorOnNode(name_21, ts.Diagnostics.An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name) }; + return grammarErrorOnNode(name_24, ts.Diagnostics.An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name); } } else { - return { value: grammarErrorOnNode(name_21, ts.Diagnostics.An_object_literal_cannot_have_property_and_accessor_with_the_same_name) }; + return grammarErrorOnNode(name_24, ts.Diagnostics.An_object_literal_cannot_have_property_and_accessor_with_the_same_name); } } - }; - for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { - var prop = _a[_i]; - var state_3 = _loop_2(prop); - if (typeof state_3 === "object") return state_3.value; } } function checkGrammarJsxElement(node) { @@ -34251,12 +40641,12 @@ var ts; continue; } var jsxAttr = attr; - var name_22 = jsxAttr.name; - if (!seen[name_22.text]) { - seen[name_22.text] = true; + var name_25 = jsxAttr.name; + if (!seen[name_25.text]) { + seen[name_25.text] = true; } else { - return grammarErrorOnNode(name_22, ts.Diagnostics.JSX_elements_cannot_have_multiple_attributes_with_the_same_name); + return grammarErrorOnNode(name_25, ts.Diagnostics.JSX_elements_cannot_have_multiple_attributes_with_the_same_name); } var initializer = jsxAttr.initializer; if (initializer && initializer.kind === 248 /* JsxExpression */ && !initializer.expression) { @@ -34313,7 +40703,7 @@ var ts; else if (ts.isInAmbientContext(accessor)) { return grammarErrorOnNode(accessor.name, ts.Diagnostics.An_accessor_cannot_be_declared_in_an_ambient_context); } - else if (accessor.body === undefined && !(accessor.flags & 128 /* Abstract */)) { + else if (accessor.body === undefined && !(ts.getModifierFlags(accessor) & 128 /* Abstract */)) { return grammarErrorAtPos(ts.getSourceFileOfNode(accessor), accessor.end - 1, ";".length, ts.Diagnostics._0_expected, "{"); } else if (accessor.typeParameters) { @@ -34464,10 +40854,27 @@ var ts; } } } + function isStringOrNumberLiteralExpression(expr) { + return expr.kind === 9 /* StringLiteral */ || expr.kind === 8 /* NumericLiteral */ || + expr.kind === 185 /* PrefixUnaryExpression */ && expr.operator === 36 /* MinusToken */ && + expr.operand.kind === 8 /* NumericLiteral */; + } function checkGrammarVariableDeclaration(node) { if (node.parent.parent.kind !== 207 /* ForInStatement */ && node.parent.parent.kind !== 208 /* ForOfStatement */) { if (ts.isInAmbientContext(node)) { if (node.initializer) { + if (ts.isConst(node) && !node.type) { + if (!isStringOrNumberLiteralExpression(node.initializer)) { + return grammarErrorOnNode(node.initializer, ts.Diagnostics.A_const_initializer_in_an_ambient_context_must_be_a_string_or_numeric_literal); + } + } + else { + // Error on equals token which immediate precedes the initializer + var equalsTokenLength = "=".length; + return grammarErrorAtPos(ts.getSourceFileOfNode(node), node.initializer.pos - equalsTokenLength, equalsTokenLength, ts.Diagnostics.Initializers_are_not_allowed_in_ambient_contexts); + } + } + if (node.initializer && !(ts.isConst(node) && isStringOrNumberLiteralExpression(node.initializer))) { // Error on equals token which immediate precedes the initializer var equalsTokenLength = "=".length; return grammarErrorAtPos(ts.getSourceFileOfNode(node), node.initializer.pos - equalsTokenLength, equalsTokenLength, ts.Diagnostics.Initializers_are_not_allowed_in_ambient_contexts); @@ -34501,7 +40908,7 @@ var ts; var elements = name.elements; for (var _i = 0, elements_2 = elements; _i < elements_2.length; _i++) { var element = elements_2[_i]; - if (element.kind !== 193 /* OmittedExpression */) { + if (!ts.isOmittedExpression(element)) { checkGrammarNameInLetOrConstDeclarations(element.name); } } @@ -34547,8 +40954,8 @@ var ts; function grammarErrorOnFirstToken(node, message, arg0, arg1, arg2) { var sourceFile = ts.getSourceFileOfNode(node); if (!hasParseDiagnostics(sourceFile)) { - var span = ts.getSpanOfTokenAtPosition(sourceFile, node.pos); - diagnostics.add(ts.createFileDiagnostic(sourceFile, span.start, span.length, message, arg0, arg1, arg2)); + var span_4 = ts.getSpanOfTokenAtPosition(sourceFile, node.pos); + diagnostics.add(ts.createFileDiagnostic(sourceFile, span_4.start, span_4.length, message, arg0, arg1, arg2)); return true; } } @@ -34621,8 +41028,7 @@ var ts; node.kind === 236 /* ExportDeclaration */ || node.kind === 235 /* ExportAssignment */ || node.kind === 228 /* NamespaceExportDeclaration */ || - (node.flags & 2 /* Ambient */) || - (node.flags & (1 /* Export */ | 512 /* Default */))) { + ts.getModifierFlags(node) & (2 /* Ambient */ | 1 /* Export */ | 512 /* Default */)) { return false; } return grammarErrorOnFirstToken(node, ts.Diagnostics.A_declare_modifier_is_required_for_a_top_level_declaration_in_a_d_ts_file); @@ -34676,11 +41082,20 @@ var ts; function grammarErrorAfterFirstToken(node, message, arg0, arg1, arg2) { var sourceFile = ts.getSourceFileOfNode(node); if (!hasParseDiagnostics(sourceFile)) { - var span = ts.getSpanOfTokenAtPosition(sourceFile, node.pos); - diagnostics.add(ts.createFileDiagnostic(sourceFile, ts.textSpanEnd(span), /*length*/ 0, message, arg0, arg1, arg2)); + var span_5 = ts.getSpanOfTokenAtPosition(sourceFile, node.pos); + diagnostics.add(ts.createFileDiagnostic(sourceFile, ts.textSpanEnd(span_5), /*length*/ 0, message, arg0, arg1, arg2)); return true; } } + function getAmbientModules() { + var result = []; + for (var sym in globals) { + if (ambientModuleSymbolRegex.test(sym)) { + result.push(globals[sym]); + } + } + return result; + } } ts.createTypeChecker = createTypeChecker; })(ts || (ts = {})); @@ -34691,12 +41106,15 @@ var ts; /// var ts; (function (ts) { + /* @internal */ + ts.compileOnSaveCommandLineOption = { name: "compileOnSave", type: "boolean" }; /* @internal */ ts.optionDeclarations = [ { name: "charset", type: "string", }, + ts.compileOnSaveCommandLineOption, { name: "declaration", shortName: "d", @@ -34716,6 +41134,7 @@ var ts; { name: "extendedDiagnostics", type: "boolean", + experimental: true }, { name: "emitBOM", @@ -34979,6 +41398,7 @@ var ts; "classic": ts.ModuleResolutionKind.Classic, }), description: ts.Diagnostics.Specify_module_resolution_strategy_Colon_node_Node_js_or_classic_TypeScript_pre_1_6, + paramType: ts.Diagnostics.STRATEGY, }, { name: "allowUnusedLabels", @@ -35092,6 +41512,7 @@ var ts; "es2017": "lib.es2017.d.ts", // Host only "dom": "lib.dom.d.ts", + "dom.iterable": "lib.dom.iterable.d.ts", "webworker": "lib.webworker.d.ts", "scripthost": "lib.scripthost.d.ts", // ES2015 Or ESNext By-feature options @@ -35119,6 +41540,11 @@ var ts; name: "strictNullChecks", type: "boolean", description: ts.Diagnostics.Enable_strict_null_checks + }, + { + name: "importHelpers", + type: "boolean", + description: ts.Diagnostics.Import_emit_helpers_from_tslib } ]; /* @internal */ @@ -35339,10 +41765,11 @@ var ts; * @param fileName The path to the config file * @param jsonText The text of the config file */ - function parseConfigFileTextToJson(fileName, jsonText) { + function parseConfigFileTextToJson(fileName, jsonText, stripComments) { + if (stripComments === void 0) { stripComments = true; } try { - var jsonTextWithoutComments = removeComments(jsonText); - return { config: /\S/.test(jsonTextWithoutComments) ? JSON.parse(jsonTextWithoutComments) : {} }; + var jsonTextToParse = stripComments ? removeComments(jsonText) : jsonText; + return { config: /\S/.test(jsonTextToParse) ? JSON.parse(jsonTextToParse) : {} }; } catch (e) { return { error: ts.createCompilerDiagnostic(ts.Diagnostics.Failed_to_parse_file_0_Colon_1, fileName, e.message) }; @@ -35389,11 +41816,11 @@ var ts; function serializeCompilerOptions(options) { var result = ts.createMap(); var optionsNameMap = getOptionNameMap().optionNameMap; - for (var name_23 in options) { - if (ts.hasProperty(options, name_23)) { + for (var name_26 in options) { + if (ts.hasProperty(options, name_26)) { // tsconfig only options cannot be specified via command line, // so we can assume that only types that can appear here string | number | boolean - switch (name_23) { + switch (name_26) { case "init": case "watch": case "version": @@ -35401,14 +41828,14 @@ var ts; case "project": break; default: - var value = options[name_23]; - var optionDefinition = optionsNameMap[name_23.toLowerCase()]; + var value = options[name_26]; + var optionDefinition = optionsNameMap[name_26.toLowerCase()]; if (optionDefinition) { var customTypeMap = getCustomTypeMapOfCommandLineOption(optionDefinition); if (!customTypeMap) { // There is no map associated with this compiler option then use the value as-is // This is the case if the value is expect to be string, number, boolean or list of string - result[name_23] = value; + result[name_26] = value; } else { if (optionDefinition.type === "list") { @@ -35417,11 +41844,11 @@ var ts; var element = _a[_i]; convertedValue.push(getNameOfCompilerOptionValue(element, customTypeMap)); } - result[name_23] = convertedValue; + result[name_26] = convertedValue; } else { // There is a typeMap associated with this command-line option so use it to map value back to its name - result[name_23] = getNameOfCompilerOptionValue(value, customTypeMap); + result[name_26] = getNameOfCompilerOptionValue(value, customTypeMap); } } } @@ -35464,22 +41891,88 @@ var ts; * @param basePath A root directory to resolve relative path entries in the config * file to. e.g. outDir */ - function parseJsonConfigFileContent(json, host, basePath, existingOptions, configFileName) { + function parseJsonConfigFileContent(json, host, basePath, existingOptions, configFileName, resolutionStack) { if (existingOptions === void 0) { existingOptions = {}; } + if (resolutionStack === void 0) { resolutionStack = []; } var errors = []; - var compilerOptions = convertCompilerOptionsFromJsonWorker(json["compilerOptions"], basePath, errors, configFileName); - var options = ts.extend(existingOptions, compilerOptions); + var getCanonicalFileName = ts.createGetCanonicalFileName(host.useCaseSensitiveFileNames); + var resolvedPath = ts.toPath(configFileName || "", basePath, getCanonicalFileName); + if (resolutionStack.indexOf(resolvedPath) >= 0) { + return { + options: {}, + fileNames: [], + typingOptions: {}, + raw: json, + errors: [ts.createCompilerDiagnostic(ts.Diagnostics.Circularity_detected_while_resolving_configuration_Colon_0, resolutionStack.concat([resolvedPath]).join(" -> "))], + wildcardDirectories: {} + }; + } + var options = convertCompilerOptionsFromJsonWorker(json["compilerOptions"], basePath, errors, configFileName); var typingOptions = convertTypingOptionsFromJsonWorker(json["typingOptions"], basePath, errors, configFileName); + if (json["extends"]) { + var _a = [undefined, undefined, undefined, {}], include = _a[0], exclude = _a[1], files = _a[2], baseOptions = _a[3]; + if (typeof json["extends"] === "string") { + _b = (tryExtendsName(json["extends"]) || [include, exclude, files, baseOptions]), include = _b[0], exclude = _b[1], files = _b[2], baseOptions = _b[3]; + } + else { + errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "extends", "string")); + } + if (include && !json["include"]) { + json["include"] = include; + } + if (exclude && !json["exclude"]) { + json["exclude"] = exclude; + } + if (files && !json["files"]) { + json["files"] = files; + } + options = ts.assign({}, baseOptions, options); + } + options = ts.extend(existingOptions, options); options.configFilePath = configFileName; - var _a = getFileNames(errors), fileNames = _a.fileNames, wildcardDirectories = _a.wildcardDirectories; + var _c = getFileNames(errors), fileNames = _c.fileNames, wildcardDirectories = _c.wildcardDirectories; + var compileOnSave = convertCompileOnSaveOptionFromJson(json, basePath, errors); return { options: options, fileNames: fileNames, typingOptions: typingOptions, raw: json, errors: errors, - wildcardDirectories: wildcardDirectories + wildcardDirectories: wildcardDirectories, + compileOnSave: compileOnSave }; + function tryExtendsName(extendedConfig) { + // If the path isn't a rooted or relative path, don't try to resolve it (we reserve the right to special case module-id like paths in the future) + if (!(ts.isRootedDiskPath(extendedConfig) || ts.startsWith(ts.normalizeSlashes(extendedConfig), "./") || ts.startsWith(ts.normalizeSlashes(extendedConfig), "../"))) { + errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.The_path_in_an_extends_options_must_be_relative_or_rooted)); + return; + } + var extendedConfigPath = ts.toPath(extendedConfig, basePath, getCanonicalFileName); + if (!host.fileExists(extendedConfigPath) && !ts.endsWith(extendedConfigPath, ".json")) { + extendedConfigPath = extendedConfigPath + ".json"; + if (!host.fileExists(extendedConfigPath)) { + errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.File_0_does_not_exist, extendedConfig)); + return; + } + } + var extendedResult = readConfigFile(extendedConfigPath, function (path) { return host.readFile(path); }); + if (extendedResult.error) { + errors.push(extendedResult.error); + return; + } + var extendedDirname = ts.getDirectoryPath(extendedConfigPath); + var relativeDifference = ts.convertToRelativePath(extendedDirname, basePath, getCanonicalFileName); + var updatePath = function (path) { return ts.isRootedDiskPath(path) ? path : ts.combinePaths(relativeDifference, path); }; + // Merge configs (copy the resolution stack so it is never reused between branches in potential diamond-problem scenarios) + var result = parseJsonConfigFileContent(extendedResult.config, host, extendedDirname, /*existingOptions*/ undefined, ts.getBaseFileName(extendedConfigPath), resolutionStack.concat([resolvedPath])); + errors.push.apply(errors, result.errors); + var _a = ts.map(["include", "exclude", "files"], function (key) { + if (!json[key] && extendedResult.config[key]) { + return ts.map(extendedResult.config[key], updatePath); + } + }), include = _a[0], exclude = _a[1], files = _a[2]; + return [include, exclude, files, result.options]; + } function getFileNames(errors) { var fileNames; if (ts.hasProperty(json, "files")) { @@ -35512,21 +42005,32 @@ var ts; errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unknown_option_excludes_Did_you_mean_exclude)); } else { - // By default, exclude common package folders + // By default, exclude common package folders and the outDir excludeSpecs = ["node_modules", "bower_components", "jspm_packages"]; - } - // Always exclude the output directory unless explicitly included - var outDir = json["compilerOptions"] && json["compilerOptions"]["outDir"]; - if (outDir) { - excludeSpecs.push(outDir); + var outDir = json["compilerOptions"] && json["compilerOptions"]["outDir"]; + if (outDir) { + excludeSpecs.push(outDir); + } } if (fileNames === undefined && includeSpecs === undefined) { includeSpecs = ["**/*"]; } return matchFileNames(fileNames, includeSpecs, excludeSpecs, basePath, options, host, errors); } + var _b; } ts.parseJsonConfigFileContent = parseJsonConfigFileContent; + function convertCompileOnSaveOptionFromJson(jsonOption, basePath, errors) { + if (!ts.hasProperty(jsonOption, ts.compileOnSaveCommandLineOption.name)) { + return false; + } + var result = convertJsonOption(ts.compileOnSaveCommandLineOption, jsonOption["compileOnSave"], basePath, errors); + if (typeof result === "boolean" && result) { + return result; + } + return false; + } + ts.convertCompileOnSaveOptionFromJson = convertCompileOnSaveOptionFromJson; function convertCompilerOptionsFromJson(jsonOptions, basePath, configFileName) { var errors = []; var options = convertCompilerOptionsFromJsonWorker(jsonOptions, basePath, errors, configFileName); @@ -35540,7 +42044,9 @@ var ts; } ts.convertTypingOptionsFromJson = convertTypingOptionsFromJson; function convertCompilerOptionsFromJsonWorker(jsonOptions, basePath, errors, configFileName) { - var options = ts.getBaseFileName(configFileName) === "jsconfig.json" ? { allowJs: true, maxNodeModuleJsDepth: 2 } : {}; + var options = ts.getBaseFileName(configFileName) === "jsconfig.json" + ? { allowJs: true, maxNodeModuleJsDepth: 2, allowSyntheticDefaultImports: true } + : {}; convertOptionsFromJson(ts.optionDeclarations, jsonOptions, basePath, options, ts.Diagnostics.Unknown_compiler_option_0, errors); return options; } @@ -35792,14 +42298,14 @@ var ts; var recursiveKeys = []; for (var _i = 0, include_1 = include; _i < include_1.length; _i++) { var file = include_1[_i]; - var name_24 = ts.normalizePath(ts.combinePaths(path, file)); - if (excludeRegex && excludeRegex.test(name_24)) { + var name_27 = ts.normalizePath(ts.combinePaths(path, file)); + if (excludeRegex && excludeRegex.test(name_27)) { continue; } - var match = wildcardDirectoryPattern.exec(name_24); + var match = wildcardDirectoryPattern.exec(name_27); if (match) { var key = useCaseSensitiveFileNames ? match[0] : match[0].toLowerCase(); - var flags = watchRecursivePattern.test(name_24) ? 1 /* Recursive */ : 0 /* None */; + var flags = watchRecursivePattern.test(name_27) ? 1 /* Recursive */ : 0 /* None */; var existingFlags = wildcardDirectories[key]; if (existingFlags === undefined || existingFlags < flags) { wildcardDirectories[key] = flags; @@ -35895,11 +42401,11 @@ var ts; return declarationDiagnostics.getDiagnostics(targetSourceFile ? targetSourceFile.fileName : undefined); function getDeclarationDiagnosticsFromFile(_a, sources, isBundledEmit) { var declarationFilePath = _a.declarationFilePath; - emitDeclarations(host, resolver, declarationDiagnostics, declarationFilePath, sources, isBundledEmit); + emitDeclarations(host, resolver, declarationDiagnostics, declarationFilePath, sources, isBundledEmit, /*emitOnlyDtsFiles*/ false); } } ts.getDeclarationDiagnostics = getDeclarationDiagnostics; - function emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFiles, isBundledEmit) { + function emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFiles, isBundledEmit, emitOnlyDtsFiles) { var newLine = host.getNewLine(); var compilerOptions = host.getCompilerOptions(); var write; @@ -35946,7 +42452,7 @@ var ts; // global file reference is added only // - if it is not bundled emit (because otherwise it would be self reference) // - and it is not already added - if (writeReferencePath(referencedFile, !isBundledEmit && !addedGlobalFileReference)) { + if (writeReferencePath(referencedFile, !isBundledEmit && !addedGlobalFileReference, emitOnlyDtsFiles)) { addedGlobalFileReference = true; } emittedReferencedFiles.push(referencedFile); @@ -36107,13807 +42613,18392 @@ var ts; } } } - function handleSymbolAccessibilityError(symbolAccessibilityResult) { - if (symbolAccessibilityResult.accessibility === 0 /* Accessible */) { - // write the aliases - if (symbolAccessibilityResult && symbolAccessibilityResult.aliasesToMakeVisible) { - writeAsynchronousModuleElements(symbolAccessibilityResult.aliasesToMakeVisible); - } + function handleSymbolAccessibilityError(symbolAccessibilityResult) { + if (symbolAccessibilityResult.accessibility === 0 /* Accessible */) { + // write the aliases + if (symbolAccessibilityResult && symbolAccessibilityResult.aliasesToMakeVisible) { + writeAsynchronousModuleElements(symbolAccessibilityResult.aliasesToMakeVisible); + } + } + else { + // Report error + reportedDeclarationError = true; + var errorInfo = writer.getSymbolAccessibilityDiagnostic(symbolAccessibilityResult); + if (errorInfo) { + if (errorInfo.typeName) { + emitterDiagnostics.add(ts.createDiagnosticForNode(symbolAccessibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, ts.getTextOfNodeFromSourceText(currentText, errorInfo.typeName), symbolAccessibilityResult.errorSymbolName, symbolAccessibilityResult.errorModuleName)); + } + else { + emitterDiagnostics.add(ts.createDiagnosticForNode(symbolAccessibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, symbolAccessibilityResult.errorSymbolName, symbolAccessibilityResult.errorModuleName)); + } + } + } + } + function trackSymbol(symbol, enclosingDeclaration, meaning) { + handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning, /*shouldComputeAliasesToMakeVisible*/ true)); + recordTypeReferenceDirectivesIfNecessary(resolver.getTypeReferenceDirectivesForSymbol(symbol, meaning)); + } + function reportInaccessibleThisError() { + if (errorNameNode) { + reportedDeclarationError = true; + emitterDiagnostics.add(ts.createDiagnosticForNode(errorNameNode, ts.Diagnostics.The_inferred_type_of_0_references_an_inaccessible_this_type_A_type_annotation_is_necessary, ts.declarationNameToString(errorNameNode))); + } + } + function writeTypeOfDeclaration(declaration, type, getSymbolAccessibilityDiagnostic) { + writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic; + write(": "); + if (type) { + // Write the type + emitType(type); + } + else { + errorNameNode = declaration.name; + resolver.writeTypeOfDeclaration(declaration, enclosingDeclaration, 2 /* UseTypeOfFunction */ | 1024 /* UseTypeAliasValue */, writer); + errorNameNode = undefined; + } + } + function writeReturnTypeAtSignature(signature, getSymbolAccessibilityDiagnostic) { + writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic; + write(": "); + if (signature.type) { + // Write the type + emitType(signature.type); + } + else { + errorNameNode = signature.name; + resolver.writeReturnTypeOfSignatureDeclaration(signature, enclosingDeclaration, 2 /* UseTypeOfFunction */ | 1024 /* UseTypeAliasValue */, writer); + errorNameNode = undefined; + } + } + function emitLines(nodes) { + for (var _i = 0, nodes_2 = nodes; _i < nodes_2.length; _i++) { + var node = nodes_2[_i]; + emit(node); + } + } + function emitSeparatedList(nodes, separator, eachNodeEmitFn, canEmitFn) { + var currentWriterPos = writer.getTextPos(); + for (var _i = 0, nodes_3 = nodes; _i < nodes_3.length; _i++) { + var node = nodes_3[_i]; + if (!canEmitFn || canEmitFn(node)) { + if (currentWriterPos !== writer.getTextPos()) { + write(separator); + } + currentWriterPos = writer.getTextPos(); + eachNodeEmitFn(node); + } + } + } + function emitCommaList(nodes, eachNodeEmitFn, canEmitFn) { + emitSeparatedList(nodes, ", ", eachNodeEmitFn, canEmitFn); + } + function writeJsDocComments(declaration) { + if (declaration) { + var jsDocComments = ts.getJsDocCommentsFromText(declaration, currentText); + ts.emitNewLineBeforeLeadingComments(currentLineMap, writer, declaration, jsDocComments); + // jsDoc comments are emitted at /*leading comment1 */space/*leading comment*/space + ts.emitComments(currentText, currentLineMap, writer, jsDocComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, ts.writeCommentRange); + } + } + function emitTypeWithNewGetSymbolAccessibilityDiagnostic(type, getSymbolAccessibilityDiagnostic) { + writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic; + emitType(type); + } + function emitType(type) { + switch (type.kind) { + case 117 /* AnyKeyword */: + case 132 /* StringKeyword */: + case 130 /* NumberKeyword */: + case 120 /* BooleanKeyword */: + case 133 /* SymbolKeyword */: + case 103 /* VoidKeyword */: + case 135 /* UndefinedKeyword */: + case 93 /* NullKeyword */: + case 127 /* NeverKeyword */: + case 165 /* ThisType */: + case 166 /* LiteralType */: + return writeTextOfNode(currentText, type); + case 194 /* ExpressionWithTypeArguments */: + return emitExpressionWithTypeArguments(type); + case 155 /* TypeReference */: + return emitTypeReference(type); + case 158 /* TypeQuery */: + return emitTypeQuery(type); + case 160 /* ArrayType */: + return emitArrayType(type); + case 161 /* TupleType */: + return emitTupleType(type); + case 162 /* UnionType */: + return emitUnionType(type); + case 163 /* IntersectionType */: + return emitIntersectionType(type); + case 164 /* ParenthesizedType */: + return emitParenType(type); + case 156 /* FunctionType */: + case 157 /* ConstructorType */: + return emitSignatureDeclarationWithJsDocComments(type); + case 159 /* TypeLiteral */: + return emitTypeLiteral(type); + case 69 /* Identifier */: + return emitEntityName(type); + case 139 /* QualifiedName */: + return emitEntityName(type); + case 154 /* TypePredicate */: + return emitTypePredicate(type); + } + function writeEntityName(entityName) { + if (entityName.kind === 69 /* Identifier */) { + writeTextOfNode(currentText, entityName); + } + else { + var left = entityName.kind === 139 /* QualifiedName */ ? entityName.left : entityName.expression; + var right = entityName.kind === 139 /* QualifiedName */ ? entityName.right : entityName.name; + writeEntityName(left); + write("."); + writeTextOfNode(currentText, right); + } + } + function emitEntityName(entityName) { + var visibilityResult = resolver.isEntityNameVisible(entityName, + // Aliases can be written asynchronously so use correct enclosing declaration + entityName.parent.kind === 229 /* ImportEqualsDeclaration */ ? entityName.parent : enclosingDeclaration); + handleSymbolAccessibilityError(visibilityResult); + recordTypeReferenceDirectivesIfNecessary(resolver.getTypeReferenceDirectivesForEntityName(entityName)); + writeEntityName(entityName); + } + function emitExpressionWithTypeArguments(node) { + if (ts.isEntityNameExpression(node.expression)) { + ts.Debug.assert(node.expression.kind === 69 /* Identifier */ || node.expression.kind === 172 /* PropertyAccessExpression */); + emitEntityName(node.expression); + if (node.typeArguments) { + write("<"); + emitCommaList(node.typeArguments, emitType); + write(">"); + } + } + } + function emitTypeReference(type) { + emitEntityName(type.typeName); + if (type.typeArguments) { + write("<"); + emitCommaList(type.typeArguments, emitType); + write(">"); + } + } + function emitTypePredicate(type) { + writeTextOfNode(currentText, type.parameterName); + write(" is "); + emitType(type.type); + } + function emitTypeQuery(type) { + write("typeof "); + emitEntityName(type.exprName); + } + function emitArrayType(type) { + emitType(type.elementType); + write("[]"); + } + function emitTupleType(type) { + write("["); + emitCommaList(type.elementTypes, emitType); + write("]"); + } + function emitUnionType(type) { + emitSeparatedList(type.types, " | ", emitType); + } + function emitIntersectionType(type) { + emitSeparatedList(type.types, " & ", emitType); + } + function emitParenType(type) { + write("("); + emitType(type.type); + write(")"); + } + function emitTypeLiteral(type) { + write("{"); + if (type.members.length) { + writeLine(); + increaseIndent(); + // write members + emitLines(type.members); + decreaseIndent(); + } + write("}"); + } + } + function emitSourceFile(node) { + currentText = node.text; + currentLineMap = ts.getLineStarts(node); + currentIdentifiers = node.identifiers; + isCurrentFileExternalModule = ts.isExternalModule(node); + enclosingDeclaration = node; + ts.emitDetachedComments(currentText, currentLineMap, writer, ts.writeCommentRange, node, newLine, true /* remove comments */); + emitLines(node.statements); + } + // Return a temp variable name to be used in `export default` statements. + // The temp name will be of the form _default_counter. + // Note that export default is only allowed at most once in a module, so we + // do not need to keep track of created temp names. + function getExportDefaultTempVariableName() { + var baseName = "_default"; + if (!(baseName in currentIdentifiers)) { + return baseName; + } + var count = 0; + while (true) { + count++; + var name_28 = baseName + "_" + count; + if (!(name_28 in currentIdentifiers)) { + return name_28; + } + } + } + function emitExportAssignment(node) { + if (node.expression.kind === 69 /* Identifier */) { + write(node.isExportEquals ? "export = " : "export default "); + writeTextOfNode(currentText, node.expression); + } + else { + // Expression + var tempVarName = getExportDefaultTempVariableName(); + if (!noDeclare) { + write("declare "); + } + write("var "); + write(tempVarName); + write(": "); + writer.getSymbolAccessibilityDiagnostic = getDefaultExportAccessibilityDiagnostic; + resolver.writeTypeOfExpression(node.expression, enclosingDeclaration, 2 /* UseTypeOfFunction */ | 1024 /* UseTypeAliasValue */, writer); + write(";"); + writeLine(); + write(node.isExportEquals ? "export = " : "export default "); + write(tempVarName); + } + write(";"); + writeLine(); + // Make all the declarations visible for the export name + if (node.expression.kind === 69 /* Identifier */) { + var nodes = resolver.collectLinkedAliases(node.expression); + // write each of these declarations asynchronously + writeAsynchronousModuleElements(nodes); + } + function getDefaultExportAccessibilityDiagnostic(diagnostic) { + return { + diagnosticMessage: ts.Diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0, + errorNode: node + }; + } + } + function isModuleElementVisible(node) { + return resolver.isDeclarationVisible(node); + } + function emitModuleElement(node, isModuleElementVisible) { + if (isModuleElementVisible) { + writeModuleElement(node); + } + else if (node.kind === 229 /* ImportEqualsDeclaration */ || + (node.parent.kind === 256 /* SourceFile */ && isCurrentFileExternalModule)) { + var isVisible = void 0; + if (asynchronousSubModuleDeclarationEmitInfo && node.parent.kind !== 256 /* SourceFile */) { + // Import declaration of another module that is visited async so lets put it in right spot + asynchronousSubModuleDeclarationEmitInfo.push({ + node: node, + outputPos: writer.getTextPos(), + indent: writer.getIndent(), + isVisible: isVisible + }); + } + else { + if (node.kind === 230 /* ImportDeclaration */) { + var importDeclaration = node; + if (importDeclaration.importClause) { + isVisible = (importDeclaration.importClause.name && resolver.isDeclarationVisible(importDeclaration.importClause)) || + isVisibleNamedBinding(importDeclaration.importClause.namedBindings); + } + } + moduleElementDeclarationEmitInfo.push({ + node: node, + outputPos: writer.getTextPos(), + indent: writer.getIndent(), + isVisible: isVisible + }); + } + } + } + function writeModuleElement(node) { + switch (node.kind) { + case 220 /* FunctionDeclaration */: + return writeFunctionDeclaration(node); + case 200 /* VariableStatement */: + return writeVariableStatement(node); + case 222 /* InterfaceDeclaration */: + return writeInterfaceDeclaration(node); + case 221 /* ClassDeclaration */: + return writeClassDeclaration(node); + case 223 /* TypeAliasDeclaration */: + return writeTypeAliasDeclaration(node); + case 224 /* EnumDeclaration */: + return writeEnumDeclaration(node); + case 225 /* ModuleDeclaration */: + return writeModuleDeclaration(node); + case 229 /* ImportEqualsDeclaration */: + return writeImportEqualsDeclaration(node); + case 230 /* ImportDeclaration */: + return writeImportDeclaration(node); + default: + ts.Debug.fail("Unknown symbol kind"); + } + } + function emitModuleElementDeclarationFlags(node) { + // If the node is parented in the current source file we need to emit export declare or just export + if (node.parent.kind === 256 /* SourceFile */) { + var modifiers = ts.getModifierFlags(node); + // If the node is exported + if (modifiers & 1 /* Export */) { + write("export "); + } + if (modifiers & 512 /* Default */) { + write("default "); + } + else if (node.kind !== 222 /* InterfaceDeclaration */ && !noDeclare) { + write("declare "); + } + } + } + function emitClassMemberDeclarationFlags(flags) { + if (flags & 8 /* Private */) { + write("private "); + } + else if (flags & 16 /* Protected */) { + write("protected "); + } + if (flags & 32 /* Static */) { + write("static "); + } + if (flags & 64 /* Readonly */) { + write("readonly "); + } + if (flags & 128 /* Abstract */) { + write("abstract "); + } + } + function writeImportEqualsDeclaration(node) { + // note usage of writer. methods instead of aliases created, just to make sure we are using + // correct writer especially to handle asynchronous alias writing + emitJsDocComments(node); + if (ts.hasModifier(node, 1 /* Export */)) { + write("export "); + } + write("import "); + writeTextOfNode(currentText, node.name); + write(" = "); + if (ts.isInternalModuleImportEqualsDeclaration(node)) { + emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.moduleReference, getImportEntityNameVisibilityError); + write(";"); + } + else { + write("require("); + emitExternalModuleSpecifier(node); + write(");"); + } + writer.writeLine(); + function getImportEntityNameVisibilityError(symbolAccessibilityResult) { + return { + diagnosticMessage: ts.Diagnostics.Import_declaration_0_is_using_private_name_1, + errorNode: node, + typeName: node.name + }; + } + } + function isVisibleNamedBinding(namedBindings) { + if (namedBindings) { + if (namedBindings.kind === 232 /* NamespaceImport */) { + return resolver.isDeclarationVisible(namedBindings); + } + else { + return ts.forEach(namedBindings.elements, function (namedImport) { return resolver.isDeclarationVisible(namedImport); }); + } + } + } + function writeImportDeclaration(node) { + emitJsDocComments(node); + if (ts.hasModifier(node, 1 /* Export */)) { + write("export "); + } + write("import "); + if (node.importClause) { + var currentWriterPos = writer.getTextPos(); + if (node.importClause.name && resolver.isDeclarationVisible(node.importClause)) { + writeTextOfNode(currentText, node.importClause.name); + } + if (node.importClause.namedBindings && isVisibleNamedBinding(node.importClause.namedBindings)) { + if (currentWriterPos !== writer.getTextPos()) { + // If the default binding was emitted, write the separated + write(", "); + } + if (node.importClause.namedBindings.kind === 232 /* NamespaceImport */) { + write("* as "); + writeTextOfNode(currentText, node.importClause.namedBindings.name); + } + else { + write("{ "); + emitCommaList(node.importClause.namedBindings.elements, emitImportOrExportSpecifier, resolver.isDeclarationVisible); + write(" }"); + } + } + write(" from "); + } + emitExternalModuleSpecifier(node); + write(";"); + writer.writeLine(); + } + function emitExternalModuleSpecifier(parent) { + // emitExternalModuleSpecifier is usually called when we emit something in the.d.ts file that will make it an external module (i.e. import/export declarations). + // the only case when it is not true is when we call it to emit correct name for module augmentation - d.ts files with just module augmentations are not considered + // external modules since they are indistinguishable from script files with ambient modules. To fix this in such d.ts files we'll emit top level 'export {}' + // so compiler will treat them as external modules. + resultHasExternalModuleIndicator = resultHasExternalModuleIndicator || parent.kind !== 225 /* ModuleDeclaration */; + var moduleSpecifier; + if (parent.kind === 229 /* ImportEqualsDeclaration */) { + var node = parent; + moduleSpecifier = ts.getExternalModuleImportEqualsDeclarationExpression(node); + } + else if (parent.kind === 225 /* ModuleDeclaration */) { + moduleSpecifier = parent.name; } else { - // Report error - reportedDeclarationError = true; - var errorInfo = writer.getSymbolAccessibilityDiagnostic(symbolAccessibilityResult); - if (errorInfo) { - if (errorInfo.typeName) { - emitterDiagnostics.add(ts.createDiagnosticForNode(symbolAccessibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, ts.getTextOfNodeFromSourceText(currentText, errorInfo.typeName), symbolAccessibilityResult.errorSymbolName, symbolAccessibilityResult.errorModuleName)); - } - else { - emitterDiagnostics.add(ts.createDiagnosticForNode(symbolAccessibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, symbolAccessibilityResult.errorSymbolName, symbolAccessibilityResult.errorModuleName)); - } + var node = parent; + moduleSpecifier = node.moduleSpecifier; + } + if (moduleSpecifier.kind === 9 /* StringLiteral */ && isBundledEmit && (compilerOptions.out || compilerOptions.outFile)) { + var moduleName = ts.getExternalModuleNameFromDeclaration(host, resolver, parent); + if (moduleName) { + write('"'); + write(moduleName); + write('"'); + return; } } + writeTextOfNode(currentText, moduleSpecifier); } - function trackSymbol(symbol, enclosingDeclaration, meaning) { - handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning)); - recordTypeReferenceDirectivesIfNecessary(resolver.getTypeReferenceDirectivesForSymbol(symbol, meaning)); - } - function reportInaccessibleThisError() { - if (errorNameNode) { - reportedDeclarationError = true; - emitterDiagnostics.add(ts.createDiagnosticForNode(errorNameNode, ts.Diagnostics.The_inferred_type_of_0_references_an_inaccessible_this_type_A_type_annotation_is_necessary, ts.declarationNameToString(errorNameNode))); + function emitImportOrExportSpecifier(node) { + if (node.propertyName) { + writeTextOfNode(currentText, node.propertyName); + write(" as "); } + writeTextOfNode(currentText, node.name); } - function writeTypeOfDeclaration(declaration, type, getSymbolAccessibilityDiagnostic) { - writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic; - write(": "); - if (type) { - // Write the type - emitType(type); + function emitExportSpecifier(node) { + emitImportOrExportSpecifier(node); + // Make all the declarations visible for the export name + var nodes = resolver.collectLinkedAliases(node.propertyName || node.name); + // write each of these declarations asynchronously + writeAsynchronousModuleElements(nodes); + } + function emitExportDeclaration(node) { + emitJsDocComments(node); + write("export "); + if (node.exportClause) { + write("{ "); + emitCommaList(node.exportClause.elements, emitExportSpecifier); + write(" }"); } else { - errorNameNode = declaration.name; - resolver.writeTypeOfDeclaration(declaration, enclosingDeclaration, 2 /* UseTypeOfFunction */, writer); - errorNameNode = undefined; + write("*"); + } + if (node.moduleSpecifier) { + write(" from "); + emitExternalModuleSpecifier(node); } + write(";"); + writer.writeLine(); } - function writeReturnTypeAtSignature(signature, getSymbolAccessibilityDiagnostic) { - writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic; - write(": "); - if (signature.type) { - // Write the type - emitType(signature.type); + function writeModuleDeclaration(node) { + emitJsDocComments(node); + emitModuleElementDeclarationFlags(node); + if (ts.isGlobalScopeAugmentation(node)) { + write("global "); } else { - errorNameNode = signature.name; - resolver.writeReturnTypeOfSignatureDeclaration(signature, enclosingDeclaration, 2 /* UseTypeOfFunction */, writer); - errorNameNode = undefined; + if (node.flags & 16 /* Namespace */) { + write("namespace "); + } + else { + write("module "); + } + if (ts.isExternalModuleAugmentation(node)) { + emitExternalModuleSpecifier(node); + } + else { + writeTextOfNode(currentText, node.name); + } } - } - function emitLines(nodes) { - for (var _i = 0, nodes_2 = nodes; _i < nodes_2.length; _i++) { - var node = nodes_2[_i]; - emit(node); + while (node.body && node.body.kind !== 226 /* ModuleBlock */) { + node = node.body; + write("."); + writeTextOfNode(currentText, node.name); + } + var prevEnclosingDeclaration = enclosingDeclaration; + if (node.body) { + enclosingDeclaration = node; + write(" {"); + writeLine(); + increaseIndent(); + emitLines(node.body.statements); + decreaseIndent(); + write("}"); + writeLine(); + enclosingDeclaration = prevEnclosingDeclaration; + } + else { + write(";"); } } - function emitSeparatedList(nodes, separator, eachNodeEmitFn, canEmitFn) { - var currentWriterPos = writer.getTextPos(); - for (var _i = 0, nodes_3 = nodes; _i < nodes_3.length; _i++) { - var node = nodes_3[_i]; - if (!canEmitFn || canEmitFn(node)) { - if (currentWriterPos !== writer.getTextPos()) { - write(separator); - } - currentWriterPos = writer.getTextPos(); - eachNodeEmitFn(node); - } + function writeTypeAliasDeclaration(node) { + var prevEnclosingDeclaration = enclosingDeclaration; + enclosingDeclaration = node; + emitJsDocComments(node); + emitModuleElementDeclarationFlags(node); + write("type "); + writeTextOfNode(currentText, node.name); + emitTypeParameters(node.typeParameters); + write(" = "); + emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError); + write(";"); + writeLine(); + enclosingDeclaration = prevEnclosingDeclaration; + function getTypeAliasDeclarationVisibilityError(symbolAccessibilityResult) { + return { + diagnosticMessage: ts.Diagnostics.Exported_type_alias_0_has_or_is_using_private_name_1, + errorNode: node.type, + typeName: node.name + }; } } - function emitCommaList(nodes, eachNodeEmitFn, canEmitFn) { - emitSeparatedList(nodes, ", ", eachNodeEmitFn, canEmitFn); + function writeEnumDeclaration(node) { + emitJsDocComments(node); + emitModuleElementDeclarationFlags(node); + if (ts.isConst(node)) { + write("const "); + } + write("enum "); + writeTextOfNode(currentText, node.name); + write(" {"); + writeLine(); + increaseIndent(); + emitLines(node.members); + decreaseIndent(); + write("}"); + writeLine(); } - function writeJsDocComments(declaration) { - if (declaration) { - var jsDocComments = ts.getJsDocCommentsFromText(declaration, currentText); - ts.emitNewLineBeforeLeadingComments(currentLineMap, writer, declaration, jsDocComments); - // jsDoc comments are emitted at /*leading comment1 */space/*leading comment*/space - ts.emitComments(currentText, currentLineMap, writer, jsDocComments, /*trailingSeparator*/ true, newLine, ts.writeCommentRange); + function emitEnumMemberDeclaration(node) { + emitJsDocComments(node); + writeTextOfNode(currentText, node.name); + var enumMemberValue = resolver.getConstantValue(node); + if (enumMemberValue !== undefined) { + write(" = "); + write(enumMemberValue.toString()); } + write(","); + writeLine(); } - function emitTypeWithNewGetSymbolAccessibilityDiagnostic(type, getSymbolAccessibilityDiagnostic) { - writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic; - emitType(type); + function isPrivateMethodTypeParameter(node) { + return node.parent.kind === 147 /* MethodDeclaration */ && ts.hasModifier(node.parent, 8 /* Private */); } - function emitType(type) { - switch (type.kind) { - case 117 /* AnyKeyword */: - case 132 /* StringKeyword */: - case 130 /* NumberKeyword */: - case 120 /* BooleanKeyword */: - case 133 /* SymbolKeyword */: - case 103 /* VoidKeyword */: - case 135 /* UndefinedKeyword */: - case 93 /* NullKeyword */: - case 127 /* NeverKeyword */: - case 165 /* ThisType */: - case 166 /* LiteralType */: - return writeTextOfNode(currentText, type); - case 194 /* ExpressionWithTypeArguments */: - return emitExpressionWithTypeArguments(type); - case 155 /* TypeReference */: - return emitTypeReference(type); - case 158 /* TypeQuery */: - return emitTypeQuery(type); - case 160 /* ArrayType */: - return emitArrayType(type); - case 161 /* TupleType */: - return emitTupleType(type); - case 162 /* UnionType */: - return emitUnionType(type); - case 163 /* IntersectionType */: - return emitIntersectionType(type); - case 164 /* ParenthesizedType */: - return emitParenType(type); - case 156 /* FunctionType */: - case 157 /* ConstructorType */: - return emitSignatureDeclarationWithJsDocComments(type); - case 159 /* TypeLiteral */: - return emitTypeLiteral(type); - case 69 /* Identifier */: - return emitEntityName(type); - case 139 /* QualifiedName */: - return emitEntityName(type); - case 154 /* TypePredicate */: - return emitTypePredicate(type); - } - function writeEntityName(entityName) { - if (entityName.kind === 69 /* Identifier */) { - writeTextOfNode(currentText, entityName); + function emitTypeParameters(typeParameters) { + function emitTypeParameter(node) { + increaseIndent(); + emitJsDocComments(node); + decreaseIndent(); + writeTextOfNode(currentText, node.name); + // If there is constraint present and this is not a type parameter of the private method emit the constraint + if (node.constraint && !isPrivateMethodTypeParameter(node)) { + write(" extends "); + if (node.parent.kind === 156 /* FunctionType */ || + node.parent.kind === 157 /* ConstructorType */ || + (node.parent.parent && node.parent.parent.kind === 159 /* TypeLiteral */)) { + ts.Debug.assert(node.parent.kind === 147 /* MethodDeclaration */ || + node.parent.kind === 146 /* MethodSignature */ || + node.parent.kind === 156 /* FunctionType */ || + node.parent.kind === 157 /* ConstructorType */ || + node.parent.kind === 151 /* CallSignature */ || + node.parent.kind === 152 /* ConstructSignature */); + emitType(node.constraint); + } + else { + emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.constraint, getTypeParameterConstraintVisibilityError); + } } - else { - var left = entityName.kind === 139 /* QualifiedName */ ? entityName.left : entityName.expression; - var right = entityName.kind === 139 /* QualifiedName */ ? entityName.right : entityName.name; - writeEntityName(left); - write("."); - writeTextOfNode(currentText, right); + function getTypeParameterConstraintVisibilityError(symbolAccessibilityResult) { + // Type parameter constraints are named by user so we should always be able to name it + var diagnosticMessage; + switch (node.parent.kind) { + case 221 /* ClassDeclaration */: + diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_class_has_or_is_using_private_name_1; + break; + case 222 /* InterfaceDeclaration */: + diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1; + break; + case 152 /* ConstructSignature */: + diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; + break; + case 151 /* CallSignature */: + diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1; + break; + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + if (ts.hasModifier(node.parent, 32 /* Static */)) { + diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1; + } + else if (node.parent.parent.kind === 221 /* ClassDeclaration */) { + diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1; + } + else { + diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1; + } + break; + case 220 /* FunctionDeclaration */: + diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_function_has_or_is_using_private_name_1; + break; + default: + ts.Debug.fail("This is unknown parent for type parameter: " + node.parent.kind); + } + return { + diagnosticMessage: diagnosticMessage, + errorNode: node, + typeName: node.name + }; } } - function emitEntityName(entityName) { - var visibilityResult = resolver.isEntityNameVisible(entityName, - // Aliases can be written asynchronously so use correct enclosing declaration - entityName.parent.kind === 229 /* ImportEqualsDeclaration */ ? entityName.parent : enclosingDeclaration); - handleSymbolAccessibilityError(visibilityResult); - recordTypeReferenceDirectivesIfNecessary(resolver.getTypeReferenceDirectivesForEntityName(entityName)); - writeEntityName(entityName); + if (typeParameters) { + write("<"); + emitCommaList(typeParameters, emitTypeParameter); + write(">"); } - function emitExpressionWithTypeArguments(node) { + } + function emitHeritageClause(typeReferences, isImplementsList) { + if (typeReferences) { + write(isImplementsList ? " implements " : " extends "); + emitCommaList(typeReferences, emitTypeOfTypeReference); + } + function emitTypeOfTypeReference(node) { if (ts.isEntityNameExpression(node.expression)) { - ts.Debug.assert(node.expression.kind === 69 /* Identifier */ || node.expression.kind === 172 /* PropertyAccessExpression */); - emitEntityName(node.expression); - if (node.typeArguments) { - write("<"); - emitCommaList(node.typeArguments, emitType); - write(">"); + emitTypeWithNewGetSymbolAccessibilityDiagnostic(node, getHeritageClauseVisibilityError); + } + else if (!isImplementsList && node.expression.kind === 93 /* NullKeyword */) { + write("null"); + } + else { + writer.getSymbolAccessibilityDiagnostic = getHeritageClauseVisibilityError; + resolver.writeBaseConstructorTypeOfClass(enclosingDeclaration, enclosingDeclaration, 2 /* UseTypeOfFunction */ | 1024 /* UseTypeAliasValue */, writer); + } + function getHeritageClauseVisibilityError(symbolAccessibilityResult) { + var diagnosticMessage; + // Heritage clause is written by user so it can always be named + if (node.parent.parent.kind === 221 /* ClassDeclaration */) { + // Class or Interface implemented/extended is inaccessible + diagnosticMessage = isImplementsList ? + ts.Diagnostics.Implements_clause_of_exported_class_0_has_or_is_using_private_name_1 : + ts.Diagnostics.Extends_clause_of_exported_class_0_has_or_is_using_private_name_1; + } + else { + // interface is inaccessible + diagnosticMessage = ts.Diagnostics.Extends_clause_of_exported_interface_0_has_or_is_using_private_name_1; } + return { + diagnosticMessage: diagnosticMessage, + errorNode: node, + typeName: node.parent.parent.name + }; } } - function emitTypeReference(type) { - emitEntityName(type.typeName); - if (type.typeArguments) { - write("<"); - emitCommaList(type.typeArguments, emitType); - write(">"); + } + function writeClassDeclaration(node) { + function emitParameterProperties(constructorDeclaration) { + if (constructorDeclaration) { + ts.forEach(constructorDeclaration.parameters, function (param) { + if (ts.hasModifier(param, 92 /* ParameterPropertyModifier */)) { + emitPropertyDeclaration(param); + } + }); } } - function emitTypePredicate(type) { - writeTextOfNode(currentText, type.parameterName); - write(" is "); - emitType(type.type); - } - function emitTypeQuery(type) { - write("typeof "); - emitEntityName(type.exprName); - } - function emitArrayType(type) { - emitType(type.elementType); - write("[]"); - } - function emitTupleType(type) { - write("["); - emitCommaList(type.elementTypes, emitType); - write("]"); + emitJsDocComments(node); + emitModuleElementDeclarationFlags(node); + if (ts.hasModifier(node, 128 /* Abstract */)) { + write("abstract "); } - function emitUnionType(type) { - emitSeparatedList(type.types, " | ", emitType); + write("class "); + writeTextOfNode(currentText, node.name); + var prevEnclosingDeclaration = enclosingDeclaration; + enclosingDeclaration = node; + emitTypeParameters(node.typeParameters); + var baseTypeNode = ts.getClassExtendsHeritageClauseElement(node); + if (baseTypeNode) { + emitHeritageClause([baseTypeNode], /*isImplementsList*/ false); } - function emitIntersectionType(type) { - emitSeparatedList(type.types, " & ", emitType); + emitHeritageClause(ts.getClassImplementsHeritageClauseElements(node), /*isImplementsList*/ true); + write(" {"); + writeLine(); + increaseIndent(); + emitParameterProperties(ts.getFirstConstructorWithBody(node)); + emitLines(node.members); + decreaseIndent(); + write("}"); + writeLine(); + enclosingDeclaration = prevEnclosingDeclaration; + } + function writeInterfaceDeclaration(node) { + emitJsDocComments(node); + emitModuleElementDeclarationFlags(node); + write("interface "); + writeTextOfNode(currentText, node.name); + var prevEnclosingDeclaration = enclosingDeclaration; + enclosingDeclaration = node; + emitTypeParameters(node.typeParameters); + emitHeritageClause(ts.getInterfaceBaseTypeNodes(node), /*isImplementsList*/ false); + write(" {"); + writeLine(); + increaseIndent(); + emitLines(node.members); + decreaseIndent(); + write("}"); + writeLine(); + enclosingDeclaration = prevEnclosingDeclaration; + } + function emitPropertyDeclaration(node) { + if (ts.hasDynamicName(node)) { + return; } - function emitParenType(type) { - write("("); - emitType(type.type); - write(")"); + emitJsDocComments(node); + emitClassMemberDeclarationFlags(ts.getModifierFlags(node)); + emitVariableDeclaration(node); + write(";"); + writeLine(); + } + function emitVariableDeclaration(node) { + // If we are emitting property it isn't moduleElement and hence we already know it needs to be emitted + // so there is no check needed to see if declaration is visible + if (node.kind !== 218 /* VariableDeclaration */ || resolver.isDeclarationVisible(node)) { + if (ts.isBindingPattern(node.name)) { + emitBindingPattern(node.name); + } + else { + // If this node is a computed name, it can only be a symbol, because we've already skipped + // it if it's not a well known symbol. In that case, the text of the name will be exactly + // what we want, namely the name expression enclosed in brackets. + writeTextOfNode(currentText, node.name); + // If optional property emit ? but in the case of parameterProperty declaration with "?" indicating optional parameter for the constructor + // we don't want to emit property declaration with "?" + if ((node.kind === 145 /* PropertyDeclaration */ || node.kind === 144 /* PropertySignature */ || + (node.kind === 142 /* Parameter */ && !ts.isParameterPropertyDeclaration(node))) && ts.hasQuestionToken(node)) { + write("?"); + } + if ((node.kind === 145 /* PropertyDeclaration */ || node.kind === 144 /* PropertySignature */) && node.parent.kind === 159 /* TypeLiteral */) { + emitTypeOfVariableDeclarationFromTypeLiteral(node); + } + else if (resolver.isLiteralConstDeclaration(node)) { + write(" = "); + resolver.writeLiteralConstValue(node, writer); + } + else if (!ts.hasModifier(node, 8 /* Private */)) { + writeTypeOfDeclaration(node, node.type, getVariableDeclarationTypeVisibilityError); + } + } } - function emitTypeLiteral(type) { - write("{"); - if (type.members.length) { - writeLine(); - increaseIndent(); - // write members - emitLines(type.members); - decreaseIndent(); + function getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult) { + if (node.kind === 218 /* VariableDeclaration */) { + return symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? + ts.Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + ts.Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Exported_variable_0_has_or_is_using_private_name_1; + } + else if (node.kind === 145 /* PropertyDeclaration */ || node.kind === 144 /* PropertySignature */) { + // TODO(jfreeman): Deal with computed properties in error reporting. + if (ts.hasModifier(node, 32 /* Static */)) { + return symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? + ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_private_name_1; + } + else if (node.parent.kind === 221 /* ClassDeclaration */) { + return symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? + ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_private_name_1; + } + else { + // Interfaces cannot have types that cannot be named + return symbolAccessibilityResult.errorModuleName ? + ts.Diagnostics.Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Property_0_of_exported_interface_has_or_is_using_private_name_1; + } } - write("}"); } - } - function emitSourceFile(node) { - currentText = node.text; - currentLineMap = ts.getLineStarts(node); - currentIdentifiers = node.identifiers; - isCurrentFileExternalModule = ts.isExternalModule(node); - enclosingDeclaration = node; - ts.emitDetachedComments(currentText, currentLineMap, writer, ts.writeCommentRange, node, newLine, true /* remove comments */); - emitLines(node.statements); - } - // Return a temp variable name to be used in `export default` statements. - // The temp name will be of the form _default_counter. - // Note that export default is only allowed at most once in a module, so we - // do not need to keep track of created temp names. - function getExportDefaultTempVariableName() { - var baseName = "_default"; - if (!(baseName in currentIdentifiers)) { - return baseName; + function getVariableDeclarationTypeVisibilityError(symbolAccessibilityResult) { + var diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult); + return diagnosticMessage !== undefined ? { + diagnosticMessage: diagnosticMessage, + errorNode: node, + typeName: node.name + } : undefined; } - var count = 0; - while (true) { - count++; - var name_25 = baseName + "_" + count; - if (!(name_25 in currentIdentifiers)) { - return name_25; + function emitBindingPattern(bindingPattern) { + // Only select non-omitted expression from the bindingPattern's elements. + // We have to do this to avoid emitting trailing commas. + // For example: + // original: var [, c,,] = [ 2,3,4] + // emitted: declare var c: number; // instead of declare var c:number, ; + var elements = []; + for (var _i = 0, _a = bindingPattern.elements; _i < _a.length; _i++) { + var element = _a[_i]; + if (element.kind !== 193 /* OmittedExpression */) { + elements.push(element); + } + } + emitCommaList(elements, emitBindingElement); + } + function emitBindingElement(bindingElement) { + function getBindingElementTypeVisibilityError(symbolAccessibilityResult) { + var diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult); + return diagnosticMessage !== undefined ? { + diagnosticMessage: diagnosticMessage, + errorNode: bindingElement, + typeName: bindingElement.name + } : undefined; + } + if (bindingElement.name) { + if (ts.isBindingPattern(bindingElement.name)) { + emitBindingPattern(bindingElement.name); + } + else { + writeTextOfNode(currentText, bindingElement.name); + writeTypeOfDeclaration(bindingElement, /*type*/ undefined, getBindingElementTypeVisibilityError); + } } } } - function emitExportAssignment(node) { - if (node.expression.kind === 69 /* Identifier */) { - write(node.isExportEquals ? "export = " : "export default "); - writeTextOfNode(currentText, node.expression); + function emitTypeOfVariableDeclarationFromTypeLiteral(node) { + // if this is property of type literal, + // or is parameter of method/call/construct/index signature of type literal + // emit only if type is specified + if (node.type) { + write(": "); + emitType(node.type); + } + } + function isVariableStatementVisible(node) { + return ts.forEach(node.declarationList.declarations, function (varDeclaration) { return resolver.isDeclarationVisible(varDeclaration); }); + } + function writeVariableStatement(node) { + emitJsDocComments(node); + emitModuleElementDeclarationFlags(node); + if (ts.isLet(node.declarationList)) { + write("let "); + } + else if (ts.isConst(node.declarationList)) { + write("const "); } else { - // Expression - var tempVarName = getExportDefaultTempVariableName(); - if (!noDeclare) { - write("declare "); - } write("var "); - write(tempVarName); - write(": "); - writer.getSymbolAccessibilityDiagnostic = getDefaultExportAccessibilityDiagnostic; - resolver.writeTypeOfExpression(node.expression, enclosingDeclaration, 2 /* UseTypeOfFunction */, writer); - write(";"); - writeLine(); - write(node.isExportEquals ? "export = " : "export default "); - write(tempVarName); } + emitCommaList(node.declarationList.declarations, emitVariableDeclaration, resolver.isDeclarationVisible); write(";"); writeLine(); - // Make all the declarations visible for the export name - if (node.expression.kind === 69 /* Identifier */) { - var nodes = resolver.collectLinkedAliases(node.expression); - // write each of these declarations asynchronously - writeAsynchronousModuleElements(nodes); + } + function emitAccessorDeclaration(node) { + if (ts.hasDynamicName(node)) { + return; } - function getDefaultExportAccessibilityDiagnostic(diagnostic) { - return { - diagnosticMessage: ts.Diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0, - errorNode: node - }; + var accessors = ts.getAllAccessorDeclarations(node.parent.members, node); + var accessorWithTypeAnnotation; + if (node === accessors.firstAccessor) { + emitJsDocComments(accessors.getAccessor); + emitJsDocComments(accessors.setAccessor); + emitClassMemberDeclarationFlags(ts.getModifierFlags(node) | (accessors.setAccessor ? 0 : 64 /* Readonly */)); + writeTextOfNode(currentText, node.name); + if (!ts.hasModifier(node, 8 /* Private */)) { + accessorWithTypeAnnotation = node; + var type = getTypeAnnotationFromAccessor(node); + if (!type) { + // couldn't get type for the first accessor, try the another one + var anotherAccessor = node.kind === 149 /* GetAccessor */ ? accessors.setAccessor : accessors.getAccessor; + type = getTypeAnnotationFromAccessor(anotherAccessor); + if (type) { + accessorWithTypeAnnotation = anotherAccessor; + } + } + writeTypeOfDeclaration(node, type, getAccessorDeclarationTypeVisibilityError); + } + write(";"); + writeLine(); } - } - function isModuleElementVisible(node) { - return resolver.isDeclarationVisible(node); - } - function emitModuleElement(node, isModuleElementVisible) { - if (isModuleElementVisible) { - writeModuleElement(node); + function getTypeAnnotationFromAccessor(accessor) { + if (accessor) { + return accessor.kind === 149 /* GetAccessor */ + ? accessor.type // Getter - return type + : accessor.parameters.length > 0 + ? accessor.parameters[0].type // Setter parameter type + : undefined; + } } - else if (node.kind === 229 /* ImportEqualsDeclaration */ || - (node.parent.kind === 256 /* SourceFile */ && isCurrentFileExternalModule)) { - var isVisible = void 0; - if (asynchronousSubModuleDeclarationEmitInfo && node.parent.kind !== 256 /* SourceFile */) { - // Import declaration of another module that is visited async so lets put it in right spot - asynchronousSubModuleDeclarationEmitInfo.push({ - node: node, - outputPos: writer.getTextPos(), - indent: writer.getIndent(), - isVisible: isVisible - }); + function getAccessorDeclarationTypeVisibilityError(symbolAccessibilityResult) { + var diagnosticMessage; + if (accessorWithTypeAnnotation.kind === 150 /* SetAccessor */) { + // Setters have to have type named and cannot infer it so, the type should always be named + if (ts.hasModifier(accessorWithTypeAnnotation.parent, 32 /* Static */)) { + diagnosticMessage = symbolAccessibilityResult.errorModuleName ? + ts.Diagnostics.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_private_name_1; + } + else { + diagnosticMessage = symbolAccessibilityResult.errorModuleName ? + ts.Diagnostics.Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_private_name_1; + } + return { + diagnosticMessage: diagnosticMessage, + errorNode: accessorWithTypeAnnotation.parameters[0], + // TODO(jfreeman): Investigate why we are passing node.name instead of node.parameters[0].name + typeName: accessorWithTypeAnnotation.name + }; } else { - if (node.kind === 230 /* ImportDeclaration */) { - var importDeclaration = node; - if (importDeclaration.importClause) { - isVisible = (importDeclaration.importClause.name && resolver.isDeclarationVisible(importDeclaration.importClause)) || - isVisibleNamedBinding(importDeclaration.importClause.namedBindings); - } + if (ts.hasModifier(accessorWithTypeAnnotation, 32 /* Static */)) { + diagnosticMessage = symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? + ts.Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : + ts.Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1 : + ts.Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_private_name_0; } - moduleElementDeclarationEmitInfo.push({ - node: node, - outputPos: writer.getTextPos(), - indent: writer.getIndent(), - isVisible: isVisible - }); + else { + diagnosticMessage = symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? + ts.Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : + ts.Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1 : + ts.Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_private_name_0; + } + return { + diagnosticMessage: diagnosticMessage, + errorNode: accessorWithTypeAnnotation.name, + typeName: undefined + }; } } } - function writeModuleElement(node) { - switch (node.kind) { - case 220 /* FunctionDeclaration */: - return writeFunctionDeclaration(node); - case 200 /* VariableStatement */: - return writeVariableStatement(node); - case 222 /* InterfaceDeclaration */: - return writeInterfaceDeclaration(node); - case 221 /* ClassDeclaration */: - return writeClassDeclaration(node); - case 223 /* TypeAliasDeclaration */: - return writeTypeAliasDeclaration(node); - case 224 /* EnumDeclaration */: - return writeEnumDeclaration(node); - case 225 /* ModuleDeclaration */: - return writeModuleDeclaration(node); - case 229 /* ImportEqualsDeclaration */: - return writeImportEqualsDeclaration(node); - case 230 /* ImportDeclaration */: - return writeImportDeclaration(node); - default: - ts.Debug.fail("Unknown symbol kind"); + function writeFunctionDeclaration(node) { + if (ts.hasDynamicName(node)) { + return; } - } - function emitModuleElementDeclarationFlags(node) { - // If the node is parented in the current source file we need to emit export declare or just export - if (node.parent.kind === 256 /* SourceFile */) { - // If the node is exported - if (node.flags & 1 /* Export */) { - write("export "); + // If we are emitting Method/Constructor it isn't moduleElement and hence already determined to be emitting + // so no need to verify if the declaration is visible + if (!resolver.isImplementationOfOverload(node)) { + emitJsDocComments(node); + if (node.kind === 220 /* FunctionDeclaration */) { + emitModuleElementDeclarationFlags(node); } - if (node.flags & 512 /* Default */) { - write("default "); + else if (node.kind === 147 /* MethodDeclaration */ || node.kind === 148 /* Constructor */) { + emitClassMemberDeclarationFlags(ts.getModifierFlags(node)); } - else if (node.kind !== 222 /* InterfaceDeclaration */ && !noDeclare) { - write("declare "); + if (node.kind === 220 /* FunctionDeclaration */) { + write("function "); + writeTextOfNode(currentText, node.name); + } + else if (node.kind === 148 /* Constructor */) { + write("constructor"); + } + else { + writeTextOfNode(currentText, node.name); + if (ts.hasQuestionToken(node)) { + write("?"); + } } + emitSignatureDeclaration(node); } } - function emitClassMemberDeclarationFlags(flags) { - if (flags & 8 /* Private */) { - write("private "); + function emitSignatureDeclarationWithJsDocComments(node) { + emitJsDocComments(node); + emitSignatureDeclaration(node); + } + function emitSignatureDeclaration(node) { + var prevEnclosingDeclaration = enclosingDeclaration; + enclosingDeclaration = node; + var closeParenthesizedFunctionType = false; + if (node.kind === 153 /* IndexSignature */) { + // Index signature can have readonly modifier + emitClassMemberDeclarationFlags(ts.getModifierFlags(node)); + write("["); } - else if (flags & 16 /* Protected */) { - write("protected "); + else { + // Construct signature or constructor type write new Signature + if (node.kind === 152 /* ConstructSignature */ || node.kind === 157 /* ConstructorType */) { + write("new "); + } + else if (node.kind === 156 /* FunctionType */) { + var currentOutput = writer.getText(); + // Do not generate incorrect type when function type with type parameters is type argument + // This could happen if user used space between two '<' making it error free + // e.g var x: A< (a: Tany)=>Tany>; + if (node.typeParameters && currentOutput.charAt(currentOutput.length - 1) === "<") { + closeParenthesizedFunctionType = true; + write("("); + } + } + emitTypeParameters(node.typeParameters); + write("("); } - if (flags & 32 /* Static */) { - write("static "); + // Parameters + emitCommaList(node.parameters, emitParameterDeclaration); + if (node.kind === 153 /* IndexSignature */) { + write("]"); } - if (flags & 64 /* Readonly */) { - write("readonly "); + else { + write(")"); } - if (flags & 128 /* Abstract */) { - write("abstract "); + // If this is not a constructor and is not private, emit the return type + var isFunctionTypeOrConstructorType = node.kind === 156 /* FunctionType */ || node.kind === 157 /* ConstructorType */; + if (isFunctionTypeOrConstructorType || node.parent.kind === 159 /* TypeLiteral */) { + // Emit type literal signature return type only if specified + if (node.type) { + write(isFunctionTypeOrConstructorType ? " => " : ": "); + emitType(node.type); + } } - } - function writeImportEqualsDeclaration(node) { - // note usage of writer. methods instead of aliases created, just to make sure we are using - // correct writer especially to handle asynchronous alias writing - emitJsDocComments(node); - if (node.flags & 1 /* Export */) { - write("export "); + else if (node.kind !== 148 /* Constructor */ && !ts.hasModifier(node, 8 /* Private */)) { + writeReturnTypeAtSignature(node, getReturnTypeVisibilityError); } - write("import "); - writeTextOfNode(currentText, node.name); - write(" = "); - if (ts.isInternalModuleImportEqualsDeclaration(node)) { - emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.moduleReference, getImportEntityNameVisibilityError); + enclosingDeclaration = prevEnclosingDeclaration; + if (!isFunctionTypeOrConstructorType) { write(";"); + writeLine(); } - else { - write("require("); - emitExternalModuleSpecifier(node); - write(");"); + else if (closeParenthesizedFunctionType) { + write(")"); } - writer.writeLine(); - function getImportEntityNameVisibilityError(symbolAccessibilityResult) { + function getReturnTypeVisibilityError(symbolAccessibilityResult) { + var diagnosticMessage; + switch (node.kind) { + case 152 /* ConstructSignature */: + // Interfaces cannot have return types that cannot be named + diagnosticMessage = symbolAccessibilityResult.errorModuleName ? + ts.Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : + ts.Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_0; + break; + case 151 /* CallSignature */: + // Interfaces cannot have return types that cannot be named + diagnosticMessage = symbolAccessibilityResult.errorModuleName ? + ts.Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : + ts.Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_private_name_0; + break; + case 153 /* IndexSignature */: + // Interfaces cannot have return types that cannot be named + diagnosticMessage = symbolAccessibilityResult.errorModuleName ? + ts.Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : + ts.Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_private_name_0; + break; + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + if (ts.hasModifier(node, 32 /* Static */)) { + diagnosticMessage = symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? + ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : + ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 : + ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_private_name_0; + } + else if (node.parent.kind === 221 /* ClassDeclaration */) { + diagnosticMessage = symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? + ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : + ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 : + ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_private_name_0; + } + else { + // Interfaces cannot have return types that cannot be named + diagnosticMessage = symbolAccessibilityResult.errorModuleName ? + ts.Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : + ts.Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_private_name_0; + } + break; + case 220 /* FunctionDeclaration */: + diagnosticMessage = symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? + ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : + ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_private_module_1 : + ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_private_name_0; + break; + default: + ts.Debug.fail("This is unknown kind for signature: " + node.kind); + } return { - diagnosticMessage: ts.Diagnostics.Import_declaration_0_is_using_private_name_1, - errorNode: node, - typeName: node.name + diagnosticMessage: diagnosticMessage, + errorNode: node.name || node }; } } - function isVisibleNamedBinding(namedBindings) { - if (namedBindings) { - if (namedBindings.kind === 232 /* NamespaceImport */) { - return resolver.isDeclarationVisible(namedBindings); - } - else { - return ts.forEach(namedBindings.elements, function (namedImport) { return resolver.isDeclarationVisible(namedImport); }); - } - } - } - function writeImportDeclaration(node) { + function emitParameterDeclaration(node) { + increaseIndent(); emitJsDocComments(node); - if (node.flags & 1 /* Export */) { - write("export "); + if (node.dotDotDotToken) { + write("..."); } - write("import "); - if (node.importClause) { - var currentWriterPos = writer.getTextPos(); - if (node.importClause.name && resolver.isDeclarationVisible(node.importClause)) { - writeTextOfNode(currentText, node.importClause.name); + if (ts.isBindingPattern(node.name)) { + // For bindingPattern, we can't simply writeTextOfNode from the source file + // because we want to omit the initializer and using writeTextOfNode will result in initializer get emitted. + // Therefore, we will have to recursively emit each element in the bindingPattern. + emitBindingPattern(node.name); + } + else { + writeTextOfNode(currentText, node.name); + } + if (resolver.isOptionalParameter(node)) { + write("?"); + } + decreaseIndent(); + if (node.parent.kind === 156 /* FunctionType */ || + node.parent.kind === 157 /* ConstructorType */ || + node.parent.parent.kind === 159 /* TypeLiteral */) { + emitTypeOfVariableDeclarationFromTypeLiteral(node); + } + else if (!ts.hasModifier(node.parent, 8 /* Private */)) { + writeTypeOfDeclaration(node, node.type, getParameterDeclarationTypeVisibilityError); + } + function getParameterDeclarationTypeVisibilityError(symbolAccessibilityResult) { + var diagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult); + return diagnosticMessage !== undefined ? { + diagnosticMessage: diagnosticMessage, + errorNode: node, + typeName: node.name + } : undefined; + } + function getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult) { + switch (node.parent.kind) { + case 148 /* Constructor */: + return symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? + ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_private_name_1; + case 152 /* ConstructSignature */: + // Interfaces cannot have parameter types that cannot be named + return symbolAccessibilityResult.errorModuleName ? + ts.Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; + case 151 /* CallSignature */: + // Interfaces cannot have parameter types that cannot be named + return symbolAccessibilityResult.errorModuleName ? + ts.Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1; + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + if (ts.hasModifier(node.parent, 32 /* Static */)) { + return symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? + ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1; + } + else if (node.parent.parent.kind === 221 /* ClassDeclaration */) { + return symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? + ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1; + } + else { + // Interfaces cannot have parameter types that cannot be named + return symbolAccessibilityResult.errorModuleName ? + ts.Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1; + } + case 220 /* FunctionDeclaration */: + return symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? + ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_private_name_1; + default: + ts.Debug.fail("This is unknown parent for parameter: " + node.parent.kind); } - if (node.importClause.namedBindings && isVisibleNamedBinding(node.importClause.namedBindings)) { - if (currentWriterPos !== writer.getTextPos()) { - // If the default binding was emitted, write the separated - write(", "); - } - if (node.importClause.namedBindings.kind === 232 /* NamespaceImport */) { - write("* as "); - writeTextOfNode(currentText, node.importClause.namedBindings.name); - } - else { - write("{ "); - emitCommaList(node.importClause.namedBindings.elements, emitImportOrExportSpecifier, resolver.isDeclarationVisible); - write(" }"); + } + function emitBindingPattern(bindingPattern) { + // We have to explicitly emit square bracket and bracket because these tokens are not store inside the node. + if (bindingPattern.kind === 167 /* ObjectBindingPattern */) { + write("{"); + emitCommaList(bindingPattern.elements, emitBindingElement); + write("}"); + } + else if (bindingPattern.kind === 168 /* ArrayBindingPattern */) { + write("["); + var elements = bindingPattern.elements; + emitCommaList(elements, emitBindingElement); + if (elements && elements.hasTrailingComma) { + write(", "); } + write("]"); } - write(" from "); - } - emitExternalModuleSpecifier(node); - write(";"); - writer.writeLine(); - } - function emitExternalModuleSpecifier(parent) { - // emitExternalModuleSpecifier is usually called when we emit something in the.d.ts file that will make it an external module (i.e. import/export declarations). - // the only case when it is not true is when we call it to emit correct name for module augmentation - d.ts files with just module augmentations are not considered - // external modules since they are indistinguishable from script files with ambient modules. To fix this in such d.ts files we'll emit top level 'export {}' - // so compiler will treat them as external modules. - resultHasExternalModuleIndicator = resultHasExternalModuleIndicator || parent.kind !== 225 /* ModuleDeclaration */; - var moduleSpecifier; - if (parent.kind === 229 /* ImportEqualsDeclaration */) { - var node = parent; - moduleSpecifier = ts.getExternalModuleImportEqualsDeclarationExpression(node); } - else if (parent.kind === 225 /* ModuleDeclaration */) { - moduleSpecifier = parent.name; - } - else { - var node = parent; - moduleSpecifier = node.moduleSpecifier; - } - if (moduleSpecifier.kind === 9 /* StringLiteral */ && isBundledEmit && (compilerOptions.out || compilerOptions.outFile)) { - var moduleName = ts.getExternalModuleNameFromDeclaration(host, resolver, parent); - if (moduleName) { - write('"'); - write(moduleName); - write('"'); - return; + function emitBindingElement(bindingElement) { + if (bindingElement.kind === 193 /* OmittedExpression */) { + // If bindingElement is an omittedExpression (i.e. containing elision), + // we will emit blank space (although this may differ from users' original code, + // it allows emitSeparatedList to write separator appropriately) + // Example: + // original: function foo([, x, ,]) {} + // emit : function foo([ , x, , ]) {} + write(" "); + } + else if (bindingElement.kind === 169 /* BindingElement */) { + if (bindingElement.propertyName) { + // bindingElement has propertyName property in the following case: + // { y: [a,b,c] ...} -> bindingPattern will have a property called propertyName for "y" + // We have to explicitly emit the propertyName before descending into its binding elements. + // Example: + // original: function foo({y: [a,b,c]}) {} + // emit : declare function foo({y: [a, b, c]}: { y: [any, any, any] }) void; + writeTextOfNode(currentText, bindingElement.propertyName); + write(": "); + } + if (bindingElement.name) { + if (ts.isBindingPattern(bindingElement.name)) { + // If it is a nested binding pattern, we will recursively descend into each element and emit each one separately. + // In the case of rest element, we will omit rest element. + // Example: + // original: function foo([a, [[b]], c] = [1,[["string"]], 3]) {} + // emit : declare function foo([a, [[b]], c]: [number, [[string]], number]): void; + // original with rest: function foo([a, ...c]) {} + // emit : declare function foo([a, ...c]): void; + emitBindingPattern(bindingElement.name); + } + else { + ts.Debug.assert(bindingElement.name.kind === 69 /* Identifier */); + // If the node is just an identifier, we will simply emit the text associated with the node's name + // Example: + // original: function foo({y = 10, x}) {} + // emit : declare function foo({y, x}: {number, any}): void; + if (bindingElement.dotDotDotToken) { + write("..."); + } + writeTextOfNode(currentText, bindingElement.name); + } + } } } - writeTextOfNode(currentText, moduleSpecifier); } - function emitImportOrExportSpecifier(node) { - if (node.propertyName) { - writeTextOfNode(currentText, node.propertyName); - write(" as "); + function emitNode(node) { + switch (node.kind) { + case 220 /* FunctionDeclaration */: + case 225 /* ModuleDeclaration */: + case 229 /* ImportEqualsDeclaration */: + case 222 /* InterfaceDeclaration */: + case 221 /* ClassDeclaration */: + case 223 /* TypeAliasDeclaration */: + case 224 /* EnumDeclaration */: + return emitModuleElement(node, isModuleElementVisible(node)); + case 200 /* VariableStatement */: + return emitModuleElement(node, isVariableStatementVisible(node)); + case 230 /* ImportDeclaration */: + // Import declaration without import clause is visible, otherwise it is not visible + return emitModuleElement(node, /*isModuleElementVisible*/ !node.importClause); + case 236 /* ExportDeclaration */: + return emitExportDeclaration(node); + case 148 /* Constructor */: + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + return writeFunctionDeclaration(node); + case 152 /* ConstructSignature */: + case 151 /* CallSignature */: + case 153 /* IndexSignature */: + return emitSignatureDeclarationWithJsDocComments(node); + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + return emitAccessorDeclaration(node); + case 145 /* PropertyDeclaration */: + case 144 /* PropertySignature */: + return emitPropertyDeclaration(node); + case 255 /* EnumMember */: + return emitEnumMemberDeclaration(node); + case 235 /* ExportAssignment */: + return emitExportAssignment(node); + case 256 /* SourceFile */: + return emitSourceFile(node); } - writeTextOfNode(currentText, node.name); - } - function emitExportSpecifier(node) { - emitImportOrExportSpecifier(node); - // Make all the declarations visible for the export name - var nodes = resolver.collectLinkedAliases(node.propertyName || node.name); - // write each of these declarations asynchronously - writeAsynchronousModuleElements(nodes); } - function emitExportDeclaration(node) { - emitJsDocComments(node); - write("export "); - if (node.exportClause) { - write("{ "); - emitCommaList(node.exportClause.elements, emitExportSpecifier); - write(" }"); + /** + * Adds the reference to referenced file, returns true if global file reference was emitted + * @param referencedFile + * @param addBundledFileReference Determines if global file reference corresponding to bundled file should be emitted or not + */ + function writeReferencePath(referencedFile, addBundledFileReference, emitOnlyDtsFiles) { + var declFileName; + var addedBundledEmitReference = false; + if (ts.isDeclarationFile(referencedFile)) { + // Declaration file, use declaration file name + declFileName = referencedFile.fileName; } else { - write("*"); - } - if (node.moduleSpecifier) { - write(" from "); - emitExternalModuleSpecifier(node); + // Get the declaration file path + ts.forEachExpectedEmitFile(host, getDeclFileName, referencedFile, emitOnlyDtsFiles); } - write(";"); - writer.writeLine(); - } - function writeModuleDeclaration(node) { - emitJsDocComments(node); - emitModuleElementDeclarationFlags(node); - if (ts.isGlobalScopeAugmentation(node)) { - write("global "); + if (declFileName) { + declFileName = ts.getRelativePathToDirectoryOrUrl(ts.getDirectoryPath(ts.normalizeSlashes(declarationFilePath)), declFileName, host.getCurrentDirectory(), host.getCanonicalFileName, + /*isAbsolutePathAnUrl*/ false); + referencesOutput += "/// " + newLine; } - else { - if (node.flags & 4096 /* Namespace */) { - write("namespace "); - } - else { - write("module "); - } - if (ts.isExternalModuleAugmentation(node)) { - emitExternalModuleSpecifier(node); - } - else { - writeTextOfNode(currentText, node.name); + return addedBundledEmitReference; + function getDeclFileName(emitFileNames, sourceFiles, isBundledEmit) { + // Dont add reference path to this file if it is a bundled emit and caller asked not emit bundled file path + if (isBundledEmit && !addBundledFileReference) { + return; } - } - while (node.body && node.body.kind !== 226 /* ModuleBlock */) { - node = node.body; - write("."); - writeTextOfNode(currentText, node.name); - } - var prevEnclosingDeclaration = enclosingDeclaration; - if (node.body) { - enclosingDeclaration = node; - write(" {"); - writeLine(); - increaseIndent(); - emitLines(node.body.statements); - decreaseIndent(); - write("}"); - writeLine(); - enclosingDeclaration = prevEnclosingDeclaration; - } - else { - write(";"); + ts.Debug.assert(!!emitFileNames.declarationFilePath || ts.isSourceFileJavaScript(referencedFile), "Declaration file is not present only for javascript files"); + declFileName = emitFileNames.declarationFilePath || emitFileNames.jsFilePath; + addedBundledEmitReference = isBundledEmit; } } - function writeTypeAliasDeclaration(node) { - var prevEnclosingDeclaration = enclosingDeclaration; - enclosingDeclaration = node; - emitJsDocComments(node); - emitModuleElementDeclarationFlags(node); - write("type "); - writeTextOfNode(currentText, node.name); - emitTypeParameters(node.typeParameters); - write(" = "); - emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError); - write(";"); - writeLine(); - enclosingDeclaration = prevEnclosingDeclaration; - function getTypeAliasDeclarationVisibilityError(symbolAccessibilityResult) { - return { - diagnosticMessage: ts.Diagnostics.Exported_type_alias_0_has_or_is_using_private_name_1, - errorNode: node.type, - typeName: node.name - }; - } + } + /* @internal */ + function writeDeclarationFile(declarationFilePath, sourceFiles, isBundledEmit, host, resolver, emitterDiagnostics, emitOnlyDtsFiles) { + var emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFiles, isBundledEmit, emitOnlyDtsFiles); + var emitSkipped = emitDeclarationResult.reportedDeclarationError || host.isEmitBlocked(declarationFilePath) || host.getCompilerOptions().noEmit; + if (!emitSkipped) { + var declarationOutput = emitDeclarationResult.referencesOutput + + getDeclarationOutput(emitDeclarationResult.synchronousDeclarationOutput, emitDeclarationResult.moduleElementDeclarationEmitInfo); + ts.writeFile(host, emitterDiagnostics, declarationFilePath, declarationOutput, host.getCompilerOptions().emitBOM, sourceFiles); } - function writeEnumDeclaration(node) { - emitJsDocComments(node); - emitModuleElementDeclarationFlags(node); - if (ts.isConst(node)) { - write("const "); - } - write("enum "); - writeTextOfNode(currentText, node.name); - write(" {"); - writeLine(); - increaseIndent(); - emitLines(node.members); - decreaseIndent(); - write("}"); - writeLine(); + return emitSkipped; + function getDeclarationOutput(synchronousDeclarationOutput, moduleElementDeclarationEmitInfo) { + var appliedSyncOutputPos = 0; + var declarationOutput = ""; + // apply asynchronous additions to the synchronous output + ts.forEach(moduleElementDeclarationEmitInfo, function (aliasEmitInfo) { + if (aliasEmitInfo.asynchronousOutput) { + declarationOutput += synchronousDeclarationOutput.substring(appliedSyncOutputPos, aliasEmitInfo.outputPos); + declarationOutput += getDeclarationOutput(aliasEmitInfo.asynchronousOutput, aliasEmitInfo.subModuleElementDeclarationEmitInfo); + appliedSyncOutputPos = aliasEmitInfo.outputPos; + } + }); + declarationOutput += synchronousDeclarationOutput.substring(appliedSyncOutputPos); + return declarationOutput; } - function emitEnumMemberDeclaration(node) { - emitJsDocComments(node); - writeTextOfNode(currentText, node.name); - var enumMemberValue = resolver.getConstantValue(node); - if (enumMemberValue !== undefined) { - write(" = "); - write(enumMemberValue.toString()); - } - write(","); - writeLine(); + } + ts.writeDeclarationFile = writeDeclarationFile; +})(ts || (ts = {})); +/// +/// +/// +/* @internal */ +var ts; +(function (ts) { + ; + /** + * This map contains information about the shape of each Node in "types.ts" pertaining to how + * each node should be traversed during a transformation. + * + * Each edge corresponds to a property in a Node subtype that should be traversed when visiting + * each child. The properties are assigned in the order in which traversal should occur. + * + * We only add entries for nodes that do not have a create/update pair defined in factory.ts + * + * NOTE: This needs to be kept up to date with changes to nodes in "types.ts". Currently, this + * map is not comprehensive. Only node edges relevant to tree transformation are + * currently defined. We may extend this to be more comprehensive, and eventually + * supplant the existing `forEachChild` implementation if performance is not + * significantly impacted. + */ + var nodeEdgeTraversalMap = ts.createMap((_a = {}, + _a[139 /* QualifiedName */] = [ + { name: "left", test: ts.isEntityName }, + { name: "right", test: ts.isIdentifier } + ], + _a[143 /* Decorator */] = [ + { name: "expression", test: ts.isLeftHandSideExpression } + ], + _a[177 /* TypeAssertionExpression */] = [ + { name: "type", test: ts.isTypeNode }, + { name: "expression", test: ts.isUnaryExpression } + ], + _a[195 /* AsExpression */] = [ + { name: "expression", test: ts.isExpression }, + { name: "type", test: ts.isTypeNode } + ], + _a[196 /* NonNullExpression */] = [ + { name: "expression", test: ts.isLeftHandSideExpression } + ], + _a[224 /* EnumDeclaration */] = [ + { name: "decorators", test: ts.isDecorator }, + { name: "modifiers", test: ts.isModifier }, + { name: "name", test: ts.isIdentifier }, + { name: "members", test: ts.isEnumMember } + ], + _a[225 /* ModuleDeclaration */] = [ + { name: "decorators", test: ts.isDecorator }, + { name: "modifiers", test: ts.isModifier }, + { name: "name", test: ts.isModuleName }, + { name: "body", test: ts.isModuleBody } + ], + _a[226 /* ModuleBlock */] = [ + { name: "statements", test: ts.isStatement } + ], + _a[229 /* ImportEqualsDeclaration */] = [ + { name: "decorators", test: ts.isDecorator }, + { name: "modifiers", test: ts.isModifier }, + { name: "name", test: ts.isIdentifier }, + { name: "moduleReference", test: ts.isModuleReference } + ], + _a[240 /* ExternalModuleReference */] = [ + { name: "expression", test: ts.isExpression, optional: true } + ], + _a[255 /* EnumMember */] = [ + { name: "name", test: ts.isPropertyName }, + { name: "initializer", test: ts.isExpression, optional: true, parenthesize: ts.parenthesizeExpressionForList } + ], + _a)); + function reduceNode(node, f, initial) { + return node ? f(initial, node) : initial; + } + /** + * Similar to `reduceLeft`, performs a reduction against each child of a node. + * NOTE: Unlike `forEachChild`, this does *not* visit every node. Only nodes added to the + * `nodeEdgeTraversalMap` above will be visited. + * + * @param node The node containing the children to reduce. + * @param f The callback function + * @param initial The initial value to supply to the reduction. + */ + function reduceEachChild(node, f, initial) { + if (node === undefined) { + return initial; } - function isPrivateMethodTypeParameter(node) { - return node.parent.kind === 147 /* MethodDeclaration */ && (node.parent.flags & 8 /* Private */); + var kind = node.kind; + // No need to visit nodes with no children. + if ((kind > 0 /* FirstToken */ && kind <= 138 /* LastToken */)) { + return initial; } - function emitTypeParameters(typeParameters) { - function emitTypeParameter(node) { - increaseIndent(); - emitJsDocComments(node); - decreaseIndent(); - writeTextOfNode(currentText, node.name); - // If there is constraint present and this is not a type parameter of the private method emit the constraint - if (node.constraint && !isPrivateMethodTypeParameter(node)) { - write(" extends "); - if (node.parent.kind === 156 /* FunctionType */ || - node.parent.kind === 157 /* ConstructorType */ || - (node.parent.parent && node.parent.parent.kind === 159 /* TypeLiteral */)) { - ts.Debug.assert(node.parent.kind === 147 /* MethodDeclaration */ || - node.parent.kind === 146 /* MethodSignature */ || - node.parent.kind === 156 /* FunctionType */ || - node.parent.kind === 157 /* ConstructorType */ || - node.parent.kind === 151 /* CallSignature */ || - node.parent.kind === 152 /* ConstructSignature */); - emitType(node.constraint); - } - else { - emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.constraint, getTypeParameterConstraintVisibilityError); - } - } - function getTypeParameterConstraintVisibilityError(symbolAccessibilityResult) { - // Type parameter constraints are named by user so we should always be able to name it - var diagnosticMessage; - switch (node.parent.kind) { - case 221 /* ClassDeclaration */: - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_class_has_or_is_using_private_name_1; - break; - case 222 /* InterfaceDeclaration */: - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1; - break; - case 152 /* ConstructSignature */: - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; - break; - case 151 /* CallSignature */: - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1; - break; - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - if (node.parent.flags & 32 /* Static */) { - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1; - } - else if (node.parent.parent.kind === 221 /* ClassDeclaration */) { - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1; - } - else { - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1; - } - break; - case 220 /* FunctionDeclaration */: - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_function_has_or_is_using_private_name_1; - break; - default: - ts.Debug.fail("This is unknown parent for type parameter: " + node.parent.kind); - } - return { - diagnosticMessage: diagnosticMessage, - errorNode: node, - typeName: node.name - }; - } - } - if (typeParameters) { - write("<"); - emitCommaList(typeParameters, emitTypeParameter); - write(">"); - } + // We do not yet support types. + if ((kind >= 154 /* TypePredicate */ && kind <= 166 /* LiteralType */)) { + return initial; } - function emitHeritageClause(typeReferences, isImplementsList) { - if (typeReferences) { - write(isImplementsList ? " implements " : " extends "); - emitCommaList(typeReferences, emitTypeOfTypeReference); - } - function emitTypeOfTypeReference(node) { - if (ts.isEntityNameExpression(node.expression)) { - emitTypeWithNewGetSymbolAccessibilityDiagnostic(node, getHeritageClauseVisibilityError); - } - else if (!isImplementsList && node.expression.kind === 93 /* NullKeyword */) { - write("null"); - } - else { - writer.getSymbolAccessibilityDiagnostic = getHeritageClauseVisibilityError; - resolver.writeBaseConstructorTypeOfClass(enclosingDeclaration, enclosingDeclaration, 2 /* UseTypeOfFunction */, writer); - } - function getHeritageClauseVisibilityError(symbolAccessibilityResult) { - var diagnosticMessage; - // Heritage clause is written by user so it can always be named - if (node.parent.parent.kind === 221 /* ClassDeclaration */) { - // Class or Interface implemented/extended is inaccessible - diagnosticMessage = isImplementsList ? - ts.Diagnostics.Implements_clause_of_exported_class_0_has_or_is_using_private_name_1 : - ts.Diagnostics.Extends_clause_of_exported_class_0_has_or_is_using_private_name_1; - } - else { - // interface is inaccessible - diagnosticMessage = ts.Diagnostics.Extends_clause_of_exported_interface_0_has_or_is_using_private_name_1; + var result = initial; + switch (node.kind) { + // Leaf nodes + case 198 /* SemicolonClassElement */: + case 201 /* EmptyStatement */: + case 193 /* OmittedExpression */: + case 217 /* DebuggerStatement */: + case 287 /* NotEmittedStatement */: + // No need to visit nodes with no children. + break; + // Names + case 140 /* ComputedPropertyName */: + result = reduceNode(node.expression, f, result); + break; + // Signature elements + case 142 /* Parameter */: + result = ts.reduceLeft(node.decorators, f, result); + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.name, f, result); + result = reduceNode(node.type, f, result); + result = reduceNode(node.initializer, f, result); + break; + case 143 /* Decorator */: + result = reduceNode(node.expression, f, result); + break; + // Type member + case 145 /* PropertyDeclaration */: + result = ts.reduceLeft(node.decorators, f, result); + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.name, f, result); + result = reduceNode(node.type, f, result); + result = reduceNode(node.initializer, f, result); + break; + case 147 /* MethodDeclaration */: + result = ts.reduceLeft(node.decorators, f, result); + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.name, f, result); + result = ts.reduceLeft(node.typeParameters, f, result); + result = ts.reduceLeft(node.parameters, f, result); + result = reduceNode(node.type, f, result); + result = reduceNode(node.body, f, result); + break; + case 148 /* Constructor */: + result = ts.reduceLeft(node.modifiers, f, result); + result = ts.reduceLeft(node.parameters, f, result); + result = reduceNode(node.body, f, result); + break; + case 149 /* GetAccessor */: + result = ts.reduceLeft(node.decorators, f, result); + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.name, f, result); + result = ts.reduceLeft(node.parameters, f, result); + result = reduceNode(node.type, f, result); + result = reduceNode(node.body, f, result); + break; + case 150 /* SetAccessor */: + result = ts.reduceLeft(node.decorators, f, result); + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.name, f, result); + result = ts.reduceLeft(node.parameters, f, result); + result = reduceNode(node.body, f, result); + break; + // Binding patterns + case 167 /* ObjectBindingPattern */: + case 168 /* ArrayBindingPattern */: + result = ts.reduceLeft(node.elements, f, result); + break; + case 169 /* BindingElement */: + result = reduceNode(node.propertyName, f, result); + result = reduceNode(node.name, f, result); + result = reduceNode(node.initializer, f, result); + break; + // Expression + case 170 /* ArrayLiteralExpression */: + result = ts.reduceLeft(node.elements, f, result); + break; + case 171 /* ObjectLiteralExpression */: + result = ts.reduceLeft(node.properties, f, result); + break; + case 172 /* PropertyAccessExpression */: + result = reduceNode(node.expression, f, result); + result = reduceNode(node.name, f, result); + break; + case 173 /* ElementAccessExpression */: + result = reduceNode(node.expression, f, result); + result = reduceNode(node.argumentExpression, f, result); + break; + case 174 /* CallExpression */: + result = reduceNode(node.expression, f, result); + result = ts.reduceLeft(node.typeArguments, f, result); + result = ts.reduceLeft(node.arguments, f, result); + break; + case 175 /* NewExpression */: + result = reduceNode(node.expression, f, result); + result = ts.reduceLeft(node.typeArguments, f, result); + result = ts.reduceLeft(node.arguments, f, result); + break; + case 176 /* TaggedTemplateExpression */: + result = reduceNode(node.tag, f, result); + result = reduceNode(node.template, f, result); + break; + case 179 /* FunctionExpression */: + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.name, f, result); + result = ts.reduceLeft(node.typeParameters, f, result); + result = ts.reduceLeft(node.parameters, f, result); + result = reduceNode(node.type, f, result); + result = reduceNode(node.body, f, result); + break; + case 180 /* ArrowFunction */: + result = ts.reduceLeft(node.modifiers, f, result); + result = ts.reduceLeft(node.typeParameters, f, result); + result = ts.reduceLeft(node.parameters, f, result); + result = reduceNode(node.type, f, result); + result = reduceNode(node.body, f, result); + break; + case 178 /* ParenthesizedExpression */: + case 181 /* DeleteExpression */: + case 182 /* TypeOfExpression */: + case 183 /* VoidExpression */: + case 184 /* AwaitExpression */: + case 190 /* YieldExpression */: + case 191 /* SpreadElementExpression */: + case 196 /* NonNullExpression */: + result = reduceNode(node.expression, f, result); + break; + case 185 /* PrefixUnaryExpression */: + case 186 /* PostfixUnaryExpression */: + result = reduceNode(node.operand, f, result); + break; + case 187 /* BinaryExpression */: + result = reduceNode(node.left, f, result); + result = reduceNode(node.right, f, result); + break; + case 188 /* ConditionalExpression */: + result = reduceNode(node.condition, f, result); + result = reduceNode(node.whenTrue, f, result); + result = reduceNode(node.whenFalse, f, result); + break; + case 189 /* TemplateExpression */: + result = reduceNode(node.head, f, result); + result = ts.reduceLeft(node.templateSpans, f, result); + break; + case 192 /* ClassExpression */: + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.name, f, result); + result = ts.reduceLeft(node.typeParameters, f, result); + result = ts.reduceLeft(node.heritageClauses, f, result); + result = ts.reduceLeft(node.members, f, result); + break; + case 194 /* ExpressionWithTypeArguments */: + result = reduceNode(node.expression, f, result); + result = ts.reduceLeft(node.typeArguments, f, result); + break; + // Misc + case 197 /* TemplateSpan */: + result = reduceNode(node.expression, f, result); + result = reduceNode(node.literal, f, result); + break; + // Element + case 199 /* Block */: + result = ts.reduceLeft(node.statements, f, result); + break; + case 200 /* VariableStatement */: + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.declarationList, f, result); + break; + case 202 /* ExpressionStatement */: + result = reduceNode(node.expression, f, result); + break; + case 203 /* IfStatement */: + result = reduceNode(node.expression, f, result); + result = reduceNode(node.thenStatement, f, result); + result = reduceNode(node.elseStatement, f, result); + break; + case 204 /* DoStatement */: + result = reduceNode(node.statement, f, result); + result = reduceNode(node.expression, f, result); + break; + case 205 /* WhileStatement */: + case 212 /* WithStatement */: + result = reduceNode(node.expression, f, result); + result = reduceNode(node.statement, f, result); + break; + case 206 /* ForStatement */: + result = reduceNode(node.initializer, f, result); + result = reduceNode(node.condition, f, result); + result = reduceNode(node.incrementor, f, result); + result = reduceNode(node.statement, f, result); + break; + case 207 /* ForInStatement */: + case 208 /* ForOfStatement */: + result = reduceNode(node.initializer, f, result); + result = reduceNode(node.expression, f, result); + result = reduceNode(node.statement, f, result); + break; + case 211 /* ReturnStatement */: + case 215 /* ThrowStatement */: + result = reduceNode(node.expression, f, result); + break; + case 213 /* SwitchStatement */: + result = reduceNode(node.expression, f, result); + result = reduceNode(node.caseBlock, f, result); + break; + case 214 /* LabeledStatement */: + result = reduceNode(node.label, f, result); + result = reduceNode(node.statement, f, result); + break; + case 216 /* TryStatement */: + result = reduceNode(node.tryBlock, f, result); + result = reduceNode(node.catchClause, f, result); + result = reduceNode(node.finallyBlock, f, result); + break; + case 218 /* VariableDeclaration */: + result = reduceNode(node.name, f, result); + result = reduceNode(node.type, f, result); + result = reduceNode(node.initializer, f, result); + break; + case 219 /* VariableDeclarationList */: + result = ts.reduceLeft(node.declarations, f, result); + break; + case 220 /* FunctionDeclaration */: + result = ts.reduceLeft(node.decorators, f, result); + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.name, f, result); + result = ts.reduceLeft(node.typeParameters, f, result); + result = ts.reduceLeft(node.parameters, f, result); + result = reduceNode(node.type, f, result); + result = reduceNode(node.body, f, result); + break; + case 221 /* ClassDeclaration */: + result = ts.reduceLeft(node.decorators, f, result); + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.name, f, result); + result = ts.reduceLeft(node.typeParameters, f, result); + result = ts.reduceLeft(node.heritageClauses, f, result); + result = ts.reduceLeft(node.members, f, result); + break; + case 227 /* CaseBlock */: + result = ts.reduceLeft(node.clauses, f, result); + break; + case 230 /* ImportDeclaration */: + result = ts.reduceLeft(node.decorators, f, result); + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.importClause, f, result); + result = reduceNode(node.moduleSpecifier, f, result); + break; + case 231 /* ImportClause */: + result = reduceNode(node.name, f, result); + result = reduceNode(node.namedBindings, f, result); + break; + case 232 /* NamespaceImport */: + result = reduceNode(node.name, f, result); + break; + case 233 /* NamedImports */: + case 237 /* NamedExports */: + result = ts.reduceLeft(node.elements, f, result); + break; + case 234 /* ImportSpecifier */: + case 238 /* ExportSpecifier */: + result = reduceNode(node.propertyName, f, result); + result = reduceNode(node.name, f, result); + break; + case 235 /* ExportAssignment */: + result = ts.reduceLeft(node.decorators, f, result); + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.expression, f, result); + break; + case 236 /* ExportDeclaration */: + result = ts.reduceLeft(node.decorators, f, result); + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.exportClause, f, result); + result = reduceNode(node.moduleSpecifier, f, result); + break; + // JSX + case 241 /* JsxElement */: + result = reduceNode(node.openingElement, f, result); + result = ts.reduceLeft(node.children, f, result); + result = reduceNode(node.closingElement, f, result); + break; + case 242 /* JsxSelfClosingElement */: + case 243 /* JsxOpeningElement */: + result = reduceNode(node.tagName, f, result); + result = ts.reduceLeft(node.attributes, f, result); + break; + case 245 /* JsxClosingElement */: + result = reduceNode(node.tagName, f, result); + break; + case 246 /* JsxAttribute */: + result = reduceNode(node.name, f, result); + result = reduceNode(node.initializer, f, result); + break; + case 247 /* JsxSpreadAttribute */: + result = reduceNode(node.expression, f, result); + break; + case 248 /* JsxExpression */: + result = reduceNode(node.expression, f, result); + break; + // Clauses + case 249 /* CaseClause */: + result = reduceNode(node.expression, f, result); + // fall-through + case 250 /* DefaultClause */: + result = ts.reduceLeft(node.statements, f, result); + break; + case 251 /* HeritageClause */: + result = ts.reduceLeft(node.types, f, result); + break; + case 252 /* CatchClause */: + result = reduceNode(node.variableDeclaration, f, result); + result = reduceNode(node.block, f, result); + break; + // Property assignments + case 253 /* PropertyAssignment */: + result = reduceNode(node.name, f, result); + result = reduceNode(node.initializer, f, result); + break; + case 254 /* ShorthandPropertyAssignment */: + result = reduceNode(node.name, f, result); + result = reduceNode(node.objectAssignmentInitializer, f, result); + break; + // Top-level nodes + case 256 /* SourceFile */: + result = ts.reduceLeft(node.statements, f, result); + break; + case 288 /* PartiallyEmittedExpression */: + result = reduceNode(node.expression, f, result); + break; + default: + var edgeTraversalPath = nodeEdgeTraversalMap[kind]; + if (edgeTraversalPath) { + for (var _i = 0, edgeTraversalPath_1 = edgeTraversalPath; _i < edgeTraversalPath_1.length; _i++) { + var edge = edgeTraversalPath_1[_i]; + var value = node[edge.name]; + if (value !== undefined) { + result = ts.isArray(value) + ? ts.reduceLeft(value, f, result) + : f(result, value); + } } - return { - diagnosticMessage: diagnosticMessage, - errorNode: node, - typeName: node.parent.parent.name - }; } - } + break; } - function writeClassDeclaration(node) { - function emitParameterProperties(constructorDeclaration) { - if (constructorDeclaration) { - ts.forEach(constructorDeclaration.parameters, function (param) { - if (param.flags & 92 /* ParameterPropertyModifier */) { - emitPropertyDeclaration(param); - } - }); - } - } - emitJsDocComments(node); - emitModuleElementDeclarationFlags(node); - if (node.flags & 128 /* Abstract */) { - write("abstract "); - } - write("class "); - writeTextOfNode(currentText, node.name); - var prevEnclosingDeclaration = enclosingDeclaration; - enclosingDeclaration = node; - emitTypeParameters(node.typeParameters); - var baseTypeNode = ts.getClassExtendsHeritageClauseElement(node); - if (baseTypeNode) { - emitHeritageClause([baseTypeNode], /*isImplementsList*/ false); - } - emitHeritageClause(ts.getClassImplementsHeritageClauseElements(node), /*isImplementsList*/ true); - write(" {"); - writeLine(); - increaseIndent(); - emitParameterProperties(ts.getFirstConstructorWithBody(node)); - emitLines(node.members); - decreaseIndent(); - write("}"); - writeLine(); - enclosingDeclaration = prevEnclosingDeclaration; + return result; + } + ts.reduceEachChild = reduceEachChild; + function visitNode(node, visitor, test, optional, lift, parenthesize, parentNode) { + if (node === undefined) { + return undefined; } - function writeInterfaceDeclaration(node) { - emitJsDocComments(node); - emitModuleElementDeclarationFlags(node); - write("interface "); - writeTextOfNode(currentText, node.name); - var prevEnclosingDeclaration = enclosingDeclaration; - enclosingDeclaration = node; - emitTypeParameters(node.typeParameters); - emitHeritageClause(ts.getInterfaceBaseTypeNodes(node), /*isImplementsList*/ false); - write(" {"); - writeLine(); - increaseIndent(); - emitLines(node.members); - decreaseIndent(); - write("}"); - writeLine(); - enclosingDeclaration = prevEnclosingDeclaration; + var visited = visitor(node); + if (visited === node) { + return node; } - function emitPropertyDeclaration(node) { - if (ts.hasDynamicName(node)) { - return; + var visitedNode; + if (visited === undefined) { + if (!optional) { + Debug.failNotOptional(); } - emitJsDocComments(node); - emitClassMemberDeclarationFlags(node.flags); - emitVariableDeclaration(node); - write(";"); - writeLine(); + return undefined; } - function emitVariableDeclaration(node) { - // If we are emitting property it isn't moduleElement and hence we already know it needs to be emitted - // so there is no check needed to see if declaration is visible - if (node.kind !== 218 /* VariableDeclaration */ || resolver.isDeclarationVisible(node)) { - if (ts.isBindingPattern(node.name)) { - emitBindingPattern(node.name); - } - else { - // If this node is a computed name, it can only be a symbol, because we've already skipped - // it if it's not a well known symbol. In that case, the text of the name will be exactly - // what we want, namely the name expression enclosed in brackets. - writeTextOfNode(currentText, node.name); - // If optional property emit ? but in the case of parameterProperty declaration with "?" indicating optional parameter for the constructor - // we don't want to emit property declaration with "?" - if ((node.kind === 145 /* PropertyDeclaration */ || node.kind === 144 /* PropertySignature */ || - (node.kind === 142 /* Parameter */ && !ts.isParameterPropertyDeclaration(node))) && ts.hasQuestionToken(node)) { - write("?"); - } - if ((node.kind === 145 /* PropertyDeclaration */ || node.kind === 144 /* PropertySignature */) && node.parent.kind === 159 /* TypeLiteral */) { - emitTypeOfVariableDeclarationFromTypeLiteral(node); - } - else if (!(node.flags & 8 /* Private */)) { - writeTypeOfDeclaration(node, node.type, getVariableDeclarationTypeVisibilityError); - } - } - } - function getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult) { - if (node.kind === 218 /* VariableDeclaration */) { - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? - ts.Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Exported_variable_0_has_or_is_using_private_name_1; - } - else if (node.kind === 145 /* PropertyDeclaration */ || node.kind === 144 /* PropertySignature */) { - // TODO(jfreeman): Deal with computed properties in error reporting. - if (node.flags & 32 /* Static */) { - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? - ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_private_name_1; - } - else if (node.parent.kind === 221 /* ClassDeclaration */) { - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? - ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_private_name_1; - } - else { - // Interfaces cannot have types that cannot be named - return symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Property_0_of_exported_interface_has_or_is_using_private_name_1; - } - } - } - function getVariableDeclarationTypeVisibilityError(symbolAccessibilityResult) { - var diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult); - return diagnosticMessage !== undefined ? { - diagnosticMessage: diagnosticMessage, - errorNode: node, - typeName: node.name - } : undefined; - } - function emitBindingPattern(bindingPattern) { - // Only select non-omitted expression from the bindingPattern's elements. - // We have to do this to avoid emitting trailing commas. - // For example: - // original: var [, c,,] = [ 2,3,4] - // emitted: declare var c: number; // instead of declare var c:number, ; - var elements = []; - for (var _i = 0, _a = bindingPattern.elements; _i < _a.length; _i++) { - var element = _a[_i]; - if (element.kind !== 193 /* OmittedExpression */) { - elements.push(element); - } - } - emitCommaList(elements, emitBindingElement); - } - function emitBindingElement(bindingElement) { - function getBindingElementTypeVisibilityError(symbolAccessibilityResult) { - var diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult); - return diagnosticMessage !== undefined ? { - diagnosticMessage: diagnosticMessage, - errorNode: bindingElement, - typeName: bindingElement.name - } : undefined; - } - if (bindingElement.name) { - if (ts.isBindingPattern(bindingElement.name)) { - emitBindingPattern(bindingElement.name); - } - else { - writeTextOfNode(currentText, bindingElement.name); - writeTypeOfDeclaration(bindingElement, /*type*/ undefined, getBindingElementTypeVisibilityError); - } - } - } + else if (ts.isArray(visited)) { + visitedNode = (lift || extractSingleNode)(visited); } - function emitTypeOfVariableDeclarationFromTypeLiteral(node) { - // if this is property of type literal, - // or is parameter of method/call/construct/index signature of type literal - // emit only if type is specified - if (node.type) { - write(": "); - emitType(node.type); - } + else { + visitedNode = visited; } - function isVariableStatementVisible(node) { - return ts.forEach(node.declarationList.declarations, function (varDeclaration) { return resolver.isDeclarationVisible(varDeclaration); }); + if (parenthesize !== undefined) { + visitedNode = parenthesize(visitedNode, parentNode); } - function writeVariableStatement(node) { - emitJsDocComments(node); - emitModuleElementDeclarationFlags(node); - if (ts.isLet(node.declarationList)) { - write("let "); - } - else if (ts.isConst(node.declarationList)) { - write("const "); - } - else { - write("var "); - } - emitCommaList(node.declarationList.declarations, emitVariableDeclaration, resolver.isDeclarationVisible); - write(";"); - writeLine(); + Debug.assertNode(visitedNode, test); + aggregateTransformFlags(visitedNode); + return visitedNode; + } + ts.visitNode = visitNode; + function visitNodes(nodes, visitor, test, start, count, parenthesize, parentNode) { + if (nodes === undefined) { + return undefined; } - function emitAccessorDeclaration(node) { - if (ts.hasDynamicName(node)) { - return; - } - var accessors = ts.getAllAccessorDeclarations(node.parent.members, node); - var accessorWithTypeAnnotation; - if (node === accessors.firstAccessor) { - emitJsDocComments(accessors.getAccessor); - emitJsDocComments(accessors.setAccessor); - emitClassMemberDeclarationFlags(node.flags | (accessors.setAccessor ? 0 : 64 /* Readonly */)); - writeTextOfNode(currentText, node.name); - if (!(node.flags & 8 /* Private */)) { - accessorWithTypeAnnotation = node; - var type = getTypeAnnotationFromAccessor(node); - if (!type) { - // couldn't get type for the first accessor, try the another one - var anotherAccessor = node.kind === 149 /* GetAccessor */ ? accessors.setAccessor : accessors.getAccessor; - type = getTypeAnnotationFromAccessor(anotherAccessor); - if (type) { - accessorWithTypeAnnotation = anotherAccessor; + var updated; + // Ensure start and count have valid values + var length = nodes.length; + if (start === undefined || start < 0) { + start = 0; + } + if (count === undefined || count > length - start) { + count = length - start; + } + if (start > 0 || count < length) { + // If we are not visiting all of the original nodes, we must always create a new array. + // Since this is a fragment of a node array, we do not copy over the previous location + // and will only copy over `hasTrailingComma` if we are including the last element. + updated = ts.createNodeArray([], /*location*/ undefined, + /*hasTrailingComma*/ nodes.hasTrailingComma && start + count === length); + } + // Visit each original node. + for (var i = 0; i < count; i++) { + var node = nodes[i + start]; + var visited = node !== undefined ? visitor(node) : undefined; + if (updated !== undefined || visited === undefined || visited !== node) { + if (updated === undefined) { + // Ensure we have a copy of `nodes`, up to the current index. + updated = ts.createNodeArray(nodes.slice(0, i), /*location*/ nodes, nodes.hasTrailingComma); + } + if (visited) { + if (ts.isArray(visited)) { + for (var _i = 0, visited_1 = visited; _i < visited_1.length; _i++) { + var visitedNode = visited_1[_i]; + visitedNode = parenthesize + ? parenthesize(visitedNode, parentNode) + : visitedNode; + Debug.assertNode(visitedNode, test); + aggregateTransformFlags(visitedNode); + updated.push(visitedNode); } } - writeTypeOfDeclaration(node, type, getAccessorDeclarationTypeVisibilityError); - } - write(";"); - writeLine(); - } - function getTypeAnnotationFromAccessor(accessor) { - if (accessor) { - return accessor.kind === 149 /* GetAccessor */ - ? accessor.type // Getter - return type - : accessor.parameters.length > 0 - ? accessor.parameters[0].type // Setter parameter type - : undefined; - } - } - function getAccessorDeclarationTypeVisibilityError(symbolAccessibilityResult) { - var diagnosticMessage; - if (accessorWithTypeAnnotation.kind === 150 /* SetAccessor */) { - // Setters have to have type named and cannot infer it so, the type should always be named - if (accessorWithTypeAnnotation.parent.flags & 32 /* Static */) { - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_private_name_1; - } - else { - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_private_name_1; - } - return { - diagnosticMessage: diagnosticMessage, - errorNode: accessorWithTypeAnnotation.parameters[0], - // TODO(jfreeman): Investigate why we are passing node.name instead of node.parameters[0].name - typeName: accessorWithTypeAnnotation.name - }; - } - else { - if (accessorWithTypeAnnotation.flags & 32 /* Static */) { - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? - ts.Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : - ts.Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_private_name_0; - } else { - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? - ts.Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : - ts.Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_private_name_0; + var visitedNode = parenthesize + ? parenthesize(visited, parentNode) + : visited; + Debug.assertNode(visitedNode, test); + aggregateTransformFlags(visitedNode); + updated.push(visitedNode); } - return { - diagnosticMessage: diagnosticMessage, - errorNode: accessorWithTypeAnnotation.name, - typeName: undefined - }; } } } - function writeFunctionDeclaration(node) { - if (ts.hasDynamicName(node)) { - return; - } - // If we are emitting Method/Constructor it isn't moduleElement and hence already determined to be emitting - // so no need to verify if the declaration is visible - if (!resolver.isImplementationOfOverload(node)) { - emitJsDocComments(node); - if (node.kind === 220 /* FunctionDeclaration */) { - emitModuleElementDeclarationFlags(node); - } - else if (node.kind === 147 /* MethodDeclaration */ || node.kind === 148 /* Constructor */) { - emitClassMemberDeclarationFlags(node.flags); - } - if (node.kind === 220 /* FunctionDeclaration */) { - write("function "); - writeTextOfNode(currentText, node.name); - } - else if (node.kind === 148 /* Constructor */) { - write("constructor"); - } - else { - writeTextOfNode(currentText, node.name); - if (ts.hasQuestionToken(node)) { - write("?"); - } - } - emitSignatureDeclaration(node); - } + return updated || nodes; + } + ts.visitNodes = visitNodes; + function visitEachChild(node, visitor, context) { + if (node === undefined) { + return undefined; } - function emitSignatureDeclarationWithJsDocComments(node) { - emitJsDocComments(node); - emitSignatureDeclaration(node); + var kind = node.kind; + // No need to visit nodes with no children. + if ((kind > 0 /* FirstToken */ && kind <= 138 /* LastToken */)) { + return node; } - function emitSignatureDeclaration(node) { - var prevEnclosingDeclaration = enclosingDeclaration; - enclosingDeclaration = node; - var closeParenthesizedFunctionType = false; - if (node.kind === 153 /* IndexSignature */) { - // Index signature can have readonly modifier - emitClassMemberDeclarationFlags(node.flags); - write("["); - } - else { - // Construct signature or constructor type write new Signature - if (node.kind === 152 /* ConstructSignature */ || node.kind === 157 /* ConstructorType */) { - write("new "); - } - else if (node.kind === 156 /* FunctionType */) { - var currentOutput = writer.getText(); - // Do not generate incorrect type when function type with type parameters is type argument - // This could happen if user used space between two '<' making it error free - // e.g var x: A< (a: Tany)=>Tany>; - if (node.typeParameters && currentOutput.charAt(currentOutput.length - 1) === "<") { - closeParenthesizedFunctionType = true; - write("("); + // We do not yet support types. + if ((kind >= 154 /* TypePredicate */ && kind <= 166 /* LiteralType */)) { + return node; + } + switch (node.kind) { + case 198 /* SemicolonClassElement */: + case 201 /* EmptyStatement */: + case 193 /* OmittedExpression */: + case 217 /* DebuggerStatement */: + // No need to visit nodes with no children. + return node; + // Names + case 140 /* ComputedPropertyName */: + return ts.updateComputedPropertyName(node, visitNode(node.expression, visitor, ts.isExpression)); + // Signature elements + case 142 /* Parameter */: + return ts.updateParameterDeclaration(node, visitNodes(node.decorators, visitor, ts.isDecorator), visitNodes(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isBindingName), visitNode(node.type, visitor, ts.isTypeNode, /*optional*/ true), visitNode(node.initializer, visitor, ts.isExpression, /*optional*/ true)); + // Type member + case 145 /* PropertyDeclaration */: + return ts.updateProperty(node, visitNodes(node.decorators, visitor, ts.isDecorator), visitNodes(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isPropertyName), visitNode(node.type, visitor, ts.isTypeNode, /*optional*/ true), visitNode(node.initializer, visitor, ts.isExpression, /*optional*/ true)); + case 147 /* MethodDeclaration */: + return ts.updateMethod(node, visitNodes(node.decorators, visitor, ts.isDecorator), visitNodes(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isPropertyName), visitNodes(node.typeParameters, visitor, ts.isTypeParameter), (context.startLexicalEnvironment(), visitNodes(node.parameters, visitor, ts.isParameter)), visitNode(node.type, visitor, ts.isTypeNode, /*optional*/ true), mergeFunctionBodyLexicalEnvironment(visitNode(node.body, visitor, ts.isFunctionBody, /*optional*/ true), context.endLexicalEnvironment())); + case 148 /* Constructor */: + return ts.updateConstructor(node, visitNodes(node.decorators, visitor, ts.isDecorator), visitNodes(node.modifiers, visitor, ts.isModifier), (context.startLexicalEnvironment(), visitNodes(node.parameters, visitor, ts.isParameter)), mergeFunctionBodyLexicalEnvironment(visitNode(node.body, visitor, ts.isFunctionBody, /*optional*/ true), context.endLexicalEnvironment())); + case 149 /* GetAccessor */: + return ts.updateGetAccessor(node, visitNodes(node.decorators, visitor, ts.isDecorator), visitNodes(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isPropertyName), (context.startLexicalEnvironment(), visitNodes(node.parameters, visitor, ts.isParameter)), visitNode(node.type, visitor, ts.isTypeNode, /*optional*/ true), mergeFunctionBodyLexicalEnvironment(visitNode(node.body, visitor, ts.isFunctionBody, /*optional*/ true), context.endLexicalEnvironment())); + case 150 /* SetAccessor */: + return ts.updateSetAccessor(node, visitNodes(node.decorators, visitor, ts.isDecorator), visitNodes(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isPropertyName), (context.startLexicalEnvironment(), visitNodes(node.parameters, visitor, ts.isParameter)), mergeFunctionBodyLexicalEnvironment(visitNode(node.body, visitor, ts.isFunctionBody, /*optional*/ true), context.endLexicalEnvironment())); + // Binding patterns + case 167 /* ObjectBindingPattern */: + return ts.updateObjectBindingPattern(node, visitNodes(node.elements, visitor, ts.isBindingElement)); + case 168 /* ArrayBindingPattern */: + return ts.updateArrayBindingPattern(node, visitNodes(node.elements, visitor, ts.isArrayBindingElement)); + case 169 /* BindingElement */: + return ts.updateBindingElement(node, visitNode(node.propertyName, visitor, ts.isPropertyName, /*optional*/ true), visitNode(node.name, visitor, ts.isBindingName), visitNode(node.initializer, visitor, ts.isExpression, /*optional*/ true)); + // Expression + case 170 /* ArrayLiteralExpression */: + return ts.updateArrayLiteral(node, visitNodes(node.elements, visitor, ts.isExpression)); + case 171 /* ObjectLiteralExpression */: + return ts.updateObjectLiteral(node, visitNodes(node.properties, visitor, ts.isObjectLiteralElementLike)); + case 172 /* PropertyAccessExpression */: + return ts.updatePropertyAccess(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.name, visitor, ts.isIdentifier)); + case 173 /* ElementAccessExpression */: + return ts.updateElementAccess(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.argumentExpression, visitor, ts.isExpression)); + case 174 /* CallExpression */: + return ts.updateCall(node, visitNode(node.expression, visitor, ts.isExpression), visitNodes(node.typeArguments, visitor, ts.isTypeNode), visitNodes(node.arguments, visitor, ts.isExpression)); + case 175 /* NewExpression */: + return ts.updateNew(node, visitNode(node.expression, visitor, ts.isExpression), visitNodes(node.typeArguments, visitor, ts.isTypeNode), visitNodes(node.arguments, visitor, ts.isExpression)); + case 176 /* TaggedTemplateExpression */: + return ts.updateTaggedTemplate(node, visitNode(node.tag, visitor, ts.isExpression), visitNode(node.template, visitor, ts.isTemplate)); + case 178 /* ParenthesizedExpression */: + return ts.updateParen(node, visitNode(node.expression, visitor, ts.isExpression)); + case 179 /* FunctionExpression */: + return ts.updateFunctionExpression(node, visitNode(node.name, visitor, ts.isPropertyName), visitNodes(node.typeParameters, visitor, ts.isTypeParameter), (context.startLexicalEnvironment(), visitNodes(node.parameters, visitor, ts.isParameter)), visitNode(node.type, visitor, ts.isTypeNode, /*optional*/ true), mergeFunctionBodyLexicalEnvironment(visitNode(node.body, visitor, ts.isFunctionBody, /*optional*/ true), context.endLexicalEnvironment())); + case 180 /* ArrowFunction */: + return ts.updateArrowFunction(node, visitNodes(node.modifiers, visitor, ts.isModifier), visitNodes(node.typeParameters, visitor, ts.isTypeParameter), (context.startLexicalEnvironment(), visitNodes(node.parameters, visitor, ts.isParameter)), visitNode(node.type, visitor, ts.isTypeNode, /*optional*/ true), mergeFunctionBodyLexicalEnvironment(visitNode(node.body, visitor, ts.isConciseBody, /*optional*/ true), context.endLexicalEnvironment())); + case 181 /* DeleteExpression */: + return ts.updateDelete(node, visitNode(node.expression, visitor, ts.isExpression)); + case 182 /* TypeOfExpression */: + return ts.updateTypeOf(node, visitNode(node.expression, visitor, ts.isExpression)); + case 183 /* VoidExpression */: + return ts.updateVoid(node, visitNode(node.expression, visitor, ts.isExpression)); + case 184 /* AwaitExpression */: + return ts.updateAwait(node, visitNode(node.expression, visitor, ts.isExpression)); + case 187 /* BinaryExpression */: + return ts.updateBinary(node, visitNode(node.left, visitor, ts.isExpression), visitNode(node.right, visitor, ts.isExpression)); + case 185 /* PrefixUnaryExpression */: + return ts.updatePrefix(node, visitNode(node.operand, visitor, ts.isExpression)); + case 186 /* PostfixUnaryExpression */: + return ts.updatePostfix(node, visitNode(node.operand, visitor, ts.isExpression)); + case 188 /* ConditionalExpression */: + return ts.updateConditional(node, visitNode(node.condition, visitor, ts.isExpression), visitNode(node.whenTrue, visitor, ts.isExpression), visitNode(node.whenFalse, visitor, ts.isExpression)); + case 189 /* TemplateExpression */: + return ts.updateTemplateExpression(node, visitNode(node.head, visitor, ts.isTemplateLiteralFragment), visitNodes(node.templateSpans, visitor, ts.isTemplateSpan)); + case 190 /* YieldExpression */: + return ts.updateYield(node, visitNode(node.expression, visitor, ts.isExpression)); + case 191 /* SpreadElementExpression */: + return ts.updateSpread(node, visitNode(node.expression, visitor, ts.isExpression)); + case 192 /* ClassExpression */: + return ts.updateClassExpression(node, visitNodes(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isIdentifier, /*optional*/ true), visitNodes(node.typeParameters, visitor, ts.isTypeParameter), visitNodes(node.heritageClauses, visitor, ts.isHeritageClause), visitNodes(node.members, visitor, ts.isClassElement)); + case 194 /* ExpressionWithTypeArguments */: + return ts.updateExpressionWithTypeArguments(node, visitNodes(node.typeArguments, visitor, ts.isTypeNode), visitNode(node.expression, visitor, ts.isExpression)); + // Misc + case 197 /* TemplateSpan */: + return ts.updateTemplateSpan(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.literal, visitor, ts.isTemplateLiteralFragment)); + // Element + case 199 /* Block */: + return ts.updateBlock(node, visitNodes(node.statements, visitor, ts.isStatement)); + case 200 /* VariableStatement */: + return ts.updateVariableStatement(node, visitNodes(node.modifiers, visitor, ts.isModifier), visitNode(node.declarationList, visitor, ts.isVariableDeclarationList)); + case 202 /* ExpressionStatement */: + return ts.updateStatement(node, visitNode(node.expression, visitor, ts.isExpression)); + case 203 /* IfStatement */: + return ts.updateIf(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.thenStatement, visitor, ts.isStatement, /*optional*/ false, liftToBlock), visitNode(node.elseStatement, visitor, ts.isStatement, /*optional*/ true, liftToBlock)); + case 204 /* DoStatement */: + return ts.updateDo(node, visitNode(node.statement, visitor, ts.isStatement, /*optional*/ false, liftToBlock), visitNode(node.expression, visitor, ts.isExpression)); + case 205 /* WhileStatement */: + return ts.updateWhile(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.statement, visitor, ts.isStatement, /*optional*/ false, liftToBlock)); + case 206 /* ForStatement */: + return ts.updateFor(node, visitNode(node.initializer, visitor, ts.isForInitializer), visitNode(node.condition, visitor, ts.isExpression), visitNode(node.incrementor, visitor, ts.isExpression), visitNode(node.statement, visitor, ts.isStatement, /*optional*/ false, liftToBlock)); + case 207 /* ForInStatement */: + return ts.updateForIn(node, visitNode(node.initializer, visitor, ts.isForInitializer), visitNode(node.expression, visitor, ts.isExpression), visitNode(node.statement, visitor, ts.isStatement, /*optional*/ false, liftToBlock)); + case 208 /* ForOfStatement */: + return ts.updateForOf(node, visitNode(node.initializer, visitor, ts.isForInitializer), visitNode(node.expression, visitor, ts.isExpression), visitNode(node.statement, visitor, ts.isStatement, /*optional*/ false, liftToBlock)); + case 209 /* ContinueStatement */: + return ts.updateContinue(node, visitNode(node.label, visitor, ts.isIdentifier, /*optional*/ true)); + case 210 /* BreakStatement */: + return ts.updateBreak(node, visitNode(node.label, visitor, ts.isIdentifier, /*optional*/ true)); + case 211 /* ReturnStatement */: + return ts.updateReturn(node, visitNode(node.expression, visitor, ts.isExpression, /*optional*/ true)); + case 212 /* WithStatement */: + return ts.updateWith(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.statement, visitor, ts.isStatement, /*optional*/ false, liftToBlock)); + case 213 /* SwitchStatement */: + return ts.updateSwitch(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.caseBlock, visitor, ts.isCaseBlock)); + case 214 /* LabeledStatement */: + return ts.updateLabel(node, visitNode(node.label, visitor, ts.isIdentifier), visitNode(node.statement, visitor, ts.isStatement, /*optional*/ false, liftToBlock)); + case 215 /* ThrowStatement */: + return ts.updateThrow(node, visitNode(node.expression, visitor, ts.isExpression)); + case 216 /* TryStatement */: + return ts.updateTry(node, visitNode(node.tryBlock, visitor, ts.isBlock), visitNode(node.catchClause, visitor, ts.isCatchClause, /*optional*/ true), visitNode(node.finallyBlock, visitor, ts.isBlock, /*optional*/ true)); + case 218 /* VariableDeclaration */: + return ts.updateVariableDeclaration(node, visitNode(node.name, visitor, ts.isBindingName), visitNode(node.type, visitor, ts.isTypeNode, /*optional*/ true), visitNode(node.initializer, visitor, ts.isExpression, /*optional*/ true)); + case 219 /* VariableDeclarationList */: + return ts.updateVariableDeclarationList(node, visitNodes(node.declarations, visitor, ts.isVariableDeclaration)); + case 220 /* FunctionDeclaration */: + return ts.updateFunctionDeclaration(node, visitNodes(node.decorators, visitor, ts.isDecorator), visitNodes(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isPropertyName), visitNodes(node.typeParameters, visitor, ts.isTypeParameter), (context.startLexicalEnvironment(), visitNodes(node.parameters, visitor, ts.isParameter)), visitNode(node.type, visitor, ts.isTypeNode, /*optional*/ true), mergeFunctionBodyLexicalEnvironment(visitNode(node.body, visitor, ts.isFunctionBody, /*optional*/ true), context.endLexicalEnvironment())); + case 221 /* ClassDeclaration */: + return ts.updateClassDeclaration(node, visitNodes(node.decorators, visitor, ts.isDecorator), visitNodes(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isIdentifier, /*optional*/ true), visitNodes(node.typeParameters, visitor, ts.isTypeParameter), visitNodes(node.heritageClauses, visitor, ts.isHeritageClause), visitNodes(node.members, visitor, ts.isClassElement)); + case 227 /* CaseBlock */: + return ts.updateCaseBlock(node, visitNodes(node.clauses, visitor, ts.isCaseOrDefaultClause)); + case 230 /* ImportDeclaration */: + return ts.updateImportDeclaration(node, visitNodes(node.decorators, visitor, ts.isDecorator), visitNodes(node.modifiers, visitor, ts.isModifier), visitNode(node.importClause, visitor, ts.isImportClause, /*optional*/ true), visitNode(node.moduleSpecifier, visitor, ts.isExpression)); + case 231 /* ImportClause */: + return ts.updateImportClause(node, visitNode(node.name, visitor, ts.isIdentifier, /*optional*/ true), visitNode(node.namedBindings, visitor, ts.isNamedImportBindings, /*optional*/ true)); + case 232 /* NamespaceImport */: + return ts.updateNamespaceImport(node, visitNode(node.name, visitor, ts.isIdentifier)); + case 233 /* NamedImports */: + return ts.updateNamedImports(node, visitNodes(node.elements, visitor, ts.isImportSpecifier)); + case 234 /* ImportSpecifier */: + return ts.updateImportSpecifier(node, visitNode(node.propertyName, visitor, ts.isIdentifier, /*optional*/ true), visitNode(node.name, visitor, ts.isIdentifier)); + case 235 /* ExportAssignment */: + return ts.updateExportAssignment(node, visitNodes(node.decorators, visitor, ts.isDecorator), visitNodes(node.modifiers, visitor, ts.isModifier), visitNode(node.expression, visitor, ts.isExpression)); + case 236 /* ExportDeclaration */: + return ts.updateExportDeclaration(node, visitNodes(node.decorators, visitor, ts.isDecorator), visitNodes(node.modifiers, visitor, ts.isModifier), visitNode(node.exportClause, visitor, ts.isNamedExports, /*optional*/ true), visitNode(node.moduleSpecifier, visitor, ts.isExpression, /*optional*/ true)); + case 237 /* NamedExports */: + return ts.updateNamedExports(node, visitNodes(node.elements, visitor, ts.isExportSpecifier)); + case 238 /* ExportSpecifier */: + return ts.updateExportSpecifier(node, visitNode(node.propertyName, visitor, ts.isIdentifier, /*optional*/ true), visitNode(node.name, visitor, ts.isIdentifier)); + // JSX + case 241 /* JsxElement */: + return ts.updateJsxElement(node, visitNode(node.openingElement, visitor, ts.isJsxOpeningElement), visitNodes(node.children, visitor, ts.isJsxChild), visitNode(node.closingElement, visitor, ts.isJsxClosingElement)); + case 242 /* JsxSelfClosingElement */: + return ts.updateJsxSelfClosingElement(node, visitNode(node.tagName, visitor, ts.isJsxTagNameExpression), visitNodes(node.attributes, visitor, ts.isJsxAttributeLike)); + case 243 /* JsxOpeningElement */: + return ts.updateJsxOpeningElement(node, visitNode(node.tagName, visitor, ts.isJsxTagNameExpression), visitNodes(node.attributes, visitor, ts.isJsxAttributeLike)); + case 245 /* JsxClosingElement */: + return ts.updateJsxClosingElement(node, visitNode(node.tagName, visitor, ts.isJsxTagNameExpression)); + case 246 /* JsxAttribute */: + return ts.updateJsxAttribute(node, visitNode(node.name, visitor, ts.isIdentifier), visitNode(node.initializer, visitor, ts.isStringLiteralOrJsxExpression)); + case 247 /* JsxSpreadAttribute */: + return ts.updateJsxSpreadAttribute(node, visitNode(node.expression, visitor, ts.isExpression)); + case 248 /* JsxExpression */: + return ts.updateJsxExpression(node, visitNode(node.expression, visitor, ts.isExpression)); + // Clauses + case 249 /* CaseClause */: + return ts.updateCaseClause(node, visitNode(node.expression, visitor, ts.isExpression), visitNodes(node.statements, visitor, ts.isStatement)); + case 250 /* DefaultClause */: + return ts.updateDefaultClause(node, visitNodes(node.statements, visitor, ts.isStatement)); + case 251 /* HeritageClause */: + return ts.updateHeritageClause(node, visitNodes(node.types, visitor, ts.isExpressionWithTypeArguments)); + case 252 /* CatchClause */: + return ts.updateCatchClause(node, visitNode(node.variableDeclaration, visitor, ts.isVariableDeclaration), visitNode(node.block, visitor, ts.isBlock)); + // Property assignments + case 253 /* PropertyAssignment */: + return ts.updatePropertyAssignment(node, visitNode(node.name, visitor, ts.isPropertyName), visitNode(node.initializer, visitor, ts.isExpression)); + case 254 /* ShorthandPropertyAssignment */: + return ts.updateShorthandPropertyAssignment(node, visitNode(node.name, visitor, ts.isIdentifier), visitNode(node.objectAssignmentInitializer, visitor, ts.isExpression)); + // Top-level nodes + case 256 /* SourceFile */: + context.startLexicalEnvironment(); + return ts.updateSourceFileNode(node, ts.createNodeArray(ts.concatenate(visitNodes(node.statements, visitor, ts.isStatement), context.endLexicalEnvironment()), node.statements)); + // Transformation nodes + case 288 /* PartiallyEmittedExpression */: + return ts.updatePartiallyEmittedExpression(node, visitNode(node.expression, visitor, ts.isExpression)); + default: + var updated = void 0; + var edgeTraversalPath = nodeEdgeTraversalMap[kind]; + if (edgeTraversalPath) { + for (var _i = 0, edgeTraversalPath_2 = edgeTraversalPath; _i < edgeTraversalPath_2.length; _i++) { + var edge = edgeTraversalPath_2[_i]; + var value = node[edge.name]; + if (value !== undefined) { + var visited = ts.isArray(value) + ? visitNodes(value, visitor, edge.test, 0, value.length, edge.parenthesize, node) + : visitNode(value, visitor, edge.test, edge.optional, edge.lift, edge.parenthesize, node); + if (updated !== undefined || visited !== value) { + if (updated === undefined) { + updated = ts.getMutableClone(node); + } + if (visited !== value) { + updated[edge.name] = visited; + } + } + } } } - emitTypeParameters(node.typeParameters); - write("("); - } - // Parameters - emitCommaList(node.parameters, emitParameterDeclaration); - if (node.kind === 153 /* IndexSignature */) { - write("]"); + return updated ? ts.updateNode(updated, node) : node; + } + // return node; + } + ts.visitEachChild = visitEachChild; + function mergeFunctionBodyLexicalEnvironment(body, declarations) { + if (body && declarations !== undefined && declarations.length > 0) { + if (ts.isBlock(body)) { + return ts.updateBlock(body, ts.createNodeArray(ts.concatenate(body.statements, declarations), body.statements)); } else { - write(")"); + return ts.createBlock(ts.createNodeArray([ts.createReturn(body, /*location*/ body)].concat(declarations), body), + /*location*/ body, + /*multiLine*/ true); + } + } + return body; + } + ts.mergeFunctionBodyLexicalEnvironment = mergeFunctionBodyLexicalEnvironment; + /** + * Lifts a NodeArray containing only Statement nodes to a block. + * + * @param nodes The NodeArray. + */ + function liftToBlock(nodes) { + Debug.assert(ts.every(nodes, ts.isStatement), "Cannot lift nodes to a Block."); + return ts.singleOrUndefined(nodes) || ts.createBlock(nodes); + } + ts.liftToBlock = liftToBlock; + /** + * Extracts the single node from a NodeArray. + * + * @param nodes The NodeArray. + */ + function extractSingleNode(nodes) { + Debug.assert(nodes.length <= 1, "Too many nodes written to output."); + return ts.singleOrUndefined(nodes); + } + /** + * Aggregates the TransformFlags for a Node and its subtree. + */ + function aggregateTransformFlags(node) { + aggregateTransformFlagsForNode(node); + return node; + } + ts.aggregateTransformFlags = aggregateTransformFlags; + /** + * Aggregates the TransformFlags for a Node and its subtree. The flags for the subtree are + * computed first, then the transform flags for the current node are computed from the subtree + * flags and the state of the current node. Finally, the transform flags of the node are + * returned, excluding any flags that should not be included in its parent node's subtree + * flags. + */ + function aggregateTransformFlagsForNode(node) { + if (node === undefined) { + return 0 /* None */; + } + else if (node.transformFlags & 536870912 /* HasComputedFlags */) { + return node.transformFlags & ~getTransformFlagsSubtreeExclusions(node.kind); + } + else { + var subtreeFlags = aggregateTransformFlagsForSubtree(node); + return ts.computeTransformFlagsForNode(node, subtreeFlags); + } + } + /** + * Aggregates the transform flags for the subtree of a node. + */ + function aggregateTransformFlagsForSubtree(node) { + // We do not transform ambient declarations or types, so there is no need to + // recursively aggregate transform flags. + if (ts.hasModifier(node, 2 /* Ambient */) || ts.isTypeNode(node)) { + return 0 /* None */; + } + // Aggregate the transform flags of each child. + return reduceEachChild(node, aggregateTransformFlagsForChildNode, 0 /* None */); + } + /** + * Aggregates the TransformFlags of a child node with the TransformFlags of its + * siblings. + */ + function aggregateTransformFlagsForChildNode(transformFlags, child) { + return transformFlags | aggregateTransformFlagsForNode(child); + } + /** + * Gets the transform flags to exclude when unioning the transform flags of a subtree. + * + * NOTE: This needs to be kept up-to-date with the exclusions used in `computeTransformFlagsForNode`. + * For performance reasons, `computeTransformFlagsForNode` uses local constant values rather + * than calling this function. + */ + function getTransformFlagsSubtreeExclusions(kind) { + if (kind >= 154 /* FirstTypeNode */ && kind <= 166 /* LastTypeNode */) { + return -3 /* TypeExcludes */; + } + switch (kind) { + case 174 /* CallExpression */: + case 175 /* NewExpression */: + case 170 /* ArrayLiteralExpression */: + return 537133909 /* ArrayLiteralOrCallOrNewExcludes */; + case 225 /* ModuleDeclaration */: + return 546335573 /* ModuleExcludes */; + case 142 /* Parameter */: + return 538968917 /* ParameterExcludes */; + case 180 /* ArrowFunction */: + return 550710101 /* ArrowFunctionExcludes */; + case 179 /* FunctionExpression */: + case 220 /* FunctionDeclaration */: + return 550726485 /* FunctionExcludes */; + case 219 /* VariableDeclarationList */: + return 538968917 /* VariableDeclarationListExcludes */; + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + return 537590613 /* ClassExcludes */; + case 148 /* Constructor */: + return 550593365 /* ConstructorExcludes */; + case 147 /* MethodDeclaration */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + return 550593365 /* MethodOrAccessorExcludes */; + case 117 /* AnyKeyword */: + case 130 /* NumberKeyword */: + case 127 /* NeverKeyword */: + case 132 /* StringKeyword */: + case 120 /* BooleanKeyword */: + case 133 /* SymbolKeyword */: + case 103 /* VoidKeyword */: + case 141 /* TypeParameter */: + case 144 /* PropertySignature */: + case 146 /* MethodSignature */: + case 151 /* CallSignature */: + case 152 /* ConstructSignature */: + case 153 /* IndexSignature */: + case 222 /* InterfaceDeclaration */: + case 223 /* TypeAliasDeclaration */: + return -3 /* TypeExcludes */; + case 171 /* ObjectLiteralExpression */: + return 537430869 /* ObjectLiteralExcludes */; + default: + return 536871765 /* NodeExcludes */; + } + } + var Debug; + (function (Debug) { + Debug.failNotOptional = Debug.shouldAssert(1 /* Normal */) + ? function (message) { return Debug.assert(false, message || "Node not optional."); } + : function (message) { }; + Debug.failBadSyntaxKind = Debug.shouldAssert(1 /* Normal */) + ? function (node, message) { return Debug.assert(false, message || "Unexpected node.", function () { return "Node " + ts.formatSyntaxKind(node.kind) + " was unexpected."; }); } + : function (node, message) { }; + Debug.assertNode = Debug.shouldAssert(1 /* Normal */) + ? function (node, test, message) { return Debug.assert(test === undefined || test(node), message || "Unexpected node.", function () { return "Node " + ts.formatSyntaxKind(node.kind) + " did not pass test '" + getFunctionName(test) + "'."; }); } + : function (node, test, message) { }; + function getFunctionName(func) { + if (typeof func !== "function") { + return ""; } - // If this is not a constructor and is not private, emit the return type - var isFunctionTypeOrConstructorType = node.kind === 156 /* FunctionType */ || node.kind === 157 /* ConstructorType */; - if (isFunctionTypeOrConstructorType || node.parent.kind === 159 /* TypeLiteral */) { - // Emit type literal signature return type only if specified - if (node.type) { - write(isFunctionTypeOrConstructorType ? " => " : ": "); - emitType(node.type); - } + else if (func.hasOwnProperty("name")) { + return func.name; } - else if (node.kind !== 148 /* Constructor */ && !(node.flags & 8 /* Private */)) { - writeReturnTypeAtSignature(node, getReturnTypeVisibilityError); + else { + var text = Function.prototype.toString.call(func); + var match = /^function\s+([\w\$]+)\s*\(/.exec(text); + return match ? match[1] : ""; } - enclosingDeclaration = prevEnclosingDeclaration; - if (!isFunctionTypeOrConstructorType) { - write(";"); - writeLine(); + } + })(Debug = ts.Debug || (ts.Debug = {})); + var _a; +})(ts || (ts = {})); +/// +/// +/*@internal*/ +var ts; +(function (ts) { + /** + * Flattens a destructuring assignment expression. + * + * @param root The destructuring assignment expression. + * @param needsValue Indicates whether the value from the right-hand-side of the + * destructuring assignment is needed as part of a larger expression. + * @param recordTempVariable A callback used to record new temporary variables. + * @param visitor An optional visitor to use to visit expressions. + */ + function flattenDestructuringAssignment(context, node, needsValue, recordTempVariable, visitor) { + if (ts.isEmptyObjectLiteralOrArrayLiteral(node.left)) { + var right = node.right; + if (ts.isDestructuringAssignment(right)) { + return flattenDestructuringAssignment(context, right, needsValue, recordTempVariable, visitor); } - else if (closeParenthesizedFunctionType) { - write(")"); + else { + return node.right; } - function getReturnTypeVisibilityError(symbolAccessibilityResult) { - var diagnosticMessage; - switch (node.kind) { - case 152 /* ConstructSignature */: - // Interfaces cannot have return types that cannot be named - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_0; - break; - case 151 /* CallSignature */: - // Interfaces cannot have return types that cannot be named - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_private_name_0; - break; - case 153 /* IndexSignature */: - // Interfaces cannot have return types that cannot be named - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_private_name_0; - break; - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - if (node.flags & 32 /* Static */) { - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? - ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : - ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_private_name_0; - } - else if (node.parent.kind === 221 /* ClassDeclaration */) { - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? - ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : - ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_private_name_0; - } - else { - // Interfaces cannot have return types that cannot be named - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_private_name_0; - } - break; - case 220 /* FunctionDeclaration */: - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? - ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : - ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_private_name_0; - break; - default: - ts.Debug.fail("This is unknown kind for signature: " + node.kind); + } + var location = node; + var value = node.right; + var expressions = []; + if (needsValue) { + // If the right-hand value of the destructuring assignment needs to be preserved (as + // is the case when the destructuring assignmen) is part of a larger expression), + // then we need to cache the right-hand value. + // + // The source map location for the assignment should point to the entire binary + // expression. + value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, location, emitTempVariableAssignment, visitor); + } + else if (ts.nodeIsSynthesized(node)) { + // Generally, the source map location for a destructuring assignment is the root + // expression. + // + // However, if the root expression is synthesized (as in the case + // of the initializer when transforming a ForOfStatement), then the source map + // location should point to the right-hand value of the expression. + location = value; + } + flattenDestructuring(context, node, value, location, emitAssignment, emitTempVariableAssignment, visitor); + if (needsValue) { + expressions.push(value); + } + var expression = ts.inlineExpressions(expressions); + ts.aggregateTransformFlags(expression); + return expression; + function emitAssignment(name, value, location) { + var expression = ts.createAssignment(name, value, location); + // NOTE: this completely disables source maps, but aligns with the behavior of + // `emitAssignment` in the old emitter. + ts.setEmitFlags(expression, 2048 /* NoNestedSourceMaps */); + ts.aggregateTransformFlags(expression); + expressions.push(expression); + } + function emitTempVariableAssignment(value, location) { + var name = ts.createTempVariable(recordTempVariable); + emitAssignment(name, value, location); + return name; + } + } + ts.flattenDestructuringAssignment = flattenDestructuringAssignment; + /** + * Flattens binding patterns in a parameter declaration. + * + * @param node The ParameterDeclaration to flatten. + * @param value The rhs value for the binding pattern. + * @param visitor An optional visitor to use to visit expressions. + */ + function flattenParameterDestructuring(context, node, value, visitor) { + var declarations = []; + flattenDestructuring(context, node, value, node, emitAssignment, emitTempVariableAssignment, visitor); + return declarations; + function emitAssignment(name, value, location) { + var declaration = ts.createVariableDeclaration(name, /*type*/ undefined, value, location); + // NOTE: this completely disables source maps, but aligns with the behavior of + // `emitAssignment` in the old emitter. + ts.setEmitFlags(declaration, 2048 /* NoNestedSourceMaps */); + ts.aggregateTransformFlags(declaration); + declarations.push(declaration); + } + function emitTempVariableAssignment(value, location) { + var name = ts.createTempVariable(/*recordTempVariable*/ undefined); + emitAssignment(name, value, location); + return name; + } + } + ts.flattenParameterDestructuring = flattenParameterDestructuring; + /** + * Flattens binding patterns in a variable declaration. + * + * @param node The VariableDeclaration to flatten. + * @param value An optional rhs value for the binding pattern. + * @param visitor An optional visitor to use to visit expressions. + */ + function flattenVariableDestructuring(context, node, value, visitor, recordTempVariable) { + var declarations = []; + var pendingAssignments; + flattenDestructuring(context, node, value, node, emitAssignment, emitTempVariableAssignment, visitor); + return declarations; + function emitAssignment(name, value, location, original) { + if (pendingAssignments) { + pendingAssignments.push(value); + value = ts.inlineExpressions(pendingAssignments); + pendingAssignments = undefined; + } + var declaration = ts.createVariableDeclaration(name, /*type*/ undefined, value, location); + declaration.original = original; + // NOTE: this completely disables source maps, but aligns with the behavior of + // `emitAssignment` in the old emitter. + ts.setEmitFlags(declaration, 2048 /* NoNestedSourceMaps */); + declarations.push(declaration); + ts.aggregateTransformFlags(declaration); + } + function emitTempVariableAssignment(value, location) { + var name = ts.createTempVariable(recordTempVariable); + if (recordTempVariable) { + var assignment = ts.createAssignment(name, value, location); + if (pendingAssignments) { + pendingAssignments.push(assignment); + } + else { + pendingAssignments = [assignment]; } - return { - diagnosticMessage: diagnosticMessage, - errorNode: node.name || node - }; } - } - function emitParameterDeclaration(node) { - increaseIndent(); - emitJsDocComments(node); - if (node.dotDotDotToken) { - write("..."); + else { + emitAssignment(name, value, location, /*original*/ undefined); } - if (ts.isBindingPattern(node.name)) { - // For bindingPattern, we can't simply writeTextOfNode from the source file - // because we want to omit the initializer and using writeTextOfNode will result in initializer get emitted. - // Therefore, we will have to recursively emit each element in the bindingPattern. - emitBindingPattern(node.name); + return name; + } + } + ts.flattenVariableDestructuring = flattenVariableDestructuring; + /** + * Flattens binding patterns in a variable declaration and transforms them into an expression. + * + * @param node The VariableDeclaration to flatten. + * @param recordTempVariable A callback used to record new temporary variables. + * @param nameSubstitution An optional callback used to substitute binding names. + * @param visitor An optional visitor to use to visit expressions. + */ + function flattenVariableDestructuringToExpression(context, node, recordTempVariable, nameSubstitution, visitor) { + var pendingAssignments = []; + flattenDestructuring(context, node, /*value*/ undefined, node, emitAssignment, emitTempVariableAssignment, visitor); + var expression = ts.inlineExpressions(pendingAssignments); + ts.aggregateTransformFlags(expression); + return expression; + function emitAssignment(name, value, location, original) { + var left = nameSubstitution && nameSubstitution(name) || name; + emitPendingAssignment(left, value, location, original); + } + function emitTempVariableAssignment(value, location) { + var name = ts.createTempVariable(recordTempVariable); + emitPendingAssignment(name, value, location, /*original*/ undefined); + return name; + } + function emitPendingAssignment(name, value, location, original) { + var expression = ts.createAssignment(name, value, location); + expression.original = original; + // NOTE: this completely disables source maps, but aligns with the behavior of + // `emitAssignment` in the old emitter. + ts.setEmitFlags(expression, 2048 /* NoNestedSourceMaps */); + pendingAssignments.push(expression); + return expression; + } + } + ts.flattenVariableDestructuringToExpression = flattenVariableDestructuringToExpression; + function flattenDestructuring(context, root, value, location, emitAssignment, emitTempVariableAssignment, visitor) { + if (value && visitor) { + value = ts.visitNode(value, visitor, ts.isExpression); + } + if (ts.isBinaryExpression(root)) { + emitDestructuringAssignment(root.left, value, location); + } + else { + emitBindingElement(root, value); + } + function emitDestructuringAssignment(bindingTarget, value, location) { + // When emitting target = value use source map node to highlight, including any temporary assignments needed for this + var target; + if (ts.isShorthandPropertyAssignment(bindingTarget)) { + var initializer = visitor + ? ts.visitNode(bindingTarget.objectAssignmentInitializer, visitor, ts.isExpression) + : bindingTarget.objectAssignmentInitializer; + if (initializer) { + value = createDefaultValueCheck(value, initializer, location); + } + target = bindingTarget.name; + } + else if (ts.isBinaryExpression(bindingTarget) && bindingTarget.operatorToken.kind === 56 /* EqualsToken */) { + var initializer = visitor + ? ts.visitNode(bindingTarget.right, visitor, ts.isExpression) + : bindingTarget.right; + value = createDefaultValueCheck(value, initializer, location); + target = bindingTarget.left; } else { - writeTextOfNode(currentText, node.name); + target = bindingTarget; } - if (resolver.isOptionalParameter(node)) { - write("?"); + if (target.kind === 171 /* ObjectLiteralExpression */) { + emitObjectLiteralAssignment(target, value, location); } - decreaseIndent(); - if (node.parent.kind === 156 /* FunctionType */ || - node.parent.kind === 157 /* ConstructorType */ || - node.parent.parent.kind === 159 /* TypeLiteral */) { - emitTypeOfVariableDeclarationFromTypeLiteral(node); + else if (target.kind === 170 /* ArrayLiteralExpression */) { + emitArrayLiteralAssignment(target, value, location); } - else if (!(node.parent.flags & 8 /* Private */)) { - writeTypeOfDeclaration(node, node.type, getParameterDeclarationTypeVisibilityError); + else { + var name_29 = ts.getMutableClone(target); + ts.setSourceMapRange(name_29, target); + ts.setCommentRange(name_29, target); + emitAssignment(name_29, value, location, /*original*/ undefined); } - function getParameterDeclarationTypeVisibilityError(symbolAccessibilityResult) { - var diagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult); - return diagnosticMessage !== undefined ? { - diagnosticMessage: diagnosticMessage, - errorNode: node, - typeName: node.name - } : undefined; + } + function emitObjectLiteralAssignment(target, value, location) { + var properties = target.properties; + if (properties.length !== 1) { + // For anything but a single element destructuring we need to generate a temporary + // to ensure value is evaluated exactly once. + // When doing so we want to hightlight the passed in source map node since thats the one needing this temp assignment + value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, location, emitTempVariableAssignment); } - function getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult) { - switch (node.parent.kind) { - case 148 /* Constructor */: - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? - ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_private_name_1; - case 152 /* ConstructSignature */: - // Interfaces cannot have parameter types that cannot be named - return symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; - case 151 /* CallSignature */: - // Interfaces cannot have parameter types that cannot be named - return symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1; - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - if (node.parent.flags & 32 /* Static */) { - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? - ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1; - } - else if (node.parent.parent.kind === 221 /* ClassDeclaration */) { - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? - ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1; - } - else { - // Interfaces cannot have parameter types that cannot be named - return symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1; - } - case 220 /* FunctionDeclaration */: - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? - ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_private_name_1; - default: - ts.Debug.fail("This is unknown parent for parameter: " + node.parent.kind); + for (var _i = 0, properties_6 = properties; _i < properties_6.length; _i++) { + var p = properties_6[_i]; + if (p.kind === 253 /* PropertyAssignment */ || p.kind === 254 /* ShorthandPropertyAssignment */) { + var propName = p.name; + var target_1 = p.kind === 254 /* ShorthandPropertyAssignment */ ? p : p.initializer || propName; + // Assignment for target = value.propName should highligh whole property, hence use p as source map node + emitDestructuringAssignment(target_1, createDestructuringPropertyAccess(value, propName), p); } } - function emitBindingPattern(bindingPattern) { - // We have to explicitly emit square bracket and bracket because these tokens are not store inside the node. - if (bindingPattern.kind === 167 /* ObjectBindingPattern */) { - write("{"); - emitCommaList(bindingPattern.elements, emitBindingElement); - write("}"); - } - else if (bindingPattern.kind === 168 /* ArrayBindingPattern */) { - write("["); - var elements = bindingPattern.elements; - emitCommaList(elements, emitBindingElement); - if (elements && elements.hasTrailingComma) { - write(", "); + } + function emitArrayLiteralAssignment(target, value, location) { + var elements = target.elements; + var numElements = elements.length; + if (numElements !== 1) { + // For anything but a single element destructuring we need to generate a temporary + // to ensure value is evaluated exactly once. + // When doing so we want to hightlight the passed in source map node since thats the one needing this temp assignment + value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, location, emitTempVariableAssignment); + } + for (var i = 0; i < numElements; i++) { + var e = elements[i]; + if (e.kind !== 193 /* OmittedExpression */) { + // Assignment for target = value.propName should highligh whole property, hence use e as source map node + if (e.kind !== 191 /* SpreadElementExpression */) { + emitDestructuringAssignment(e, ts.createElementAccess(value, ts.createLiteral(i)), e); + } + else if (i === numElements - 1) { + emitDestructuringAssignment(e.expression, ts.createArraySlice(value, i), e); } - write("]"); } } - function emitBindingElement(bindingElement) { - if (bindingElement.kind === 193 /* OmittedExpression */) { - // If bindingElement is an omittedExpression (i.e. containing elision), - // we will emit blank space (although this may differ from users' original code, - // it allows emitSeparatedList to write separator appropriately) - // Example: - // original: function foo([, x, ,]) {} - // emit : function foo([ , x, , ]) {} - write(" "); - } - else if (bindingElement.kind === 169 /* BindingElement */) { - if (bindingElement.propertyName) { - // bindingElement has propertyName property in the following case: - // { y: [a,b,c] ...} -> bindingPattern will have a property called propertyName for "y" - // We have to explicitly emit the propertyName before descending into its binding elements. - // Example: - // original: function foo({y: [a,b,c]}) {} - // emit : declare function foo({y: [a, b, c]}: { y: [any, any, any] }) void; - writeTextOfNode(currentText, bindingElement.propertyName); - write(": "); + } + function emitBindingElement(target, value) { + // Any temporary assignments needed to emit target = value should point to target + var initializer = visitor ? ts.visitNode(target.initializer, visitor, ts.isExpression) : target.initializer; + if (initializer) { + // Combine value and initializer + value = value ? createDefaultValueCheck(value, initializer, target) : initializer; + } + else if (!value) { + // Use 'void 0' in absence of value and initializer + value = ts.createVoidZero(); + } + var name = target.name; + if (ts.isBindingPattern(name)) { + var elements = name.elements; + var numElements = elements.length; + if (numElements !== 1) { + // For anything other than a single-element destructuring we need to generate a temporary + // to ensure value is evaluated exactly once. Additionally, if we have zero elements + // we need to emit *something* to ensure that in case a 'var' keyword was already emitted, + // so in that case, we'll intentionally create that temporary. + value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ numElements !== 0, target, emitTempVariableAssignment); + } + for (var i = 0; i < numElements; i++) { + var element = elements[i]; + if (ts.isOmittedExpression(element)) { + continue; } - if (bindingElement.name) { - if (ts.isBindingPattern(bindingElement.name)) { - // If it is a nested binding pattern, we will recursively descend into each element and emit each one separately. - // In the case of rest element, we will omit rest element. - // Example: - // original: function foo([a, [[b]], c] = [1,[["string"]], 3]) {} - // emit : declare function foo([a, [[b]], c]: [number, [[string]], number]): void; - // original with rest: function foo([a, ...c]) {} - // emit : declare function foo([a, ...c]): void; - emitBindingPattern(bindingElement.name); + else if (name.kind === 167 /* ObjectBindingPattern */) { + // Rewrite element to a declaration with an initializer that fetches property + var propName = element.propertyName || element.name; + emitBindingElement(element, createDestructuringPropertyAccess(value, propName)); + } + else { + if (!element.dotDotDotToken) { + // Rewrite element to a declaration that accesses array element at index i + emitBindingElement(element, ts.createElementAccess(value, i)); } - else { - ts.Debug.assert(bindingElement.name.kind === 69 /* Identifier */); - // If the node is just an identifier, we will simply emit the text associated with the node's name - // Example: - // original: function foo({y = 10, x}) {} - // emit : declare function foo({y, x}: {number, any}): void; - if (bindingElement.dotDotDotToken) { - write("..."); - } - writeTextOfNode(currentText, bindingElement.name); + else if (i === numElements - 1) { + emitBindingElement(element, ts.createArraySlice(value, i)); } } } } - } - function emitNode(node) { - switch (node.kind) { - case 220 /* FunctionDeclaration */: - case 225 /* ModuleDeclaration */: - case 229 /* ImportEqualsDeclaration */: - case 222 /* InterfaceDeclaration */: - case 221 /* ClassDeclaration */: - case 223 /* TypeAliasDeclaration */: - case 224 /* EnumDeclaration */: - return emitModuleElement(node, isModuleElementVisible(node)); - case 200 /* VariableStatement */: - return emitModuleElement(node, isVariableStatementVisible(node)); - case 230 /* ImportDeclaration */: - // Import declaration without import clause is visible, otherwise it is not visible - return emitModuleElement(node, /*isModuleElementVisible*/ !node.importClause); - case 236 /* ExportDeclaration */: - return emitExportDeclaration(node); - case 148 /* Constructor */: - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - return writeFunctionDeclaration(node); - case 152 /* ConstructSignature */: - case 151 /* CallSignature */: - case 153 /* IndexSignature */: - return emitSignatureDeclarationWithJsDocComments(node); - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - return emitAccessorDeclaration(node); - case 145 /* PropertyDeclaration */: - case 144 /* PropertySignature */: - return emitPropertyDeclaration(node); - case 255 /* EnumMember */: - return emitEnumMemberDeclaration(node); - case 235 /* ExportAssignment */: - return emitExportAssignment(node); - case 256 /* SourceFile */: - return emitSourceFile(node); + else { + emitAssignment(name, value, target, target); } } + function createDefaultValueCheck(value, defaultValue, location) { + value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, location, emitTempVariableAssignment); + return ts.createConditional(ts.createStrictEquality(value, ts.createVoidZero()), ts.createToken(53 /* QuestionToken */), defaultValue, ts.createToken(54 /* ColonToken */), value); + } /** - * Adds the reference to referenced file, returns true if global file reference was emitted - * @param referencedFile - * @param addBundledFileReference Determines if global file reference corresponding to bundled file should be emitted or not + * Creates either a PropertyAccessExpression or an ElementAccessExpression for the + * right-hand side of a transformed destructuring assignment. + * + * @param expression The right-hand expression that is the source of the property. + * @param propertyName The destructuring property name. */ - function writeReferencePath(referencedFile, addBundledFileReference) { - var declFileName; - var addedBundledEmitReference = false; - if (ts.isDeclarationFile(referencedFile)) { - // Declaration file, use declaration file name - declFileName = referencedFile.fileName; - } - else { - // Get the declaration file path - ts.forEachExpectedEmitFile(host, getDeclFileName, referencedFile); + function createDestructuringPropertyAccess(expression, propertyName) { + if (ts.isComputedPropertyName(propertyName)) { + return ts.createElementAccess(expression, ensureIdentifier(propertyName.expression, /*reuseIdentifierExpressions*/ false, /*location*/ propertyName, emitTempVariableAssignment)); } - if (declFileName) { - declFileName = ts.getRelativePathToDirectoryOrUrl(ts.getDirectoryPath(ts.normalizeSlashes(declarationFilePath)), declFileName, host.getCurrentDirectory(), host.getCanonicalFileName, - /*isAbsolutePathAnUrl*/ false); - referencesOutput += "/// " + newLine; + else if (ts.isLiteralExpression(propertyName)) { + var clone_2 = ts.getSynthesizedClone(propertyName); + clone_2.text = ts.unescapeIdentifier(clone_2.text); + return ts.createElementAccess(expression, clone_2); } - return addedBundledEmitReference; - function getDeclFileName(emitFileNames, sourceFiles, isBundledEmit) { - // Dont add reference path to this file if it is a bundled emit and caller asked not emit bundled file path - if (isBundledEmit && !addBundledFileReference) { - return; + else { + if (ts.isGeneratedIdentifier(propertyName)) { + var clone_3 = ts.getSynthesizedClone(propertyName); + clone_3.text = ts.unescapeIdentifier(clone_3.text); + return ts.createPropertyAccess(expression, clone_3); + } + else { + return ts.createPropertyAccess(expression, ts.createIdentifier(ts.unescapeIdentifier(propertyName.text))); } - ts.Debug.assert(!!emitFileNames.declarationFilePath || ts.isSourceFileJavaScript(referencedFile), "Declaration file is not present only for javascript files"); - declFileName = emitFileNames.declarationFilePath || emitFileNames.jsFilePath; - addedBundledEmitReference = isBundledEmit; } } } - /* @internal */ - function writeDeclarationFile(declarationFilePath, sourceFiles, isBundledEmit, host, resolver, emitterDiagnostics) { - var emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFiles, isBundledEmit); - var emitSkipped = emitDeclarationResult.reportedDeclarationError || host.isEmitBlocked(declarationFilePath) || host.getCompilerOptions().noEmit; - if (!emitSkipped) { - var declarationOutput = emitDeclarationResult.referencesOutput - + getDeclarationOutput(emitDeclarationResult.synchronousDeclarationOutput, emitDeclarationResult.moduleElementDeclarationEmitInfo); - ts.writeFile(host, emitterDiagnostics, declarationFilePath, declarationOutput, host.getCompilerOptions().emitBOM, sourceFiles); + /** + * Ensures that there exists a declared identifier whose value holds the given expression. + * This function is useful to ensure that the expression's value can be read from in subsequent expressions. + * Unless 'reuseIdentifierExpressions' is false, 'value' will be returned if it is just an identifier. + * + * @param value the expression whose value needs to be bound. + * @param reuseIdentifierExpressions true if identifier expressions can simply be returned; + * false if it is necessary to always emit an identifier. + * @param location The location to use for source maps and comments. + * @param emitTempVariableAssignment A callback used to emit a temporary variable. + * @param visitor An optional callback used to visit the value. + */ + function ensureIdentifier(value, reuseIdentifierExpressions, location, emitTempVariableAssignment, visitor) { + if (ts.isIdentifier(value) && reuseIdentifierExpressions) { + return value; } - return emitSkipped; - function getDeclarationOutput(synchronousDeclarationOutput, moduleElementDeclarationEmitInfo) { - var appliedSyncOutputPos = 0; - var declarationOutput = ""; - // apply asynchronous additions to the synchronous output - ts.forEach(moduleElementDeclarationEmitInfo, function (aliasEmitInfo) { - if (aliasEmitInfo.asynchronousOutput) { - declarationOutput += synchronousDeclarationOutput.substring(appliedSyncOutputPos, aliasEmitInfo.outputPos); - declarationOutput += getDeclarationOutput(aliasEmitInfo.asynchronousOutput, aliasEmitInfo.subModuleElementDeclarationEmitInfo); - appliedSyncOutputPos = aliasEmitInfo.outputPos; - } - }); - declarationOutput += synchronousDeclarationOutput.substring(appliedSyncOutputPos); - return declarationOutput; + else { + if (visitor) { + value = ts.visitNode(value, visitor, ts.isExpression); + } + return emitTempVariableAssignment(value, location); } } - ts.writeDeclarationFile = writeDeclarationFile; })(ts || (ts = {})); -/// -/* @internal */ +/// +/// +/// +/*@internal*/ var ts; (function (ts) { - var nullSourceMapWriter; - // Used for initialize lastEncodedSourceMapSpan and reset lastEncodedSourceMapSpan when updateLastEncodedAndRecordedSpans - var defaultLastEncodedSourceMapSpan = { - emittedLine: 1, - emittedColumn: 1, - sourceLine: 1, - sourceColumn: 1, - sourceIndex: 0 - }; - function getNullSourceMapWriter() { - if (nullSourceMapWriter === undefined) { - nullSourceMapWriter = { - getSourceMapData: function () { return undefined; }, - setSourceFile: function (sourceFile) { }, - emitStart: function (range) { }, - emitEnd: function (range, stopOverridingSpan) { }, - emitPos: function (pos) { }, - changeEmitSourcePos: function () { }, - getText: function () { return undefined; }, - getSourceMappingURL: function () { return undefined; }, - initialize: function (filePath, sourceMapFilePath, sourceFiles, isBundledEmit) { }, - reset: function () { }, - }; - } - return nullSourceMapWriter; - } - ts.getNullSourceMapWriter = getNullSourceMapWriter; - function createSourceMapWriter(host, writer) { - var compilerOptions = host.getCompilerOptions(); - var extendedDiagnostics = compilerOptions.extendedDiagnostics; + /** + * Indicates whether to emit type metadata in the new format. + */ + var USE_NEW_TYPE_METADATA_FORMAT = false; + var TypeScriptSubstitutionFlags; + (function (TypeScriptSubstitutionFlags) { + /** Enables substitutions for decorated classes. */ + TypeScriptSubstitutionFlags[TypeScriptSubstitutionFlags["ClassAliases"] = 1] = "ClassAliases"; + /** Enables substitutions for namespace exports. */ + TypeScriptSubstitutionFlags[TypeScriptSubstitutionFlags["NamespaceExports"] = 2] = "NamespaceExports"; + /** Enables substitutions for async methods with `super` calls. */ + TypeScriptSubstitutionFlags[TypeScriptSubstitutionFlags["AsyncMethodsWithSuper"] = 4] = "AsyncMethodsWithSuper"; + /* Enables substitutions for unqualified enum members */ + TypeScriptSubstitutionFlags[TypeScriptSubstitutionFlags["NonQualifiedEnumMembers"] = 8] = "NonQualifiedEnumMembers"; + })(TypeScriptSubstitutionFlags || (TypeScriptSubstitutionFlags = {})); + function transformTypeScript(context) { + var startLexicalEnvironment = context.startLexicalEnvironment, endLexicalEnvironment = context.endLexicalEnvironment, hoistVariableDeclaration = context.hoistVariableDeclaration; + var resolver = context.getEmitResolver(); + var compilerOptions = context.getCompilerOptions(); + var languageVersion = ts.getEmitScriptTarget(compilerOptions); + var moduleKind = ts.getEmitModuleKind(compilerOptions); + // Save the previous transformation hooks. + var previousOnEmitNode = context.onEmitNode; + var previousOnSubstituteNode = context.onSubstituteNode; + // Set new transformation hooks. + context.onEmitNode = onEmitNode; + context.onSubstituteNode = onSubstituteNode; + // Enable substitution for property/element access to emit const enum values. + context.enableSubstitution(172 /* PropertyAccessExpression */); + context.enableSubstitution(173 /* ElementAccessExpression */); + // These variables contain state that changes as we descend into the tree. var currentSourceFile; - var sourceMapDir; // The directory in which sourcemap will be - var stopOverridingSpan = false; - var modifyLastSourcePos = false; - // Current source map file and its index in the sources list - var sourceMapSourceIndex; - // Last recorded and encoded spans - var lastRecordedSourceMapSpan; - var lastEncodedSourceMapSpan; - var lastEncodedNameIndex; - // Source map data - var sourceMapData; - return { - getSourceMapData: function () { return sourceMapData; }, - setSourceFile: setSourceFile, - emitPos: emitPos, - emitStart: emitStart, - emitEnd: emitEnd, - changeEmitSourcePos: changeEmitSourcePos, - getText: getText, - getSourceMappingURL: getSourceMappingURL, - initialize: initialize, - reset: reset, - }; - function initialize(filePath, sourceMapFilePath, sourceFiles, isBundledEmit) { - if (sourceMapData) { - reset(); + var currentNamespace; + var currentNamespaceContainerName; + var currentScope; + var currentScopeFirstDeclarationsOfName; + var currentSourceFileExternalHelpersModuleName; + /** + * Keeps track of whether expression substitution has been enabled for specific edge cases. + * They are persisted between each SourceFile transformation and should not be reset. + */ + var enabledSubstitutions; + /** + * A map that keeps track of aliases created for classes with decorators to avoid issues + * with the double-binding behavior of classes. + */ + var classAliases; + /** + * Keeps track of whether we are within any containing namespaces when performing + * just-in-time substitution while printing an expression identifier. + */ + var applicableSubstitutions; + /** + * This keeps track of containers where `super` is valid, for use with + * just-in-time substitution for `super` expressions inside of async methods. + */ + var currentSuperContainer; + return transformSourceFile; + /** + * Transform TypeScript-specific syntax in a SourceFile. + * + * @param node A SourceFile node. + */ + function transformSourceFile(node) { + if (ts.isDeclarationFile(node)) { + return node; } - currentSourceFile = undefined; - // Current source map file and its index in the sources list - sourceMapSourceIndex = -1; - // Last recorded and encoded spans - lastRecordedSourceMapSpan = undefined; - lastEncodedSourceMapSpan = defaultLastEncodedSourceMapSpan; - lastEncodedNameIndex = 0; - // Initialize source map data - sourceMapData = { - sourceMapFilePath: sourceMapFilePath, - jsSourceMappingURL: !compilerOptions.inlineSourceMap ? ts.getBaseFileName(ts.normalizeSlashes(sourceMapFilePath)) : undefined, - sourceMapFile: ts.getBaseFileName(ts.normalizeSlashes(filePath)), - sourceMapSourceRoot: compilerOptions.sourceRoot || "", - sourceMapSources: [], - inputSourceFileNames: [], - sourceMapNames: [], - sourceMapMappings: "", - sourceMapSourcesContent: compilerOptions.inlineSources ? [] : undefined, - sourceMapDecodedMappings: [] - }; - // Normalize source root and make sure it has trailing "/" so that it can be used to combine paths with the - // relative paths of the sources list in the sourcemap - sourceMapData.sourceMapSourceRoot = ts.normalizeSlashes(sourceMapData.sourceMapSourceRoot); - if (sourceMapData.sourceMapSourceRoot.length && sourceMapData.sourceMapSourceRoot.charCodeAt(sourceMapData.sourceMapSourceRoot.length - 1) !== 47 /* slash */) { - sourceMapData.sourceMapSourceRoot += ts.directorySeparator; + return ts.visitNode(node, visitor, ts.isSourceFile); + } + /** + * Visits a node, saving and restoring state variables on the stack. + * + * @param node The node to visit. + */ + function saveStateAndInvoke(node, f) { + // Save state + var savedCurrentScope = currentScope; + var savedCurrentScopeFirstDeclarationsOfName = currentScopeFirstDeclarationsOfName; + // Handle state changes before visiting a node. + onBeforeVisitNode(node); + var visited = f(node); + // Restore state + if (currentScope !== savedCurrentScope) { + currentScopeFirstDeclarationsOfName = savedCurrentScopeFirstDeclarationsOfName; + } + currentScope = savedCurrentScope; + return visited; + } + /** + * General-purpose node visitor. + * + * @param node The node to visit. + */ + function visitor(node) { + return saveStateAndInvoke(node, visitorWorker); + } + /** + * Visits and possibly transforms any node. + * + * @param node The node to visit. + */ + function visitorWorker(node) { + if (node.kind === 256 /* SourceFile */) { + return visitSourceFile(node); } - if (compilerOptions.mapRoot) { - sourceMapDir = ts.normalizeSlashes(compilerOptions.mapRoot); - if (!isBundledEmit) { - ts.Debug.assert(sourceFiles.length === 1); - // For modules or multiple emit files the mapRoot will have directory structure like the sources - // So if src\a.ts and src\lib\b.ts are compiled together user would be moving the maps into mapRoot\a.js.map and mapRoot\lib\b.js.map - sourceMapDir = ts.getDirectoryPath(ts.getSourceFilePathInNewDir(sourceFiles[0], host, sourceMapDir)); - } - if (!ts.isRootedDiskPath(sourceMapDir) && !ts.isUrl(sourceMapDir)) { - // The relative paths are relative to the common directory - sourceMapDir = ts.combinePaths(host.getCommonSourceDirectory(), sourceMapDir); - sourceMapData.jsSourceMappingURL = ts.getRelativePathToDirectoryOrUrl(ts.getDirectoryPath(ts.normalizePath(filePath)), // get the relative sourceMapDir path based on jsFilePath - ts.combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL), // this is where user expects to see sourceMap - host.getCurrentDirectory(), host.getCanonicalFileName, - /*isAbsolutePathAnUrl*/ true); - } - else { - sourceMapData.jsSourceMappingURL = ts.combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL); - } + else if (node.transformFlags & 1 /* TypeScript */) { + // This node is explicitly marked as TypeScript, so we should transform the node. + return visitTypeScript(node); } - else { - sourceMapDir = ts.getDirectoryPath(ts.normalizePath(filePath)); + else if (node.transformFlags & 2 /* ContainsTypeScript */) { + // This node contains TypeScript, so we should visit its children. + return ts.visitEachChild(node, visitor, context); + } + return node; + } + /** + * Specialized visitor that visits the immediate children of a namespace. + * + * @param node The node to visit. + */ + function namespaceElementVisitor(node) { + return saveStateAndInvoke(node, namespaceElementVisitorWorker); + } + /** + * Specialized visitor that visits the immediate children of a namespace. + * + * @param node The node to visit. + */ + function namespaceElementVisitorWorker(node) { + if (node.kind === 236 /* ExportDeclaration */ || + node.kind === 230 /* ImportDeclaration */ || + node.kind === 231 /* ImportClause */ || + (node.kind === 229 /* ImportEqualsDeclaration */ && + node.moduleReference.kind === 240 /* ExternalModuleReference */)) { + // do not emit ES6 imports and exports since they are illegal inside a namespace + return undefined; + } + else if (node.transformFlags & 1 /* TypeScript */ || ts.hasModifier(node, 1 /* Export */)) { + // This node is explicitly marked as TypeScript, or is exported at the namespace + // level, so we should transform the node. + return visitTypeScript(node); + } + else if (node.transformFlags & 2 /* ContainsTypeScript */) { + // This node contains TypeScript, so we should visit its children. + return ts.visitEachChild(node, visitor, context); + } + return node; + } + /** + * Specialized visitor that visits the immediate children of a class with TypeScript syntax. + * + * @param node The node to visit. + */ + function classElementVisitor(node) { + return saveStateAndInvoke(node, classElementVisitorWorker); + } + /** + * Specialized visitor that visits the immediate children of a class with TypeScript syntax. + * + * @param node The node to visit. + */ + function classElementVisitorWorker(node) { + switch (node.kind) { + case 148 /* Constructor */: + // TypeScript constructors are transformed in `visitClassDeclaration`. + // We elide them here as `visitorWorker` checks transform flags, which could + // erronously include an ES6 constructor without TypeScript syntax. + return undefined; + case 145 /* PropertyDeclaration */: + case 153 /* IndexSignature */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 147 /* MethodDeclaration */: + // Fallback to the default visit behavior. + return visitorWorker(node); + case 198 /* SemicolonClassElement */: + return node; + default: + ts.Debug.failBadSyntaxKind(node); + return undefined; + } + } + /** + * Branching visitor, visits a TypeScript syntax node. + * + * @param node The node to visit. + */ + function visitTypeScript(node) { + if (ts.hasModifier(node, 2 /* Ambient */) && ts.isStatement(node)) { + // TypeScript ambient declarations are elided, but some comments may be preserved. + // See the implementation of `getLeadingComments` in comments.ts for more details. + return ts.createNotEmittedStatement(node); + } + switch (node.kind) { + case 82 /* ExportKeyword */: + case 77 /* DefaultKeyword */: + // ES6 export and default modifiers are elided when inside a namespace. + return currentNamespace ? undefined : node; + case 112 /* PublicKeyword */: + case 110 /* PrivateKeyword */: + case 111 /* ProtectedKeyword */: + case 115 /* AbstractKeyword */: + case 118 /* AsyncKeyword */: + case 74 /* ConstKeyword */: + case 122 /* DeclareKeyword */: + case 128 /* ReadonlyKeyword */: + // TypeScript accessibility and readonly modifiers are elided. + case 160 /* ArrayType */: + case 161 /* TupleType */: + case 159 /* TypeLiteral */: + case 154 /* TypePredicate */: + case 141 /* TypeParameter */: + case 117 /* AnyKeyword */: + case 120 /* BooleanKeyword */: + case 132 /* StringKeyword */: + case 130 /* NumberKeyword */: + case 127 /* NeverKeyword */: + case 103 /* VoidKeyword */: + case 133 /* SymbolKeyword */: + case 157 /* ConstructorType */: + case 156 /* FunctionType */: + case 158 /* TypeQuery */: + case 155 /* TypeReference */: + case 162 /* UnionType */: + case 163 /* IntersectionType */: + case 164 /* ParenthesizedType */: + case 165 /* ThisType */: + case 166 /* LiteralType */: + // TypeScript type nodes are elided. + case 153 /* IndexSignature */: + // TypeScript index signatures are elided. + case 143 /* Decorator */: + // TypeScript decorators are elided. They will be emitted as part of visitClassDeclaration. + case 223 /* TypeAliasDeclaration */: + // TypeScript type-only declarations are elided. + case 145 /* PropertyDeclaration */: + // TypeScript property declarations are elided. + case 148 /* Constructor */: + // TypeScript constructors are transformed in `visitClassDeclaration`. + return undefined; + case 222 /* InterfaceDeclaration */: + // TypeScript interfaces are elided, but some comments may be preserved. + // See the implementation of `getLeadingComments` in comments.ts for more details. + return ts.createNotEmittedStatement(node); + case 221 /* ClassDeclaration */: + // This is a class declaration with TypeScript syntax extensions. + // + // TypeScript class syntax extensions include: + // - decorators + // - optional `implements` heritage clause + // - parameter property assignments in the constructor + // - property declarations + // - index signatures + // - method overload signatures + // - async methods + return visitClassDeclaration(node); + case 192 /* ClassExpression */: + // This is a class expression with TypeScript syntax extensions. + // + // TypeScript class syntax extensions include: + // - decorators + // - optional `implements` heritage clause + // - parameter property assignments in the constructor + // - property declarations + // - index signatures + // - method overload signatures + // - async methods + return visitClassExpression(node); + case 251 /* HeritageClause */: + // This is a heritage clause with TypeScript syntax extensions. + // + // TypeScript heritage clause extensions include: + // - `implements` clause + return visitHeritageClause(node); + case 194 /* ExpressionWithTypeArguments */: + // TypeScript supports type arguments on an expression in an `extends` heritage clause. + return visitExpressionWithTypeArguments(node); + case 147 /* MethodDeclaration */: + // TypeScript method declarations may be 'async', and may have decorators, modifiers + // or type annotations. + return visitMethodDeclaration(node); + case 149 /* GetAccessor */: + // Get Accessors can have TypeScript modifiers, decorators, and type annotations. + return visitGetAccessor(node); + case 150 /* SetAccessor */: + // Set Accessors can have TypeScript modifiers, decorators, and type annotations. + return visitSetAccessor(node); + case 220 /* FunctionDeclaration */: + // TypeScript function declarations may be 'async' + return visitFunctionDeclaration(node); + case 179 /* FunctionExpression */: + // TypeScript function expressions may be 'async' + return visitFunctionExpression(node); + case 180 /* ArrowFunction */: + // TypeScript arrow functions may be 'async' + return visitArrowFunction(node); + case 142 /* Parameter */: + // This is a parameter declaration with TypeScript syntax extensions. + // + // TypeScript parameter declaration syntax extensions include: + // - decorators + // - accessibility modifiers + // - the question mark (?) token for optional parameters + // - type annotations + // - this parameters + return visitParameter(node); + case 178 /* ParenthesizedExpression */: + // ParenthesizedExpressions are TypeScript if their expression is a + // TypeAssertion or AsExpression + return visitParenthesizedExpression(node); + case 177 /* TypeAssertionExpression */: + case 195 /* AsExpression */: + // TypeScript type assertions are removed, but their subtrees are preserved. + return visitAssertionExpression(node); + case 196 /* NonNullExpression */: + // TypeScript non-null expressions are removed, but their subtrees are preserved. + return visitNonNullExpression(node); + case 224 /* EnumDeclaration */: + // TypeScript enum declarations do not exist in ES6 and must be rewritten. + return visitEnumDeclaration(node); + case 184 /* AwaitExpression */: + // TypeScript 'await' expressions must be transformed. + return visitAwaitExpression(node); + case 200 /* VariableStatement */: + // TypeScript namespace exports for variable statements must be transformed. + return visitVariableStatement(node); + case 225 /* ModuleDeclaration */: + // TypeScript namespace declarations must be transformed. + return visitModuleDeclaration(node); + case 229 /* ImportEqualsDeclaration */: + // TypeScript namespace or external module import. + return visitImportEqualsDeclaration(node); + default: + ts.Debug.failBadSyntaxKind(node); + return ts.visitEachChild(node, visitor, context); } } - function reset() { - currentSourceFile = undefined; - sourceMapDir = undefined; - sourceMapSourceIndex = undefined; - lastRecordedSourceMapSpan = undefined; - lastEncodedSourceMapSpan = undefined; - lastEncodedNameIndex = undefined; - sourceMapData = undefined; - } - function updateLastEncodedAndRecordedSpans() { - if (modifyLastSourcePos) { - // Reset the source pos - modifyLastSourcePos = false; - // Change Last recorded Map with last encoded emit line and character - lastRecordedSourceMapSpan.emittedLine = lastEncodedSourceMapSpan.emittedLine; - lastRecordedSourceMapSpan.emittedColumn = lastEncodedSourceMapSpan.emittedColumn; - // Pop sourceMapDecodedMappings to remove last entry - sourceMapData.sourceMapDecodedMappings.pop(); - // Point the lastEncodedSourceMapSpace to the previous encoded sourceMapSpan - // If the list is empty which indicates that we are at the beginning of the file, - // we have to reset it to default value (same value when we first initialize sourceMapWriter) - lastEncodedSourceMapSpan = sourceMapData.sourceMapDecodedMappings.length ? - sourceMapData.sourceMapDecodedMappings[sourceMapData.sourceMapDecodedMappings.length - 1] : - defaultLastEncodedSourceMapSpan; - // TODO: Update lastEncodedNameIndex - // Since we dont support this any more, lets not worry about it right now. - // When we start supporting nameIndex, we will get back to this - // Change the encoded source map - var sourceMapMappings = sourceMapData.sourceMapMappings; - var lenthToSet = sourceMapMappings.length - 1; - for (; lenthToSet >= 0; lenthToSet--) { - var currentChar = sourceMapMappings.charAt(lenthToSet); - if (currentChar === ",") { - // Separator for the entry found - break; - } - if (currentChar === ";" && lenthToSet !== 0 && sourceMapMappings.charAt(lenthToSet - 1) !== ";") { - // Last line separator found + /** + * Performs actions that should always occur immediately before visiting a node. + * + * @param node The node to visit. + */ + function onBeforeVisitNode(node) { + switch (node.kind) { + case 256 /* SourceFile */: + case 227 /* CaseBlock */: + case 226 /* ModuleBlock */: + case 199 /* Block */: + currentScope = node; + currentScopeFirstDeclarationsOfName = undefined; + break; + case 221 /* ClassDeclaration */: + case 220 /* FunctionDeclaration */: + if (ts.hasModifier(node, 2 /* Ambient */)) { break; } - } - sourceMapData.sourceMapMappings = sourceMapMappings.substr(0, Math.max(0, lenthToSet)); + recordEmittedDeclarationInScope(node); + break; } } - // Encoding for sourcemap span - function encodeLastRecordedSourceMapSpan() { - if (!lastRecordedSourceMapSpan || lastRecordedSourceMapSpan === lastEncodedSourceMapSpan) { - return; - } - var prevEncodedEmittedColumn = lastEncodedSourceMapSpan.emittedColumn; - // Line/Comma delimiters - if (lastEncodedSourceMapSpan.emittedLine === lastRecordedSourceMapSpan.emittedLine) { - // Emit comma to separate the entry - if (sourceMapData.sourceMapMappings) { - sourceMapData.sourceMapMappings += ","; - } + function visitSourceFile(node) { + currentSourceFile = node; + // If the source file requires any helpers and is an external module, and + // the importHelpers compiler option is enabled, emit a synthesized import + // statement for the helpers library. + if (node.flags & 31744 /* EmitHelperFlags */ + && compilerOptions.importHelpers + && (ts.isExternalModule(node) || compilerOptions.isolatedModules)) { + startLexicalEnvironment(); + var statements = []; + var statementOffset = ts.addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ false, visitor); + var externalHelpersModuleName = ts.createUniqueName(ts.externalHelpersModuleNameText); + var externalHelpersModuleImport = ts.createImportDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, ts.createImportClause(/*name*/ undefined, ts.createNamespaceImport(externalHelpersModuleName)), ts.createLiteral(ts.externalHelpersModuleNameText)); + externalHelpersModuleImport.parent = node; + externalHelpersModuleImport.flags &= ~8 /* Synthesized */; + statements.push(externalHelpersModuleImport); + currentSourceFileExternalHelpersModuleName = externalHelpersModuleName; + ts.addRange(statements, ts.visitNodes(node.statements, visitor, ts.isStatement, statementOffset)); + ts.addRange(statements, endLexicalEnvironment()); + currentSourceFileExternalHelpersModuleName = undefined; + node = ts.updateSourceFileNode(node, ts.createNodeArray(statements, node.statements)); + node.externalHelpersModuleName = externalHelpersModuleName; } else { - // Emit line delimiters - for (var encodedLine = lastEncodedSourceMapSpan.emittedLine; encodedLine < lastRecordedSourceMapSpan.emittedLine; encodedLine++) { - sourceMapData.sourceMapMappings += ";"; - } - prevEncodedEmittedColumn = 1; - } - // 1. Relative Column 0 based - sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.emittedColumn - prevEncodedEmittedColumn); - // 2. Relative sourceIndex - sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceIndex - lastEncodedSourceMapSpan.sourceIndex); - // 3. Relative sourceLine 0 based - sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceLine - lastEncodedSourceMapSpan.sourceLine); - // 4. Relative sourceColumn 0 based - sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceColumn - lastEncodedSourceMapSpan.sourceColumn); - // 5. Relative namePosition 0 based - if (lastRecordedSourceMapSpan.nameIndex >= 0) { - ts.Debug.assert(false, "We do not support name index right now, Make sure to update updateLastEncodedAndRecordedSpans when we start using this"); - sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.nameIndex - lastEncodedNameIndex); - lastEncodedNameIndex = lastRecordedSourceMapSpan.nameIndex; + node = ts.visitEachChild(node, visitor, context); } - lastEncodedSourceMapSpan = lastRecordedSourceMapSpan; - sourceMapData.sourceMapDecodedMappings.push(lastEncodedSourceMapSpan); + ts.setEmitFlags(node, 1 /* EmitEmitHelpers */ | ts.getEmitFlags(node)); + return node; } - function emitPos(pos) { - if (pos === -1) { - return; - } - if (extendedDiagnostics) { - ts.performance.mark("beforeSourcemap"); + /** + * Tests whether we should emit a __decorate call for a class declaration. + */ + function shouldEmitDecorateCallForClass(node) { + if (node.decorators && node.decorators.length > 0) { + return true; } - var sourceLinePos = ts.getLineAndCharacterOfPosition(currentSourceFile, pos); - // Convert the location to be one-based. - sourceLinePos.line++; - sourceLinePos.character++; - var emittedLine = writer.getLine(); - var emittedColumn = writer.getColumn(); - // If this location wasn't recorded or the location in source is going backwards, record the span - if (!lastRecordedSourceMapSpan || - lastRecordedSourceMapSpan.emittedLine !== emittedLine || - lastRecordedSourceMapSpan.emittedColumn !== emittedColumn || - (lastRecordedSourceMapSpan.sourceIndex === sourceMapSourceIndex && - (lastRecordedSourceMapSpan.sourceLine > sourceLinePos.line || - (lastRecordedSourceMapSpan.sourceLine === sourceLinePos.line && lastRecordedSourceMapSpan.sourceColumn > sourceLinePos.character)))) { - // Encode the last recordedSpan before assigning new - encodeLastRecordedSourceMapSpan(); - // New span - lastRecordedSourceMapSpan = { - emittedLine: emittedLine, - emittedColumn: emittedColumn, - sourceLine: sourceLinePos.line, - sourceColumn: sourceLinePos.character, - sourceIndex: sourceMapSourceIndex - }; - stopOverridingSpan = false; + var constructor = ts.getFirstConstructorWithBody(node); + if (constructor) { + return ts.forEach(constructor.parameters, shouldEmitDecorateCallForParameter); } - else if (!stopOverridingSpan) { - // Take the new pos instead since there is no change in emittedLine and column since last location - lastRecordedSourceMapSpan.sourceLine = sourceLinePos.line; - lastRecordedSourceMapSpan.sourceColumn = sourceLinePos.character; - lastRecordedSourceMapSpan.sourceIndex = sourceMapSourceIndex; + return false; + } + /** + * Tests whether we should emit a __decorate call for a parameter declaration. + */ + function shouldEmitDecorateCallForParameter(parameter) { + return parameter.decorators !== undefined && parameter.decorators.length > 0; + } + /** + * Transforms a class declaration with TypeScript syntax into compatible ES6. + * + * This function will only be called when one of the following conditions are met: + * - The class has decorators. + * - The class has property declarations with initializers. + * - The class contains a constructor that contains parameters with accessibility modifiers. + * - The class is an export in a TypeScript namespace. + * + * @param node The node to transform. + */ + function visitClassDeclaration(node) { + var staticProperties = getInitializedProperties(node, /*isStatic*/ true); + var hasExtendsClause = ts.getClassExtendsHeritageClauseElement(node) !== undefined; + var isDecoratedClass = shouldEmitDecorateCallForClass(node); + var classAlias; + // emit name if + // - node has a name + // - node has static initializers + // + var name = node.name; + if (!name && staticProperties.length > 0) { + name = ts.getGeneratedNameForNode(node); } - updateLastEncodedAndRecordedSpans(); - if (extendedDiagnostics) { - ts.performance.mark("afterSourcemap"); - ts.performance.measure("Source Map", "beforeSourcemap", "afterSourcemap"); + var statements = []; + if (!isDecoratedClass) { + // ${modifiers} class ${name} ${heritageClauses} { + // ${members} + // } + var classDeclaration = ts.createClassDeclaration( + /*decorators*/ undefined, ts.visitNodes(node.modifiers, visitor, ts.isModifier), name, + /*typeParameters*/ undefined, ts.visitNodes(node.heritageClauses, visitor, ts.isHeritageClause), transformClassMembers(node, hasExtendsClause), + /*location*/ node); + ts.setOriginalNode(classDeclaration, node); + // To better align with the old emitter, we should not emit a trailing source map + // entry if the class has static properties. + if (staticProperties.length > 0) { + ts.setEmitFlags(classDeclaration, 1024 /* NoTrailingSourceMap */ | ts.getEmitFlags(classDeclaration)); + } + statements.push(classDeclaration); } + else { + classAlias = addClassDeclarationHeadWithDecorators(statements, node, name, hasExtendsClause); + } + // Emit static property assignment. Because classDeclaration is lexically evaluated, + // it is safe to emit static property assignment after classDeclaration + // From ES6 specification: + // HasLexicalDeclaration (N) : Determines if the argument identifier has a binding in this environment record that was created using + // a lexical declaration such as a LexicalDeclaration or a ClassDeclaration. + if (staticProperties.length) { + addInitializedPropertyStatements(statements, node, staticProperties, getLocalName(node, /*noSourceMaps*/ true)); + } + // Write any decorators of the node. + addClassElementDecorationStatements(statements, node, /*isStatic*/ false); + addClassElementDecorationStatements(statements, node, /*isStatic*/ true); + addConstructorDecorationStatement(statements, node, classAlias); + // If the class is exported as part of a TypeScript namespace, emit the namespace export. + // Otherwise, if the class was exported at the top level and was decorated, emit an export + // declaration or export default for the class. + if (isNamespaceExport(node)) { + addExportMemberAssignment(statements, node); + } + else if (isDecoratedClass) { + if (isDefaultExternalModuleExport(node)) { + statements.push(ts.createExportAssignment( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*isExportEquals*/ false, getLocalName(node))); + } + else if (isNamedExternalModuleExport(node)) { + statements.push(createExternalModuleExport(name)); + } + } + return statements; + } + /** + * Transforms a decorated class declaration and appends the resulting statements. If + * the class requires an alias to avoid issues with double-binding, the alias is returned. + * + * @param node A ClassDeclaration node. + * @param name The name of the class. + * @param hasExtendsClause A value indicating whether + */ + function addClassDeclarationHeadWithDecorators(statements, node, name, hasExtendsClause) { + // When we emit an ES6 class that has a class decorator, we must tailor the + // emit to certain specific cases. + // + // In the simplest case, we emit the class declaration as a let declaration, and + // evaluate decorators after the close of the class body: + // + // [Example 1] + // --------------------------------------------------------------------- + // TypeScript | Javascript + // --------------------------------------------------------------------- + // @dec | let C = class C { + // class C { | } + // } | C = __decorate([dec], C); + // --------------------------------------------------------------------- + // @dec | let C = class C { + // export class C { | } + // } | C = __decorate([dec], C); + // | export { C }; + // --------------------------------------------------------------------- + // + // If a class declaration contains a reference to itself *inside* of the class body, + // this introduces two bindings to the class: One outside of the class body, and one + // inside of the class body. If we apply decorators as in [Example 1] above, there + // is the possibility that the decorator `dec` will return a new value for the + // constructor, which would result in the binding inside of the class no longer + // pointing to the same reference as the binding outside of the class. + // + // As a result, we must instead rewrite all references to the class *inside* of the + // class body to instead point to a local temporary alias for the class: + // + // [Example 2] + // --------------------------------------------------------------------- + // TypeScript | Javascript + // --------------------------------------------------------------------- + // @dec | let C_1 = class C { + // class C { | static x() { return C_1.y; } + // static x() { return C.y; } | } + // static y = 1; | let C = C_1; + // } | C.y = 1; + // | C = C_1 = __decorate([dec], C); + // --------------------------------------------------------------------- + // @dec | let C_1 = class C { + // export class C { | static x() { return C_1.y; } + // static x() { return C.y; } | } + // static y = 1; | let C = C_1; + // } | C.y = 1; + // | C = C_1 = __decorate([dec], C); + // | export { C }; + // --------------------------------------------------------------------- + // + // If a class declaration is the default export of a module, we instead emit + // the export after the decorated declaration: + // + // [Example 3] + // --------------------------------------------------------------------- + // TypeScript | Javascript + // --------------------------------------------------------------------- + // @dec | let default_1 = class { + // export default class { | } + // } | default_1 = __decorate([dec], default_1); + // | export default default_1; + // --------------------------------------------------------------------- + // @dec | let C = class C { + // export default class C { | } + // } | C = __decorate([dec], C); + // | export default C; + // --------------------------------------------------------------------- + // + // If the class declaration is the default export and a reference to itself + // inside of the class body, we must emit both an alias for the class *and* + // move the export after the declaration: + // + // [Example 4] + // --------------------------------------------------------------------- + // TypeScript | Javascript + // --------------------------------------------------------------------- + // @dec | let C_1 = class C { + // export default class C { | static x() { return C_1.y; } + // static x() { return C.y; } | } + // static y = 1; | let C = C_1; + // } | C.y = 1; + // | C = C_1 = __decorate([dec], C); + // | export default C; + // --------------------------------------------------------------------- + // + var location = ts.moveRangePastDecorators(node); + // ... = class ${name} ${heritageClauses} { + // ${members} + // } + var classExpression = ts.setOriginalNode(ts.createClassExpression( + /*modifiers*/ undefined, name, + /*typeParameters*/ undefined, ts.visitNodes(node.heritageClauses, visitor, ts.isHeritageClause), transformClassMembers(node, hasExtendsClause), + /*location*/ location), node); + if (!name) { + name = ts.getGeneratedNameForNode(node); + } + // Record an alias to avoid class double-binding. + var classAlias; + if (resolver.getNodeCheckFlags(node) & 8388608 /* ClassWithConstructorReference */) { + enableSubstitutionForClassAliases(); + classAlias = ts.createUniqueName(node.name && !ts.isGeneratedIdentifier(node.name) ? node.name.text : "default"); + classAliases[ts.getOriginalNodeId(node)] = classAlias; + } + var declaredName = getDeclarationName(node, /*allowComments*/ true); + // let ${name} = ${classExpression} where name is either declaredName if the class doesn't contain self-reference + // or decoratedClassAlias if the class contain self-reference. + var transformedClassExpression = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createLetDeclarationList([ + ts.createVariableDeclaration(classAlias || declaredName, + /*type*/ undefined, classExpression) + ]), + /*location*/ location); + ts.setCommentRange(transformedClassExpression, node); + statements.push(ts.setOriginalNode( + /*node*/ transformedClassExpression, + /*original*/ node)); + if (classAlias) { + // We emit the class alias as a `let` declaration here so that it has the same + // TDZ as the class. + // let ${declaredName} = ${decoratedClassAlias} + statements.push(ts.setOriginalNode(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createLetDeclarationList([ + ts.createVariableDeclaration(declaredName, + /*type*/ undefined, classAlias) + ]), + /*location*/ location), + /*original*/ node)); + } + return classAlias; + } + /** + * Transforms a class expression with TypeScript syntax into compatible ES6. + * + * This function will only be called when one of the following conditions are met: + * - The class has property declarations with initializers. + * - The class contains a constructor that contains parameters with accessibility modifiers. + * + * @param node The node to transform. + */ + function visitClassExpression(node) { + var staticProperties = getInitializedProperties(node, /*isStatic*/ true); + var heritageClauses = ts.visitNodes(node.heritageClauses, visitor, ts.isHeritageClause); + var members = transformClassMembers(node, heritageClauses !== undefined); + var classExpression = ts.setOriginalNode(ts.createClassExpression( + /*modifiers*/ undefined, node.name, + /*typeParameters*/ undefined, heritageClauses, members, + /*location*/ node), node); + if (staticProperties.length > 0) { + var expressions = []; + var temp = ts.createTempVariable(hoistVariableDeclaration); + if (resolver.getNodeCheckFlags(node) & 8388608 /* ClassWithConstructorReference */) { + // record an alias as the class name is not in scope for statics. + enableSubstitutionForClassAliases(); + classAliases[ts.getOriginalNodeId(node)] = ts.getSynthesizedClone(temp); + } + // To preserve the behavior of the old emitter, we explicitly indent + // the body of a class with static initializers. + ts.setEmitFlags(classExpression, 524288 /* Indented */ | ts.getEmitFlags(classExpression)); + expressions.push(ts.startOnNewLine(ts.createAssignment(temp, classExpression))); + ts.addRange(expressions, generateInitializedPropertyExpressions(node, staticProperties, temp)); + expressions.push(ts.startOnNewLine(temp)); + return ts.inlineExpressions(expressions); + } + return classExpression; } - function getStartPos(range) { - var rangeHasDecorators = !!range.decorators; - return range.pos !== -1 ? ts.skipTrivia(currentSourceFile.text, rangeHasDecorators ? range.decorators.end : range.pos) : -1; + /** + * Transforms the members of a class. + * + * @param node The current class. + * @param hasExtendsClause A value indicating whether the class has an extends clause. + */ + function transformClassMembers(node, hasExtendsClause) { + var members = []; + var constructor = transformConstructor(node, hasExtendsClause); + if (constructor) { + members.push(constructor); + } + ts.addRange(members, ts.visitNodes(node.members, classElementVisitor, ts.isClassElement)); + return ts.createNodeArray(members, /*location*/ node.members); } - function emitStart(range) { - emitPos(getStartPos(range)); + /** + * Transforms (or creates) a constructor for a class. + * + * @param node The current class. + * @param hasExtendsClause A value indicating whether the class has an extends clause. + */ + function transformConstructor(node, hasExtendsClause) { + // Check if we have property assignment inside class declaration. + // If there is a property assignment, we need to emit constructor whether users define it or not + // If there is no property assignment, we can omit constructor if users do not define it + var hasInstancePropertyWithInitializer = ts.forEach(node.members, isInstanceInitializedProperty); + var hasParameterPropertyAssignments = node.transformFlags & 131072 /* ContainsParameterPropertyAssignments */; + var constructor = ts.getFirstConstructorWithBody(node); + // If the class does not contain nodes that require a synthesized constructor, + // accept the current constructor if it exists. + if (!hasInstancePropertyWithInitializer && !hasParameterPropertyAssignments) { + return ts.visitEachChild(constructor, visitor, context); + } + var parameters = transformConstructorParameters(constructor); + var body = transformConstructorBody(node, constructor, hasExtendsClause, parameters); + // constructor(${parameters}) { + // ${body} + // } + return ts.startOnNewLine(ts.setOriginalNode(ts.createConstructor( + /*decorators*/ undefined, + /*modifiers*/ undefined, parameters, body, + /*location*/ constructor || node), constructor)); } - function emitEnd(range, stopOverridingEnd) { - emitPos(range.end); - stopOverridingSpan = stopOverridingEnd; + /** + * Transforms (or creates) the parameters for the constructor of a class with + * parameter property assignments or instance property initializers. + * + * @param constructor The constructor declaration. + * @param hasExtendsClause A value indicating whether the class has an extends clause. + */ + function transformConstructorParameters(constructor) { + // The ES2015 spec specifies in 14.5.14. Runtime Semantics: ClassDefinitionEvaluation: + // If constructor is empty, then + // If ClassHeritag_eopt is present and protoParent is not null, then + // Let constructor be the result of parsing the source text + // constructor(...args) { super (...args);} + // using the syntactic grammar with the goal symbol MethodDefinition[~Yield]. + // Else, + // Let constructor be the result of parsing the source text + // constructor( ){ } + // using the syntactic grammar with the goal symbol MethodDefinition[~Yield]. + // + // While we could emit the '...args' rest parameter, certain later tools in the pipeline might + // downlevel the '...args' portion less efficiently by naively copying the contents of 'arguments' to an array. + // Instead, we'll avoid using a rest parameter and spread into the super call as + // 'super(...arguments)' instead of 'super(...args)', as you can see in "transformConstructorBody". + return constructor + ? ts.visitNodes(constructor.parameters, visitor, ts.isParameter) + : []; } - function changeEmitSourcePos() { - ts.Debug.assert(!modifyLastSourcePos); - modifyLastSourcePos = true; + /** + * Transforms (or creates) a constructor body for a class with parameter property + * assignments or instance property initializers. + * + * @param node The current class. + * @param constructor The current class constructor. + * @param hasExtendsClause A value indicating whether the class has an extends clause. + * @param parameters The transformed parameters for the constructor. + */ + function transformConstructorBody(node, constructor, hasExtendsClause, parameters) { + var statements = []; + var indexOfFirstStatement = 0; + // The body of a constructor is a new lexical environment + startLexicalEnvironment(); + if (constructor) { + indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(constructor, statements); + // Add parameters with property assignments. Transforms this: + // + // constructor (public x, public y) { + // } + // + // Into this: + // + // constructor (x, y) { + // this.x = x; + // this.y = y; + // } + // + var propertyAssignments = getParametersWithPropertyAssignments(constructor); + ts.addRange(statements, ts.map(propertyAssignments, transformParameterWithPropertyAssignment)); + } + else if (hasExtendsClause) { + // Add a synthetic `super` call: + // + // super(...arguments); + // + statements.push(ts.createStatement(ts.createCall(ts.createSuper(), + /*typeArguments*/ undefined, [ts.createSpread(ts.createIdentifier("arguments"))]))); + } + // Add the property initializers. Transforms this: + // + // public x = 1; + // + // Into this: + // + // constructor() { + // this.x = 1; + // } + // + var properties = getInitializedProperties(node, /*isStatic*/ false); + addInitializedPropertyStatements(statements, node, properties, ts.createThis()); + if (constructor) { + // The class already had a constructor, so we should add the existing statements, skipping the initial super call. + ts.addRange(statements, ts.visitNodes(constructor.body.statements, visitor, ts.isStatement, indexOfFirstStatement)); + } + // End the lexical environment. + ts.addRange(statements, endLexicalEnvironment()); + return ts.setMultiLine(ts.createBlock(ts.createNodeArray(statements, + /*location*/ constructor ? constructor.body.statements : node.members), + /*location*/ constructor ? constructor.body : undefined), true); } - function setSourceFile(sourceFile) { - currentSourceFile = sourceFile; - // Add the file to tsFilePaths - // If sourceroot option: Use the relative path corresponding to the common directory path - // otherwise source locations relative to map file location - var sourcesDirectoryPath = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir; - var source = ts.getRelativePathToDirectoryOrUrl(sourcesDirectoryPath, currentSourceFile.fileName, host.getCurrentDirectory(), host.getCanonicalFileName, - /*isAbsolutePathAnUrl*/ true); - sourceMapSourceIndex = ts.indexOf(sourceMapData.sourceMapSources, source); - if (sourceMapSourceIndex === -1) { - sourceMapSourceIndex = sourceMapData.sourceMapSources.length; - sourceMapData.sourceMapSources.push(source); - // The one that can be used from program to get the actual source file - sourceMapData.inputSourceFileNames.push(sourceFile.fileName); - if (compilerOptions.inlineSources) { - sourceMapData.sourceMapSourcesContent.push(sourceFile.text); + /** + * Adds super call and preceding prologue directives into the list of statements. + * + * @param ctor The constructor node. + * @returns index of the statement that follows super call + */ + function addPrologueDirectivesAndInitialSuperCall(ctor, result) { + if (ctor.body) { + var statements = ctor.body.statements; + // add prologue directives to the list (if any) + var index = ts.addPrologueDirectives(result, statements, /*ensureUseStrict*/ false, visitor); + if (index === statements.length) { + // list contains nothing but prologue directives (or empty) - exit + return index; + } + var statement = statements[index]; + if (statement.kind === 202 /* ExpressionStatement */ && ts.isSuperCallExpression(statement.expression)) { + result.push(ts.visitNode(statement, visitor, ts.isStatement)); + return index + 1; } + return index; } + return 0; } - function getText() { - encodeLastRecordedSourceMapSpan(); - return ts.stringify({ - version: 3, - file: sourceMapData.sourceMapFile, - sourceRoot: sourceMapData.sourceMapSourceRoot, - sources: sourceMapData.sourceMapSources, - names: sourceMapData.sourceMapNames, - mappings: sourceMapData.sourceMapMappings, - sourcesContent: sourceMapData.sourceMapSourcesContent, - }); + /** + * Gets all parameters of a constructor that should be transformed into property assignments. + * + * @param node The constructor node. + */ + function getParametersWithPropertyAssignments(node) { + return ts.filter(node.parameters, isParameterWithPropertyAssignment); } - function getSourceMappingURL() { - if (compilerOptions.inlineSourceMap) { - // Encode the sourceMap into the sourceMap url - var base64SourceMapText = ts.convertToBase64(getText()); - return sourceMapData.jsSourceMappingURL = "data:application/json;base64," + base64SourceMapText; - } - else { - return sourceMapData.jsSourceMappingURL; - } + /** + * Determines whether a parameter should be transformed into a property assignment. + * + * @param parameter The parameter node. + */ + function isParameterWithPropertyAssignment(parameter) { + return ts.hasModifier(parameter, 92 /* ParameterPropertyModifier */) + && ts.isIdentifier(parameter.name); } - } - ts.createSourceMapWriter = createSourceMapWriter; - var base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - function base64FormatEncode(inValue) { - if (inValue < 64) { - return base64Chars.charAt(inValue); + /** + * Transforms a parameter into a property assignment statement. + * + * @param node The parameter declaration. + */ + function transformParameterWithPropertyAssignment(node) { + ts.Debug.assert(ts.isIdentifier(node.name)); + var name = node.name; + var propertyName = ts.getMutableClone(name); + ts.setEmitFlags(propertyName, 49152 /* NoComments */ | 1536 /* NoSourceMap */); + var localName = ts.getMutableClone(name); + ts.setEmitFlags(localName, 49152 /* NoComments */); + return ts.startOnNewLine(ts.createStatement(ts.createAssignment(ts.createPropertyAccess(ts.createThis(), propertyName, + /*location*/ node.name), localName), + /*location*/ ts.moveRangePos(node, -1))); } - throw TypeError(inValue + ": not a 64 based value"); - } - function base64VLQFormatEncode(inValue) { - // Add a new least significant bit that has the sign of the value. - // if negative number the least significant bit that gets added to the number has value 1 - // else least significant bit value that gets added is 0 - // eg. -1 changes to binary : 01 [1] => 3 - // +1 changes to binary : 01 [0] => 2 - if (inValue < 0) { - inValue = ((-inValue) << 1) + 1; + /** + * Gets all property declarations with initializers on either the static or instance side of a class. + * + * @param node The class node. + * @param isStatic A value indicating whether to get properties from the static or instance side of the class. + */ + function getInitializedProperties(node, isStatic) { + return ts.filter(node.members, isStatic ? isStaticInitializedProperty : isInstanceInitializedProperty); } - else { - inValue = inValue << 1; + /** + * Gets a value indicating whether a class element is a static property declaration with an initializer. + * + * @param member The class element node. + */ + function isStaticInitializedProperty(member) { + return isInitializedProperty(member, /*isStatic*/ true); } - // Encode 5 bits at a time starting from least significant bits - var encodedStr = ""; - do { - var currentDigit = inValue & 31; // 11111 - inValue = inValue >> 5; - if (inValue > 0) { - // There are still more digits to decode, set the msb (6th bit) - currentDigit = currentDigit | 32; + /** + * Gets a value indicating whether a class element is an instance property declaration with an initializer. + * + * @param member The class element node. + */ + function isInstanceInitializedProperty(member) { + return isInitializedProperty(member, /*isStatic*/ false); + } + /** + * Gets a value indicating whether a class element is either a static or an instance property declaration with an initializer. + * + * @param member The class element node. + * @param isStatic A value indicating whether the member should be a static or instance member. + */ + function isInitializedProperty(member, isStatic) { + return member.kind === 145 /* PropertyDeclaration */ + && isStatic === ts.hasModifier(member, 32 /* Static */) + && member.initializer !== undefined; + } + /** + * Generates assignment statements for property initializers. + * + * @param node The class node. + * @param properties An array of property declarations to transform. + * @param receiver The receiver on which each property should be assigned. + */ + function addInitializedPropertyStatements(statements, node, properties, receiver) { + for (var _i = 0, properties_7 = properties; _i < properties_7.length; _i++) { + var property = properties_7[_i]; + var statement = ts.createStatement(transformInitializedProperty(node, property, receiver)); + ts.setSourceMapRange(statement, ts.moveRangePastModifiers(property)); + ts.setCommentRange(statement, property); + statements.push(statement); } - encodedStr = encodedStr + base64FormatEncode(currentDigit); - } while (inValue > 0); - return encodedStr; - } -})(ts || (ts = {})); -/// -/// -/// -/* @internal */ -var ts; -(function (ts) { - function getResolvedExternalModuleName(host, file) { - return file.moduleName || ts.getExternalModuleNameFromPath(host, file.fileName); - } - ts.getResolvedExternalModuleName = getResolvedExternalModuleName; - function getExternalModuleNameFromDeclaration(host, resolver, declaration) { - var file = resolver.getExternalModuleFileFromDeclaration(declaration); - if (!file || ts.isDeclarationFile(file)) { - return undefined; } - return getResolvedExternalModuleName(host, file); - } - ts.getExternalModuleNameFromDeclaration = getExternalModuleNameFromDeclaration; - var Jump; - (function (Jump) { - Jump[Jump["Break"] = 2] = "Break"; - Jump[Jump["Continue"] = 4] = "Continue"; - Jump[Jump["Return"] = 8] = "Return"; - })(Jump || (Jump = {})); - var entities = ts.createMap({ - "quot": 0x0022, - "amp": 0x0026, - "apos": 0x0027, - "lt": 0x003C, - "gt": 0x003E, - "nbsp": 0x00A0, - "iexcl": 0x00A1, - "cent": 0x00A2, - "pound": 0x00A3, - "curren": 0x00A4, - "yen": 0x00A5, - "brvbar": 0x00A6, - "sect": 0x00A7, - "uml": 0x00A8, - "copy": 0x00A9, - "ordf": 0x00AA, - "laquo": 0x00AB, - "not": 0x00AC, - "shy": 0x00AD, - "reg": 0x00AE, - "macr": 0x00AF, - "deg": 0x00B0, - "plusmn": 0x00B1, - "sup2": 0x00B2, - "sup3": 0x00B3, - "acute": 0x00B4, - "micro": 0x00B5, - "para": 0x00B6, - "middot": 0x00B7, - "cedil": 0x00B8, - "sup1": 0x00B9, - "ordm": 0x00BA, - "raquo": 0x00BB, - "frac14": 0x00BC, - "frac12": 0x00BD, - "frac34": 0x00BE, - "iquest": 0x00BF, - "Agrave": 0x00C0, - "Aacute": 0x00C1, - "Acirc": 0x00C2, - "Atilde": 0x00C3, - "Auml": 0x00C4, - "Aring": 0x00C5, - "AElig": 0x00C6, - "Ccedil": 0x00C7, - "Egrave": 0x00C8, - "Eacute": 0x00C9, - "Ecirc": 0x00CA, - "Euml": 0x00CB, - "Igrave": 0x00CC, - "Iacute": 0x00CD, - "Icirc": 0x00CE, - "Iuml": 0x00CF, - "ETH": 0x00D0, - "Ntilde": 0x00D1, - "Ograve": 0x00D2, - "Oacute": 0x00D3, - "Ocirc": 0x00D4, - "Otilde": 0x00D5, - "Ouml": 0x00D6, - "times": 0x00D7, - "Oslash": 0x00D8, - "Ugrave": 0x00D9, - "Uacute": 0x00DA, - "Ucirc": 0x00DB, - "Uuml": 0x00DC, - "Yacute": 0x00DD, - "THORN": 0x00DE, - "szlig": 0x00DF, - "agrave": 0x00E0, - "aacute": 0x00E1, - "acirc": 0x00E2, - "atilde": 0x00E3, - "auml": 0x00E4, - "aring": 0x00E5, - "aelig": 0x00E6, - "ccedil": 0x00E7, - "egrave": 0x00E8, - "eacute": 0x00E9, - "ecirc": 0x00EA, - "euml": 0x00EB, - "igrave": 0x00EC, - "iacute": 0x00ED, - "icirc": 0x00EE, - "iuml": 0x00EF, - "eth": 0x00F0, - "ntilde": 0x00F1, - "ograve": 0x00F2, - "oacute": 0x00F3, - "ocirc": 0x00F4, - "otilde": 0x00F5, - "ouml": 0x00F6, - "divide": 0x00F7, - "oslash": 0x00F8, - "ugrave": 0x00F9, - "uacute": 0x00FA, - "ucirc": 0x00FB, - "uuml": 0x00FC, - "yacute": 0x00FD, - "thorn": 0x00FE, - "yuml": 0x00FF, - "OElig": 0x0152, - "oelig": 0x0153, - "Scaron": 0x0160, - "scaron": 0x0161, - "Yuml": 0x0178, - "fnof": 0x0192, - "circ": 0x02C6, - "tilde": 0x02DC, - "Alpha": 0x0391, - "Beta": 0x0392, - "Gamma": 0x0393, - "Delta": 0x0394, - "Epsilon": 0x0395, - "Zeta": 0x0396, - "Eta": 0x0397, - "Theta": 0x0398, - "Iota": 0x0399, - "Kappa": 0x039A, - "Lambda": 0x039B, - "Mu": 0x039C, - "Nu": 0x039D, - "Xi": 0x039E, - "Omicron": 0x039F, - "Pi": 0x03A0, - "Rho": 0x03A1, - "Sigma": 0x03A3, - "Tau": 0x03A4, - "Upsilon": 0x03A5, - "Phi": 0x03A6, - "Chi": 0x03A7, - "Psi": 0x03A8, - "Omega": 0x03A9, - "alpha": 0x03B1, - "beta": 0x03B2, - "gamma": 0x03B3, - "delta": 0x03B4, - "epsilon": 0x03B5, - "zeta": 0x03B6, - "eta": 0x03B7, - "theta": 0x03B8, - "iota": 0x03B9, - "kappa": 0x03BA, - "lambda": 0x03BB, - "mu": 0x03BC, - "nu": 0x03BD, - "xi": 0x03BE, - "omicron": 0x03BF, - "pi": 0x03C0, - "rho": 0x03C1, - "sigmaf": 0x03C2, - "sigma": 0x03C3, - "tau": 0x03C4, - "upsilon": 0x03C5, - "phi": 0x03C6, - "chi": 0x03C7, - "psi": 0x03C8, - "omega": 0x03C9, - "thetasym": 0x03D1, - "upsih": 0x03D2, - "piv": 0x03D6, - "ensp": 0x2002, - "emsp": 0x2003, - "thinsp": 0x2009, - "zwnj": 0x200C, - "zwj": 0x200D, - "lrm": 0x200E, - "rlm": 0x200F, - "ndash": 0x2013, - "mdash": 0x2014, - "lsquo": 0x2018, - "rsquo": 0x2019, - "sbquo": 0x201A, - "ldquo": 0x201C, - "rdquo": 0x201D, - "bdquo": 0x201E, - "dagger": 0x2020, - "Dagger": 0x2021, - "bull": 0x2022, - "hellip": 0x2026, - "permil": 0x2030, - "prime": 0x2032, - "Prime": 0x2033, - "lsaquo": 0x2039, - "rsaquo": 0x203A, - "oline": 0x203E, - "frasl": 0x2044, - "euro": 0x20AC, - "image": 0x2111, - "weierp": 0x2118, - "real": 0x211C, - "trade": 0x2122, - "alefsym": 0x2135, - "larr": 0x2190, - "uarr": 0x2191, - "rarr": 0x2192, - "darr": 0x2193, - "harr": 0x2194, - "crarr": 0x21B5, - "lArr": 0x21D0, - "uArr": 0x21D1, - "rArr": 0x21D2, - "dArr": 0x21D3, - "hArr": 0x21D4, - "forall": 0x2200, - "part": 0x2202, - "exist": 0x2203, - "empty": 0x2205, - "nabla": 0x2207, - "isin": 0x2208, - "notin": 0x2209, - "ni": 0x220B, - "prod": 0x220F, - "sum": 0x2211, - "minus": 0x2212, - "lowast": 0x2217, - "radic": 0x221A, - "prop": 0x221D, - "infin": 0x221E, - "ang": 0x2220, - "and": 0x2227, - "or": 0x2228, - "cap": 0x2229, - "cup": 0x222A, - "int": 0x222B, - "there4": 0x2234, - "sim": 0x223C, - "cong": 0x2245, - "asymp": 0x2248, - "ne": 0x2260, - "equiv": 0x2261, - "le": 0x2264, - "ge": 0x2265, - "sub": 0x2282, - "sup": 0x2283, - "nsub": 0x2284, - "sube": 0x2286, - "supe": 0x2287, - "oplus": 0x2295, - "otimes": 0x2297, - "perp": 0x22A5, - "sdot": 0x22C5, - "lceil": 0x2308, - "rceil": 0x2309, - "lfloor": 0x230A, - "rfloor": 0x230B, - "lang": 0x2329, - "rang": 0x232A, - "loz": 0x25CA, - "spades": 0x2660, - "clubs": 0x2663, - "hearts": 0x2665, - "diams": 0x2666 - }); - // Flags enum to track count of temp variables and a few dedicated names - var TempFlags; - (function (TempFlags) { - TempFlags[TempFlags["Auto"] = 0] = "Auto"; - TempFlags[TempFlags["CountMask"] = 268435455] = "CountMask"; - TempFlags[TempFlags["_i"] = 268435456] = "_i"; - })(TempFlags || (TempFlags = {})); - var CopyDirection; - (function (CopyDirection) { - CopyDirection[CopyDirection["ToOriginal"] = 0] = "ToOriginal"; - CopyDirection[CopyDirection["ToOutParameter"] = 1] = "ToOutParameter"; - })(CopyDirection || (CopyDirection = {})); - // targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature - function emitFiles(resolver, host, targetSourceFile) { - // emit output for the __extends helper function - var extendsHelper = "\nvar __extends = (this && this.__extends) || function (d, b) {\n for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n};"; - var assignHelper = "\nvar __assign = (this && this.__assign) || Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n};"; - // emit output for the __decorate helper function - var decorateHelper = "\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};"; - // emit output for the __metadata helper function - var metadataHelper = "\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};"; - // emit output for the __param helper function - var paramHelper = "\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};"; - var awaiterHelper = "\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments)).next());\n });\n};"; - var compilerOptions = host.getCompilerOptions(); - var languageVersion = ts.getEmitScriptTarget(compilerOptions); - var modulekind = ts.getEmitModuleKind(compilerOptions); - var sourceMapDataList = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? [] : undefined; - var emittedFilesList = compilerOptions.listEmittedFiles ? [] : undefined; - var emitterDiagnostics = ts.createDiagnosticCollection(); - var emitSkipped = false; - var newLine = host.getNewLine(); - var emitJavaScript = createFileEmitter(); - ts.forEachExpectedEmitFile(host, emitFile, targetSourceFile); - return { - emitSkipped: emitSkipped, - diagnostics: emitterDiagnostics.getDiagnostics(), - emittedFiles: emittedFilesList, - sourceMaps: sourceMapDataList - }; - function isUniqueLocalName(name, container) { - for (var node = container; ts.isNodeDescendentOf(node, container); node = node.nextContainer) { - if (node.locals && name in node.locals) { - // We conservatively include alias symbols to cover cases where they're emitted as locals - if (node.locals[name].flags & (107455 /* Value */ | 1048576 /* ExportValue */ | 8388608 /* Alias */)) { - return false; + /** + * Generates assignment expressions for property initializers. + * + * @param node The class node. + * @param properties An array of property declarations to transform. + * @param receiver The receiver on which each property should be assigned. + */ + function generateInitializedPropertyExpressions(node, properties, receiver) { + var expressions = []; + for (var _i = 0, properties_8 = properties; _i < properties_8.length; _i++) { + var property = properties_8[_i]; + var expression = transformInitializedProperty(node, property, receiver); + expression.startsOnNewLine = true; + ts.setSourceMapRange(expression, ts.moveRangePastModifiers(property)); + ts.setCommentRange(expression, property); + expressions.push(expression); + } + return expressions; + } + /** + * Transforms a property initializer into an assignment statement. + * + * @param node The class containing the property. + * @param property The property declaration. + * @param receiver The object receiving the property assignment. + */ + function transformInitializedProperty(node, property, receiver) { + var propertyName = visitPropertyNameOfClassElement(property); + var initializer = ts.visitNode(property.initializer, visitor, ts.isExpression); + var memberAccess = ts.createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName); + return ts.createAssignment(memberAccess, initializer); + } + /** + * Gets either the static or instance members of a class that are decorated, or have + * parameters that are decorated. + * + * @param node The class containing the member. + * @param isStatic A value indicating whether to retrieve static or instance members of + * the class. + */ + function getDecoratedClassElements(node, isStatic) { + return ts.filter(node.members, isStatic ? isStaticDecoratedClassElement : isInstanceDecoratedClassElement); + } + /** + * Determines whether a class member is a static member of a class that is decorated, or + * has parameters that are decorated. + * + * @param member The class member. + */ + function isStaticDecoratedClassElement(member) { + return isDecoratedClassElement(member, /*isStatic*/ true); + } + /** + * Determines whether a class member is an instance member of a class that is decorated, + * or has parameters that are decorated. + * + * @param member The class member. + */ + function isInstanceDecoratedClassElement(member) { + return isDecoratedClassElement(member, /*isStatic*/ false); + } + /** + * Determines whether a class member is either a static or an instance member of a class + * that is decorated, or has parameters that are decorated. + * + * @param member The class member. + */ + function isDecoratedClassElement(member, isStatic) { + return ts.nodeOrChildIsDecorated(member) + && isStatic === ts.hasModifier(member, 32 /* Static */); + } + /** + * Gets an array of arrays of decorators for the parameters of a function-like node. + * The offset into the result array should correspond to the offset of the parameter. + * + * @param node The function-like node. + */ + function getDecoratorsOfParameters(node) { + var decorators; + if (node) { + var parameters = node.parameters; + for (var i = 0; i < parameters.length; i++) { + var parameter = parameters[i]; + if (decorators || parameter.decorators) { + if (!decorators) { + decorators = new Array(parameters.length); + } + decorators[i] = parameter.decorators; } } } - return true; + return decorators; } - function setLabeledJump(state, isBreak, labelText, labelMarker) { - if (isBreak) { - if (!state.labeledNonLocalBreaks) { - state.labeledNonLocalBreaks = ts.createMap(); - } - state.labeledNonLocalBreaks[labelText] = labelMarker; + /** + * Gets an AllDecorators object containing the decorators for the class and the decorators for the + * parameters of the constructor of the class. + * + * @param node The class node. + */ + function getAllDecoratorsOfConstructor(node) { + var decorators = node.decorators; + var parameters = getDecoratorsOfParameters(ts.getFirstConstructorWithBody(node)); + if (!decorators && !parameters) { + return undefined; } - else { - if (!state.labeledNonLocalContinues) { - state.labeledNonLocalContinues = ts.createMap(); - } - state.labeledNonLocalContinues[labelText] = labelMarker; + return { + decorators: decorators, + parameters: parameters + }; + } + /** + * Gets an AllDecorators object containing the decorators for the member and its parameters. + * + * @param node The class node that contains the member. + * @param member The class member. + */ + function getAllDecoratorsOfClassElement(node, member) { + switch (member.kind) { + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + return getAllDecoratorsOfAccessors(node, member); + case 147 /* MethodDeclaration */: + return getAllDecoratorsOfMethod(member); + case 145 /* PropertyDeclaration */: + return getAllDecoratorsOfProperty(member); + default: + return undefined; } } - function hoistVariableDeclarationFromLoop(state, declaration) { - if (!state.hoistedLocalVariables) { - state.hoistedLocalVariables = []; + /** + * Gets an AllDecorators object containing the decorators for the accessor and its parameters. + * + * @param node The class node that contains the accessor. + * @param accessor The class accessor member. + */ + function getAllDecoratorsOfAccessors(node, accessor) { + if (!accessor.body) { + return undefined; } - visit(declaration.name); - function visit(node) { - if (node.kind === 69 /* Identifier */) { - state.hoistedLocalVariables.push(node); - } - else { - for (var _a = 0, _b = node.elements; _a < _b.length; _a++) { - var element = _b[_a]; - visit(element.name); - } - } + var _a = ts.getAllAccessorDeclarations(node.members, accessor), firstAccessor = _a.firstAccessor, secondAccessor = _a.secondAccessor, setAccessor = _a.setAccessor; + if (accessor !== firstAccessor) { + return undefined; } + var decorators = firstAccessor.decorators || (secondAccessor && secondAccessor.decorators); + var parameters = getDecoratorsOfParameters(setAccessor); + if (!decorators && !parameters) { + return undefined; + } + return { decorators: decorators, parameters: parameters }; } - function createFileEmitter() { - var writer = ts.createTextWriter(newLine); - var write = writer.write, writeTextOfNode = writer.writeTextOfNode, writeLine = writer.writeLine, increaseIndent = writer.increaseIndent, decreaseIndent = writer.decreaseIndent; - var sourceMap = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? ts.createSourceMapWriter(host, writer) : ts.getNullSourceMapWriter(); - var setSourceFile = sourceMap.setSourceFile, emitStart = sourceMap.emitStart, emitEnd = sourceMap.emitEnd, emitPos = sourceMap.emitPos; - var currentSourceFile; - var currentText; - var currentLineMap; - var currentFileIdentifiers; - var renamedDependencies; - var isEs6Module; - var isCurrentFileExternalModule; - // name of an exporter function if file is a System external module - // System.register([...], function () {...}) - // exporting in System modules looks like: - // export var x; ... x = 1 - // => - // var x;... exporter("x", x = 1) - var exportFunctionForFile; - var contextObjectForFile; - var generatedNameSet; - var nodeToGeneratedName; - var computedPropertyNamesToGeneratedNames; - var decoratedClassAliases; - var convertedLoopState; - var extendsEmitted; - var assignEmitted; - var decorateEmitted; - var paramEmitted; - var awaiterEmitted; - var tempFlags = 0; - var tempVariables; - var tempParameters; - var externalImports; - var exportSpecifiers; - var exportEquals; - var hasExportStarsToExportValues; - var detachedCommentsInfo; - /** Sourcemap data that will get encoded */ - var sourceMapData; - /** Is the file being emitted into its own file */ - var isOwnFileEmit; - /** If removeComments is true, no leading-comments needed to be emitted **/ - var emitLeadingCommentsOfPosition = compilerOptions.removeComments ? function (pos) { } : emitLeadingCommentsOfPositionWorker; - var setSourceMapWriterEmit = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? changeSourceMapEmit : function (writer) { }; - var moduleEmitDelegates = ts.createMap((_a = {}, - _a[ts.ModuleKind.ES6] = emitES6Module, - _a[ts.ModuleKind.AMD] = emitAMDModule, - _a[ts.ModuleKind.System] = emitSystemModule, - _a[ts.ModuleKind.UMD] = emitUMDModule, - _a[ts.ModuleKind.CommonJS] = emitCommonJSModule, - _a - )); - var bundleEmitDelegates = ts.createMap((_b = {}, - _b[ts.ModuleKind.ES6] = function () { }, - _b[ts.ModuleKind.AMD] = emitAMDModule, - _b[ts.ModuleKind.System] = emitSystemModule, - _b[ts.ModuleKind.UMD] = function () { }, - _b[ts.ModuleKind.CommonJS] = function () { }, - _b - )); - return doEmit; - function doEmit(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit) { - sourceMap.initialize(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit); - generatedNameSet = ts.createMap(); - nodeToGeneratedName = []; - decoratedClassAliases = []; - isOwnFileEmit = !isBundledEmit; - // Emit helpers from all the files - if (isBundledEmit && modulekind) { - ts.forEach(sourceFiles, emitEmitHelpers); - } - // Do not call emit directly. It does not set the currentSourceFile. - ts.forEach(sourceFiles, emitSourceFile); - writeLine(); - var sourceMappingURL = sourceMap.getSourceMappingURL(); - if (sourceMappingURL) { - write("//# " + "sourceMappingURL" + "=" + sourceMappingURL); // Sometimes tools can sometimes see this line as a source mapping url comment - } - writeEmittedFiles(writer.getText(), jsFilePath, sourceMapFilePath, /*writeByteOrderMark*/ compilerOptions.emitBOM, sourceFiles); - // reset the state - sourceMap.reset(); - writer.reset(); - currentSourceFile = undefined; - currentText = undefined; - currentLineMap = undefined; - exportFunctionForFile = undefined; - contextObjectForFile = undefined; - generatedNameSet = undefined; - nodeToGeneratedName = undefined; - decoratedClassAliases = undefined; - computedPropertyNamesToGeneratedNames = undefined; - convertedLoopState = undefined; - extendsEmitted = false; - decorateEmitted = false; - paramEmitted = false; - awaiterEmitted = false; - assignEmitted = false; - tempFlags = 0; - tempVariables = undefined; - tempParameters = undefined; - externalImports = undefined; - exportSpecifiers = undefined; - exportEquals = undefined; - hasExportStarsToExportValues = undefined; - detachedCommentsInfo = undefined; - sourceMapData = undefined; - isEs6Module = false; - renamedDependencies = undefined; - isCurrentFileExternalModule = false; - } - function emitSourceFile(sourceFile) { - currentSourceFile = sourceFile; - currentText = sourceFile.text; - currentLineMap = ts.getLineStarts(sourceFile); - exportFunctionForFile = undefined; - contextObjectForFile = undefined; - isEs6Module = sourceFile.symbol && sourceFile.symbol.exports && !!sourceFile.symbol.exports["___esModule"]; - renamedDependencies = sourceFile.renamedDependencies; - currentFileIdentifiers = sourceFile.identifiers; - isCurrentFileExternalModule = ts.isExternalModule(sourceFile); - setSourceFile(sourceFile); - emitNodeWithCommentsAndWithoutSourcemap(sourceFile); - } - function isUniqueName(name) { - return !resolver.hasGlobalName(name) && - !(name in currentFileIdentifiers) && - !(name in generatedNameSet); - } - // Return the next available name in the pattern _a ... _z, _0, _1, ... - // TempFlags._i or TempFlags._n may be used to express a preference for that dedicated name. - // Note that names generated by makeTempVariableName and makeUniqueName will never conflict. - function makeTempVariableName(flags) { - if (flags && !(tempFlags & flags)) { - var name_26 = flags === 268435456 /* _i */ ? "_i" : "_n"; - if (isUniqueName(name_26)) { - tempFlags |= flags; - return name_26; - } - } - while (true) { - var count = tempFlags & 268435455 /* CountMask */; - tempFlags++; - // Skip over 'i' and 'n' - if (count !== 8 && count !== 13) { - var name_27 = count < 26 ? "_" + String.fromCharCode(97 /* a */ + count) : "_" + (count - 26); - if (isUniqueName(name_27)) { - return name_27; - } - } - } + /** + * Gets an AllDecorators object containing the decorators for the method and its parameters. + * + * @param method The class method member. + */ + function getAllDecoratorsOfMethod(method) { + if (!method.body) { + return undefined; } - // Generate a name that is unique within the current file and doesn't conflict with any names - // in global scope. The name is formed by adding an '_n' suffix to the specified base name, - // where n is a positive integer. Note that names generated by makeTempVariableName and - // makeUniqueName are guaranteed to never conflict. - function makeUniqueName(baseName) { - // Find the first unique 'name_n', where n is a positive number - if (baseName.charCodeAt(baseName.length - 1) !== 95 /* _ */) { - baseName += "_"; - } - var i = 1; - while (true) { - var generatedName = baseName + i; - if (isUniqueName(generatedName)) { - return generatedNameSet[generatedName] = generatedName; - } - i++; - } + var decorators = method.decorators; + var parameters = getDecoratorsOfParameters(method); + if (!decorators && !parameters) { + return undefined; } - function generateNameForModuleOrEnum(node) { - var name = node.name.text; - // Use module/enum name itself if it is unique, otherwise make a unique variation - return isUniqueLocalName(name, node) ? name : makeUniqueName(name); + return { decorators: decorators, parameters: parameters }; + } + /** + * Gets an AllDecorators object containing the decorators for the property. + * + * @param property The class property member. + */ + function getAllDecoratorsOfProperty(property) { + var decorators = property.decorators; + if (!decorators) { + return undefined; } - function generateNameForImportOrExportDeclaration(node) { - var expr = ts.getExternalModuleName(node); - var baseName = expr.kind === 9 /* StringLiteral */ ? - ts.escapeIdentifier(ts.makeIdentifierFromModuleName(expr.text)) : "module"; - return makeUniqueName(baseName); + return { decorators: decorators }; + } + /** + * Transforms all of the decorators for a declaration into an array of expressions. + * + * @param node The declaration node. + * @param allDecorators An object containing all of the decorators for the declaration. + */ + function transformAllDecoratorsOfDeclaration(node, allDecorators) { + if (!allDecorators) { + return undefined; } - function generateNameForExportDefault() { - return makeUniqueName("default"); + var decoratorExpressions = []; + ts.addRange(decoratorExpressions, ts.map(allDecorators.decorators, transformDecorator)); + ts.addRange(decoratorExpressions, ts.flatMap(allDecorators.parameters, transformDecoratorsOfParameter)); + addTypeMetadata(node, decoratorExpressions); + return decoratorExpressions; + } + /** + * Generates statements used to apply decorators to either the static or instance members + * of a class. + * + * @param node The class node. + * @param isStatic A value indicating whether to generate statements for static or + * instance members. + */ + function addClassElementDecorationStatements(statements, node, isStatic) { + ts.addRange(statements, ts.map(generateClassElementDecorationExpressions(node, isStatic), expressionToStatement)); + } + /** + * Generates expressions used to apply decorators to either the static or instance members + * of a class. + * + * @param node The class node. + * @param isStatic A value indicating whether to generate expressions for static or + * instance members. + */ + function generateClassElementDecorationExpressions(node, isStatic) { + var members = getDecoratedClassElements(node, isStatic); + var expressions; + for (var _i = 0, members_2 = members; _i < members_2.length; _i++) { + var member = members_2[_i]; + var expression = generateClassElementDecorationExpression(node, member); + if (expression) { + if (!expressions) { + expressions = [expression]; + } + else { + expressions.push(expression); + } + } } - function generateNameForClassExpression() { - return makeUniqueName("class"); + return expressions; + } + /** + * Generates an expression used to evaluate class element decorators at runtime. + * + * @param node The class node that contains the member. + * @param member The class member. + */ + function generateClassElementDecorationExpression(node, member) { + var allDecorators = getAllDecoratorsOfClassElement(node, member); + var decoratorExpressions = transformAllDecoratorsOfDeclaration(member, allDecorators); + if (!decoratorExpressions) { + return undefined; } - function generateNameForNode(node) { - switch (node.kind) { - case 69 /* Identifier */: - return makeUniqueName(node.text); - case 225 /* ModuleDeclaration */: - case 224 /* EnumDeclaration */: - return generateNameForModuleOrEnum(node); - case 230 /* ImportDeclaration */: - case 236 /* ExportDeclaration */: - return generateNameForImportOrExportDeclaration(node); - case 220 /* FunctionDeclaration */: - case 221 /* ClassDeclaration */: - case 235 /* ExportAssignment */: - return generateNameForExportDefault(); - case 192 /* ClassExpression */: - return generateNameForClassExpression(); - default: - ts.Debug.fail(); - } + // Emit the call to __decorate. Given the following: + // + // class C { + // @dec method(@dec2 x) {} + // @dec get accessor() {} + // @dec prop; + // } + // + // The emit for a method is: + // + // __decorate([ + // dec, + // __param(0, dec2), + // __metadata("design:type", Function), + // __metadata("design:paramtypes", [Object]), + // __metadata("design:returntype", void 0) + // ], C.prototype, "method", undefined); + // + // The emit for an accessor is: + // + // __decorate([ + // dec + // ], C.prototype, "accessor", undefined); + // + // The emit for a property is: + // + // __decorate([ + // dec + // ], C.prototype, "prop"); + // + var prefix = getClassMemberPrefix(node, member); + var memberName = getExpressionForPropertyName(member, /*generateNameForComputedPropertyName*/ true); + var descriptor = languageVersion > 0 /* ES3 */ + ? member.kind === 145 /* PropertyDeclaration */ + ? ts.createVoidZero() + : ts.createNull() + : undefined; + var helper = ts.createDecorateHelper(currentSourceFileExternalHelpersModuleName, decoratorExpressions, prefix, memberName, descriptor, ts.moveRangePastDecorators(member)); + ts.setEmitFlags(helper, 49152 /* NoComments */); + return helper; + } + /** + * Generates a __decorate helper call for a class constructor. + * + * @param node The class node. + */ + function addConstructorDecorationStatement(statements, node, decoratedClassAlias) { + var expression = generateConstructorDecorationExpression(node, decoratedClassAlias); + if (expression) { + statements.push(ts.setOriginalNode(ts.createStatement(expression), node)); } - function getGeneratedNameForNode(node) { - var id = ts.getNodeId(node); - return nodeToGeneratedName[id] || (nodeToGeneratedName[id] = ts.unescapeIdentifier(generateNameForNode(node))); + } + /** + * Generates a __decorate helper call for a class constructor. + * + * @param node The class node. + */ + function generateConstructorDecorationExpression(node, decoratedClassAlias) { + var allDecorators = getAllDecoratorsOfConstructor(node); + var decoratorExpressions = transformAllDecoratorsOfDeclaration(node, allDecorators); + if (!decoratorExpressions) { + return undefined; } - /** Write emitted output to disk */ - function writeEmittedFiles(emitOutput, jsFilePath, sourceMapFilePath, writeByteOrderMark, sourceFiles) { - if (compilerOptions.sourceMap && !compilerOptions.inlineSourceMap) { - ts.writeFile(host, emitterDiagnostics, sourceMapFilePath, sourceMap.getText(), /*writeByteOrderMark*/ false, sourceFiles); - } - if (sourceMapDataList) { - sourceMapDataList.push(sourceMap.getSourceMapData()); - } - ts.writeFile(host, emitterDiagnostics, jsFilePath, emitOutput, writeByteOrderMark, sourceFiles); + // Emit the call to __decorate. Given the class: + // + // @dec + // class C { + // } + // + // The emit for the class is: + // + // C = C_1 = __decorate([dec], C); + // + if (decoratedClassAlias) { + var expression = ts.createAssignment(decoratedClassAlias, ts.createDecorateHelper(currentSourceFileExternalHelpersModuleName, decoratorExpressions, getDeclarationName(node))); + var result = ts.createAssignment(getDeclarationName(node), expression, ts.moveRangePastDecorators(node)); + ts.setEmitFlags(result, 49152 /* NoComments */); + return result; } - // Create a temporary variable with a unique unused name. - function createTempVariable(flags) { - var result = ts.createSynthesizedNode(69 /* Identifier */); - result.text = makeTempVariableName(flags); + else { + var result = ts.createAssignment(getDeclarationName(node), ts.createDecorateHelper(currentSourceFileExternalHelpersModuleName, decoratorExpressions, getDeclarationName(node)), ts.moveRangePastDecorators(node)); + ts.setEmitFlags(result, 49152 /* NoComments */); return result; } - function recordTempDeclaration(name) { - if (!tempVariables) { - tempVariables = []; + } + /** + * Transforms a decorator into an expression. + * + * @param decorator The decorator node. + */ + function transformDecorator(decorator) { + return ts.visitNode(decorator.expression, visitor, ts.isExpression); + } + /** + * Transforms the decorators of a parameter. + * + * @param decorators The decorators for the parameter at the provided offset. + * @param parameterOffset The offset of the parameter. + */ + function transformDecoratorsOfParameter(decorators, parameterOffset) { + var expressions; + if (decorators) { + expressions = []; + for (var _i = 0, decorators_1 = decorators; _i < decorators_1.length; _i++) { + var decorator = decorators_1[_i]; + var helper = ts.createParamHelper(currentSourceFileExternalHelpersModuleName, transformDecorator(decorator), parameterOffset, + /*location*/ decorator.expression); + ts.setEmitFlags(helper, 49152 /* NoComments */); + expressions.push(helper); } - tempVariables.push(name); } - function createAndRecordTempVariable(flags) { - var temp = createTempVariable(flags); - recordTempDeclaration(temp); - return temp; + return expressions; + } + /** + * Adds optional type metadata for a declaration. + * + * @param node The declaration node. + * @param decoratorExpressions The destination array to which to add new decorator expressions. + */ + function addTypeMetadata(node, decoratorExpressions) { + if (USE_NEW_TYPE_METADATA_FORMAT) { + addNewTypeMetadata(node, decoratorExpressions); } - function emitTempDeclarations(newLine) { - if (tempVariables) { - if (newLine) { - writeLine(); - } - else { - write(" "); - } - write("var "); - emitCommaList(tempVariables); - write(";"); - } - } - /** Emit the text for the given token that comes after startPos - * This by default writes the text provided with the given tokenKind - * but if optional emitFn callback is provided the text is emitted using the callback instead of default text - * @param tokenKind the kind of the token to search and emit - * @param startPos the position in the source to start searching for the token - * @param emitFn if given will be invoked to emit the text instead of actual token emit */ - function emitToken(tokenKind, startPos, emitFn) { - var tokenStartPos = ts.skipTrivia(currentText, startPos); - emitPos(tokenStartPos); - var tokenString = ts.tokenToString(tokenKind); - if (emitFn) { - emitFn(); - } - else { - write(tokenString); - } - var tokenEndPos = tokenStartPos + tokenString.length; - emitPos(tokenEndPos); - return tokenEndPos; + else { + addOldTypeMetadata(node, decoratorExpressions); } - function emitOptional(prefix, node) { - if (node) { - write(prefix); - emit(node); + } + function addOldTypeMetadata(node, decoratorExpressions) { + if (compilerOptions.emitDecoratorMetadata) { + if (shouldAddTypeMetadata(node)) { + decoratorExpressions.push(ts.createMetadataHelper(currentSourceFileExternalHelpersModuleName, "design:type", serializeTypeOfNode(node))); } - } - function emitParenthesizedIf(node, parenthesized) { - if (parenthesized) { - write("("); + if (shouldAddParamTypesMetadata(node)) { + decoratorExpressions.push(ts.createMetadataHelper(currentSourceFileExternalHelpersModuleName, "design:paramtypes", serializeParameterTypesOfNode(node))); } - emit(node); - if (parenthesized) { - write(")"); + if (shouldAddReturnTypeMetadata(node)) { + decoratorExpressions.push(ts.createMetadataHelper(currentSourceFileExternalHelpersModuleName, "design:returntype", serializeReturnTypeOfNode(node))); } } - function emitLinePreservingList(parent, nodes, allowTrailingComma, spacesBetweenBraces) { - ts.Debug.assert(nodes.length > 0); - increaseIndent(); - if (nodeStartPositionsAreOnSameLine(parent, nodes[0])) { - if (spacesBetweenBraces) { - write(" "); - } - } - else { - writeLine(); - } - for (var i = 0, n = nodes.length; i < n; i++) { - if (i) { - if (nodeEndIsOnSameLineAsNodeStart(nodes[i - 1], nodes[i])) { - write(", "); - } - else { - write(","); - writeLine(); - } - } - emit(nodes[i]); + } + function addNewTypeMetadata(node, decoratorExpressions) { + if (compilerOptions.emitDecoratorMetadata) { + var properties = void 0; + if (shouldAddTypeMetadata(node)) { + (properties || (properties = [])).push(ts.createPropertyAssignment("type", ts.createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, /*equalsGreaterThanToken*/ undefined, serializeTypeOfNode(node)))); } - if (nodes.hasTrailingComma && allowTrailingComma) { - write(","); + if (shouldAddParamTypesMetadata(node)) { + (properties || (properties = [])).push(ts.createPropertyAssignment("paramTypes", ts.createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, /*equalsGreaterThanToken*/ undefined, serializeParameterTypesOfNode(node)))); } - decreaseIndent(); - if (nodeEndPositionsAreOnSameLine(parent, ts.lastOrUndefined(nodes))) { - if (spacesBetweenBraces) { - write(" "); - } + if (shouldAddReturnTypeMetadata(node)) { + (properties || (properties = [])).push(ts.createPropertyAssignment("returnType", ts.createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, /*equalsGreaterThanToken*/ undefined, serializeReturnTypeOfNode(node)))); } - else { - writeLine(); + if (properties) { + decoratorExpressions.push(ts.createMetadataHelper(currentSourceFileExternalHelpersModuleName, "design:typeinfo", ts.createObjectLiteral(properties, /*location*/ undefined, /*multiLine*/ true))); } } - function emitList(nodes, start, count, multiLine, trailingComma, leadingComma, noTrailingNewLine, emitNode) { - if (!emitNode) { - emitNode = emit; - } - for (var i = 0; i < count; i++) { - if (multiLine) { - if (i || leadingComma) { - write(","); - } - writeLine(); + } + /** + * Determines whether to emit the "design:type" metadata based on the node's kind. + * The caller should have already tested whether the node has decorators and whether the + * emitDecoratorMetadata compiler option is set. + * + * @param node The node to test. + */ + function shouldAddTypeMetadata(node) { + var kind = node.kind; + return kind === 147 /* MethodDeclaration */ + || kind === 149 /* GetAccessor */ + || kind === 150 /* SetAccessor */ + || kind === 145 /* PropertyDeclaration */; + } + /** + * Determines whether to emit the "design:returntype" metadata based on the node's kind. + * The caller should have already tested whether the node has decorators and whether the + * emitDecoratorMetadata compiler option is set. + * + * @param node The node to test. + */ + function shouldAddReturnTypeMetadata(node) { + return node.kind === 147 /* MethodDeclaration */; + } + /** + * Determines whether to emit the "design:paramtypes" metadata based on the node's kind. + * The caller should have already tested whether the node has decorators and whether the + * emitDecoratorMetadata compiler option is set. + * + * @param node The node to test. + */ + function shouldAddParamTypesMetadata(node) { + var kind = node.kind; + return kind === 221 /* ClassDeclaration */ + || kind === 192 /* ClassExpression */ + || kind === 147 /* MethodDeclaration */ + || kind === 149 /* GetAccessor */ + || kind === 150 /* SetAccessor */; + } + /** + * Serializes the type of a node for use with decorator type metadata. + * + * @param node The node that should have its type serialized. + */ + function serializeTypeOfNode(node) { + switch (node.kind) { + case 145 /* PropertyDeclaration */: + case 142 /* Parameter */: + case 149 /* GetAccessor */: + return serializeTypeNode(node.type); + case 150 /* SetAccessor */: + return serializeTypeNode(ts.getSetAccessorTypeAnnotationNode(node)); + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + case 147 /* MethodDeclaration */: + return ts.createIdentifier("Function"); + default: + return ts.createVoidZero(); + } + } + /** + * Gets the most likely element type for a TypeNode. This is not an exhaustive test + * as it assumes a rest argument can only be an array type (either T[], or Array). + * + * @param node The type node. + */ + function getRestParameterElementType(node) { + if (node && node.kind === 160 /* ArrayType */) { + return node.elementType; + } + else if (node && node.kind === 155 /* TypeReference */) { + return ts.singleOrUndefined(node.typeArguments); + } + else { + return undefined; + } + } + /** + * Serializes the types of the parameters of a node for use with decorator type metadata. + * + * @param node The node that should have its parameter types serialized. + */ + function serializeParameterTypesOfNode(node) { + var valueDeclaration = ts.isClassLike(node) + ? ts.getFirstConstructorWithBody(node) + : ts.isFunctionLike(node) && ts.nodeIsPresent(node.body) + ? node + : undefined; + var expressions = []; + if (valueDeclaration) { + var parameters = valueDeclaration.parameters; + var numParameters = parameters.length; + for (var i = 0; i < numParameters; i++) { + var parameter = parameters[i]; + if (i === 0 && ts.isIdentifier(parameter.name) && parameter.name.text === "this") { + continue; + } + if (parameter.dotDotDotToken) { + expressions.push(serializeTypeNode(getRestParameterElementType(parameter.type))); } else { - if (i || leadingComma) { - write(", "); - } + expressions.push(serializeTypeOfNode(parameter)); } - var node = nodes[start + i]; - // This emitting is to make sure we emit following comment properly - // ...(x, /*comment1*/ y)... - // ^ => node.pos - // "comment1" is not considered leading comment for "y" but rather - // considered as trailing comment of the previous node. - emitTrailingCommentsOfPosition(node.pos); - emitNode(node); - leadingComma = true; - } - if (trailingComma) { - write(","); - } - if (multiLine && !noTrailingNewLine) { - writeLine(); } - return count; } - function emitCommaList(nodes) { - if (nodes) { - emitList(nodes, 0, nodes.length, /*multiLine*/ false, /*trailingComma*/ false); - } + return ts.createArrayLiteral(expressions); + } + /** + * Serializes the return type of a node for use with decorator type metadata. + * + * @param node The node that should have its return type serialized. + */ + function serializeReturnTypeOfNode(node) { + if (ts.isFunctionLike(node) && node.type) { + return serializeTypeNode(node.type); } - function emitLines(nodes) { - emitLinesStartingAt(nodes, /*startIndex*/ 0); + else if (ts.isAsyncFunctionLike(node)) { + return ts.createIdentifier("Promise"); } - function emitLinesStartingAt(nodes, startIndex) { - for (var i = startIndex; i < nodes.length; i++) { - writeLine(); - emit(nodes[i]); - } + return ts.createVoidZero(); + } + /** + * Serializes a type node for use with decorator type metadata. + * + * Types are serialized in the following fashion: + * - Void types point to "undefined" (e.g. "void 0") + * - Function and Constructor types point to the global "Function" constructor. + * - Interface types with a call or construct signature types point to the global + * "Function" constructor. + * - Array and Tuple types point to the global "Array" constructor. + * - Type predicates and booleans point to the global "Boolean" constructor. + * - String literal types and strings point to the global "String" constructor. + * - Enum and number types point to the global "Number" constructor. + * - Symbol types point to the global "Symbol" constructor. + * - Type references to classes (or class-like variables) point to the constructor for the class. + * - Anything else points to the global "Object" constructor. + * + * @param node The type node to serialize. + */ + function serializeTypeNode(node) { + if (node === undefined) { + return ts.createIdentifier("Object"); } - function isBinaryOrOctalIntegerLiteral(node, text) { - if (node.kind === 8 /* NumericLiteral */ && text.length > 1) { - switch (text.charCodeAt(1)) { - case 98 /* b */: - case 66 /* B */: - case 111 /* o */: - case 79 /* O */: - return true; + switch (node.kind) { + case 103 /* VoidKeyword */: + return ts.createVoidZero(); + case 164 /* ParenthesizedType */: + return serializeTypeNode(node.type); + case 156 /* FunctionType */: + case 157 /* ConstructorType */: + return ts.createIdentifier("Function"); + case 160 /* ArrayType */: + case 161 /* TupleType */: + return ts.createIdentifier("Array"); + case 154 /* TypePredicate */: + case 120 /* BooleanKeyword */: + return ts.createIdentifier("Boolean"); + case 132 /* StringKeyword */: + return ts.createIdentifier("String"); + case 166 /* LiteralType */: + switch (node.literal.kind) { + case 9 /* StringLiteral */: + return ts.createIdentifier("String"); + case 8 /* NumericLiteral */: + return ts.createIdentifier("Number"); + case 99 /* TrueKeyword */: + case 84 /* FalseKeyword */: + return ts.createIdentifier("Boolean"); + default: + ts.Debug.failBadSyntaxKind(node.literal); + break; } - } - return false; + break; + case 130 /* NumberKeyword */: + return ts.createIdentifier("Number"); + case 133 /* SymbolKeyword */: + return languageVersion < 2 /* ES6 */ + ? getGlobalSymbolNameWithFallback() + : ts.createIdentifier("Symbol"); + case 155 /* TypeReference */: + return serializeTypeReferenceNode(node); + case 158 /* TypeQuery */: + case 159 /* TypeLiteral */: + case 162 /* UnionType */: + case 163 /* IntersectionType */: + case 117 /* AnyKeyword */: + case 165 /* ThisType */: + break; + default: + ts.Debug.failBadSyntaxKind(node); + break; } - function emitLiteral(node) { - var text = getLiteralText(node); - if ((compilerOptions.sourceMap || compilerOptions.inlineSourceMap) && (node.kind === 9 /* StringLiteral */ || ts.isTemplateLiteralKind(node.kind))) { - writer.writeLiteral(text); - } - else if (languageVersion < 2 /* ES6 */ && isBinaryOrOctalIntegerLiteral(node, text)) { - write(node.text); - } - else { - write(text); - } + return ts.createIdentifier("Object"); + } + /** + * Serializes a TypeReferenceNode to an appropriate JS constructor value for use with + * decorator type metadata. + * + * @param node The type reference node. + */ + function serializeTypeReferenceNode(node) { + switch (resolver.getTypeReferenceSerializationKind(node.typeName, currentScope)) { + case ts.TypeReferenceSerializationKind.Unknown: + var serialized = serializeEntityNameAsExpression(node.typeName, /*useFallback*/ true); + var temp = ts.createTempVariable(hoistVariableDeclaration); + return ts.createLogicalOr(ts.createLogicalAnd(ts.createStrictEquality(ts.createTypeOf(ts.createAssignment(temp, serialized)), ts.createLiteral("function")), temp), ts.createIdentifier("Object")); + case ts.TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue: + return serializeEntityNameAsExpression(node.typeName, /*useFallback*/ false); + case ts.TypeReferenceSerializationKind.VoidNullableOrNeverType: + return ts.createVoidZero(); + case ts.TypeReferenceSerializationKind.BooleanType: + return ts.createIdentifier("Boolean"); + case ts.TypeReferenceSerializationKind.NumberLikeType: + return ts.createIdentifier("Number"); + case ts.TypeReferenceSerializationKind.StringLikeType: + return ts.createIdentifier("String"); + case ts.TypeReferenceSerializationKind.ArrayLikeType: + return ts.createIdentifier("Array"); + case ts.TypeReferenceSerializationKind.ESSymbolType: + return languageVersion < 2 /* ES6 */ + ? getGlobalSymbolNameWithFallback() + : ts.createIdentifier("Symbol"); + case ts.TypeReferenceSerializationKind.TypeWithCallSignature: + return ts.createIdentifier("Function"); + case ts.TypeReferenceSerializationKind.Promise: + return ts.createIdentifier("Promise"); + case ts.TypeReferenceSerializationKind.ObjectType: + default: + return ts.createIdentifier("Object"); } - function getLiteralText(node) { - // Any template literal or string literal with an extended escape - // (e.g. "\u{0067}") will need to be downleveled as a escaped string literal. - if (languageVersion < 2 /* ES6 */ && (ts.isTemplateLiteralKind(node.kind) || node.hasExtendedUnicodeEscape)) { - return getQuotedEscapedLiteralText('"', node.text, '"'); - } - // If we don't need to downlevel and we can reach the original source text using - // the node's parent reference, then simply get the text as it was originally written. - if (node.parent) { - return ts.getTextOfNodeFromSourceText(currentText, node); - } - // If we can't reach the original source text, use the canonical form if it's a number, - // or an escaped quoted form of the original text if it's string-like. - switch (node.kind) { - case 9 /* StringLiteral */: - return getQuotedEscapedLiteralText('"', node.text, '"'); - case 11 /* NoSubstitutionTemplateLiteral */: - return getQuotedEscapedLiteralText("`", node.text, "`"); - case 12 /* TemplateHead */: - return getQuotedEscapedLiteralText("`", node.text, "${"); - case 13 /* TemplateMiddle */: - return getQuotedEscapedLiteralText("}", node.text, "${"); - case 14 /* TemplateTail */: - return getQuotedEscapedLiteralText("}", node.text, "`"); - case 8 /* NumericLiteral */: - return node.text; - } - ts.Debug.fail("Literal kind '" + node.kind + "' not accounted for."); - } - function getQuotedEscapedLiteralText(leftQuote, text, rightQuote) { - return leftQuote + ts.escapeNonAsciiCharacters(ts.escapeString(text)) + rightQuote; - } - function emitDownlevelRawTemplateLiteral(node) { - // Find original source text, since we need to emit the raw strings of the tagged template. - // The raw strings contain the (escaped) strings of what the user wrote. - // Examples: `\n` is converted to "\\n", a template string with a newline to "\n". - var text = ts.getTextOfNodeFromSourceText(currentText, node); - // text contains the original source, it will also contain quotes ("`"), dollar signs and braces ("${" and "}"), - // thus we need to remove those characters. - // First template piece starts with "`", others with "}" - // Last template piece ends with "`", others with "${" - var isLast = node.kind === 11 /* NoSubstitutionTemplateLiteral */ || node.kind === 14 /* TemplateTail */; - text = text.substring(1, text.length - (isLast ? 1 : 2)); - // Newline normalization: - // ES6 Spec 11.8.6.1 - Static Semantics of TV's and TRV's - // and LineTerminatorSequences are normalized to for both TV and TRV. - text = text.replace(/\r\n?/g, "\n"); - text = ts.escapeString(text); - write("\"" + text + "\""); - } - function emitDownlevelTaggedTemplateArray(node, literalEmitter) { - write("["); - if (node.template.kind === 11 /* NoSubstitutionTemplateLiteral */) { - literalEmitter(node.template); - } - else { - literalEmitter(node.template.head); - ts.forEach(node.template.templateSpans, function (child) { - write(", "); - literalEmitter(child.literal); - }); - } - write("]"); + } + /** + * Serializes an entity name as an expression for decorator type metadata. + * + * @param node The entity name to serialize. + * @param useFallback A value indicating whether to use logical operators to test for the + * entity name at runtime. + */ + function serializeEntityNameAsExpression(node, useFallback) { + switch (node.kind) { + case 69 /* Identifier */: + // Create a clone of the name with a new parent, and treat it as if it were + // a source tree node for the purposes of the checker. + var name_30 = ts.getMutableClone(node); + name_30.flags &= ~8 /* Synthesized */; + name_30.original = undefined; + name_30.parent = currentScope; + if (useFallback) { + return ts.createLogicalAnd(ts.createStrictInequality(ts.createTypeOf(name_30), ts.createLiteral("undefined")), name_30); + } + return name_30; + case 139 /* QualifiedName */: + return serializeQualifiedNameAsExpression(node, useFallback); } - function emitDownlevelTaggedTemplate(node) { - var tempVariable = createAndRecordTempVariable(0 /* Auto */); - write("("); - emit(tempVariable); - write(" = "); - emitDownlevelTaggedTemplateArray(node, emit); - write(", "); - emit(tempVariable); - write(".raw = "); - emitDownlevelTaggedTemplateArray(node, emitDownlevelRawTemplateLiteral); - write(", "); - emitParenthesizedIf(node.tag, needsParenthesisForPropertyAccessOrInvocation(node.tag)); - write("("); - emit(tempVariable); - // Now we emit the expressions - if (node.template.kind === 189 /* TemplateExpression */) { - ts.forEach(node.template.templateSpans, function (templateSpan) { - write(", "); - var needsParens = templateSpan.expression.kind === 187 /* BinaryExpression */ - && templateSpan.expression.operatorToken.kind === 24 /* CommaToken */; - emitParenthesizedIf(templateSpan.expression, needsParens); - }); - } - write("))"); + } + /** + * Serializes an qualified name as an expression for decorator type metadata. + * + * @param node The qualified name to serialize. + * @param useFallback A value indicating whether to use logical operators to test for the + * qualified name at runtime. + */ + function serializeQualifiedNameAsExpression(node, useFallback) { + var left; + if (node.left.kind === 69 /* Identifier */) { + left = serializeEntityNameAsExpression(node.left, useFallback); } - function emitTemplateExpression(node) { - // In ES6 mode and above, we can simply emit each portion of a template in order, but in - // ES3 & ES5 we must convert the template expression into a series of string concatenations. - if (languageVersion >= 2 /* ES6 */) { - ts.forEachChild(node, emit); - return; - } - var emitOuterParens = ts.isExpression(node.parent) - && templateNeedsParens(node, node.parent); - if (emitOuterParens) { - write("("); - } - var headEmitted = false; - if (shouldEmitTemplateHead()) { - emitLiteral(node.head); - headEmitted = true; - } - for (var i = 0, n = node.templateSpans.length; i < n; i++) { - var templateSpan = node.templateSpans[i]; - // Check if the expression has operands and binds its operands less closely than binary '+'. - // If it does, we need to wrap the expression in parentheses. Otherwise, something like - // `abc${ 1 << 2 }` - // becomes - // "abc" + 1 << 2 + "" - // which is really - // ("abc" + 1) << (2 + "") - // rather than - // "abc" + (1 << 2) + "" - var needsParens = templateSpan.expression.kind !== 178 /* ParenthesizedExpression */ - && comparePrecedenceToBinaryPlus(templateSpan.expression) !== 1 /* GreaterThan */; - if (i > 0 || headEmitted) { - // If this is the first span and the head was not emitted, then this templateSpan's - // expression will be the first to be emitted. Don't emit the preceding ' + ' in that - // case. - write(" + "); - } - emitParenthesizedIf(templateSpan.expression, needsParens); - // Only emit if the literal is non-empty. - // The binary '+' operator is left-associative, so the first string concatenation - // with the head will force the result up to this point to be a string. - // Emitting a '+ ""' has no semantic effect for middles and tails. - if (templateSpan.literal.text.length !== 0) { - write(" + "); - emitLiteral(templateSpan.literal); - } - } - if (emitOuterParens) { - write(")"); - } - function shouldEmitTemplateHead() { - // If this expression has an empty head literal and the first template span has a non-empty - // literal, then emitting the empty head literal is not necessary. - // `${ foo } and ${ bar }` - // can be emitted as - // foo + " and " + bar - // This is because it is only required that one of the first two operands in the emit - // output must be a string literal, so that the other operand and all following operands - // are forced into strings. - // - // If the first template span has an empty literal, then the head must still be emitted. - // `${ foo }${ bar }` - // must still be emitted as - // "" + foo + bar - // There is always atleast one templateSpan in this code path, since - // NoSubstitutionTemplateLiterals are directly emitted via emitLiteral() - ts.Debug.assert(node.templateSpans.length !== 0); - return node.head.text.length !== 0 || node.templateSpans[0].literal.text.length === 0; - } - function templateNeedsParens(template, parent) { - switch (parent.kind) { - case 174 /* CallExpression */: - case 175 /* NewExpression */: - return parent.expression === template; - case 176 /* TaggedTemplateExpression */: - case 178 /* ParenthesizedExpression */: - return false; - default: - return comparePrecedenceToBinaryPlus(parent) !== -1 /* LessThan */; - } - } - /** - * Returns whether the expression has lesser, greater, - * or equal precedence to the binary '+' operator - */ - function comparePrecedenceToBinaryPlus(expression) { - // All binary expressions have lower precedence than '+' apart from '*', '/', and '%' - // which have greater precedence and '-' which has equal precedence. - // All unary operators have a higher precedence apart from yield. - // Arrow functions and conditionals have a lower precedence, - // although we convert the former into regular function expressions in ES5 mode, - // and in ES6 mode this function won't get called anyway. - // - // TODO (drosen): Note that we need to account for the upcoming 'yield' and - // spread ('...') unary operators that are anticipated for ES6. - switch (expression.kind) { - case 187 /* BinaryExpression */: - switch (expression.operatorToken.kind) { - case 37 /* AsteriskToken */: - case 39 /* SlashToken */: - case 40 /* PercentToken */: - return 1 /* GreaterThan */; - case 35 /* PlusToken */: - case 36 /* MinusToken */: - return 0 /* EqualTo */; - default: - return -1 /* LessThan */; - } - case 190 /* YieldExpression */: - case 188 /* ConditionalExpression */: - return -1 /* LessThan */; - default: - return 1 /* GreaterThan */; - } - } + else if (useFallback) { + var temp = ts.createTempVariable(hoistVariableDeclaration); + left = ts.createLogicalAnd(ts.createAssignment(temp, serializeEntityNameAsExpression(node.left, /*useFallback*/ true)), temp); } - function emitTemplateSpan(span) { - emit(span.expression); - emit(span.literal); + else { + left = serializeEntityNameAsExpression(node.left, /*useFallback*/ false); } - function jsxEmitReact(node) { - /// Emit a tag name, which is either '"div"' for lower-cased names, or - /// 'Div' for upper-cased or dotted names - function emitTagName(name) { - if (name.kind === 69 /* Identifier */ && ts.isIntrinsicJsxName(name.text)) { - write('"'); - emit(name); - write('"'); - } - else { - emit(name); - } - } - /// Emit an attribute name, which is quoted if it needs to be quoted. Because - /// these emit into an object literal property name, we don't need to be worried - /// about keywords, just non-identifier characters - function emitAttributeName(name) { - if (/^[A-Za-z_]\w*$/.test(name.text)) { - emit(name); - } - else { - write('"'); - emit(name); - write('"'); - } - } - /// Emit an name/value pair for an attribute (e.g. "x: 3") - function emitJsxAttribute(node) { - emitAttributeName(node.name); - write(": "); - if (node.initializer) { - emit(node.initializer); - } - else { - write("true"); - } - } - function emitJsxElement(openingNode, children) { - var syntheticReactRef = ts.createSynthesizedNode(69 /* Identifier */); - syntheticReactRef.text = compilerOptions.reactNamespace ? compilerOptions.reactNamespace : "React"; - syntheticReactRef.parent = openingNode; - // Call React.createElement(tag, ... - emitLeadingComments(openingNode); - emitExpressionIdentifier(syntheticReactRef); - write(".createElement("); - emitTagName(openingNode.tagName); - write(", "); - // Attribute list - if (openingNode.attributes.length === 0) { - // When there are no attributes, React wants "null" - write("null"); - } - else { - // Either emit one big object literal (no spread attribs), or - // a call to the __assign helper - var attrs = openingNode.attributes; - if (ts.forEach(attrs, function (attr) { return attr.kind === 247 /* JsxSpreadAttribute */; })) { - write("__assign("); - var haveOpenedObjectLiteral = false; - for (var i = 0; i < attrs.length; i++) { - if (attrs[i].kind === 247 /* JsxSpreadAttribute */) { - // If this is the first argument, we need to emit a {} as the first argument - if (i === 0) { - write("{}, "); - } - if (haveOpenedObjectLiteral) { - write("}"); - haveOpenedObjectLiteral = false; - } - if (i > 0) { - write(", "); - } - emit(attrs[i].expression); - } - else { - ts.Debug.assert(attrs[i].kind === 246 /* JsxAttribute */); - if (haveOpenedObjectLiteral) { - write(", "); - } - else { - haveOpenedObjectLiteral = true; - if (i > 0) { - write(", "); - } - write("{"); - } - emitJsxAttribute(attrs[i]); - } - } - if (haveOpenedObjectLiteral) - write("}"); - write(")"); // closing paren to React.__spread( - } - else { - // One object literal with all the attributes in them - write("{"); - for (var i = 0, n = attrs.length; i < n; i++) { - if (i > 0) { - write(", "); - } - emitJsxAttribute(attrs[i]); - } - write("}"); - } - } - // Children - if (children) { - var firstChild = void 0; - var multipleEmittableChildren = false; - for (var i = 0, n = children.length; i < n; i++) { - var jsxChild = children[i]; - if (isJsxChildEmittable(jsxChild)) { - // we need to decide whether to emit in single line or multiple lines as indented list - // store firstChild reference, if we see another emittable child, then emit accordingly - if (!firstChild) { - write(", "); - firstChild = jsxChild; - } - else { - // more than one emittable child, emit indented list - if (!multipleEmittableChildren) { - multipleEmittableChildren = true; - increaseIndent(); - writeLine(); - emit(firstChild); - } - write(", "); - writeLine(); - emit(jsxChild); - } - } - } - if (multipleEmittableChildren) { - decreaseIndent(); - } - else if (firstChild) { - if (firstChild.kind !== 241 /* JsxElement */ && firstChild.kind !== 242 /* JsxSelfClosingElement */) { - emit(firstChild); - } - else { - // If the only child is jsx element, put it on a new indented line - increaseIndent(); - writeLine(); - emit(firstChild); - writeLine(); - decreaseIndent(); - } - } - } - // Closing paren - write(")"); // closes "React.createElement(" - emitTrailingComments(openingNode); - } - if (node.kind === 241 /* JsxElement */) { - emitJsxElement(node.openingElement, node.children); - } - else { - ts.Debug.assert(node.kind === 242 /* JsxSelfClosingElement */); - emitJsxElement(node); - } + return ts.createPropertyAccess(left, node.right); + } + /** + * Gets an expression that points to the global "Symbol" constructor at runtime if it is + * available. + */ + function getGlobalSymbolNameWithFallback() { + return ts.createConditional(ts.createStrictEquality(ts.createTypeOf(ts.createIdentifier("Symbol")), ts.createLiteral("function")), ts.createToken(53 /* QuestionToken */), ts.createIdentifier("Symbol"), ts.createToken(54 /* ColonToken */), ts.createIdentifier("Object")); + } + /** + * Gets an expression that represents a property name. For a computed property, a + * name is generated for the node. + * + * @param member The member whose name should be converted into an expression. + */ + function getExpressionForPropertyName(member, generateNameForComputedPropertyName) { + var name = member.name; + if (ts.isComputedPropertyName(name)) { + return generateNameForComputedPropertyName + ? ts.getGeneratedNameForNode(name) + : name.expression; } - function jsxEmitPreserve(node) { - function emitJsxAttribute(node) { - emit(node.name); - if (node.initializer) { - write("="); - emit(node.initializer); - } - } - function emitJsxSpreadAttribute(node) { - write("{..."); - emit(node.expression); - write("}"); - } - function emitAttributes(attribs) { - for (var i = 0, n = attribs.length; i < n; i++) { - if (i > 0) { - write(" "); - } - if (attribs[i].kind === 247 /* JsxSpreadAttribute */) { - emitJsxSpreadAttribute(attribs[i]); - } - else { - ts.Debug.assert(attribs[i].kind === 246 /* JsxAttribute */); - emitJsxAttribute(attribs[i]); - } - } - } - function emitJsxOpeningOrSelfClosingElement(node) { - write("<"); - emit(node.tagName); - if (node.attributes.length > 0 || (node.kind === 242 /* JsxSelfClosingElement */)) { - write(" "); - } - emitAttributes(node.attributes); - if (node.kind === 242 /* JsxSelfClosingElement */) { - write("/>"); - } - else { - write(">"); - } - } - function emitJsxClosingElement(node) { - write(""); - } - function emitJsxElement(node) { - emitJsxOpeningOrSelfClosingElement(node.openingElement); - for (var i = 0, n = node.children.length; i < n; i++) { - emit(node.children[i]); - } - emitJsxClosingElement(node.closingElement); - } - if (node.kind === 241 /* JsxElement */) { - emitJsxElement(node); - } - else { - ts.Debug.assert(node.kind === 242 /* JsxSelfClosingElement */); - emitJsxOpeningOrSelfClosingElement(node); - } + else if (ts.isIdentifier(name)) { + return ts.createLiteral(name.text); } - // This function specifically handles numeric/string literals for enum and accessor 'identifiers'. - // In a sense, it does not actually emit identifiers as much as it declares a name for a specific property. - // For example, this is utilized when feeding in a result to Object.defineProperty. - function emitExpressionForPropertyName(node) { - ts.Debug.assert(node.kind !== 169 /* BindingElement */); - if (node.kind === 9 /* StringLiteral */) { - emitLiteral(node); - } - else if (node.kind === 140 /* ComputedPropertyName */) { - // if this is a decorated computed property, we will need to capture the result - // of the property expression so that we can apply decorators later. This is to ensure - // we don't introduce unintended side effects: - // - // class C { - // [_a = x]() { } - // } - // - // The emit for the decorated computed property decorator is: - // - // __decorate([dec], C.prototype, _a, Object.getOwnPropertyDescriptor(C.prototype, _a)); - // - if (ts.nodeIsDecorated(node.parent)) { - if (!computedPropertyNamesToGeneratedNames) { - computedPropertyNamesToGeneratedNames = []; - } - var generatedName = computedPropertyNamesToGeneratedNames[ts.getNodeId(node)]; - if (generatedName) { - // we have already generated a variable for this node, write that value instead. - write(generatedName); - return; - } - generatedName = createAndRecordTempVariable(0 /* Auto */).text; - computedPropertyNamesToGeneratedNames[ts.getNodeId(node)] = generatedName; - write(generatedName); - write(" = "); - } - emit(node.expression); - } - else { - write('"'); - if (node.kind === 8 /* NumericLiteral */) { - write(node.text); - } - else { - writeTextOfNode(currentText, node); - } - write('"'); - } + else { + return ts.getSynthesizedClone(name); } - function isExpressionIdentifier(node) { - var parent = node.parent; - switch (parent.kind) { - case 170 /* ArrayLiteralExpression */: - case 195 /* AsExpression */: - case 184 /* AwaitExpression */: - case 187 /* BinaryExpression */: - case 174 /* CallExpression */: - case 249 /* CaseClause */: - case 140 /* ComputedPropertyName */: - case 188 /* ConditionalExpression */: - case 143 /* Decorator */: - case 181 /* DeleteExpression */: - case 204 /* DoStatement */: - case 173 /* ElementAccessExpression */: - case 235 /* ExportAssignment */: - case 202 /* ExpressionStatement */: - case 194 /* ExpressionWithTypeArguments */: - case 206 /* ForStatement */: - case 207 /* ForInStatement */: - case 208 /* ForOfStatement */: - case 203 /* IfStatement */: - case 245 /* JsxClosingElement */: - case 242 /* JsxSelfClosingElement */: - case 243 /* JsxOpeningElement */: - case 247 /* JsxSpreadAttribute */: - case 248 /* JsxExpression */: - case 175 /* NewExpression */: - case 196 /* NonNullExpression */: - case 178 /* ParenthesizedExpression */: - case 186 /* PostfixUnaryExpression */: - case 185 /* PrefixUnaryExpression */: - case 211 /* ReturnStatement */: - case 254 /* ShorthandPropertyAssignment */: - case 191 /* SpreadElementExpression */: - case 213 /* SwitchStatement */: - case 176 /* TaggedTemplateExpression */: - case 197 /* TemplateSpan */: - case 215 /* ThrowStatement */: - case 177 /* TypeAssertionExpression */: - case 182 /* TypeOfExpression */: - case 183 /* VoidExpression */: - case 205 /* WhileStatement */: - case 212 /* WithStatement */: - case 190 /* YieldExpression */: - return true; - case 169 /* BindingElement */: - case 255 /* EnumMember */: - case 142 /* Parameter */: - case 253 /* PropertyAssignment */: - case 145 /* PropertyDeclaration */: - case 218 /* VariableDeclaration */: - return parent.initializer === node; - case 172 /* PropertyAccessExpression */: - return parent.expression === node; - case 180 /* ArrowFunction */: - case 179 /* FunctionExpression */: - return parent.body === node; - case 229 /* ImportEqualsDeclaration */: - return parent.moduleReference === node; - case 139 /* QualifiedName */: - return parent.left === node; + } + /** + * Visits the property name of a class element, for use when emitting property + * initializers. For a computed property on a node with decorators, a temporary + * value is stored for later use. + * + * @param member The member whose name should be visited. + */ + function visitPropertyNameOfClassElement(member) { + var name = member.name; + if (ts.isComputedPropertyName(name)) { + var expression = ts.visitNode(name.expression, visitor, ts.isExpression); + if (member.decorators) { + var generatedName = ts.getGeneratedNameForNode(name); + hoistVariableDeclaration(generatedName); + expression = ts.createAssignment(generatedName, expression); } - return false; + return ts.setOriginalNode(ts.createComputedPropertyName(expression, /*location*/ name), name); } - function emitExpressionIdentifier(node) { - var container = resolver.getReferencedExportContainer(node); - if (container) { - if (container.kind === 256 /* SourceFile */) { - // Identifier references module export - if (modulekind !== ts.ModuleKind.ES6 && modulekind !== ts.ModuleKind.System) { - write("exports."); - } - } - else { - // Identifier references namespace export - write(getGeneratedNameForNode(container)); - write("."); - } - } - else { - if (modulekind !== ts.ModuleKind.ES6) { - var declaration = resolver.getReferencedImportDeclaration(node); - if (declaration) { - if (declaration.kind === 231 /* ImportClause */) { - // Identifier references default import - write(getGeneratedNameForNode(declaration.parent)); - write(languageVersion === 0 /* ES3 */ ? '["default"]' : ".default"); - return; - } - else if (declaration.kind === 234 /* ImportSpecifier */) { - // Identifier references named import - write(getGeneratedNameForNode(declaration.parent.parent.parent)); - var name_28 = declaration.propertyName || declaration.name; - var identifier = ts.getTextOfNodeFromSourceText(currentText, name_28); - if (languageVersion === 0 /* ES3 */ && identifier === "default") { - write('["default"]'); - } - else { - write("."); - write(identifier); - } - return; - } - } - } - if (languageVersion < 2 /* ES6 */) { - var declaration = resolver.getReferencedDeclarationWithCollidingName(node); - if (declaration) { - write(getGeneratedNameForNode(declaration.name)); - return; - } - } - else if (resolver.getNodeCheckFlags(node) & 1048576 /* BodyScopedClassBinding */) { - // Due to the emit for class decorators, any reference to the class from inside of the class body - // must instead be rewritten to point to a temporary variable to avoid issues with the double-bind - // behavior of class names in ES6. - var declaration = resolver.getReferencedValueDeclaration(node); - if (declaration) { - var classAlias = decoratedClassAliases[ts.getNodeId(declaration)]; - if (classAlias !== undefined) { - write(classAlias); - return; - } - } - } - } - if (ts.nodeIsSynthesized(node)) { - write(node.text); - } - else { - writeTextOfNode(currentText, node); - } + else { + return name; } - function isNameOfNestedBlockScopedRedeclarationOrCapturedBinding(node) { - if (languageVersion < 2 /* ES6 */) { - var parent_13 = node.parent; - switch (parent_13.kind) { - case 169 /* BindingElement */: - case 221 /* ClassDeclaration */: - case 224 /* EnumDeclaration */: - case 218 /* VariableDeclaration */: - return parent_13.name === node && resolver.isDeclarationWithCollidingName(parent_13); - } - } - return false; + } + /** + * Transforms a HeritageClause with TypeScript syntax. + * + * This function will only be called when one of the following conditions are met: + * - The node is a non-`extends` heritage clause that should be elided. + * - The node is an `extends` heritage clause that should be visited, but only allow a single type. + * + * @param node The HeritageClause to transform. + */ + function visitHeritageClause(node) { + if (node.token === 83 /* ExtendsKeyword */) { + var types = ts.visitNodes(node.types, visitor, ts.isExpressionWithTypeArguments, 0, 1); + return ts.createHeritageClause(83 /* ExtendsKeyword */, types, node); } - function getClassExpressionInPropertyAccessInStaticPropertyDeclaration(node) { - if (languageVersion >= 2 /* ES6 */) { - var parent_14 = node.parent; - if (parent_14.kind === 172 /* PropertyAccessExpression */ && parent_14.expression === node) { - parent_14 = parent_14.parent; - while (parent_14 && parent_14.kind !== 145 /* PropertyDeclaration */) { - parent_14 = parent_14.parent; - } - return parent_14 && parent_14.kind === 145 /* PropertyDeclaration */ && (parent_14.flags & 32 /* Static */) !== 0 && - parent_14.parent.kind === 192 /* ClassExpression */ ? parent_14.parent : undefined; - } - } + return undefined; + } + /** + * Transforms an ExpressionWithTypeArguments with TypeScript syntax. + * + * This function will only be called when one of the following conditions are met: + * - The node contains type arguments that should be elided. + * + * @param node The ExpressionWithTypeArguments to transform. + */ + function visitExpressionWithTypeArguments(node) { + var expression = ts.visitNode(node.expression, visitor, ts.isLeftHandSideExpression); + return ts.createExpressionWithTypeArguments( + /*typeArguments*/ undefined, expression, node); + } + /** + * Determines whether to emit a function-like declaration. We should not emit the + * declaration if it does not have a body. + * + * @param node The declaration node. + */ + function shouldEmitFunctionLikeDeclaration(node) { + return !ts.nodeIsMissing(node.body); + } + /** + * Visits a method declaration of a class. + * + * This function will be called when one of the following conditions are met: + * - The node is an overload + * - The node is marked as abstract, async, public, private, protected, or readonly + * - The node has both a decorator and a computed property name + * + * @param node The method node. + */ + function visitMethodDeclaration(node) { + if (!shouldEmitFunctionLikeDeclaration(node)) { return undefined; } - function emitIdentifier(node) { - if (convertedLoopState) { - if (node.text == "arguments" && resolver.isArgumentsLocalBinding(node)) { - // in converted loop body arguments cannot be used directly. - var name_29 = convertedLoopState.argumentsName || (convertedLoopState.argumentsName = makeUniqueName("arguments")); - write(name_29); - return; - } - } - if (!node.parent) { - write(node.text); - } - else if (isExpressionIdentifier(node)) { - var classExpression = getClassExpressionInPropertyAccessInStaticPropertyDeclaration(node); - if (classExpression) { - var declaration = resolver.getReferencedValueDeclaration(node); - if (declaration === classExpression) { - write(getGeneratedNameForNode(declaration.name)); - return; - } - } - emitExpressionIdentifier(node); - } - else if (isNameOfNestedBlockScopedRedeclarationOrCapturedBinding(node)) { - write(getGeneratedNameForNode(node)); - } - else if (ts.nodeIsSynthesized(node)) { - write(node.text); - } - else { - writeTextOfNode(currentText, node); - } + var method = ts.createMethod( + /*decorators*/ undefined, ts.visitNodes(node.modifiers, visitor, ts.isModifier), node.asteriskToken, visitPropertyNameOfClassElement(node), + /*typeParameters*/ undefined, ts.visitNodes(node.parameters, visitor, ts.isParameter), + /*type*/ undefined, transformFunctionBody(node), + /*location*/ node); + // While we emit the source map for the node after skipping decorators and modifiers, + // we need to emit the comments for the original range. + ts.setCommentRange(method, node); + ts.setSourceMapRange(method, ts.moveRangePastDecorators(node)); + ts.setOriginalNode(method, node); + return method; + } + /** + * Determines whether to emit an accessor declaration. We should not emit the + * declaration if it does not have a body and is abstract. + * + * @param node The declaration node. + */ + function shouldEmitAccessorDeclaration(node) { + return !(ts.nodeIsMissing(node.body) && ts.hasModifier(node, 128 /* Abstract */)); + } + /** + * Visits a get accessor declaration of a class. + * + * This function will be called when one of the following conditions are met: + * - The node is marked as abstract, public, private, or protected + * - The node has both a decorator and a computed property name + * + * @param node The get accessor node. + */ + function visitGetAccessor(node) { + if (!shouldEmitAccessorDeclaration(node)) { + return undefined; } - function emitThis(node) { - if (resolver.getNodeCheckFlags(node) & 2 /* LexicalThis */) { - write("_this"); - } - else if (convertedLoopState) { - write(convertedLoopState.thisName || (convertedLoopState.thisName = makeUniqueName("this"))); + var accessor = ts.createGetAccessor( + /*decorators*/ undefined, ts.visitNodes(node.modifiers, visitor, ts.isModifier), visitPropertyNameOfClassElement(node), ts.visitNodes(node.parameters, visitor, ts.isParameter), + /*type*/ undefined, node.body ? ts.visitEachChild(node.body, visitor, context) : ts.createBlock([]), + /*location*/ node); + // While we emit the source map for the node after skipping decorators and modifiers, + // we need to emit the comments for the original range. + ts.setCommentRange(accessor, node); + ts.setSourceMapRange(accessor, ts.moveRangePastDecorators(node)); + ts.setOriginalNode(accessor, node); + return accessor; + } + /** + * Visits a set accessor declaration of a class. + * + * This function will be called when one of the following conditions are met: + * - The node is marked as abstract, public, private, or protected + * - The node has both a decorator and a computed property name + * + * @param node The set accessor node. + */ + function visitSetAccessor(node) { + if (!shouldEmitAccessorDeclaration(node)) { + return undefined; + } + var accessor = ts.createSetAccessor( + /*decorators*/ undefined, ts.visitNodes(node.modifiers, visitor, ts.isModifier), visitPropertyNameOfClassElement(node), ts.visitNodes(node.parameters, visitor, ts.isParameter), node.body ? ts.visitEachChild(node.body, visitor, context) : ts.createBlock([]), + /*location*/ node); + // While we emit the source map for the node after skipping decorators and modifiers, + // we need to emit the comments for the original range. + ts.setCommentRange(accessor, node); + ts.setSourceMapRange(accessor, ts.moveRangePastDecorators(node)); + ts.setOriginalNode(accessor, node); + return accessor; + } + /** + * Visits a function declaration. + * + * This function will be called when one of the following conditions are met: + * - The node is an overload + * - The node is marked async + * - The node is exported from a TypeScript namespace + * + * @param node The function node. + */ + function visitFunctionDeclaration(node) { + if (!shouldEmitFunctionLikeDeclaration(node)) { + return ts.createNotEmittedStatement(node); + } + var func = ts.createFunctionDeclaration( + /*decorators*/ undefined, ts.visitNodes(node.modifiers, visitor, ts.isModifier), node.asteriskToken, node.name, + /*typeParameters*/ undefined, ts.visitNodes(node.parameters, visitor, ts.isParameter), + /*type*/ undefined, transformFunctionBody(node), + /*location*/ node); + ts.setOriginalNode(func, node); + if (isNamespaceExport(node)) { + var statements = [func]; + addExportMemberAssignment(statements, node); + return statements; + } + return func; + } + /** + * Visits a function expression node. + * + * This function will be called when one of the following conditions are met: + * - The node is marked async + * + * @param node The function expression node. + */ + function visitFunctionExpression(node) { + if (ts.nodeIsMissing(node.body)) { + return ts.createOmittedExpression(); + } + var func = ts.createFunctionExpression(node.asteriskToken, node.name, + /*typeParameters*/ undefined, ts.visitNodes(node.parameters, visitor, ts.isParameter), + /*type*/ undefined, transformFunctionBody(node), + /*location*/ node); + ts.setOriginalNode(func, node); + return func; + } + /** + * @remarks + * This function will be called when one of the following conditions are met: + * - The node is marked async + */ + function visitArrowFunction(node) { + var func = ts.createArrowFunction( + /*modifiers*/ undefined, + /*typeParameters*/ undefined, ts.visitNodes(node.parameters, visitor, ts.isParameter), + /*type*/ undefined, node.equalsGreaterThanToken, transformConciseBody(node), + /*location*/ node); + ts.setOriginalNode(func, node); + return func; + } + function transformFunctionBody(node) { + if (ts.isAsyncFunctionLike(node)) { + return transformAsyncFunctionBody(node); + } + return transformFunctionBodyWorker(node.body); + } + function transformFunctionBodyWorker(body, start) { + if (start === void 0) { start = 0; } + var savedCurrentScope = currentScope; + currentScope = body; + startLexicalEnvironment(); + var statements = ts.visitNodes(body.statements, visitor, ts.isStatement, start); + var visited = ts.updateBlock(body, statements); + var declarations = endLexicalEnvironment(); + currentScope = savedCurrentScope; + return ts.mergeFunctionBodyLexicalEnvironment(visited, declarations); + } + function transformConciseBody(node) { + if (ts.isAsyncFunctionLike(node)) { + return transformAsyncFunctionBody(node); + } + return transformConciseBodyWorker(node.body, /*forceBlockFunctionBody*/ false); + } + function transformConciseBodyWorker(body, forceBlockFunctionBody) { + if (ts.isBlock(body)) { + return transformFunctionBodyWorker(body); + } + else { + startLexicalEnvironment(); + var visited = ts.visitNode(body, visitor, ts.isConciseBody); + var declarations = endLexicalEnvironment(); + var merged = ts.mergeFunctionBodyLexicalEnvironment(visited, declarations); + if (forceBlockFunctionBody && !ts.isBlock(merged)) { + return ts.createBlock([ + ts.createReturn(merged) + ]); } else { - write("this"); + return merged; } } - function emitSuper(node) { - if (languageVersion >= 2 /* ES6 */) { - write("super"); + } + function getPromiseConstructor(type) { + var typeName = ts.getEntityNameFromTypeNode(type); + if (typeName && ts.isEntityName(typeName)) { + var serializationKind = resolver.getTypeReferenceSerializationKind(typeName); + if (serializationKind === ts.TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue + || serializationKind === ts.TypeReferenceSerializationKind.Unknown) { + return typeName; } - else { - var flags = resolver.getNodeCheckFlags(node); - if (flags & 256 /* SuperInstance */) { - write("_super.prototype"); + } + return undefined; + } + function transformAsyncFunctionBody(node) { + var promiseConstructor = languageVersion < 2 /* ES6 */ ? getPromiseConstructor(node.type) : undefined; + var isArrowFunction = node.kind === 180 /* ArrowFunction */; + var hasLexicalArguments = (resolver.getNodeCheckFlags(node) & 8192 /* CaptureArguments */) !== 0; + // An async function is emit as an outer function that calls an inner + // generator function. To preserve lexical bindings, we pass the current + // `this` and `arguments` objects to `__awaiter`. The generator function + // passed to `__awaiter` is executed inside of the callback to the + // promise constructor. + if (!isArrowFunction) { + var statements = []; + var statementOffset = ts.addPrologueDirectives(statements, node.body.statements, /*ensureUseStrict*/ false, visitor); + statements.push(ts.createReturn(ts.createAwaiterHelper(currentSourceFileExternalHelpersModuleName, hasLexicalArguments, promiseConstructor, transformFunctionBodyWorker(node.body, statementOffset)))); + var block = ts.createBlock(statements, /*location*/ node.body, /*multiLine*/ true); + // Minor optimization, emit `_super` helper to capture `super` access in an arrow. + // This step isn't needed if we eventually transform this to ES5. + if (languageVersion >= 2 /* ES6 */) { + if (resolver.getNodeCheckFlags(node) & 4096 /* AsyncMethodWithSuperBinding */) { + enableSubstitutionForAsyncMethodsWithSuper(); + ts.setEmitFlags(block, 8 /* EmitAdvancedSuperHelper */); } - else { - write("_super"); + else if (resolver.getNodeCheckFlags(node) & 2048 /* AsyncMethodWithSuper */) { + enableSubstitutionForAsyncMethodsWithSuper(); + ts.setEmitFlags(block, 4 /* EmitSuperHelper */); } } + return block; } - function emitObjectBindingPattern(node) { - write("{ "); - var elements = node.elements; - emitList(elements, 0, elements.length, /*multiLine*/ false, /*trailingComma*/ elements.hasTrailingComma); - write(" }"); + else { + return ts.createAwaiterHelper(currentSourceFileExternalHelpersModuleName, hasLexicalArguments, promiseConstructor, transformConciseBodyWorker(node.body, /*forceBlockFunctionBody*/ true)); } - function emitArrayBindingPattern(node) { - write("["); - var elements = node.elements; - emitList(elements, 0, elements.length, /*multiLine*/ false, /*trailingComma*/ elements.hasTrailingComma); - write("]"); + } + /** + * Visits a parameter declaration node. + * + * This function will be called when one of the following conditions are met: + * - The node has an accessibility modifier. + * - The node has a questionToken. + * - The node's kind is ThisKeyword. + * + * @param node The parameter declaration node. + */ + function visitParameter(node) { + if (node.name && ts.isIdentifier(node.name) && node.name.originalKeywordKind === 97 /* ThisKeyword */) { + return undefined; } - function emitBindingElement(node) { - if (node.propertyName) { - emit(node.propertyName); - write(": "); - } - if (node.dotDotDotToken) { - write("..."); - } - if (ts.isBindingPattern(node.name)) { - emit(node.name); - } - else { - emitModuleMemberName(node); + var parameter = ts.createParameterDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, node.dotDotDotToken, ts.visitNode(node.name, visitor, ts.isBindingName), + /*questionToken*/ undefined, + /*type*/ undefined, ts.visitNode(node.initializer, visitor, ts.isExpression), + /*location*/ ts.moveRangePastModifiers(node)); + // While we emit the source map for the node after skipping decorators and modifiers, + // we need to emit the comments for the original range. + ts.setOriginalNode(parameter, node); + ts.setCommentRange(parameter, node); + ts.setSourceMapRange(parameter, ts.moveRangePastModifiers(node)); + ts.setEmitFlags(parameter.name, 1024 /* NoTrailingSourceMap */); + return parameter; + } + /** + * Visits a variable statement in a namespace. + * + * This function will be called when one of the following conditions are met: + * - The node is exported from a TypeScript namespace. + */ + function visitVariableStatement(node) { + if (isNamespaceExport(node)) { + var variables = ts.getInitializedVariables(node.declarationList); + if (variables.length === 0) { + // elide statement if there are no initialized variables. + return undefined; } - emitOptional(" = ", node.initializer); + return ts.createStatement(ts.inlineExpressions(ts.map(variables, transformInitializedVariable)), + /*location*/ node); } - function emitSpreadElementExpression(node) { - write("..."); - emit(node.expression); - } - function emitYieldExpression(node) { - write(ts.tokenToString(114 /* YieldKeyword */)); - if (node.asteriskToken) { - write("*"); - } - if (node.expression) { - write(" "); - emit(node.expression); - } + else { + return ts.visitEachChild(node, visitor, context); } - function emitAwaitExpression(node) { - var needsParenthesis = needsParenthesisForAwaitExpressionAsYield(node); - if (needsParenthesis) { - write("("); - } - write(ts.tokenToString(114 /* YieldKeyword */)); - write(" "); - emit(node.expression); - if (needsParenthesis) { - write(")"); - } + } + function transformInitializedVariable(node) { + var name = node.name; + if (ts.isBindingPattern(name)) { + return ts.flattenVariableDestructuringToExpression(context, node, hoistVariableDeclaration, getNamespaceMemberNameWithSourceMapsAndWithoutComments, visitor); } - function needsParenthesisForAwaitExpressionAsYield(node) { - if (node.parent.kind === 187 /* BinaryExpression */ && !ts.isAssignmentOperator(node.parent.operatorToken.kind)) { - return true; - } - else if (node.parent.kind === 188 /* ConditionalExpression */ && node.parent.condition === node) { - return true; - } - else if (node.parent.kind === 185 /* PrefixUnaryExpression */ || node.parent.kind === 181 /* DeleteExpression */ || - node.parent.kind === 182 /* TypeOfExpression */ || node.parent.kind === 183 /* VoidExpression */) { - return true; - } - return false; + else { + return ts.createAssignment(getNamespaceMemberNameWithSourceMapsAndWithoutComments(name), ts.visitNode(node.initializer, visitor, ts.isExpression), + /*location*/ node); } - function needsParenthesisForPropertyAccessOrInvocation(node) { - switch (node.kind) { - case 69 /* Identifier */: - case 170 /* ArrayLiteralExpression */: - case 172 /* PropertyAccessExpression */: - case 173 /* ElementAccessExpression */: - case 174 /* CallExpression */: - case 178 /* ParenthesizedExpression */: - // This list is not exhaustive and only includes those cases that are relevant - // to the check in emitArrayLiteral. More cases can be added as needed. - return false; - } - return true; + } + /** + * Visits an await expression. + * + * This function will be called any time a TypeScript await expression is encountered. + * + * @param node The await expression node. + */ + function visitAwaitExpression(node) { + return ts.setOriginalNode(ts.createYield( + /*asteriskToken*/ undefined, ts.visitNode(node.expression, visitor, ts.isExpression), + /*location*/ node), node); + } + /** + * Visits a parenthesized expression that contains either a type assertion or an `as` + * expression. + * + * @param node The parenthesized expression node. + */ + function visitParenthesizedExpression(node) { + var innerExpression = ts.skipOuterExpressions(node.expression, ~2 /* Assertions */); + if (ts.isAssertionExpression(innerExpression)) { + // Make sure we consider all nested cast expressions, e.g.: + // (-A).x; + var expression = ts.visitNode(node.expression, visitor, ts.isExpression); + // We have an expression of the form: (SubExpr). Emitting this as (SubExpr) + // is really not desirable. We would like to emit the subexpression as-is. Omitting + // the parentheses, however, could cause change in the semantics of the generated + // code if the casted expression has a lower precedence than the rest of the + // expression. + // + // Due to the auto-parenthesization rules used by the visitor and factory functions + // we can safely elide the parentheses here, as a new synthetic + // ParenthesizedExpression will be inserted if we remove parentheses too + // aggressively. + // + // To preserve comments, we return a "PartiallyEmittedExpression" here which will + // preserve the position information of the original expression. + return ts.createPartiallyEmittedExpression(expression, node); } - function emitListWithSpread(elements, needsUniqueCopy, multiLine, trailingComma, useConcat) { - var pos = 0; - var group = 0; - var length = elements.length; - while (pos < length) { - // Emit using the pattern .concat(, , ...) - if (group === 1 && useConcat) { - write(".concat("); - } - else if (group > 0) { - write(", "); - } - var e = elements[pos]; - if (e.kind === 191 /* SpreadElementExpression */) { - e = e.expression; - emitParenthesizedIf(e, /*parenthesized*/ group === 0 && needsParenthesisForPropertyAccessOrInvocation(e)); - pos++; - if (pos === length && group === 0 && needsUniqueCopy && e.kind !== 170 /* ArrayLiteralExpression */) { - write(".slice()"); - } - } - else { - var i = pos; - while (i < length && elements[i].kind !== 191 /* SpreadElementExpression */) { - i++; - } - write("["); - if (multiLine) { - increaseIndent(); - } - emitList(elements, pos, i - pos, multiLine, trailingComma && i === length); - if (multiLine) { - decreaseIndent(); - } - write("]"); - pos = i; - } - group++; - } - if (group > 1) { - if (useConcat) { - write(")"); - } - } + return ts.visitEachChild(node, visitor, context); + } + function visitAssertionExpression(node) { + var expression = ts.visitNode(node.expression, visitor, ts.isExpression); + return ts.createPartiallyEmittedExpression(expression, node); + } + function visitNonNullExpression(node) { + var expression = ts.visitNode(node.expression, visitor, ts.isLeftHandSideExpression); + return ts.createPartiallyEmittedExpression(expression, node); + } + /** + * Determines whether to emit an enum declaration. + * + * @param node The enum declaration node. + */ + function shouldEmitEnumDeclaration(node) { + return !ts.isConst(node) + || compilerOptions.preserveConstEnums + || compilerOptions.isolatedModules; + } + function shouldEmitVarForEnumDeclaration(node) { + return isFirstEmittedDeclarationInScope(node) + && (!ts.hasModifier(node, 1 /* Export */) + || isES6ExportedDeclaration(node)); + } + /* + * Adds a trailing VariableStatement for an enum or module declaration. + */ + function addVarForEnumExportedFromNamespace(statements, node) { + var statement = ts.createVariableStatement( + /*modifiers*/ undefined, [ts.createVariableDeclaration(getDeclarationName(node), + /*type*/ undefined, getExportName(node))]); + ts.setSourceMapRange(statement, node); + statements.push(statement); + } + /** + * Visits an enum declaration. + * + * This function will be called any time a TypeScript enum is encountered. + * + * @param node The enum declaration node. + */ + function visitEnumDeclaration(node) { + if (!shouldEmitEnumDeclaration(node)) { + return undefined; } - function isSpreadElementExpression(node) { - return node.kind === 191 /* SpreadElementExpression */; + var statements = []; + // We request to be advised when the printer is about to print this node. This allows + // us to set up the correct state for later substitutions. + var emitFlags = 64 /* AdviseOnEmitNode */; + // If needed, we should emit a variable declaration for the enum. If we emit + // a leading variable declaration, we should not emit leading comments for the + // enum body. + recordEmittedDeclarationInScope(node); + if (shouldEmitVarForEnumDeclaration(node)) { + addVarForEnumOrModuleDeclaration(statements, node); + // We should still emit the comments if we are emitting a system module. + if (moduleKind !== ts.ModuleKind.System || currentScope !== currentSourceFile) { + emitFlags |= 16384 /* NoLeadingComments */; + } + } + // `parameterName` is the declaration name used inside of the enum. + var parameterName = getNamespaceParameterName(node); + // `containerName` is the expression used inside of the enum for assignments. + var containerName = getNamespaceContainerName(node); + // `exportName` is the expression used within this node's container for any exported references. + var exportName = getExportName(node); + // (function (x) { + // x[x["y"] = 0] = "y"; + // ... + // })(x || (x = {})); + var enumStatement = ts.createStatement(ts.createCall(ts.createFunctionExpression( + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ts.createParameter(parameterName)], + /*type*/ undefined, transformEnumBody(node, containerName)), + /*typeArguments*/ undefined, [ts.createLogicalOr(exportName, ts.createAssignment(exportName, ts.createObjectLiteral()))]), + /*location*/ node); + ts.setOriginalNode(enumStatement, node); + ts.setEmitFlags(enumStatement, emitFlags); + statements.push(enumStatement); + if (isNamespaceExport(node)) { + addVarForEnumExportedFromNamespace(statements, node); + } + return statements; + } + /** + * Transforms the body of an enum declaration. + * + * @param node The enum declaration node. + */ + function transformEnumBody(node, localName) { + var savedCurrentNamespaceLocalName = currentNamespaceContainerName; + currentNamespaceContainerName = localName; + var statements = []; + startLexicalEnvironment(); + ts.addRange(statements, ts.map(node.members, transformEnumMember)); + ts.addRange(statements, endLexicalEnvironment()); + currentNamespaceContainerName = savedCurrentNamespaceLocalName; + return ts.createBlock(ts.createNodeArray(statements, /*location*/ node.members), + /*location*/ undefined, + /*multiLine*/ true); + } + /** + * Transforms an enum member into a statement. + * + * @param member The enum member node. + */ + function transformEnumMember(member) { + // enums don't support computed properties + // we pass false as 'generateNameForComputedPropertyName' for a backward compatibility purposes + // old emitter always generate 'expression' part of the name as-is. + var name = getExpressionForPropertyName(member, /*generateNameForComputedPropertyName*/ false); + return ts.createStatement(ts.createAssignment(ts.createElementAccess(currentNamespaceContainerName, ts.createAssignment(ts.createElementAccess(currentNamespaceContainerName, name), transformEnumMemberDeclarationValue(member))), name, + /*location*/ member), + /*location*/ member); + } + /** + * Transforms the value of an enum member. + * + * @param member The enum member node. + */ + function transformEnumMemberDeclarationValue(member) { + var value = resolver.getConstantValue(member); + if (value !== undefined) { + return ts.createLiteral(value); } - function emitArrayLiteral(node) { - var elements = node.elements; - if (elements.length === 0) { - write("[]"); - } - else if (languageVersion >= 2 /* ES6 */ || !ts.forEach(elements, isSpreadElementExpression)) { - write("["); - emitLinePreservingList(node, node.elements, elements.hasTrailingComma, /*spacesBetweenBraces*/ false); - write("]"); + else { + enableSubstitutionForNonQualifiedEnumMembers(); + if (member.initializer) { + return ts.visitNode(member.initializer, visitor, ts.isExpression); } else { - emitListWithSpread(elements, /*needsUniqueCopy*/ true, /*multiLine*/ node.multiLine, - /*trailingComma*/ elements.hasTrailingComma, /*useConcat*/ true); + return ts.createVoidZero(); } } - function emitObjectLiteralBody(node, numElements) { - if (numElements === 0) { - write("{}"); - return; + } + /** + * Determines whether to elide a module declaration. + * + * @param node The module declaration node. + */ + function shouldEmitModuleDeclaration(node) { + return ts.isInstantiatedModule(node, compilerOptions.preserveConstEnums || compilerOptions.isolatedModules); + } + function isES6ExportedDeclaration(node) { + return isExternalModuleExport(node) + && moduleKind === ts.ModuleKind.ES6; + } + /** + * Records that a declaration was emitted in the current scope, if it was the first + * declaration for the provided symbol. + * + * NOTE: if there is ever a transformation above this one, we may not be able to rely + * on symbol names. + */ + function recordEmittedDeclarationInScope(node) { + var name = node.symbol && node.symbol.name; + if (name) { + if (!currentScopeFirstDeclarationsOfName) { + currentScopeFirstDeclarationsOfName = ts.createMap(); } - write("{"); - if (numElements > 0) { - var properties = node.properties; - // If we are not doing a downlevel transformation for object literals, - // then try to preserve the original shape of the object literal. - // Otherwise just try to preserve the formatting. - if (numElements === properties.length) { - emitLinePreservingList(node, properties, /*allowTrailingComma*/ languageVersion >= 1 /* ES5 */, /*spacesBetweenBraces*/ true); - } - else { - var multiLine = node.multiLine; - if (!multiLine) { - write(" "); - } - else { - increaseIndent(); - } - emitList(properties, 0, numElements, /*multiLine*/ multiLine, /*trailingComma*/ false); - if (!multiLine) { - write(" "); - } - else { - decreaseIndent(); - } - } + if (!(name in currentScopeFirstDeclarationsOfName)) { + currentScopeFirstDeclarationsOfName[name] = node; } - write("}"); } - function emitDownlevelObjectLiteralWithComputedProperties(node, firstComputedPropertyIndex) { - var multiLine = node.multiLine; - var properties = node.properties; - write("("); - if (multiLine) { - increaseIndent(); - } - // For computed properties, we need to create a unique handle to the object - // literal so we can modify it without risking internal assignments tainting the object. - var tempVar = createAndRecordTempVariable(0 /* Auto */); - // Write out the first non-computed properties - // (or all properties if none of them are computed), - // then emit the rest through indexing on the temp variable. - emit(tempVar); - write(" = "); - emitObjectLiteralBody(node, firstComputedPropertyIndex); - for (var i = firstComputedPropertyIndex, n = properties.length; i < n; i++) { - writeComma(); - var property = properties[i]; - emitStart(property); - if (property.kind === 149 /* GetAccessor */ || property.kind === 150 /* SetAccessor */) { - // TODO (drosen): Reconcile with 'emitMemberFunctions'. - var accessors = ts.getAllAccessorDeclarations(node.properties, property); - if (property !== accessors.firstAccessor) { - continue; - } - write("Object.defineProperty("); - emit(tempVar); - write(", "); - emitStart(property.name); - emitExpressionForPropertyName(property.name); - emitEnd(property.name); - write(", {"); - increaseIndent(); - if (accessors.getAccessor) { - writeLine(); - emitLeadingComments(accessors.getAccessor); - write("get: "); - emitStart(accessors.getAccessor); - write("function "); - emitSignatureAndBody(accessors.getAccessor); - emitEnd(accessors.getAccessor); - emitTrailingComments(accessors.getAccessor); - write(","); - } - if (accessors.setAccessor) { - writeLine(); - emitLeadingComments(accessors.setAccessor); - write("set: "); - emitStart(accessors.setAccessor); - write("function "); - emitSignatureAndBody(accessors.setAccessor); - emitEnd(accessors.setAccessor); - emitTrailingComments(accessors.setAccessor); - write(","); - } - writeLine(); - write("enumerable: true,"); - writeLine(); - write("configurable: true"); - decreaseIndent(); - writeLine(); - write("})"); - emitEnd(property); - } - else { - emitLeadingComments(property); - emitStart(property.name); - emit(tempVar); - emitMemberAccessForPropertyName(property.name); - emitEnd(property.name); - write(" = "); - if (property.kind === 253 /* PropertyAssignment */) { - emit(property.initializer); - } - else if (property.kind === 254 /* ShorthandPropertyAssignment */) { - emitExpressionIdentifier(property.name); - } - else if (property.kind === 147 /* MethodDeclaration */) { - emitFunctionDeclaration(property); - } - else { - ts.Debug.fail("ObjectLiteralElement type not accounted for: " + property.kind); - } - } - emitEnd(property); - } - writeComma(); - emit(tempVar); - if (multiLine) { - decreaseIndent(); - writeLine(); - } - write(")"); - function writeComma() { - if (multiLine) { - write(","); - writeLine(); - } - else { - write(", "); - } + } + /** + * Determines whether a declaration is the first declaration with the same name emitted + * in the current scope. + */ + function isFirstEmittedDeclarationInScope(node) { + if (currentScopeFirstDeclarationsOfName) { + var name_31 = node.symbol && node.symbol.name; + if (name_31) { + return currentScopeFirstDeclarationsOfName[name_31] === node; } } - function emitObjectLiteral(node) { - var properties = node.properties; - if (languageVersion < 2 /* ES6 */) { - var numProperties = properties.length; - // Find the first computed property. - // Everything until that point can be emitted as part of the initial object literal. - var numInitialNonComputedProperties = numProperties; - for (var i = 0, n = properties.length; i < n; i++) { - if (properties[i].name.kind === 140 /* ComputedPropertyName */) { - numInitialNonComputedProperties = i; - break; - } - } - var hasComputedProperty = numInitialNonComputedProperties !== properties.length; - if (hasComputedProperty) { - emitDownlevelObjectLiteralWithComputedProperties(node, numInitialNonComputedProperties); - return; - } - } - // Ordinary case: either the object has no computed properties - // or we're compiling with an ES6+ target. - emitObjectLiteralBody(node, properties.length); + return false; + } + function shouldEmitVarForModuleDeclaration(node) { + return isFirstEmittedDeclarationInScope(node); + } + /** + * Adds a leading VariableStatement for a enum or module declaration. + */ + function addVarForEnumOrModuleDeclaration(statements, node) { + // Emit a variable statement for the module. + var statement = ts.createVariableStatement(isES6ExportedDeclaration(node) + ? ts.visitNodes(node.modifiers, visitor, ts.isModifier) + : undefined, [ + ts.createVariableDeclaration(getDeclarationName(node, /*allowComments*/ false, /*allowSourceMaps*/ true)) + ]); + ts.setOriginalNode(statement, /*original*/ node); + // Adjust the source map emit to match the old emitter. + if (node.kind === 224 /* EnumDeclaration */) { + ts.setSourceMapRange(statement.declarationList, node); } - function createBinaryExpression(left, operator, right, startsOnNewLine) { - var result = ts.createSynthesizedNode(187 /* BinaryExpression */, startsOnNewLine); - result.operatorToken = ts.createSynthesizedNode(operator); - result.left = left; - result.right = right; - return result; + else { + ts.setSourceMapRange(statement, node); } - function createPropertyAccessExpression(expression, name) { - var result = ts.createSynthesizedNode(172 /* PropertyAccessExpression */); - result.expression = parenthesizeForAccess(expression); - result.name = name; - return result; + // Trailing comments for module declaration should be emitted after the function closure + // instead of the variable statement: + // + // /** Module comment*/ + // module m1 { + // function foo4Export() { + // } + // } // trailing comment module + // + // Should emit: + // + // /** Module comment*/ + // var m1; + // (function (m1) { + // function foo4Export() { + // } + // })(m1 || (m1 = {})); // trailing comment module + // + ts.setCommentRange(statement, node); + ts.setEmitFlags(statement, 32768 /* NoTrailingComments */); + statements.push(statement); + } + /** + * Visits a module declaration node. + * + * This function will be called any time a TypeScript namespace (ModuleDeclaration) is encountered. + * + * @param node The module declaration node. + */ + function visitModuleDeclaration(node) { + if (!shouldEmitModuleDeclaration(node)) { + return ts.createNotEmittedStatement(node); + } + ts.Debug.assert(ts.isIdentifier(node.name), "TypeScript module should have an Identifier name."); + enableSubstitutionForNamespaceExports(); + var statements = []; + // We request to be advised when the printer is about to print this node. This allows + // us to set up the correct state for later substitutions. + var emitFlags = 64 /* AdviseOnEmitNode */; + // If needed, we should emit a variable declaration for the module. If we emit + // a leading variable declaration, we should not emit leading comments for the + // module body. + recordEmittedDeclarationInScope(node); + if (shouldEmitVarForModuleDeclaration(node)) { + addVarForEnumOrModuleDeclaration(statements, node); + // We should still emit the comments if we are emitting a system module. + if (moduleKind !== ts.ModuleKind.System || currentScope !== currentSourceFile) { + emitFlags |= 16384 /* NoLeadingComments */; + } + } + // `parameterName` is the declaration name used inside of the namespace. + var parameterName = getNamespaceParameterName(node); + // `containerName` is the expression used inside of the namespace for exports. + var containerName = getNamespaceContainerName(node); + // `exportName` is the expression used within this node's container for any exported references. + var exportName = getExportName(node); + // x || (x = {}) + // exports.x || (exports.x = {}) + var moduleArg = ts.createLogicalOr(exportName, ts.createAssignment(exportName, ts.createObjectLiteral())); + if (ts.hasModifier(node, 1 /* Export */) && !isES6ExportedDeclaration(node)) { + // `localName` is the expression used within this node's containing scope for any local references. + var localName = getLocalName(node); + // x = (exports.x || (exports.x = {})) + moduleArg = ts.createAssignment(localName, moduleArg); + } + // (function (x_1) { + // x_1.y = ...; + // })(x || (x = {})); + var moduleStatement = ts.createStatement(ts.createCall(ts.createFunctionExpression( + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ts.createParameter(parameterName)], + /*type*/ undefined, transformModuleBody(node, containerName)), + /*typeArguments*/ undefined, [moduleArg]), + /*location*/ node); + ts.setOriginalNode(moduleStatement, node); + ts.setEmitFlags(moduleStatement, emitFlags); + statements.push(moduleStatement); + return statements; + } + /** + * Transforms the body of a module declaration. + * + * @param node The module declaration node. + */ + function transformModuleBody(node, namespaceLocalName) { + var savedCurrentNamespaceContainerName = currentNamespaceContainerName; + var savedCurrentNamespace = currentNamespace; + var savedCurrentScopeFirstDeclarationsOfName = currentScopeFirstDeclarationsOfName; + currentNamespaceContainerName = namespaceLocalName; + currentNamespace = node; + currentScopeFirstDeclarationsOfName = undefined; + var statements = []; + startLexicalEnvironment(); + var statementsLocation; + var blockLocation; + var body = node.body; + if (body.kind === 226 /* ModuleBlock */) { + ts.addRange(statements, ts.visitNodes(body.statements, namespaceElementVisitor, ts.isStatement)); + statementsLocation = body.statements; + blockLocation = body; } - function createElementAccessExpression(expression, argumentExpression) { - var result = ts.createSynthesizedNode(173 /* ElementAccessExpression */); - result.expression = parenthesizeForAccess(expression); - result.argumentExpression = argumentExpression; - return result; + else { + var result = visitModuleDeclaration(body); + if (result) { + if (ts.isArray(result)) { + ts.addRange(statements, result); + } + else { + statements.push(result); + } + } + var moduleBlock = getInnerMostModuleDeclarationFromDottedModule(node).body; + statementsLocation = ts.moveRangePos(moduleBlock.statements, -1); + } + ts.addRange(statements, endLexicalEnvironment()); + currentNamespaceContainerName = savedCurrentNamespaceContainerName; + currentNamespace = savedCurrentNamespace; + currentScopeFirstDeclarationsOfName = savedCurrentScopeFirstDeclarationsOfName; + var block = ts.createBlock(ts.createNodeArray(statements, + /*location*/ statementsLocation), + /*location*/ blockLocation, + /*multiLine*/ true); + // namespace hello.hi.world { + // function foo() {} + // + // // TODO, blah + // } + // + // should be emitted as + // + // var hello; + // (function (hello) { + // var hi; + // (function (hi) { + // var world; + // (function (world) { + // function foo() { } + // // TODO, blah + // })(world = hi.world || (hi.world = {})); + // })(hi = hello.hi || (hello.hi = {})); + // })(hello || (hello = {})); + // We only want to emit comment on the namespace which contains block body itself, not the containing namespaces. + if (body.kind !== 226 /* ModuleBlock */) { + ts.setEmitFlags(block, ts.getEmitFlags(block) | 49152 /* NoComments */); } - function parenthesizeForAccess(expr) { - // When diagnosing whether the expression needs parentheses, the decision should be based - // on the innermost expression in a chain of nested type assertions. - while (expr.kind === 177 /* TypeAssertionExpression */ || - expr.kind === 195 /* AsExpression */ || - expr.kind === 196 /* NonNullExpression */) { - expr = expr.expression; - } - // isLeftHandSideExpression is almost the correct criterion for when it is not necessary - // to parenthesize the expression before a dot. The known exceptions are: - // - // NewExpression: - // new C.x -> not the same as (new C).x - // NumberLiteral - // 1.x -> not the same as (1).x - // - if (ts.isLeftHandSideExpression(expr) && - expr.kind !== 175 /* NewExpression */ && - expr.kind !== 8 /* NumericLiteral */) { - return expr; - } - var node = ts.createSynthesizedNode(178 /* ParenthesizedExpression */); - node.expression = expr; - return node; + return block; + } + function getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration) { + if (moduleDeclaration.body.kind === 225 /* ModuleDeclaration */) { + var recursiveInnerModule = getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration.body); + return recursiveInnerModule || moduleDeclaration.body; } - function emitComputedPropertyName(node) { - write("["); - emitExpressionForPropertyName(node); - write("]"); + } + /** + * Determines whether to emit an import equals declaration. + * + * @param node The import equals declaration node. + */ + function shouldEmitImportEqualsDeclaration(node) { + // preserve old compiler's behavior: emit 'var' for import declaration (even if we do not consider them referenced) when + // - current file is not external module + // - import declaration is top level and target is value imported by entity name + return resolver.isReferencedAliasDeclaration(node) + || (!ts.isExternalModule(currentSourceFile) + && resolver.isTopLevelValueImportEqualsWithEntityName(node)); + } + /** + * Visits an import equals declaration. + * + * @param node The import equals declaration node. + */ + function visitImportEqualsDeclaration(node) { + if (ts.isExternalModuleImportEqualsDeclaration(node)) { + return ts.visitEachChild(node, visitor, context); } - function emitMethod(node) { - if (languageVersion >= 2 /* ES6 */ && node.asteriskToken) { - write("*"); - } - emit(node.name); - if (languageVersion < 2 /* ES6 */) { - write(": function "); - } - emitSignatureAndBody(node); + if (!shouldEmitImportEqualsDeclaration(node)) { + return undefined; } - function emitPropertyAssignment(node) { - emit(node.name); - write(": "); - // This is to ensure that we emit comment in the following case: - // For example: - // obj = { - // id: /*comment1*/ ()=>void - // } - // "comment1" is not considered to be leading comment for node.initializer - // but rather a trailing comment on the previous node. - emitTrailingCommentsOfPosition(node.initializer.pos); - emit(node.initializer); - } - // Return true if identifier resolves to an exported member of a namespace - function isExportReference(node) { - var container = resolver.getReferencedExportContainer(node); - return !!container; - } - // Return true if identifier resolves to an imported identifier - function isImportedReference(node) { - var declaration = resolver.getReferencedImportDeclaration(node); - return declaration && (declaration.kind === 231 /* ImportClause */ || declaration.kind === 234 /* ImportSpecifier */); + var moduleReference = ts.createExpressionFromEntityName(node.moduleReference); + ts.setEmitFlags(moduleReference, 49152 /* NoComments */ | 65536 /* NoNestedComments */); + if (isNamedExternalModuleExport(node) || !isNamespaceExport(node)) { + // export var ${name} = ${moduleReference}; + // var ${name} = ${moduleReference}; + return ts.setOriginalNode(ts.createVariableStatement(ts.visitNodes(node.modifiers, visitor, ts.isModifier), ts.createVariableDeclarationList([ + ts.createVariableDeclaration(node.name, + /*type*/ undefined, moduleReference) + ]), node), node); } - function emitShorthandPropertyAssignment(node) { - // The name property of a short-hand property assignment is considered an expression position, so here - // we manually emit the identifier to avoid rewriting. - writeTextOfNode(currentText, node.name); - // If emitting pre-ES6 code, or if the name requires rewriting when resolved as an expression identifier, - // we emit a normal property assignment. For example: - // module m { - // export let y; - // } - // module m { - // let obj = { y }; - // } - // Here we need to emit obj = { y : m.y } regardless of the output target. - // The same rules apply for imported identifiers when targeting module formats with indirect access to - // the imported identifiers. For example, when targeting CommonJS: - // - // import {foo} from './foo'; - // export const baz = { foo }; - // - // Must be transformed into: - // - // const foo_1 = require('./foo'); - // exports.baz = { foo: foo_1.foo }; - // - if (languageVersion < 2 /* ES6 */ || (modulekind !== ts.ModuleKind.ES6 && isImportedReference(node.name)) || isExportReference(node.name)) { - // Emit identifier as an identifier - write(": "); - emitExpressionIdentifier(node.name); - } - if (languageVersion >= 2 /* ES6 */ && node.objectAssignmentInitializer) { - write(" = "); - emit(node.objectAssignmentInitializer); - } + else { + // exports.${name} = ${moduleReference}; + return ts.setOriginalNode(createNamespaceExport(node.name, moduleReference, node), node); } - function tryEmitConstantValue(node) { - var constantValue = tryGetConstEnumValue(node); - if (constantValue !== undefined) { - write(constantValue.toString()); - if (!compilerOptions.removeComments) { - var propertyName = node.kind === 172 /* PropertyAccessExpression */ ? ts.declarationNameToString(node.name) : ts.getTextOfNode(node.argumentExpression); - write(" /* " + propertyName + " */"); - } - return true; - } - return false; + } + /** + * Gets a value indicating whether the node is exported from a namespace. + * + * @param node The node to test. + */ + function isNamespaceExport(node) { + return currentNamespace !== undefined && ts.hasModifier(node, 1 /* Export */); + } + /** + * Gets a value indicating whether the node is exported from an external module. + * + * @param node The node to test. + */ + function isExternalModuleExport(node) { + return currentNamespace === undefined && ts.hasModifier(node, 1 /* Export */); + } + /** + * Gets a value indicating whether the node is a named export from an external module. + * + * @param node The node to test. + */ + function isNamedExternalModuleExport(node) { + return isExternalModuleExport(node) + && !ts.hasModifier(node, 512 /* Default */); + } + /** + * Gets a value indicating whether the node is the default export of an external module. + * + * @param node The node to test. + */ + function isDefaultExternalModuleExport(node) { + return isExternalModuleExport(node) + && ts.hasModifier(node, 512 /* Default */); + } + /** + * Creates a statement for the provided expression. This is used in calls to `map`. + */ + function expressionToStatement(expression) { + return ts.createStatement(expression, /*location*/ undefined); + } + function addExportMemberAssignment(statements, node) { + var expression = ts.createAssignment(getExportName(node), getLocalName(node, /*noSourceMaps*/ true)); + ts.setSourceMapRange(expression, ts.createRange(node.name.pos, node.end)); + var statement = ts.createStatement(expression); + ts.setSourceMapRange(statement, ts.createRange(-1, node.end)); + statements.push(statement); + } + function createNamespaceExport(exportName, exportValue, location) { + return ts.createStatement(ts.createAssignment(getNamespaceMemberName(exportName, /*allowComments*/ false, /*allowSourceMaps*/ true), exportValue), location); + } + function createExternalModuleExport(exportName) { + return ts.createExportDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, ts.createNamedExports([ + ts.createExportSpecifier(exportName) + ])); + } + function getNamespaceMemberName(name, allowComments, allowSourceMaps) { + var qualifiedName = ts.createPropertyAccess(currentNamespaceContainerName, ts.getSynthesizedClone(name), /*location*/ name); + var emitFlags; + if (!allowComments) { + emitFlags |= 49152 /* NoComments */; } - function tryGetConstEnumValue(node) { - if (compilerOptions.isolatedModules) { - return undefined; - } - return node.kind === 172 /* PropertyAccessExpression */ || node.kind === 173 /* ElementAccessExpression */ - ? resolver.getConstantValue(node) - : undefined; + if (!allowSourceMaps) { + emitFlags |= 1536 /* NoSourceMap */; } - // Returns 'true' if the code was actually indented, false otherwise. - // If the code is not indented, an optional valueToWriteWhenNotIndenting will be - // emitted instead. - function indentIfOnDifferentLines(parent, node1, node2, valueToWriteWhenNotIndenting) { - var realNodesAreOnDifferentLines = !ts.nodeIsSynthesized(parent) && !nodeEndIsOnSameLineAsNodeStart(node1, node2); - // Always use a newline for synthesized code if the synthesizer desires it. - var synthesizedNodeIsOnDifferentLine = synthesizedNodeStartsOnNewLine(node2); - if (realNodesAreOnDifferentLines || synthesizedNodeIsOnDifferentLine) { - increaseIndent(); - writeLine(); - return true; - } - else { - if (valueToWriteWhenNotIndenting) { - write(valueToWriteWhenNotIndenting); - } - return false; - } + if (emitFlags) { + ts.setEmitFlags(qualifiedName, emitFlags); } - function emitPropertyAccess(node) { - if (tryEmitConstantValue(node)) { - return; - } - if (languageVersion === 2 /* ES6 */ && - node.expression.kind === 95 /* SuperKeyword */ && - isInAsyncMethodWithSuperInES6(node)) { - var name_30 = ts.createSynthesizedNode(9 /* StringLiteral */); - name_30.text = node.name.text; - emitSuperAccessInAsyncMethod(node.expression, name_30); - return; - } - emit(node.expression); - var dotRangeStart = ts.nodeIsSynthesized(node.expression) ? -1 : node.expression.end; - var dotRangeEnd = ts.nodeIsSynthesized(node.expression) ? -1 : ts.skipTrivia(currentText, node.expression.end) + 1; - var dotToken = { pos: dotRangeStart, end: dotRangeEnd }; - var indentedBeforeDot = indentIfOnDifferentLines(node, node.expression, dotToken); - // 1 .toString is a valid property access, emit a space after the literal - // Also emit a space if expression is a integer const enum value - it will appear in generated code as numeric literal - var shouldEmitSpace = false; - if (!indentedBeforeDot) { - if (node.expression.kind === 8 /* NumericLiteral */) { - // check if numeric literal was originally written with a dot - var text = ts.getTextOfNodeFromSourceText(currentText, node.expression); - shouldEmitSpace = text.indexOf(ts.tokenToString(21 /* DotToken */)) < 0; - } - else { - // check if constant enum value is integer - var constantValue = tryGetConstEnumValue(node.expression); - // isFinite handles cases when constantValue is undefined - shouldEmitSpace = isFinite(constantValue) && Math.floor(constantValue) === constantValue; - } + return qualifiedName; + } + function getNamespaceMemberNameWithSourceMapsAndWithoutComments(name) { + return getNamespaceMemberName(name, /*allowComments*/ false, /*allowSourceMaps*/ true); + } + /** + * Gets the declaration name used inside of a namespace or enum. + */ + function getNamespaceParameterName(node) { + var name = ts.getGeneratedNameForNode(node); + ts.setSourceMapRange(name, node.name); + return name; + } + /** + * Gets the expression used to refer to a namespace or enum within the body + * of its declaration. + */ + function getNamespaceContainerName(node) { + return ts.getGeneratedNameForNode(node); + } + /** + * Gets the local name for a declaration for use in expressions. + * + * A local name will *never* be prefixed with an module or namespace export modifier like + * "exports.". + * + * @param node The declaration. + * @param noSourceMaps A value indicating whether source maps may not be emitted for the name. + * @param allowComments A value indicating whether comments may be emitted for the name. + */ + function getLocalName(node, noSourceMaps, allowComments) { + return getDeclarationName(node, allowComments, !noSourceMaps, 262144 /* LocalName */); + } + /** + * Gets the export name for a declaration for use in expressions. + * + * An export name will *always* be prefixed with an module or namespace export modifier + * like "exports." if one is required. + * + * @param node The declaration. + * @param noSourceMaps A value indicating whether source maps may not be emitted for the name. + * @param allowComments A value indicating whether comments may be emitted for the name. + */ + function getExportName(node, noSourceMaps, allowComments) { + if (isNamespaceExport(node)) { + return getNamespaceMemberName(getDeclarationName(node), allowComments, !noSourceMaps); + } + return getDeclarationName(node, allowComments, !noSourceMaps, 131072 /* ExportName */); + } + /** + * Gets the name for a declaration for use in declarations. + * + * @param node The declaration. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + * @param emitFlags Additional NodeEmitFlags to specify for the name. + */ + function getDeclarationName(node, allowComments, allowSourceMaps, emitFlags) { + if (node.name) { + var name_32 = ts.getMutableClone(node.name); + emitFlags |= ts.getEmitFlags(node.name); + if (!allowSourceMaps) { + emitFlags |= 1536 /* NoSourceMap */; } - if (shouldEmitSpace) { - write(" ."); + if (!allowComments) { + emitFlags |= 49152 /* NoComments */; } - else { - write("."); + if (emitFlags) { + ts.setEmitFlags(name_32, emitFlags); } - var indentedAfterDot = indentIfOnDifferentLines(node, dotToken, node.name); - emit(node.name); - decreaseIndentIf(indentedBeforeDot, indentedAfterDot); + return name_32; } - function emitQualifiedName(node) { - emit(node.left); - write("."); - emit(node.right); + else { + return ts.getGeneratedNameForNode(node); + } + } + function getClassPrototype(node) { + return ts.createPropertyAccess(getDeclarationName(node), "prototype"); + } + function getClassMemberPrefix(node, member) { + return ts.hasModifier(member, 32 /* Static */) + ? getDeclarationName(node) + : getClassPrototype(node); + } + function enableSubstitutionForNonQualifiedEnumMembers() { + if ((enabledSubstitutions & 8 /* NonQualifiedEnumMembers */) === 0) { + enabledSubstitutions |= 8 /* NonQualifiedEnumMembers */; + context.enableSubstitution(69 /* Identifier */); + } + } + function enableSubstitutionForAsyncMethodsWithSuper() { + if ((enabledSubstitutions & 4 /* AsyncMethodsWithSuper */) === 0) { + enabledSubstitutions |= 4 /* AsyncMethodsWithSuper */; + // We need to enable substitutions for call, property access, and element access + // if we need to rewrite super calls. + context.enableSubstitution(174 /* CallExpression */); + context.enableSubstitution(172 /* PropertyAccessExpression */); + context.enableSubstitution(173 /* ElementAccessExpression */); + // We need to be notified when entering and exiting declarations that bind super. + context.enableEmitNotification(221 /* ClassDeclaration */); + context.enableEmitNotification(147 /* MethodDeclaration */); + context.enableEmitNotification(149 /* GetAccessor */); + context.enableEmitNotification(150 /* SetAccessor */); + context.enableEmitNotification(148 /* Constructor */); + } + } + function enableSubstitutionForClassAliases() { + if ((enabledSubstitutions & 1 /* ClassAliases */) === 0) { + enabledSubstitutions |= 1 /* ClassAliases */; + // We need to enable substitutions for identifiers. This allows us to + // substitute class names inside of a class declaration. + context.enableSubstitution(69 /* Identifier */); + // Keep track of class aliases. + classAliases = ts.createMap(); + } + } + function enableSubstitutionForNamespaceExports() { + if ((enabledSubstitutions & 2 /* NamespaceExports */) === 0) { + enabledSubstitutions |= 2 /* NamespaceExports */; + // We need to enable substitutions for identifiers and shorthand property assignments. This allows us to + // substitute the names of exported members of a namespace. + context.enableSubstitution(69 /* Identifier */); + context.enableSubstitution(254 /* ShorthandPropertyAssignment */); + // We need to be notified when entering and exiting namespaces. + context.enableEmitNotification(225 /* ModuleDeclaration */); + } + } + function isSuperContainer(node) { + var kind = node.kind; + return kind === 221 /* ClassDeclaration */ + || kind === 148 /* Constructor */ + || kind === 147 /* MethodDeclaration */ + || kind === 149 /* GetAccessor */ + || kind === 150 /* SetAccessor */; + } + function isTransformedModuleDeclaration(node) { + return ts.getOriginalNode(node).kind === 225 /* ModuleDeclaration */; + } + function isTransformedEnumDeclaration(node) { + return ts.getOriginalNode(node).kind === 224 /* EnumDeclaration */; + } + /** + * Hook for node emit. + * + * @param node The node to emit. + * @param emit A callback used to emit the node in the printer. + */ + function onEmitNode(emitContext, node, emitCallback) { + var savedApplicableSubstitutions = applicableSubstitutions; + var savedCurrentSuperContainer = currentSuperContainer; + // If we need to support substitutions for `super` in an async method, + // we should track it here. + if (enabledSubstitutions & 4 /* AsyncMethodsWithSuper */ && isSuperContainer(node)) { + currentSuperContainer = node; } - function emitQualifiedNameAsExpression(node, useFallback) { - if (node.left.kind === 69 /* Identifier */) { - emitEntityNameAsExpression(node.left, useFallback); - } - else if (useFallback) { - var temp = createAndRecordTempVariable(0 /* Auto */); - write("("); - emitNodeWithoutSourceMap(temp); - write(" = "); - emitEntityNameAsExpression(node.left, /*useFallback*/ true); - write(") && "); - emitNodeWithoutSourceMap(temp); - } - else { - emitEntityNameAsExpression(node.left, /*useFallback*/ false); - } - write("."); - emit(node.right); + if (enabledSubstitutions & 2 /* NamespaceExports */ && isTransformedModuleDeclaration(node)) { + applicableSubstitutions |= 2 /* NamespaceExports */; } - function emitEntityNameAsExpression(node, useFallback) { - switch (node.kind) { - case 69 /* Identifier */: - if (useFallback) { - write("typeof "); - emitExpressionIdentifier(node); - write(" !== 'undefined' && "); - } - emitExpressionIdentifier(node); - break; - case 139 /* QualifiedName */: - emitQualifiedNameAsExpression(node, useFallback); - break; - default: - emitNodeWithoutSourceMap(node); - break; - } + if (enabledSubstitutions & 8 /* NonQualifiedEnumMembers */ && isTransformedEnumDeclaration(node)) { + applicableSubstitutions |= 8 /* NonQualifiedEnumMembers */; } - function emitIndexedAccess(node) { - if (tryEmitConstantValue(node)) { - return; - } - if (languageVersion === 2 /* ES6 */ && - node.expression.kind === 95 /* SuperKeyword */ && - isInAsyncMethodWithSuperInES6(node)) { - emitSuperAccessInAsyncMethod(node.expression, node.argumentExpression); - return; - } - emit(node.expression); - write("["); - emit(node.argumentExpression); - write("]"); + previousOnEmitNode(emitContext, node, emitCallback); + applicableSubstitutions = savedApplicableSubstitutions; + currentSuperContainer = savedCurrentSuperContainer; + } + /** + * Hooks node substitutions. + * + * @param node The node to substitute. + * @param isExpression A value indicating whether the node is to be used in an expression + * position. + */ + function onSubstituteNode(emitContext, node) { + node = previousOnSubstituteNode(emitContext, node); + if (emitContext === 1 /* Expression */) { + return substituteExpression(node); } - function hasSpreadElement(elements) { - return ts.forEach(elements, function (e) { return e.kind === 191 /* SpreadElementExpression */; }); + else if (ts.isShorthandPropertyAssignment(node)) { + return substituteShorthandPropertyAssignment(node); } - function skipParentheses(node) { - while (node.kind === 178 /* ParenthesizedExpression */ || - node.kind === 177 /* TypeAssertionExpression */ || - node.kind === 195 /* AsExpression */ || - node.kind === 196 /* NonNullExpression */) { - node = node.expression; + return node; + } + function substituteShorthandPropertyAssignment(node) { + if (enabledSubstitutions & 2 /* NamespaceExports */) { + var name_33 = node.name; + var exportedName = trySubstituteNamespaceExportedName(name_33); + if (exportedName) { + // A shorthand property with an assignment initializer is probably part of a + // destructuring assignment + if (node.objectAssignmentInitializer) { + var initializer = ts.createAssignment(exportedName, node.objectAssignmentInitializer); + return ts.createPropertyAssignment(name_33, initializer, /*location*/ node); + } + return ts.createPropertyAssignment(name_33, exportedName, /*location*/ node); } - return node; } - function emitCallTarget(node) { - if (node.kind === 69 /* Identifier */ || node.kind === 97 /* ThisKeyword */ || node.kind === 95 /* SuperKeyword */) { - emit(node); - return node; - } - var temp = createAndRecordTempVariable(0 /* Auto */); - write("("); - emit(temp); - write(" = "); - emit(node); - write(")"); - return temp; - } - function emitCallWithSpread(node) { - var target; - var expr = skipParentheses(node.expression); - if (expr.kind === 172 /* PropertyAccessExpression */) { - // Target will be emitted as "this" argument - target = emitCallTarget(expr.expression); - write("."); - emit(expr.name); - } - else if (expr.kind === 173 /* ElementAccessExpression */) { - // Target will be emitted as "this" argument - target = emitCallTarget(expr.expression); - write("["); - emit(expr.argumentExpression); - write("]"); - } - else if (expr.kind === 95 /* SuperKeyword */) { - target = expr; - write("_super"); - } - else { - emit(node.expression); - } - write(".apply("); - if (target) { - if (target.kind === 95 /* SuperKeyword */) { - // Calls of form super(...) and super.foo(...) - emitThis(target); - } - else { - // Calls of form obj.foo(...) - emit(target); + return node; + } + function substituteExpression(node) { + switch (node.kind) { + case 69 /* Identifier */: + return substituteExpressionIdentifier(node); + case 172 /* PropertyAccessExpression */: + return substitutePropertyAccessExpression(node); + case 173 /* ElementAccessExpression */: + return substituteElementAccessExpression(node); + case 174 /* CallExpression */: + if (enabledSubstitutions & 4 /* AsyncMethodsWithSuper */) { + return substituteCallExpression(node); } - } - else { - // Calls of form foo(...) - write("void 0"); - } - write(", "); - emitListWithSpread(node.arguments, /*needsUniqueCopy*/ false, /*multiLine*/ false, /*trailingComma*/ false, /*useConcat*/ true); - write(")"); + break; } - function isInAsyncMethodWithSuperInES6(node) { - if (languageVersion === 2 /* ES6 */) { - var container = ts.getSuperContainer(node, /*includeFunctions*/ false); - if (container && resolver.getNodeCheckFlags(container) & (2048 /* AsyncMethodWithSuper */ | 4096 /* AsyncMethodWithSuperBinding */)) { - return true; + return node; + } + function substituteExpressionIdentifier(node) { + return trySubstituteClassAlias(node) + || trySubstituteNamespaceExportedName(node) + || node; + } + function trySubstituteClassAlias(node) { + if (enabledSubstitutions & 1 /* ClassAliases */) { + if (resolver.getNodeCheckFlags(node) & 16777216 /* ConstructorReferenceInClass */) { + // Due to the emit for class decorators, any reference to the class from inside of the class body + // must instead be rewritten to point to a temporary variable to avoid issues with the double-bind + // behavior of class names in ES6. + // Also, when emitting statics for class expressions, we must substitute a class alias for + // constructor references in static property initializers. + var declaration = resolver.getReferencedValueDeclaration(node); + if (declaration) { + var classAlias = classAliases[declaration.id]; + if (classAlias) { + var clone_4 = ts.getSynthesizedClone(classAlias); + ts.setSourceMapRange(clone_4, node); + ts.setCommentRange(clone_4, node); + return clone_4; + } } } - return false; } - function emitSuperAccessInAsyncMethod(superNode, argumentExpression) { - var container = ts.getSuperContainer(superNode, /*includeFunctions*/ false); - var isSuperBinding = resolver.getNodeCheckFlags(container) & 4096 /* AsyncMethodWithSuperBinding */; - write("_super("); - emit(argumentExpression); - write(isSuperBinding ? ").value" : ")"); - } - function emitCallExpression(node) { - if (languageVersion < 2 /* ES6 */ && hasSpreadElement(node.arguments)) { - emitCallWithSpread(node); - return; - } - var expression = node.expression; - var superCall = false; - var isAsyncMethodWithSuper = false; - if (expression.kind === 95 /* SuperKeyword */) { - emitSuper(expression); - superCall = true; - } - else { - superCall = ts.isSuperPropertyOrElementAccess(expression); - isAsyncMethodWithSuper = superCall && isInAsyncMethodWithSuperInES6(node); - emit(expression); - } - if (superCall && (languageVersion < 2 /* ES6 */ || isAsyncMethodWithSuper)) { - write(".call("); - emitThis(expression); - if (node.arguments.length) { - write(", "); - emitCommaList(node.arguments); + return undefined; + } + function trySubstituteNamespaceExportedName(node) { + // If this is explicitly a local name, do not substitute. + if (enabledSubstitutions & applicableSubstitutions && (ts.getEmitFlags(node) & 262144 /* LocalName */) === 0) { + // If we are nested within a namespace declaration, we may need to qualifiy + // an identifier that is exported from a merged namespace. + var container = resolver.getReferencedExportContainer(node, /*prefixLocals*/ false); + if (container) { + var substitute = (applicableSubstitutions & 2 /* NamespaceExports */ && container.kind === 225 /* ModuleDeclaration */) || + (applicableSubstitutions & 8 /* NonQualifiedEnumMembers */ && container.kind === 224 /* EnumDeclaration */); + if (substitute) { + return ts.createPropertyAccess(ts.getGeneratedNameForNode(container), node, /*location*/ node); } - write(")"); - } - else { - write("("); - emitCommaList(node.arguments); - write(")"); } } - function emitNewExpression(node) { - write("new "); - // Spread operator logic is supported in new expressions in ES5 using a combination - // of Function.prototype.bind() and Function.prototype.apply(). - // - // Example: - // - // var args = [1, 2, 3, 4, 5]; - // new Array(...args); - // - // is compiled into the following ES5: - // - // var args = [1, 2, 3, 4, 5]; - // new (Array.bind.apply(Array, [void 0].concat(args))); - // - // The 'thisArg' to 'bind' is ignored when invoking the result of 'bind' with 'new', - // Thus, we set it to undefined ('void 0'). - if (languageVersion === 1 /* ES5 */ && - node.arguments && - hasSpreadElement(node.arguments)) { - write("("); - var target = emitCallTarget(node.expression); - write(".bind.apply("); - emit(target); - write(", [void 0].concat("); - emitListWithSpread(node.arguments, /*needsUniqueCopy*/ false, /*multiLine*/ false, /*trailingComma*/ false, /*useConcat*/ false); - write(")))"); - write("()"); + return undefined; + } + function substituteCallExpression(node) { + var expression = node.expression; + if (ts.isSuperProperty(expression)) { + var flags = getSuperContainerAsyncMethodFlags(); + if (flags) { + var argumentExpression = ts.isPropertyAccessExpression(expression) + ? substitutePropertyAccessExpression(expression) + : substituteElementAccessExpression(expression); + return ts.createCall(ts.createPropertyAccess(argumentExpression, "call"), + /*typeArguments*/ undefined, [ + ts.createThis() + ].concat(node.arguments)); } - else { - emit(node.expression); - if (node.arguments) { - write("("); - emitCommaList(node.arguments); - write(")"); - } + } + return node; + } + function substitutePropertyAccessExpression(node) { + if (enabledSubstitutions & 4 /* AsyncMethodsWithSuper */ && node.expression.kind === 95 /* SuperKeyword */) { + var flags = getSuperContainerAsyncMethodFlags(); + if (flags) { + return createSuperAccessInAsyncMethod(ts.createLiteral(node.name.text), flags, node); } } - function emitTaggedTemplateExpression(node) { - if (languageVersion >= 2 /* ES6 */) { - emit(node.tag); - write(" "); - emit(node.template); + return substituteConstantValue(node); + } + function substituteElementAccessExpression(node) { + if (enabledSubstitutions & 4 /* AsyncMethodsWithSuper */ && node.expression.kind === 95 /* SuperKeyword */) { + var flags = getSuperContainerAsyncMethodFlags(); + if (flags) { + return createSuperAccessInAsyncMethod(node.argumentExpression, flags, node); } - else { - emitDownlevelTaggedTemplate(node); - } - } - function emitParenExpression(node) { - // If the node is synthesized, it means the emitter put the parentheses there, - // not the user. If we didn't want them, the emitter would not have put them - // there. - if (!ts.nodeIsSynthesized(node) && node.parent.kind !== 180 /* ArrowFunction */) { - if (node.expression.kind === 177 /* TypeAssertionExpression */ || - node.expression.kind === 195 /* AsExpression */ || - node.expression.kind === 196 /* NonNullExpression */) { - var operand = node.expression.expression; - // Make sure we consider all nested cast expressions, e.g.: - // (-A).x; - while (operand.kind === 177 /* TypeAssertionExpression */ || - operand.kind === 195 /* AsExpression */ || - operand.kind === 196 /* NonNullExpression */) { - operand = operand.expression; - } - // We have an expression of the form: (SubExpr) or (SubExpr as Type) - // Emitting this as (SubExpr) is really not desirable. We would like to emit the subexpr as is. - // Omitting the parentheses, however, could cause change in the semantics of the generated - // code if the casted expression has a lower precedence than the rest of the expression, e.g.: - // (new A).foo should be emitted as (new A).foo and not new A.foo - // (typeof A).toString() should be emitted as (typeof A).toString() and not typeof A.toString() - // new (A()) should be emitted as new (A()) and not new A() - // (function foo() { })() should be emitted as an IIF (function foo(){})() and not declaration function foo(){} () - if (operand.kind !== 185 /* PrefixUnaryExpression */ && - operand.kind !== 183 /* VoidExpression */ && - operand.kind !== 182 /* TypeOfExpression */ && - operand.kind !== 181 /* DeleteExpression */ && - operand.kind !== 186 /* PostfixUnaryExpression */ && - operand.kind !== 175 /* NewExpression */ && - !(operand.kind === 187 /* BinaryExpression */ && node.expression.kind === 195 /* AsExpression */) && - !(operand.kind === 174 /* CallExpression */ && node.parent.kind === 175 /* NewExpression */) && - !(operand.kind === 179 /* FunctionExpression */ && node.parent.kind === 174 /* CallExpression */) && - !(operand.kind === 8 /* NumericLiteral */ && node.parent.kind === 172 /* PropertyAccessExpression */)) { - emit(operand); - return; - } - } + } + return substituteConstantValue(node); + } + function substituteConstantValue(node) { + var constantValue = tryGetConstEnumValue(node); + if (constantValue !== undefined) { + var substitute = ts.createLiteral(constantValue); + ts.setSourceMapRange(substitute, node); + ts.setCommentRange(substitute, node); + if (!compilerOptions.removeComments) { + var propertyName = ts.isPropertyAccessExpression(node) + ? ts.declarationNameToString(node.name) + : ts.getTextOfNode(node.argumentExpression); + substitute.trailingComment = " " + propertyName + " "; } - write("("); - emit(node.expression); - write(")"); + ts.setConstantValue(node, constantValue); + return substitute; } - function emitDeleteExpression(node) { - write(ts.tokenToString(78 /* DeleteKeyword */)); - write(" "); - emit(node.expression); + return node; + } + function tryGetConstEnumValue(node) { + if (compilerOptions.isolatedModules) { + return undefined; } - function emitVoidExpression(node) { - write(ts.tokenToString(103 /* VoidKeyword */)); - write(" "); - emit(node.expression); + return ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node) + ? resolver.getConstantValue(node) + : undefined; + } + function createSuperAccessInAsyncMethod(argumentExpression, flags, location) { + if (flags & 4096 /* AsyncMethodWithSuperBinding */) { + return ts.createPropertyAccess(ts.createCall(ts.createIdentifier("_super"), + /*typeArguments*/ undefined, [argumentExpression]), "value", location); } - function emitTypeOfExpression(node) { - write(ts.tokenToString(101 /* TypeOfKeyword */)); - write(" "); - emit(node.expression); + else { + return ts.createCall(ts.createIdentifier("_super"), + /*typeArguments*/ undefined, [argumentExpression], location); } - function isNameOfExportedSourceLevelDeclarationInSystemExternalModule(node) { - if (!isCurrentFileSystemExternalModule() || node.kind !== 69 /* Identifier */ || ts.nodeIsSynthesized(node)) { - return false; - } - var isVariableDeclarationOrBindingElement = node.parent && (node.parent.kind === 218 /* VariableDeclaration */ || node.parent.kind === 169 /* BindingElement */); - var targetDeclaration = isVariableDeclarationOrBindingElement - ? node.parent - : resolver.getReferencedValueDeclaration(node); - return isSourceFileLevelDeclarationInSystemJsModule(targetDeclaration, /*isExported*/ true); + } + function getSuperContainerAsyncMethodFlags() { + return currentSuperContainer !== undefined + && resolver.getNodeCheckFlags(currentSuperContainer) & (2048 /* AsyncMethodWithSuper */ | 4096 /* AsyncMethodWithSuperBinding */); + } + } + ts.transformTypeScript = transformTypeScript; +})(ts || (ts = {})); +/// +/// +/*@internal*/ +var ts; +(function (ts) { + var entities = createEntitiesMap(); + function transformJsx(context) { + var compilerOptions = context.getCompilerOptions(); + var currentSourceFile; + return transformSourceFile; + /** + * Transform JSX-specific syntax in a SourceFile. + * + * @param node A SourceFile node. + */ + function transformSourceFile(node) { + if (ts.isDeclarationFile(node)) { + return node; } - function isNameOfExportedDeclarationInNonES6Module(node) { - if (modulekind === ts.ModuleKind.System || node.kind !== 69 /* Identifier */ || ts.nodeIsSynthesized(node)) { - return false; - } - return !exportEquals && exportSpecifiers && node.text in exportSpecifiers; - } - function emitPrefixUnaryExpression(node) { - var isPlusPlusOrMinusMinus = (node.operator === 41 /* PlusPlusToken */ - || node.operator === 42 /* MinusMinusToken */); - var externalExportChanged = isPlusPlusOrMinusMinus && - isNameOfExportedSourceLevelDeclarationInSystemExternalModule(node.operand); - if (externalExportChanged) { - // emit - // ++x - // as - // exports('x', ++x) - write(exportFunctionForFile + "(\""); - emitNodeWithoutSourceMap(node.operand); - write("\", "); - } - var internalExportChanged = isPlusPlusOrMinusMinus && - isNameOfExportedDeclarationInNonES6Module(node.operand); - if (internalExportChanged) { - emitAliasEqual(node.operand); - } - write(ts.tokenToString(node.operator)); - // In some cases, we need to emit a space between the operator and the operand. One obvious case - // is when the operator is an identifier, like delete or typeof. We also need to do this for plus - // and minus expressions in certain cases. Specifically, consider the following two cases (parens - // are just for clarity of exposition, and not part of the source code): - // - // (+(+1)) - // (+(++1)) - // - // We need to emit a space in both cases. In the first case, the absence of a space will make - // the resulting expression a prefix increment operation. And in the second, it will make the resulting - // expression a prefix increment whose operand is a plus expression - (++(+x)) - // The same is true of minus of course. - if (node.operand.kind === 185 /* PrefixUnaryExpression */) { - var operand = node.operand; - if (node.operator === 35 /* PlusToken */ && (operand.operator === 35 /* PlusToken */ || operand.operator === 41 /* PlusPlusToken */)) { - write(" "); - } - else if (node.operator === 36 /* MinusToken */ && (operand.operator === 36 /* MinusToken */ || operand.operator === 42 /* MinusMinusToken */)) { - write(" "); - } - } - emit(node.operand); - if (externalExportChanged) { - write(")"); - } - } - function emitPostfixUnaryExpression(node) { - var externalExportChanged = isNameOfExportedSourceLevelDeclarationInSystemExternalModule(node.operand); - var internalExportChanged = isNameOfExportedDeclarationInNonES6Module(node.operand); - if (externalExportChanged) { - // export function returns the value that was passes as the second argument - // however for postfix unary expressions result value should be the value before modification. - // emit 'x++' as '(export('x', ++x) - 1)' and 'x--' as '(export('x', --x) + 1)' - write("(" + exportFunctionForFile + "(\""); - emitNodeWithoutSourceMap(node.operand); - write("\", "); - write(ts.tokenToString(node.operator)); - emit(node.operand); - if (node.operator === 41 /* PlusPlusToken */) { - write(") - 1)"); - } - else { - write(") + 1)"); - } - } - else if (internalExportChanged) { - emitAliasEqual(node.operand); - emit(node.operand); - if (node.operator === 41 /* PlusPlusToken */) { - write(" += 1"); - } - else { - write(" -= 1"); - } - } - else { - emit(node.operand); - write(ts.tokenToString(node.operator)); - } + currentSourceFile = node; + node = ts.visitEachChild(node, visitor, context); + currentSourceFile = undefined; + return node; + } + function visitor(node) { + if (node.transformFlags & 4 /* Jsx */) { + return visitorWorker(node); } - function shouldHoistDeclarationInSystemJsModule(node) { - return isSourceFileLevelDeclarationInSystemJsModule(node, /*isExported*/ false); + else if (node.transformFlags & 8 /* ContainsJsx */) { + return ts.visitEachChild(node, visitor, context); } - /* - * Checks if given node is a source file level declaration (not nested in module/function). - * If 'isExported' is true - then declaration must also be exported. - * This function is used in two cases: - * - check if node is a exported source file level value to determine - * if we should also export the value after its it changed - * - check if node is a source level declaration to emit it differently, - * i.e non-exported variable statement 'var x = 1' is hoisted so - * when we emit variable statement 'var' should be dropped. - */ - function isSourceFileLevelDeclarationInSystemJsModule(node, isExported) { - if (!node || !isCurrentFileSystemExternalModule()) { - return false; - } - var current = ts.getRootDeclaration(node).parent; - while (current) { - if (current.kind === 256 /* SourceFile */) { - return !isExported || ((ts.getCombinedNodeFlags(node) & 1 /* Export */) !== 0); - } - else if (ts.isDeclaration(current)) { - return false; - } - else { - current = current.parent; - } - } + else { + return node; + } + } + function visitorWorker(node) { + switch (node.kind) { + case 241 /* JsxElement */: + return visitJsxElement(node, /*isChild*/ false); + case 242 /* JsxSelfClosingElement */: + return visitJsxSelfClosingElement(node, /*isChild*/ false); + case 248 /* JsxExpression */: + return visitJsxExpression(node); + default: + ts.Debug.failBadSyntaxKind(node); + return undefined; + } + } + function transformJsxChildToExpression(node) { + switch (node.kind) { + case 244 /* JsxText */: + return visitJsxText(node); + case 248 /* JsxExpression */: + return visitJsxExpression(node); + case 241 /* JsxElement */: + return visitJsxElement(node, /*isChild*/ true); + case 242 /* JsxSelfClosingElement */: + return visitJsxSelfClosingElement(node, /*isChild*/ true); + default: + ts.Debug.failBadSyntaxKind(node); + return undefined; } - /** - * Emit ES7 exponentiation operator downlevel using Math.pow - * @param node a binary expression node containing exponentiationOperator (**, **=) - */ - function emitExponentiationOperator(node) { - var leftHandSideExpression = node.left; - if (node.operatorToken.kind === 60 /* AsteriskAsteriskEqualsToken */) { - var synthesizedLHS = void 0; - var shouldEmitParentheses = false; - if (ts.isElementAccessExpression(leftHandSideExpression)) { - shouldEmitParentheses = true; - write("("); - synthesizedLHS = ts.createSynthesizedNode(173 /* ElementAccessExpression */, /*startsOnNewLine*/ false); - var identifier = emitTempVariableAssignment(leftHandSideExpression.expression, /*canDefineTempVariablesInPlace*/ false, /*shouldEmitCommaBeforeAssignment*/ false); - synthesizedLHS.expression = identifier; - if (leftHandSideExpression.argumentExpression.kind !== 8 /* NumericLiteral */ && - leftHandSideExpression.argumentExpression.kind !== 9 /* StringLiteral */) { - var tempArgumentExpression = createAndRecordTempVariable(268435456 /* _i */); - synthesizedLHS.argumentExpression = tempArgumentExpression; - emitAssignment(tempArgumentExpression, leftHandSideExpression.argumentExpression, /*shouldEmitCommaBeforeAssignment*/ true, leftHandSideExpression.expression); - } - else { - synthesizedLHS.argumentExpression = leftHandSideExpression.argumentExpression; - } - write(", "); - } - else if (ts.isPropertyAccessExpression(leftHandSideExpression)) { - shouldEmitParentheses = true; - write("("); - synthesizedLHS = ts.createSynthesizedNode(172 /* PropertyAccessExpression */, /*startsOnNewLine*/ false); - var identifier = emitTempVariableAssignment(leftHandSideExpression.expression, /*canDefineTempVariablesInPlace*/ false, /*shouldEmitCommaBeforeAssignment*/ false); - synthesizedLHS.expression = identifier; - synthesizedLHS.name = leftHandSideExpression.name; - write(", "); - } - emit(synthesizedLHS || leftHandSideExpression); - write(" = "); - write("Math.pow("); - emit(synthesizedLHS || leftHandSideExpression); - write(", "); - emit(node.right); - write(")"); - if (shouldEmitParentheses) { - write(")"); - } - } - else { - write("Math.pow("); - emit(leftHandSideExpression); - write(", "); - emit(node.right); - write(")"); - } + } + function visitJsxElement(node, isChild) { + return visitJsxOpeningLikeElement(node.openingElement, node.children, isChild, /*location*/ node); + } + function visitJsxSelfClosingElement(node, isChild) { + return visitJsxOpeningLikeElement(node, /*children*/ undefined, isChild, /*location*/ node); + } + function visitJsxOpeningLikeElement(node, children, isChild, location) { + var tagName = getTagName(node); + var objectProperties; + var attrs = node.attributes; + if (attrs.length === 0) { + // When there are no attributes, React wants "null" + objectProperties = ts.createNull(); } - function emitAliasEqual(name) { - for (var _a = 0, _b = exportSpecifiers[name.text]; _a < _b.length; _a++) { - var specifier = _b[_a]; - emitStart(specifier.name); - emitContainingModuleName(specifier); - if (languageVersion === 0 /* ES3 */ && name.text === "default") { - write('["default"]'); - } - else { - write("."); - emitNodeWithCommentsAndWithoutSourcemap(specifier.name); - } - emitEnd(specifier.name); - write(" = "); - } - return true; + else { + // Map spans of JsxAttribute nodes into object literals and spans + // of JsxSpreadAttribute nodes into expressions. + var segments = ts.flatten(ts.spanMap(attrs, ts.isJsxSpreadAttribute, function (attrs, isSpread) { return isSpread + ? ts.map(attrs, transformJsxSpreadAttributeToExpression) + : ts.createObjectLiteral(ts.map(attrs, transformJsxAttributeToObjectLiteralElement)); })); + if (ts.isJsxSpreadAttribute(attrs[0])) { + // We must always emit at least one object literal before a spread + // argument. + segments.unshift(ts.createObjectLiteral()); + } + // Either emit one big object literal (no spread attribs), or + // a call to the __assign helper. + objectProperties = ts.singleOrUndefined(segments) + || ts.createAssignHelper(currentSourceFile.externalHelpersModuleName, segments); + } + var element = ts.createReactCreateElement(compilerOptions.reactNamespace, tagName, objectProperties, ts.filter(ts.map(children, transformJsxChildToExpression), ts.isDefined), node, location); + if (isChild) { + ts.startOnNewLine(element); + } + return element; + } + function transformJsxSpreadAttributeToExpression(node) { + return ts.visitNode(node.expression, visitor, ts.isExpression); + } + function transformJsxAttributeToObjectLiteralElement(node) { + var name = getAttributeName(node); + var expression = transformJsxAttributeInitializer(node.initializer); + return ts.createPropertyAssignment(name, expression); + } + function transformJsxAttributeInitializer(node) { + if (node === undefined) { + return ts.createLiteral(true); + } + else if (node.kind === 9 /* StringLiteral */) { + var decoded = tryDecodeEntities(node.text); + return decoded ? ts.createLiteral(decoded, /*location*/ node) : node; + } + else if (node.kind === 248 /* JsxExpression */) { + return visitJsxExpression(node); } - function emitBinaryExpression(node) { - if (languageVersion < 2 /* ES6 */ && node.operatorToken.kind === 56 /* EqualsToken */ && - (node.left.kind === 171 /* ObjectLiteralExpression */ || node.left.kind === 170 /* ArrayLiteralExpression */)) { - emitDestructuring(node, node.parent.kind === 202 /* ExpressionStatement */); - } - else { - var isAssignment = ts.isAssignmentOperator(node.operatorToken.kind); - var externalExportChanged = isAssignment && - isNameOfExportedSourceLevelDeclarationInSystemExternalModule(node.left); - if (externalExportChanged) { - // emit assignment 'x y' as 'exports("x", x y)' - write(exportFunctionForFile + "(\""); - emitNodeWithoutSourceMap(node.left); - write("\", "); - } - var internalExportChanged = isAssignment && - isNameOfExportedDeclarationInNonES6Module(node.left); - if (internalExportChanged) { - // export { foo } - // emit foo = 2 as exports.foo = foo = 2 - emitAliasEqual(node.left); - } - if (node.operatorToken.kind === 38 /* AsteriskAsteriskToken */ || node.operatorToken.kind === 60 /* AsteriskAsteriskEqualsToken */) { - // Downleveled emit exponentiation operator using Math.pow - emitExponentiationOperator(node); - } - else { - emit(node.left); - // Add indentation before emit the operator if the operator is on different line - // For example: - // 3 - // + 2; - // emitted as - // 3 - // + 2; - var indentedBeforeOperator = indentIfOnDifferentLines(node, node.left, node.operatorToken, node.operatorToken.kind !== 24 /* CommaToken */ ? " " : undefined); - write(ts.tokenToString(node.operatorToken.kind)); - var indentedAfterOperator = indentIfOnDifferentLines(node, node.operatorToken, node.right, " "); - emit(node.right); - decreaseIndentIf(indentedBeforeOperator, indentedAfterOperator); + else { + ts.Debug.failBadSyntaxKind(node); + } + } + function visitJsxText(node) { + var text = ts.getTextOfNode(node, /*includeTrivia*/ true); + var parts; + var firstNonWhitespace = 0; + var lastNonWhitespace = -1; + // JSX trims whitespace at the end and beginning of lines, except that the + // start/end of a tag is considered a start/end of a line only if that line is + // on the same line as the closing tag. See examples in + // tests/cases/conformance/jsx/tsxReactEmitWhitespace.tsx + for (var i = 0; i < text.length; i++) { + var c = text.charCodeAt(i); + if (ts.isLineBreak(c)) { + if (firstNonWhitespace !== -1 && (lastNonWhitespace - firstNonWhitespace + 1 > 0)) { + var part = text.substr(firstNonWhitespace, lastNonWhitespace - firstNonWhitespace + 1); + if (!parts) { + parts = []; + } + // We do not escape the string here as that is handled by the printer + // when it emits the literal. We do, however, need to decode JSX entities. + parts.push(ts.createLiteral(decodeEntities(part))); } - if (externalExportChanged) { - write(")"); + firstNonWhitespace = -1; + } + else if (!ts.isWhiteSpace(c)) { + lastNonWhitespace = i; + if (firstNonWhitespace === -1) { + firstNonWhitespace = i; } } } - function synthesizedNodeStartsOnNewLine(node) { - return ts.nodeIsSynthesized(node) && node.startsOnNewLine; - } - function emitConditionalExpression(node) { - emit(node.condition); - var indentedBeforeQuestion = indentIfOnDifferentLines(node, node.condition, node.questionToken, " "); - write("?"); - var indentedAfterQuestion = indentIfOnDifferentLines(node, node.questionToken, node.whenTrue, " "); - emit(node.whenTrue); - decreaseIndentIf(indentedBeforeQuestion, indentedAfterQuestion); - var indentedBeforeColon = indentIfOnDifferentLines(node, node.whenTrue, node.colonToken, " "); - write(":"); - var indentedAfterColon = indentIfOnDifferentLines(node, node.colonToken, node.whenFalse, " "); - emit(node.whenFalse); - decreaseIndentIf(indentedBeforeColon, indentedAfterColon); - } - // Helper function to decrease the indent if we previously indented. Allows multiple - // previous indent values to be considered at a time. This also allows caller to just - // call this once, passing in all their appropriate indent values, instead of needing - // to call this helper function multiple times. - function decreaseIndentIf(value1, value2) { - if (value1) { - decreaseIndent(); - } - if (value2) { - decreaseIndent(); + if (firstNonWhitespace !== -1) { + var part = text.substr(firstNonWhitespace); + if (!parts) { + parts = []; } + // We do not escape the string here as that is handled by the printer + // when it emits the literal. We do, however, need to decode JSX entities. + parts.push(ts.createLiteral(decodeEntities(part))); } - function isSingleLineEmptyBlock(node) { - if (node && node.kind === 199 /* Block */) { - var block = node; - return block.statements.length === 0 && nodeEndIsOnSameLineAsNodeStart(block, block); - } + if (parts) { + return ts.reduceLeft(parts, aggregateJsxTextParts); } - function emitBlock(node) { - if (isSingleLineEmptyBlock(node)) { - emitToken(15 /* OpenBraceToken */, node.pos); - write(" "); - emitToken(16 /* CloseBraceToken */, node.statements.end); - return; + return undefined; + } + /** + * Aggregates two expressions by interpolating them with a whitespace literal. + */ + function aggregateJsxTextParts(left, right) { + return ts.createAdd(ts.createAdd(left, ts.createLiteral(" ")), right); + } + /** + * Replace entities like " ", "{", and "�" with the characters they encode. + * See https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references + */ + function decodeEntities(text) { + return text.replace(/&((#((\d+)|x([\da-fA-F]+)))|(\w+));/g, function (match, _all, _number, _digits, decimal, hex, word) { + if (decimal) { + return String.fromCharCode(parseInt(decimal, 10)); } - emitToken(15 /* OpenBraceToken */, node.pos); - increaseIndent(); - if (node.kind === 226 /* ModuleBlock */) { - ts.Debug.assert(node.parent.kind === 225 /* ModuleDeclaration */); - emitCaptureThisForNodeIfNecessary(node.parent); + else if (hex) { + return String.fromCharCode(parseInt(hex, 16)); } - emitLines(node.statements); - if (node.kind === 226 /* ModuleBlock */) { - emitTempDeclarations(/*newLine*/ true); + else { + var ch = entities[word]; + // If this is not a valid entity, then just use `match` (replace it with itself, i.e. don't replace) + return ch ? String.fromCharCode(ch) : match; } - decreaseIndent(); - writeLine(); - emitToken(16 /* CloseBraceToken */, node.statements.end); + }); + } + /** Like `decodeEntities` but returns `undefined` if there were no entities to decode. */ + function tryDecodeEntities(text) { + var decoded = decodeEntities(text); + return decoded === text ? undefined : decoded; + } + function getTagName(node) { + if (node.kind === 241 /* JsxElement */) { + return getTagName(node.openingElement); } - function emitEmbeddedStatement(node) { - if (node.kind === 199 /* Block */) { - write(" "); - emit(node); + else { + var name_34 = node.tagName; + if (ts.isIdentifier(name_34) && ts.isIntrinsicJsxName(name_34.text)) { + return ts.createLiteral(name_34.text); } else { - increaseIndent(); - writeLine(); - emit(node); - decreaseIndent(); + return ts.createExpressionFromEntityName(name_34); } } - function emitExpressionStatement(node) { - emitParenthesizedIf(node.expression, /*parenthesized*/ node.expression.kind === 180 /* ArrowFunction */); - write(";"); + } + /** + * Emit an attribute name, which is quoted if it needs to be quoted. Because + * these emit into an object literal property name, we don't need to be worried + * about keywords, just non-identifier characters + */ + function getAttributeName(node) { + var name = node.name; + if (/^[A-Za-z_]\w*$/.test(name.text)) { + return name; } - function emitIfStatement(node) { - var endPos = emitToken(88 /* IfKeyword */, node.pos); - write(" "); - endPos = emitToken(17 /* OpenParenToken */, endPos); - emit(node.expression); - emitToken(18 /* CloseParenToken */, node.expression.end); - emitEmbeddedStatement(node.thenStatement); - if (node.elseStatement) { - writeLine(); - emitToken(80 /* ElseKeyword */, node.thenStatement.end); - if (node.elseStatement.kind === 203 /* IfStatement */) { - write(" "); - emit(node.elseStatement); - } - else { - emitEmbeddedStatement(node.elseStatement); - } - } + else { + return ts.createLiteral(name.text); + } + } + function visitJsxExpression(node) { + return ts.visitNode(node.expression, visitor, ts.isExpression); + } + } + ts.transformJsx = transformJsx; + function createEntitiesMap() { + return ts.createMap({ + "quot": 0x0022, + "amp": 0x0026, + "apos": 0x0027, + "lt": 0x003C, + "gt": 0x003E, + "nbsp": 0x00A0, + "iexcl": 0x00A1, + "cent": 0x00A2, + "pound": 0x00A3, + "curren": 0x00A4, + "yen": 0x00A5, + "brvbar": 0x00A6, + "sect": 0x00A7, + "uml": 0x00A8, + "copy": 0x00A9, + "ordf": 0x00AA, + "laquo": 0x00AB, + "not": 0x00AC, + "shy": 0x00AD, + "reg": 0x00AE, + "macr": 0x00AF, + "deg": 0x00B0, + "plusmn": 0x00B1, + "sup2": 0x00B2, + "sup3": 0x00B3, + "acute": 0x00B4, + "micro": 0x00B5, + "para": 0x00B6, + "middot": 0x00B7, + "cedil": 0x00B8, + "sup1": 0x00B9, + "ordm": 0x00BA, + "raquo": 0x00BB, + "frac14": 0x00BC, + "frac12": 0x00BD, + "frac34": 0x00BE, + "iquest": 0x00BF, + "Agrave": 0x00C0, + "Aacute": 0x00C1, + "Acirc": 0x00C2, + "Atilde": 0x00C3, + "Auml": 0x00C4, + "Aring": 0x00C5, + "AElig": 0x00C6, + "Ccedil": 0x00C7, + "Egrave": 0x00C8, + "Eacute": 0x00C9, + "Ecirc": 0x00CA, + "Euml": 0x00CB, + "Igrave": 0x00CC, + "Iacute": 0x00CD, + "Icirc": 0x00CE, + "Iuml": 0x00CF, + "ETH": 0x00D0, + "Ntilde": 0x00D1, + "Ograve": 0x00D2, + "Oacute": 0x00D3, + "Ocirc": 0x00D4, + "Otilde": 0x00D5, + "Ouml": 0x00D6, + "times": 0x00D7, + "Oslash": 0x00D8, + "Ugrave": 0x00D9, + "Uacute": 0x00DA, + "Ucirc": 0x00DB, + "Uuml": 0x00DC, + "Yacute": 0x00DD, + "THORN": 0x00DE, + "szlig": 0x00DF, + "agrave": 0x00E0, + "aacute": 0x00E1, + "acirc": 0x00E2, + "atilde": 0x00E3, + "auml": 0x00E4, + "aring": 0x00E5, + "aelig": 0x00E6, + "ccedil": 0x00E7, + "egrave": 0x00E8, + "eacute": 0x00E9, + "ecirc": 0x00EA, + "euml": 0x00EB, + "igrave": 0x00EC, + "iacute": 0x00ED, + "icirc": 0x00EE, + "iuml": 0x00EF, + "eth": 0x00F0, + "ntilde": 0x00F1, + "ograve": 0x00F2, + "oacute": 0x00F3, + "ocirc": 0x00F4, + "otilde": 0x00F5, + "ouml": 0x00F6, + "divide": 0x00F7, + "oslash": 0x00F8, + "ugrave": 0x00F9, + "uacute": 0x00FA, + "ucirc": 0x00FB, + "uuml": 0x00FC, + "yacute": 0x00FD, + "thorn": 0x00FE, + "yuml": 0x00FF, + "OElig": 0x0152, + "oelig": 0x0153, + "Scaron": 0x0160, + "scaron": 0x0161, + "Yuml": 0x0178, + "fnof": 0x0192, + "circ": 0x02C6, + "tilde": 0x02DC, + "Alpha": 0x0391, + "Beta": 0x0392, + "Gamma": 0x0393, + "Delta": 0x0394, + "Epsilon": 0x0395, + "Zeta": 0x0396, + "Eta": 0x0397, + "Theta": 0x0398, + "Iota": 0x0399, + "Kappa": 0x039A, + "Lambda": 0x039B, + "Mu": 0x039C, + "Nu": 0x039D, + "Xi": 0x039E, + "Omicron": 0x039F, + "Pi": 0x03A0, + "Rho": 0x03A1, + "Sigma": 0x03A3, + "Tau": 0x03A4, + "Upsilon": 0x03A5, + "Phi": 0x03A6, + "Chi": 0x03A7, + "Psi": 0x03A8, + "Omega": 0x03A9, + "alpha": 0x03B1, + "beta": 0x03B2, + "gamma": 0x03B3, + "delta": 0x03B4, + "epsilon": 0x03B5, + "zeta": 0x03B6, + "eta": 0x03B7, + "theta": 0x03B8, + "iota": 0x03B9, + "kappa": 0x03BA, + "lambda": 0x03BB, + "mu": 0x03BC, + "nu": 0x03BD, + "xi": 0x03BE, + "omicron": 0x03BF, + "pi": 0x03C0, + "rho": 0x03C1, + "sigmaf": 0x03C2, + "sigma": 0x03C3, + "tau": 0x03C4, + "upsilon": 0x03C5, + "phi": 0x03C6, + "chi": 0x03C7, + "psi": 0x03C8, + "omega": 0x03C9, + "thetasym": 0x03D1, + "upsih": 0x03D2, + "piv": 0x03D6, + "ensp": 0x2002, + "emsp": 0x2003, + "thinsp": 0x2009, + "zwnj": 0x200C, + "zwj": 0x200D, + "lrm": 0x200E, + "rlm": 0x200F, + "ndash": 0x2013, + "mdash": 0x2014, + "lsquo": 0x2018, + "rsquo": 0x2019, + "sbquo": 0x201A, + "ldquo": 0x201C, + "rdquo": 0x201D, + "bdquo": 0x201E, + "dagger": 0x2020, + "Dagger": 0x2021, + "bull": 0x2022, + "hellip": 0x2026, + "permil": 0x2030, + "prime": 0x2032, + "Prime": 0x2033, + "lsaquo": 0x2039, + "rsaquo": 0x203A, + "oline": 0x203E, + "frasl": 0x2044, + "euro": 0x20AC, + "image": 0x2111, + "weierp": 0x2118, + "real": 0x211C, + "trade": 0x2122, + "alefsym": 0x2135, + "larr": 0x2190, + "uarr": 0x2191, + "rarr": 0x2192, + "darr": 0x2193, + "harr": 0x2194, + "crarr": 0x21B5, + "lArr": 0x21D0, + "uArr": 0x21D1, + "rArr": 0x21D2, + "dArr": 0x21D3, + "hArr": 0x21D4, + "forall": 0x2200, + "part": 0x2202, + "exist": 0x2203, + "empty": 0x2205, + "nabla": 0x2207, + "isin": 0x2208, + "notin": 0x2209, + "ni": 0x220B, + "prod": 0x220F, + "sum": 0x2211, + "minus": 0x2212, + "lowast": 0x2217, + "radic": 0x221A, + "prop": 0x221D, + "infin": 0x221E, + "ang": 0x2220, + "and": 0x2227, + "or": 0x2228, + "cap": 0x2229, + "cup": 0x222A, + "int": 0x222B, + "there4": 0x2234, + "sim": 0x223C, + "cong": 0x2245, + "asymp": 0x2248, + "ne": 0x2260, + "equiv": 0x2261, + "le": 0x2264, + "ge": 0x2265, + "sub": 0x2282, + "sup": 0x2283, + "nsub": 0x2284, + "sube": 0x2286, + "supe": 0x2287, + "oplus": 0x2295, + "otimes": 0x2297, + "perp": 0x22A5, + "sdot": 0x22C5, + "lceil": 0x2308, + "rceil": 0x2309, + "lfloor": 0x230A, + "rfloor": 0x230B, + "lang": 0x2329, + "rang": 0x232A, + "loz": 0x25CA, + "spades": 0x2660, + "clubs": 0x2663, + "hearts": 0x2665, + "diams": 0x2666 + }); + } +})(ts || (ts = {})); +/// +/// +/*@internal*/ +var ts; +(function (ts) { + function transformES7(context) { + var hoistVariableDeclaration = context.hoistVariableDeclaration; + return transformSourceFile; + function transformSourceFile(node) { + if (ts.isDeclarationFile(node)) { + return node; } - function emitDoStatement(node) { - emitLoop(node, emitDoStatementWorker); + return ts.visitEachChild(node, visitor, context); + } + function visitor(node) { + if (node.transformFlags & 16 /* ES7 */) { + return visitorWorker(node); } - function emitDoStatementWorker(node, loop) { - write("do"); - if (loop) { - emitConvertedLoopCall(loop, /*emitAsBlock*/ true); - } - else { - emitNormalLoopBody(node, /*emitAsEmbeddedStatement*/ true); - } - if (node.statement.kind === 199 /* Block */) { - write(" "); - } - else { - writeLine(); - } - write("while ("); - emit(node.expression); - write(");"); + else if (node.transformFlags & 32 /* ContainsES7 */) { + return ts.visitEachChild(node, visitor, context); } - function emitWhileStatement(node) { - emitLoop(node, emitWhileStatementWorker); + else { + return node; } - function emitWhileStatementWorker(node, loop) { - write("while ("); - emit(node.expression); - write(")"); - if (loop) { - emitConvertedLoopCall(loop, /*emitAsBlock*/ true); + } + function visitorWorker(node) { + switch (node.kind) { + case 187 /* BinaryExpression */: + return visitBinaryExpression(node); + default: + ts.Debug.failBadSyntaxKind(node); + return ts.visitEachChild(node, visitor, context); + } + } + function visitBinaryExpression(node) { + // We are here because ES7 adds support for the exponentiation operator. + var left = ts.visitNode(node.left, visitor, ts.isExpression); + var right = ts.visitNode(node.right, visitor, ts.isExpression); + if (node.operatorToken.kind === 60 /* AsteriskAsteriskEqualsToken */) { + var target = void 0; + var value = void 0; + if (ts.isElementAccessExpression(left)) { + // Transforms `a[x] **= b` into `(_a = a)[_x = x] = Math.pow(_a[_x], b)` + var expressionTemp = ts.createTempVariable(hoistVariableDeclaration); + var argumentExpressionTemp = ts.createTempVariable(hoistVariableDeclaration); + target = ts.createElementAccess(ts.createAssignment(expressionTemp, left.expression, /*location*/ left.expression), ts.createAssignment(argumentExpressionTemp, left.argumentExpression, /*location*/ left.argumentExpression), + /*location*/ left); + value = ts.createElementAccess(expressionTemp, argumentExpressionTemp, + /*location*/ left); + } + else if (ts.isPropertyAccessExpression(left)) { + // Transforms `a.x **= b` into `(_a = a).x = Math.pow(_a.x, b)` + var expressionTemp = ts.createTempVariable(hoistVariableDeclaration); + target = ts.createPropertyAccess(ts.createAssignment(expressionTemp, left.expression, /*location*/ left.expression), left.name, + /*location*/ left); + value = ts.createPropertyAccess(expressionTemp, left.name, + /*location*/ left); } else { - emitNormalLoopBody(node, /*emitAsEmbeddedStatement*/ true); + // Transforms `a **= b` into `a = Math.pow(a, b)` + target = left; + value = left; } + return ts.createAssignment(target, ts.createMathPow(value, right, /*location*/ node), /*location*/ node); } - /** - * Returns true if start of variable declaration list was emitted. - * Returns false if nothing was written - this can happen for source file level variable declarations - * in system modules where such variable declarations are hoisted. - */ - function tryEmitStartOfVariableDeclarationList(decl) { - if (shouldHoistVariable(decl, /*checkIfSourceFileLevelDecl*/ true)) { - // variables in variable declaration list were already hoisted - return false; - } - if (convertedLoopState && (ts.getCombinedNodeFlags(decl) & 3072 /* BlockScoped */) === 0) { - // we are inside a converted loop - this can only happen in downlevel scenarios - // record names for all variable declarations - for (var _a = 0, _b = decl.declarations; _a < _b.length; _a++) { - var varDecl = _b[_a]; - hoistVariableDeclarationFromLoop(convertedLoopState, varDecl); - } - return false; + else if (node.operatorToken.kind === 38 /* AsteriskAsteriskToken */) { + // Transforms `a ** b` into `Math.pow(a, b)` + return ts.createMathPow(left, right, /*location*/ node); + } + else { + ts.Debug.failBadSyntaxKind(node); + return ts.visitEachChild(node, visitor, context); + } + } + } + ts.transformES7 = transformES7; +})(ts || (ts = {})); +/// +/// +/*@internal*/ +var ts; +(function (ts) { + var ES6SubstitutionFlags; + (function (ES6SubstitutionFlags) { + /** Enables substitutions for captured `this` */ + ES6SubstitutionFlags[ES6SubstitutionFlags["CapturedThis"] = 1] = "CapturedThis"; + /** Enables substitutions for block-scoped bindings. */ + ES6SubstitutionFlags[ES6SubstitutionFlags["BlockScopedBindings"] = 2] = "BlockScopedBindings"; + })(ES6SubstitutionFlags || (ES6SubstitutionFlags = {})); + var CopyDirection; + (function (CopyDirection) { + CopyDirection[CopyDirection["ToOriginal"] = 0] = "ToOriginal"; + CopyDirection[CopyDirection["ToOutParameter"] = 1] = "ToOutParameter"; + })(CopyDirection || (CopyDirection = {})); + var Jump; + (function (Jump) { + Jump[Jump["Break"] = 2] = "Break"; + Jump[Jump["Continue"] = 4] = "Continue"; + Jump[Jump["Return"] = 8] = "Return"; + })(Jump || (Jump = {})); + var SuperCaptureResult; + (function (SuperCaptureResult) { + /** + * A capture may have been added for calls to 'super', but + * the caller should emit subsequent statements normally. + */ + SuperCaptureResult[SuperCaptureResult["NoReplacement"] = 0] = "NoReplacement"; + /** + * A call to 'super()' got replaced with a capturing statement like: + * + * var _this = _super.call(...) || this; + * + * Callers should skip the current statement. + */ + SuperCaptureResult[SuperCaptureResult["ReplaceSuperCapture"] = 1] = "ReplaceSuperCapture"; + /** + * A call to 'super()' got replaced with a capturing statement like: + * + * return _super.call(...) || this; + * + * Callers should skip the current statement and avoid any returns of '_this'. + */ + SuperCaptureResult[SuperCaptureResult["ReplaceWithReturn"] = 2] = "ReplaceWithReturn"; + })(SuperCaptureResult || (SuperCaptureResult = {})); + function transformES6(context) { + var startLexicalEnvironment = context.startLexicalEnvironment, endLexicalEnvironment = context.endLexicalEnvironment, hoistVariableDeclaration = context.hoistVariableDeclaration; + var resolver = context.getEmitResolver(); + var previousOnSubstituteNode = context.onSubstituteNode; + var previousOnEmitNode = context.onEmitNode; + context.onEmitNode = onEmitNode; + context.onSubstituteNode = onSubstituteNode; + var currentSourceFile; + var currentText; + var currentParent; + var currentNode; + var enclosingVariableStatement; + var enclosingBlockScopeContainer; + var enclosingBlockScopeContainerParent; + var enclosingFunction; + var enclosingNonArrowFunction; + var enclosingNonAsyncFunctionBody; + /** + * Used to track if we are emitting body of the converted loop + */ + var convertedLoopState; + /** + * Keeps track of whether substitutions have been enabled for specific cases. + * They are persisted between each SourceFile transformation and should not + * be reset. + */ + var enabledSubstitutions; + return transformSourceFile; + function transformSourceFile(node) { + if (ts.isDeclarationFile(node)) { + return node; + } + currentSourceFile = node; + currentText = node.text; + return ts.visitNode(node, visitor, ts.isSourceFile); + } + function visitor(node) { + return saveStateAndInvoke(node, dispatcher); + } + function dispatcher(node) { + return convertedLoopState + ? visitorForConvertedLoopWorker(node) + : visitorWorker(node); + } + function saveStateAndInvoke(node, f) { + var savedEnclosingFunction = enclosingFunction; + var savedEnclosingNonArrowFunction = enclosingNonArrowFunction; + var savedEnclosingNonAsyncFunctionBody = enclosingNonAsyncFunctionBody; + var savedEnclosingBlockScopeContainer = enclosingBlockScopeContainer; + var savedEnclosingBlockScopeContainerParent = enclosingBlockScopeContainerParent; + var savedEnclosingVariableStatement = enclosingVariableStatement; + var savedCurrentParent = currentParent; + var savedCurrentNode = currentNode; + var savedConvertedLoopState = convertedLoopState; + if (ts.nodeStartsNewLexicalEnvironment(node)) { + // don't treat content of nodes that start new lexical environment as part of converted loop copy + convertedLoopState = undefined; + } + onBeforeVisitNode(node); + var visited = f(node); + convertedLoopState = savedConvertedLoopState; + enclosingFunction = savedEnclosingFunction; + enclosingNonArrowFunction = savedEnclosingNonArrowFunction; + enclosingNonAsyncFunctionBody = savedEnclosingNonAsyncFunctionBody; + enclosingBlockScopeContainer = savedEnclosingBlockScopeContainer; + enclosingBlockScopeContainerParent = savedEnclosingBlockScopeContainerParent; + enclosingVariableStatement = savedEnclosingVariableStatement; + currentParent = savedCurrentParent; + currentNode = savedCurrentNode; + return visited; + } + function shouldCheckNode(node) { + return (node.transformFlags & 64 /* ES6 */) !== 0 || + node.kind === 214 /* LabeledStatement */ || + (ts.isIterationStatement(node, /*lookInLabeledStatements*/ false) && shouldConvertIterationStatementBody(node)); + } + function visitorWorker(node) { + if (shouldCheckNode(node)) { + return visitJavaScript(node); + } + else if (node.transformFlags & 128 /* ContainsES6 */) { + return ts.visitEachChild(node, visitor, context); + } + else { + return node; + } + } + function visitorForConvertedLoopWorker(node) { + var result; + if (shouldCheckNode(node)) { + result = visitJavaScript(node); + } + else { + result = visitNodesInConvertedLoop(node); + } + return result; + } + function visitNodesInConvertedLoop(node) { + switch (node.kind) { + case 211 /* ReturnStatement */: + return visitReturnStatement(node); + case 200 /* VariableStatement */: + return visitVariableStatement(node); + case 213 /* SwitchStatement */: + return visitSwitchStatement(node); + case 210 /* BreakStatement */: + case 209 /* ContinueStatement */: + return visitBreakOrContinueStatement(node); + case 97 /* ThisKeyword */: + return visitThisKeyword(node); + case 69 /* Identifier */: + return visitIdentifier(node); + default: + return ts.visitEachChild(node, visitor, context); + } + } + function visitJavaScript(node) { + switch (node.kind) { + case 82 /* ExportKeyword */: + return node; + case 221 /* ClassDeclaration */: + return visitClassDeclaration(node); + case 192 /* ClassExpression */: + return visitClassExpression(node); + case 142 /* Parameter */: + return visitParameter(node); + case 220 /* FunctionDeclaration */: + return visitFunctionDeclaration(node); + case 180 /* ArrowFunction */: + return visitArrowFunction(node); + case 179 /* FunctionExpression */: + return visitFunctionExpression(node); + case 218 /* VariableDeclaration */: + return visitVariableDeclaration(node); + case 69 /* Identifier */: + return visitIdentifier(node); + case 219 /* VariableDeclarationList */: + return visitVariableDeclarationList(node); + case 214 /* LabeledStatement */: + return visitLabeledStatement(node); + case 204 /* DoStatement */: + return visitDoStatement(node); + case 205 /* WhileStatement */: + return visitWhileStatement(node); + case 206 /* ForStatement */: + return visitForStatement(node); + case 207 /* ForInStatement */: + return visitForInStatement(node); + case 208 /* ForOfStatement */: + return visitForOfStatement(node); + case 202 /* ExpressionStatement */: + return visitExpressionStatement(node); + case 171 /* ObjectLiteralExpression */: + return visitObjectLiteralExpression(node); + case 254 /* ShorthandPropertyAssignment */: + return visitShorthandPropertyAssignment(node); + case 170 /* ArrayLiteralExpression */: + return visitArrayLiteralExpression(node); + case 174 /* CallExpression */: + return visitCallExpression(node); + case 175 /* NewExpression */: + return visitNewExpression(node); + case 178 /* ParenthesizedExpression */: + return visitParenthesizedExpression(node, /*needsDestructuringValue*/ true); + case 187 /* BinaryExpression */: + return visitBinaryExpression(node, /*needsDestructuringValue*/ true); + case 11 /* NoSubstitutionTemplateLiteral */: + case 12 /* TemplateHead */: + case 13 /* TemplateMiddle */: + case 14 /* TemplateTail */: + return visitTemplateLiteral(node); + case 176 /* TaggedTemplateExpression */: + return visitTaggedTemplateExpression(node); + case 189 /* TemplateExpression */: + return visitTemplateExpression(node); + case 190 /* YieldExpression */: + return visitYieldExpression(node); + case 95 /* SuperKeyword */: + return visitSuperKeyword(node); + case 190 /* YieldExpression */: + // `yield` will be handled by a generators transform. + return ts.visitEachChild(node, visitor, context); + case 147 /* MethodDeclaration */: + return visitMethodDeclaration(node); + case 256 /* SourceFile */: + return visitSourceFileNode(node); + case 200 /* VariableStatement */: + return visitVariableStatement(node); + default: + ts.Debug.failBadSyntaxKind(node); + return ts.visitEachChild(node, visitor, context); + } + } + function onBeforeVisitNode(node) { + if (currentNode) { + if (ts.isBlockScope(currentNode, currentParent)) { + enclosingBlockScopeContainer = currentNode; + enclosingBlockScopeContainerParent = currentParent; } - emitStart(decl); - if (decl && languageVersion >= 2 /* ES6 */) { - if (ts.isLet(decl)) { - write("let "); - } - else if (ts.isConst(decl)) { - write("const "); - } - else { - write("var "); + if (ts.isFunctionLike(currentNode)) { + enclosingFunction = currentNode; + if (currentNode.kind !== 180 /* ArrowFunction */) { + enclosingNonArrowFunction = currentNode; + if (!(ts.getEmitFlags(currentNode) & 2097152 /* AsyncFunctionBody */)) { + enclosingNonAsyncFunctionBody = currentNode; + } } } - else { - write("var "); + // keep track of the enclosing variable statement when in the context of + // variable statements, variable declarations, binding elements, and binding + // patterns. + switch (currentNode.kind) { + case 200 /* VariableStatement */: + enclosingVariableStatement = currentNode; + break; + case 219 /* VariableDeclarationList */: + case 218 /* VariableDeclaration */: + case 169 /* BindingElement */: + case 167 /* ObjectBindingPattern */: + case 168 /* ArrayBindingPattern */: + break; + default: + enclosingVariableStatement = undefined; } - // Note here we specifically dont emit end so that if we are going to emit binding pattern - // we can alter the source map correctly - return true; } - function emitVariableDeclarationListSkippingUninitializedEntries(list) { - var started = false; - for (var _a = 0, _b = list.declarations; _a < _b.length; _a++) { - var decl = _b[_a]; - if (!decl.initializer) { - continue; - } - if (!started) { - started = true; - } - else { - write(", "); - } - emit(decl); - } - return started; + currentParent = currentNode; + currentNode = node; + } + function visitSwitchStatement(node) { + ts.Debug.assert(convertedLoopState !== undefined); + var savedAllowedNonLabeledJumps = convertedLoopState.allowedNonLabeledJumps; + // for switch statement allow only non-labeled break + convertedLoopState.allowedNonLabeledJumps |= 2 /* Break */; + var result = ts.visitEachChild(node, visitor, context); + convertedLoopState.allowedNonLabeledJumps = savedAllowedNonLabeledJumps; + return result; + } + function visitReturnStatement(node) { + ts.Debug.assert(convertedLoopState !== undefined); + convertedLoopState.nonLocalJumps |= 8 /* Return */; + return ts.createReturn(ts.createObjectLiteral([ + ts.createPropertyAssignment(ts.createIdentifier("value"), node.expression + ? ts.visitNode(node.expression, visitor, ts.isExpression) + : ts.createVoidZero()) + ])); + } + function visitThisKeyword(node) { + ts.Debug.assert(convertedLoopState !== undefined); + if (enclosingFunction && enclosingFunction.kind === 180 /* ArrowFunction */) { + // if the enclosing function is an ArrowFunction is then we use the captured 'this' keyword. + convertedLoopState.containsLexicalThis = true; + return node; + } + return convertedLoopState.thisName || (convertedLoopState.thisName = ts.createUniqueName("this")); + } + function visitIdentifier(node) { + if (!convertedLoopState) { + return node; } - function shouldConvertLoopBody(node) { - return languageVersion < 2 /* ES6 */ && - (resolver.getNodeCheckFlags(node) & 65536 /* LoopWithCapturedBlockScopedBinding */) !== 0; + if (ts.isGeneratedIdentifier(node)) { + return node; } - function emitLoop(node, loopEmitter) { - var shouldConvert = shouldConvertLoopBody(node); - if (!shouldConvert) { - loopEmitter(node, /* convertedLoop*/ undefined); - } - else { - var loop = convertLoopBody(node); - if (node.parent.kind === 214 /* LabeledStatement */) { - // if parent of the loop was labeled statement - attach the label to loop skipping converted loop body - emitLabelAndColon(node.parent); - } - loopEmitter(node, loop); - } + if (node.text !== "arguments" && !resolver.isArgumentsLocalBinding(node)) { + return node; } - function convertLoopBody(node) { - var functionName = makeUniqueName("_loop"); - var loopInitializer; - switch (node.kind) { - case 206 /* ForStatement */: - case 207 /* ForInStatement */: - case 208 /* ForOfStatement */: - var initializer = node.initializer; - if (initializer && initializer.kind === 219 /* VariableDeclarationList */) { - loopInitializer = node.initializer; + return convertedLoopState.argumentsName || (convertedLoopState.argumentsName = ts.createUniqueName("arguments")); + } + function visitBreakOrContinueStatement(node) { + if (convertedLoopState) { + // check if we can emit break/continue as is + // it is possible if either + // - break/continue is labeled and label is located inside the converted loop + // - break/continue is non-labeled and located in non-converted loop/switch statement + var jump = node.kind === 210 /* BreakStatement */ ? 2 /* Break */ : 4 /* Continue */; + var canUseBreakOrContinue = (node.label && convertedLoopState.labels && convertedLoopState.labels[node.label.text]) || + (!node.label && (convertedLoopState.allowedNonLabeledJumps & jump)); + if (!canUseBreakOrContinue) { + var labelMarker = void 0; + if (!node.label) { + if (node.kind === 210 /* BreakStatement */) { + convertedLoopState.nonLocalJumps |= 2 /* Break */; + labelMarker = "break"; } - break; - } - var loopParameters; - var loopOutParameters; - if (loopInitializer && (ts.getCombinedNodeFlags(loopInitializer) & 3072 /* BlockScoped */)) { - // if loop initializer contains block scoped variables - they should be passed to converted loop body as parameters - loopParameters = []; - for (var _a = 0, _b = loopInitializer.declarations; _a < _b.length; _a++) { - var varDeclaration = _b[_a]; - processVariableDeclaration(varDeclaration.name); - } - } - var bodyIsBlock = node.statement.kind === 199 /* Block */; - var paramList = loopParameters ? loopParameters.join(", ") : ""; - writeLine(); - write("var " + functionName + " = function(" + paramList + ")"); - var convertedOuterLoopState = convertedLoopState; - convertedLoopState = { loopOutParameters: loopOutParameters }; - if (convertedOuterLoopState) { - // convertedOuterLoopState !== undefined means that this converted loop is nested in another converted loop. - // if outer converted loop has already accumulated some state - pass it through - if (convertedOuterLoopState.argumentsName) { - // outer loop has already used 'arguments' so we've already have some name to alias it - // use the same name in all nested loops - convertedLoopState.argumentsName = convertedOuterLoopState.argumentsName; - } - if (convertedOuterLoopState.thisName) { - // outer loop has already used 'this' so we've already have some name to alias it - // use the same name in all nested loops - convertedLoopState.thisName = convertedOuterLoopState.thisName; - } - if (convertedOuterLoopState.hoistedLocalVariables) { - // we've already collected some non-block scoped variable declarations in enclosing loop - // use the same storage in nested loop - convertedLoopState.hoistedLocalVariables = convertedOuterLoopState.hoistedLocalVariables; - } - } - write(" {"); - writeLine(); - increaseIndent(); - if (bodyIsBlock) { - emitLines(node.statement.statements); - } - else { - emit(node.statement); - } - writeLine(); - // end of loop body -> copy out parameter - copyLoopOutParameters(convertedLoopState, 1 /* ToOutParameter */, /*emitAsStatements*/ true); - decreaseIndent(); - writeLine(); - write("};"); - writeLine(); - if (loopOutParameters) { - // declare variables to hold out params for loop body - write("var "); - for (var i = 0; i < loopOutParameters.length; i++) { - if (i !== 0) { - write(", "); + else { + convertedLoopState.nonLocalJumps |= 4 /* Continue */; + // note: return value is emitted only to simplify debugging, call to converted loop body does not do any dispatching on it. + labelMarker = "continue"; } - write(loopOutParameters[i].outParamName); - } - write(";"); - writeLine(); - } - if (convertedLoopState.argumentsName) { - // if alias for arguments is set - if (convertedOuterLoopState) { - // pass it to outer converted loop - convertedOuterLoopState.argumentsName = convertedLoopState.argumentsName; - } - else { - // this is top level converted loop and we need to create an alias for 'arguments' object - write("var " + convertedLoopState.argumentsName + " = arguments;"); - writeLine(); - } - } - if (convertedLoopState.thisName) { - // if alias for this is set - if (convertedOuterLoopState) { - // pass it to outer converted loop - convertedOuterLoopState.thisName = convertedLoopState.thisName; - } - else { - // this is top level converted loop so we need to create an alias for 'this' here - // NOTE: - // if converted loops were all nested in arrow function then we'll always emit '_this' so convertedLoopState.thisName will not be set. - // If it is set this means that all nested loops are not nested in arrow function and it is safe to capture 'this'. - write("var " + convertedLoopState.thisName + " = this;"); - writeLine(); - } - } - if (convertedLoopState.hoistedLocalVariables) { - // if hoistedLocalVariables !== undefined this means that we've possibly collected some variable declarations to be hoisted later - if (convertedOuterLoopState) { - // pass them to outer converted loop - convertedOuterLoopState.hoistedLocalVariables = convertedLoopState.hoistedLocalVariables; } else { - // deduplicate and hoist collected variable declarations - write("var "); - var seen = void 0; - for (var _c = 0, _d = convertedLoopState.hoistedLocalVariables; _c < _d.length; _c++) { - var id = _d[_c]; - // Don't initialize seen unless we have at least one element. - // Emit a comma to separate for all but the first element. - if (!seen) { - seen = ts.createMap(); + if (node.kind === 210 /* BreakStatement */) { + labelMarker = "break-" + node.label.text; + setLabeledJump(convertedLoopState, /*isBreak*/ true, node.label.text, labelMarker); + } + else { + labelMarker = "continue-" + node.label.text; + setLabeledJump(convertedLoopState, /*isBreak*/ false, node.label.text, labelMarker); + } + } + var returnExpression = ts.createLiteral(labelMarker); + if (convertedLoopState.loopOutParameters.length) { + var outParams = convertedLoopState.loopOutParameters; + var expr = void 0; + for (var i = 0; i < outParams.length; i++) { + var copyExpr = copyOutParameter(outParams[i], 1 /* ToOutParameter */); + if (i === 0) { + expr = copyExpr; } else { - write(", "); - } - if (!(id.text in seen)) { - emit(id); - seen[id.text] = id.text; + expr = ts.createBinary(expr, 24 /* CommaToken */, copyExpr); } } - write(";"); - writeLine(); - } - } - var currentLoopState = convertedLoopState; - convertedLoopState = convertedOuterLoopState; - return { functionName: functionName, paramList: paramList, state: currentLoopState }; - function processVariableDeclaration(name) { - if (name.kind === 69 /* Identifier */) { - var nameText = isNameOfNestedBlockScopedRedeclarationOrCapturedBinding(name) - ? getGeneratedNameForNode(name) - : name.text; - loopParameters.push(nameText); - if (resolver.getNodeCheckFlags(name.parent) & 2097152 /* NeedsLoopOutParameter */) { - var reassignedVariable = { originalName: name, outParamName: makeUniqueName("out_" + nameText) }; - (loopOutParameters || (loopOutParameters = [])).push(reassignedVariable); - } - } - else { - for (var _a = 0, _b = name.elements; _a < _b.length; _a++) { - var element = _b[_a]; - processVariableDeclaration(element.name); - } + returnExpression = ts.createBinary(expr, 24 /* CommaToken */, returnExpression); } + return ts.createReturn(returnExpression); } } - function emitNormalLoopBody(node, emitAsEmbeddedStatement) { - var saveAllowedNonLabeledJumps; - if (convertedLoopState) { - // we get here if we are trying to emit normal loop loop inside converted loop - // set allowedNonLabeledJumps to Break | Continue to mark that break\continue inside the loop should be emitted as is - saveAllowedNonLabeledJumps = convertedLoopState.allowedNonLabeledJumps; - convertedLoopState.allowedNonLabeledJumps = 2 /* Break */ | 4 /* Continue */; + return ts.visitEachChild(node, visitor, context); + } + /** + * Visits a ClassDeclaration and transforms it into a variable statement. + * + * @param node A ClassDeclaration node. + */ + function visitClassDeclaration(node) { + // [source] + // class C { } + // + // [output] + // var C = (function () { + // function C() { + // } + // return C; + // }()); + var modifierFlags = ts.getModifierFlags(node); + var isExported = modifierFlags & 1 /* Export */; + var isDefault = modifierFlags & 512 /* Default */; + // Add an `export` modifier to the statement if needed (for `--target es5 --module es6`) + var modifiers = isExported && !isDefault + ? ts.filter(node.modifiers, isExportModifier) + : undefined; + var statement = ts.createVariableStatement(modifiers, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(getDeclarationName(node, /*allowComments*/ true), + /*type*/ undefined, transformClassLikeDeclarationToExpression(node)) + ]), + /*location*/ node); + ts.setOriginalNode(statement, node); + ts.startOnNewLine(statement); + // Add an `export default` statement for default exports (for `--target es5 --module es6`) + if (isExported && isDefault) { + var statements = [statement]; + statements.push(ts.createExportAssignment( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*isExportEquals*/ false, getDeclarationName(node, /*allowComments*/ false))); + return statements; + } + return statement; + } + function isExportModifier(node) { + return node.kind === 82 /* ExportKeyword */; + } + /** + * Visits a ClassExpression and transforms it into an expression. + * + * @param node A ClassExpression node. + */ + function visitClassExpression(node) { + // [source] + // C = class { } + // + // [output] + // C = (function () { + // function class_1() { + // } + // return class_1; + // }()) + return transformClassLikeDeclarationToExpression(node); + } + /** + * Transforms a ClassExpression or ClassDeclaration into an expression. + * + * @param node A ClassExpression or ClassDeclaration node. + */ + function transformClassLikeDeclarationToExpression(node) { + // [source] + // class C extends D { + // constructor() {} + // method() {} + // get prop() {} + // set prop(v) {} + // } + // + // [output] + // (function (_super) { + // __extends(C, _super); + // function C() { + // } + // C.prototype.method = function () {} + // Object.defineProperty(C.prototype, "prop", { + // get: function() {}, + // set: function() {}, + // enumerable: true, + // configurable: true + // }); + // return C; + // }(D)) + if (node.name) { + enableSubstitutionsForBlockScopedBindings(); + } + var extendsClauseElement = ts.getClassExtendsHeritageClauseElement(node); + var classFunction = ts.createFunctionExpression( + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, extendsClauseElement ? [ts.createParameter("_super")] : [], + /*type*/ undefined, transformClassBody(node, extendsClauseElement)); + // To preserve the behavior of the old emitter, we explicitly indent + // the body of the function here if it was requested in an earlier + // transformation. + if (ts.getEmitFlags(node) & 524288 /* Indented */) { + ts.setEmitFlags(classFunction, 524288 /* Indented */); + } + // "inner" and "outer" below are added purely to preserve source map locations from + // the old emitter + var inner = ts.createPartiallyEmittedExpression(classFunction); + inner.end = node.end; + ts.setEmitFlags(inner, 49152 /* NoComments */); + var outer = ts.createPartiallyEmittedExpression(inner); + outer.end = ts.skipTrivia(currentText, node.pos); + ts.setEmitFlags(outer, 49152 /* NoComments */); + return ts.createParen(ts.createCall(outer, + /*typeArguments*/ undefined, extendsClauseElement + ? [ts.visitNode(extendsClauseElement.expression, visitor, ts.isExpression)] + : [])); + } + /** + * Transforms a ClassExpression or ClassDeclaration into a function body. + * + * @param node A ClassExpression or ClassDeclaration node. + * @param extendsClauseElement The expression for the class `extends` clause. + */ + function transformClassBody(node, extendsClauseElement) { + var statements = []; + startLexicalEnvironment(); + addExtendsHelperIfNeeded(statements, node, extendsClauseElement); + addConstructor(statements, node, extendsClauseElement); + addClassMembers(statements, node); + // Create a synthetic text range for the return statement. + var closingBraceLocation = ts.createTokenRange(ts.skipTrivia(currentText, node.members.end), 16 /* CloseBraceToken */); + var localName = getLocalName(node); + // The following partially-emitted expression exists purely to align our sourcemap + // emit with the original emitter. + var outer = ts.createPartiallyEmittedExpression(localName); + outer.end = closingBraceLocation.end; + ts.setEmitFlags(outer, 49152 /* NoComments */); + var statement = ts.createReturn(outer); + statement.pos = closingBraceLocation.pos; + ts.setEmitFlags(statement, 49152 /* NoComments */ | 12288 /* NoTokenSourceMaps */); + statements.push(statement); + ts.addRange(statements, endLexicalEnvironment()); + var block = ts.createBlock(ts.createNodeArray(statements, /*location*/ node.members), /*location*/ undefined, /*multiLine*/ true); + ts.setEmitFlags(block, 49152 /* NoComments */); + return block; + } + /** + * Adds a call to the `__extends` helper if needed for a class. + * + * @param statements The statements of the class body function. + * @param node The ClassExpression or ClassDeclaration node. + * @param extendsClauseElement The expression for the class `extends` clause. + */ + function addExtendsHelperIfNeeded(statements, node, extendsClauseElement) { + if (extendsClauseElement) { + statements.push(ts.createStatement(ts.createExtendsHelper(currentSourceFile.externalHelpersModuleName, getDeclarationName(node)), + /*location*/ extendsClauseElement)); + } + } + /** + * Adds the constructor of the class to a class body function. + * + * @param statements The statements of the class body function. + * @param node The ClassExpression or ClassDeclaration node. + * @param extendsClauseElement The expression for the class `extends` clause. + */ + function addConstructor(statements, node, extendsClauseElement) { + var constructor = ts.getFirstConstructorWithBody(node); + var hasSynthesizedSuper = hasSynthesizedDefaultSuperCall(constructor, extendsClauseElement !== undefined); + var constructorFunction = ts.createFunctionDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, getDeclarationName(node), + /*typeParameters*/ undefined, transformConstructorParameters(constructor, hasSynthesizedSuper), + /*type*/ undefined, transformConstructorBody(constructor, node, extendsClauseElement, hasSynthesizedSuper), + /*location*/ constructor || node); + if (extendsClauseElement) { + ts.setEmitFlags(constructorFunction, 256 /* CapturesThis */); + } + statements.push(constructorFunction); + } + /** + * Transforms the parameters of the constructor declaration of a class. + * + * @param constructor The constructor for the class. + * @param hasSynthesizedSuper A value indicating whether the constructor starts with a + * synthesized `super` call. + */ + function transformConstructorParameters(constructor, hasSynthesizedSuper) { + // If the TypeScript transformer needed to synthesize a constructor for property + // initializers, it would have also added a synthetic `...args` parameter and + // `super` call. + // If this is the case, we do not include the synthetic `...args` parameter and + // will instead use the `arguments` object in ES5/3. + if (constructor && !hasSynthesizedSuper) { + return ts.visitNodes(constructor.parameters, visitor, ts.isParameter); + } + return []; + } + /** + * Transforms the body of a constructor declaration of a class. + * + * @param constructor The constructor for the class. + * @param node The node which contains the constructor. + * @param extendsClauseElement The expression for the class `extends` clause. + * @param hasSynthesizedSuper A value indicating whether the constructor starts with a + * synthesized `super` call. + */ + function transformConstructorBody(constructor, node, extendsClauseElement, hasSynthesizedSuper) { + var statements = []; + startLexicalEnvironment(); + var statementOffset = -1; + if (hasSynthesizedSuper) { + // If a super call has already been synthesized, + // we're going to assume that we should just transform everything after that. + // The assumption is that no prior step in the pipeline has added any prologue directives. + statementOffset = 1; + } + else if (constructor) { + // Otherwise, try to emit all potential prologue directives first. + statementOffset = ts.addPrologueDirectives(statements, constructor.body.statements, /*ensureUseStrict*/ false, visitor); + } + if (constructor) { + addDefaultValueAssignmentsIfNeeded(statements, constructor); + addRestParameterIfNeeded(statements, constructor, hasSynthesizedSuper); + ts.Debug.assert(statementOffset >= 0, "statementOffset not initialized correctly!"); + } + var superCaptureStatus = declareOrCaptureOrReturnThisForConstructorIfNeeded(statements, constructor, !!extendsClauseElement, hasSynthesizedSuper, statementOffset); + // The last statement expression was replaced. Skip it. + if (superCaptureStatus === 1 /* ReplaceSuperCapture */ || superCaptureStatus === 2 /* ReplaceWithReturn */) { + statementOffset++; + } + if (constructor) { + var body = saveStateAndInvoke(constructor, function (constructor) { return ts.visitNodes(constructor.body.statements, visitor, ts.isStatement, /*start*/ statementOffset); }); + ts.addRange(statements, body); + } + // Return `_this` unless we're sure enough that it would be pointless to add a return statement. + // If there's a constructor that we can tell returns in enough places, then we *do not* want to add a return. + if (extendsClauseElement + && superCaptureStatus !== 2 /* ReplaceWithReturn */ + && !(constructor && isSufficientlyCoveredByReturnStatements(constructor.body))) { + statements.push(ts.createReturn(ts.createIdentifier("_this"))); + } + ts.addRange(statements, endLexicalEnvironment()); + var block = ts.createBlock(ts.createNodeArray(statements, + /*location*/ constructor ? constructor.body.statements : node.members), + /*location*/ constructor ? constructor.body : node, + /*multiLine*/ true); + if (!constructor) { + ts.setEmitFlags(block, 49152 /* NoComments */); + } + return block; + } + /** + * We want to try to avoid emitting a return statement in certain cases if a user already returned something. + * It would generate obviously dead code, so we'll try to make things a little bit prettier + * by doing a minimal check on whether some common patterns always explicitly return. + */ + function isSufficientlyCoveredByReturnStatements(statement) { + // A return statement is considered covered. + if (statement.kind === 211 /* ReturnStatement */) { + return true; + } + else if (statement.kind === 203 /* IfStatement */) { + var ifStatement = statement; + if (ifStatement.elseStatement) { + return isSufficientlyCoveredByReturnStatements(ifStatement.thenStatement) && + isSufficientlyCoveredByReturnStatements(ifStatement.elseStatement); } - if (emitAsEmbeddedStatement) { - emitEmbeddedStatement(node.statement); + } + else if (statement.kind === 199 /* Block */) { + var lastStatement = ts.lastOrUndefined(statement.statements); + if (lastStatement && isSufficientlyCoveredByReturnStatements(lastStatement)) { + return true; } - else if (node.statement.kind === 199 /* Block */) { - emitLines(node.statement.statements); + } + return false; + } + /** + * Declares a `_this` variable for derived classes and for when arrow functions capture `this`. + * + * @returns The new statement offset into the `statements` array. + */ + function declareOrCaptureOrReturnThisForConstructorIfNeeded(statements, ctor, hasExtendsClause, hasSynthesizedSuper, statementOffset) { + // If this isn't a derived class, just capture 'this' for arrow functions if necessary. + if (!hasExtendsClause) { + if (ctor) { + addCaptureThisForNodeIfNeeded(statements, ctor); + } + return 0 /* NoReplacement */; + } + // We must be here because the user didn't write a constructor + // but we needed to call 'super(...args)' anyway as per 14.5.14 of the ES2016 spec. + // If that's the case we can just immediately return the result of a 'super()' call. + if (!ctor) { + statements.push(ts.createReturn(createDefaultSuperCallOrThis())); + return 2 /* ReplaceWithReturn */; + } + // The constructor exists, but it and the 'super()' call it contains were generated + // for something like property initializers. + // Create a captured '_this' variable and assume it will subsequently be used. + if (hasSynthesizedSuper) { + captureThisForNode(statements, ctor, createDefaultSuperCallOrThis()); + enableSubstitutionsForCapturedThis(); + return 1 /* ReplaceSuperCapture */; + } + // Most of the time, a 'super' call will be the first real statement in a constructor body. + // In these cases, we'd like to transform these into a *single* statement instead of a declaration + // followed by an assignment statement for '_this'. For instance, if we emitted without an initializer, + // we'd get: + // + // var _this; + // _this = _super.call(...) || this; + // + // instead of + // + // var _this = _super.call(...) || this; + // + // Additionally, if the 'super()' call is the last statement, we should just avoid capturing + // entirely and immediately return the result like so: + // + // return _super.call(...) || this; + // + var firstStatement; + var superCallExpression; + var ctorStatements = ctor.body.statements; + if (statementOffset < ctorStatements.length) { + firstStatement = ctorStatements[statementOffset]; + if (firstStatement.kind === 202 /* ExpressionStatement */ && ts.isSuperCallExpression(firstStatement.expression)) { + var superCall = firstStatement.expression; + superCallExpression = ts.setOriginalNode(saveStateAndInvoke(superCall, visitImmediateSuperCallInBody), superCall); + } + } + // Return the result if we have an immediate super() call on the last statement. + if (superCallExpression && statementOffset === ctorStatements.length - 1) { + statements.push(ts.createReturn(superCallExpression)); + return 2 /* ReplaceWithReturn */; + } + // Perform the capture. + captureThisForNode(statements, ctor, superCallExpression, firstStatement); + // If we're actually replacing the original statement, we need to signal this to the caller. + if (superCallExpression) { + return 1 /* ReplaceSuperCapture */; + } + return 0 /* NoReplacement */; + } + function createDefaultSuperCallOrThis() { + var actualThis = ts.createThis(); + ts.setEmitFlags(actualThis, 128 /* NoSubstitution */); + var superCall = ts.createFunctionApply(ts.createIdentifier("_super"), actualThis, ts.createIdentifier("arguments")); + return ts.createLogicalOr(superCall, actualThis); + } + /** + * Visits a parameter declaration. + * + * @param node A ParameterDeclaration node. + */ + function visitParameter(node) { + if (node.dotDotDotToken) { + // rest parameters are elided + return undefined; + } + else if (ts.isBindingPattern(node.name)) { + // Binding patterns are converted into a generated name and are + // evaluated inside the function body. + return ts.setOriginalNode(ts.createParameter(ts.getGeneratedNameForNode(node), + /*initializer*/ undefined, + /*location*/ node), + /*original*/ node); + } + else if (node.initializer) { + // Initializers are elided + return ts.setOriginalNode(ts.createParameter(node.name, + /*initializer*/ undefined, + /*location*/ node), + /*original*/ node); + } + else { + return node; + } + } + /** + * Gets a value indicating whether we need to add default value assignments for a + * function-like node. + * + * @param node A function-like node. + */ + function shouldAddDefaultValueAssignments(node) { + return (node.transformFlags & 65536 /* ContainsDefaultValueAssignments */) !== 0; + } + /** + * Adds statements to the body of a function-like node if it contains parameters with + * binding patterns or initializers. + * + * @param statements The statements for the new function body. + * @param node A function-like node. + */ + function addDefaultValueAssignmentsIfNeeded(statements, node) { + if (!shouldAddDefaultValueAssignments(node)) { + return; + } + for (var _i = 0, _a = node.parameters; _i < _a.length; _i++) { + var parameter = _a[_i]; + var name_35 = parameter.name, initializer = parameter.initializer, dotDotDotToken = parameter.dotDotDotToken; + // A rest parameter cannot have a binding pattern or an initializer, + // so let's just ignore it. + if (dotDotDotToken) { + continue; } - else { - writeLine(); - emit(node.statement); + if (ts.isBindingPattern(name_35)) { + addDefaultValueAssignmentForBindingPattern(statements, parameter, name_35, initializer); } - if (convertedLoopState) { - convertedLoopState.allowedNonLabeledJumps = saveAllowedNonLabeledJumps; + else if (initializer) { + addDefaultValueAssignmentForInitializer(statements, parameter, name_35, initializer); } } - function copyLoopOutParameters(state, copyDirection, emitAsStatements) { - if (state.loopOutParameters) { - for (var _a = 0, _b = state.loopOutParameters; _a < _b.length; _a++) { - var outParam = _b[_a]; - if (copyDirection === 0 /* ToOriginal */) { - emitIdentifier(outParam.originalName); - write(" = " + outParam.outParamName); - } - else { - write(outParam.outParamName + " = "); - emitIdentifier(outParam.originalName); - } - if (emitAsStatements) { - write(";"); - writeLine(); - } - else { - write(", "); - } - } - } + } + /** + * Adds statements to the body of a function-like node for parameters with binding patterns + * + * @param statements The statements for the new function body. + * @param parameter The parameter for the function. + * @param name The name of the parameter. + * @param initializer The initializer for the parameter. + */ + function addDefaultValueAssignmentForBindingPattern(statements, parameter, name, initializer) { + var temp = ts.getGeneratedNameForNode(parameter); + // In cases where a binding pattern is simply '[]' or '{}', + // we usually don't want to emit a var declaration; however, in the presence + // of an initializer, we must emit that expression to preserve side effects. + if (name.elements.length > 0) { + statements.push(ts.setEmitFlags(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList(ts.flattenParameterDestructuring(context, parameter, temp, visitor))), 8388608 /* CustomPrologue */)); } - function emitConvertedLoopCall(loop, emitAsBlock) { - if (emitAsBlock) { - write(" {"); - writeLine(); - increaseIndent(); - } - // loop is considered simple if it does not have any return statements or break\continue that transfer control outside of the loop - // simple loops are emitted as just 'loop()'; - // NOTE: if loop uses only 'continue' it still will be emitted as simple loop - var isSimpleLoop = !(loop.state.nonLocalJumps & ~4 /* Continue */) && - !loop.state.labeledNonLocalBreaks && - !loop.state.labeledNonLocalContinues; - var loopResult = makeUniqueName("state"); - if (!isSimpleLoop) { - write("var " + loopResult + " = "); - } - write(loop.functionName + "(" + loop.paramList + ");"); - writeLine(); - copyLoopOutParameters(loop.state, 0 /* ToOriginal */, /*emitAsStatements*/ true); - if (!isSimpleLoop) { - // for non simple loops we need to store result returned from converted loop function and use it to do dispatching - // converted loop function can return: - // - object - used when body of the converted loop contains return statement. Property "value" of this object stores retuned value - // - string - used to dispatch jumps. "break" and "continue" are used to non-labeled jumps, other values are used to transfer control to - // different labels - writeLine(); - if (loop.state.nonLocalJumps & 8 /* Return */) { - write("if (typeof " + loopResult + " === \"object\") "); - if (convertedLoopState) { - // we are currently nested in another converted loop - return unwrapped result - write("return " + loopResult + ";"); - // propagate 'hasReturn' flag to outer loop - convertedLoopState.nonLocalJumps |= 8 /* Return */; - } - else { - // top level converted loop - return unwrapped value - write("return " + loopResult + ".value;"); + else if (initializer) { + statements.push(ts.setEmitFlags(ts.createStatement(ts.createAssignment(temp, ts.visitNode(initializer, visitor, ts.isExpression))), 8388608 /* CustomPrologue */)); + } + } + /** + * Adds statements to the body of a function-like node for parameters with initializers. + * + * @param statements The statements for the new function body. + * @param parameter The parameter for the function. + * @param name The name of the parameter. + * @param initializer The initializer for the parameter. + */ + function addDefaultValueAssignmentForInitializer(statements, parameter, name, initializer) { + initializer = ts.visitNode(initializer, visitor, ts.isExpression); + var statement = ts.createIf(ts.createStrictEquality(ts.getSynthesizedClone(name), ts.createVoidZero()), ts.setEmitFlags(ts.createBlock([ + ts.createStatement(ts.createAssignment(ts.setEmitFlags(ts.getMutableClone(name), 1536 /* NoSourceMap */), ts.setEmitFlags(initializer, 1536 /* NoSourceMap */ | ts.getEmitFlags(initializer)), + /*location*/ parameter)) + ], /*location*/ parameter), 32 /* SingleLine */ | 1024 /* NoTrailingSourceMap */ | 12288 /* NoTokenSourceMaps */), + /*elseStatement*/ undefined, + /*location*/ parameter); + statement.startsOnNewLine = true; + ts.setEmitFlags(statement, 12288 /* NoTokenSourceMaps */ | 1024 /* NoTrailingSourceMap */ | 8388608 /* CustomPrologue */); + statements.push(statement); + } + /** + * Gets a value indicating whether we need to add statements to handle a rest parameter. + * + * @param node A ParameterDeclaration node. + * @param inConstructorWithSynthesizedSuper A value indicating whether the parameter is + * part of a constructor declaration with a + * synthesized call to `super` + */ + function shouldAddRestParameter(node, inConstructorWithSynthesizedSuper) { + return node && node.dotDotDotToken && node.name.kind === 69 /* Identifier */ && !inConstructorWithSynthesizedSuper; + } + /** + * Adds statements to the body of a function-like node if it contains a rest parameter. + * + * @param statements The statements for the new function body. + * @param node A function-like node. + * @param inConstructorWithSynthesizedSuper A value indicating whether the parameter is + * part of a constructor declaration with a + * synthesized call to `super` + */ + function addRestParameterIfNeeded(statements, node, inConstructorWithSynthesizedSuper) { + var parameter = ts.lastOrUndefined(node.parameters); + if (!shouldAddRestParameter(parameter, inConstructorWithSynthesizedSuper)) { + return; + } + // `declarationName` is the name of the local declaration for the parameter. + var declarationName = ts.getMutableClone(parameter.name); + ts.setEmitFlags(declarationName, 1536 /* NoSourceMap */); + // `expressionName` is the name of the parameter used in expressions. + var expressionName = ts.getSynthesizedClone(parameter.name); + var restIndex = node.parameters.length - 1; + var temp = ts.createLoopVariable(); + // var param = []; + statements.push(ts.setEmitFlags(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(declarationName, + /*type*/ undefined, ts.createArrayLiteral([])) + ]), + /*location*/ parameter), 8388608 /* CustomPrologue */)); + // for (var _i = restIndex; _i < arguments.length; _i++) { + // param[_i - restIndex] = arguments[_i]; + // } + var forStatement = ts.createFor(ts.createVariableDeclarationList([ + ts.createVariableDeclaration(temp, /*type*/ undefined, ts.createLiteral(restIndex)) + ], /*location*/ parameter), ts.createLessThan(temp, ts.createPropertyAccess(ts.createIdentifier("arguments"), "length"), + /*location*/ parameter), ts.createPostfixIncrement(temp, /*location*/ parameter), ts.createBlock([ + ts.startOnNewLine(ts.createStatement(ts.createAssignment(ts.createElementAccess(expressionName, ts.createSubtract(temp, ts.createLiteral(restIndex))), ts.createElementAccess(ts.createIdentifier("arguments"), temp)), + /*location*/ parameter)) + ])); + ts.setEmitFlags(forStatement, 8388608 /* CustomPrologue */); + ts.startOnNewLine(forStatement); + statements.push(forStatement); + } + /** + * Adds a statement to capture the `this` of a function declaration if it is needed. + * + * @param statements The statements for the new function body. + * @param node A node. + */ + function addCaptureThisForNodeIfNeeded(statements, node) { + if (node.transformFlags & 16384 /* ContainsCapturedLexicalThis */ && node.kind !== 180 /* ArrowFunction */) { + captureThisForNode(statements, node, ts.createThis()); + } + } + function captureThisForNode(statements, node, initializer, originalStatement) { + enableSubstitutionsForCapturedThis(); + var captureThisStatement = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration("_this", + /*type*/ undefined, initializer) + ]), originalStatement); + ts.setEmitFlags(captureThisStatement, 49152 /* NoComments */ | 8388608 /* CustomPrologue */); + ts.setSourceMapRange(captureThisStatement, node); + statements.push(captureThisStatement); + } + /** + * Adds statements to the class body function for a class to define the members of the + * class. + * + * @param statements The statements for the class body function. + * @param node The ClassExpression or ClassDeclaration node. + */ + function addClassMembers(statements, node) { + for (var _i = 0, _a = node.members; _i < _a.length; _i++) { + var member = _a[_i]; + switch (member.kind) { + case 198 /* SemicolonClassElement */: + statements.push(transformSemicolonClassElementToStatement(member)); + break; + case 147 /* MethodDeclaration */: + statements.push(transformClassMethodDeclarationToStatement(getClassMemberPrefix(node, member), member)); + break; + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + var accessors = ts.getAllAccessorDeclarations(node.members, member); + if (member === accessors.firstAccessor) { + statements.push(transformAccessorsToStatement(getClassMemberPrefix(node, member), accessors)); } - writeLine(); - } - if (loop.state.nonLocalJumps & 2 /* Break */) { - write("if (" + loopResult + " === \"break\") break;"); - writeLine(); - } - // in case of labeled breaks emit code that either breaks to some known label inside outer loop or delegates jump decision to outer loop - emitDispatchTableForLabeledJumps(loopResult, loop.state, convertedLoopState); - } - if (emitAsBlock) { - writeLine(); - decreaseIndent(); - write("}"); - } - function emitDispatchTableForLabeledJumps(loopResultVariable, currentLoop, outerLoop) { - if (!currentLoop.labeledNonLocalBreaks && !currentLoop.labeledNonLocalContinues) { - return; - } - write("switch(" + loopResultVariable + ") {"); - increaseIndent(); - emitDispatchEntriesForLabeledJumps(currentLoop.labeledNonLocalBreaks, /*isBreak*/ true, loopResultVariable, outerLoop); - emitDispatchEntriesForLabeledJumps(currentLoop.labeledNonLocalContinues, /*isBreak*/ false, loopResultVariable, outerLoop); - decreaseIndent(); - writeLine(); - write("}"); + break; + case 148 /* Constructor */: + // Constructors are handled in visitClassExpression/visitClassDeclaration + break; + default: + ts.Debug.failBadSyntaxKind(node); + break; } - function emitDispatchEntriesForLabeledJumps(table, isBreak, loopResultVariable, outerLoop) { - if (!table) { - return; - } - for (var labelText in table) { - var labelMarker = table[labelText]; - writeLine(); - write("case \"" + labelMarker + "\": "); - // if there are no outer converted loop or outer label in question is located inside outer converted loop - // then emit labeled break\continue - // otherwise propagate pair 'label -> marker' to outer converted loop and emit 'return labelMarker' so outer loop can later decide what to do - if (!outerLoop || (outerLoop.labels && outerLoop.labels[labelText])) { - if (isBreak) { - write("break "); - } - else { - write("continue "); - } - write(labelText + ";"); - } - else { - setLabeledJump(outerLoop, isBreak, labelText, labelMarker); - write("return " + loopResultVariable + ";"); - } - } + } + } + /** + * Transforms a SemicolonClassElement into a statement for a class body function. + * + * @param member The SemicolonClassElement node. + */ + function transformSemicolonClassElementToStatement(member) { + return ts.createEmptyStatement(/*location*/ member); + } + /** + * Transforms a MethodDeclaration into a statement for a class body function. + * + * @param receiver The receiver for the member. + * @param member The MethodDeclaration node. + */ + function transformClassMethodDeclarationToStatement(receiver, member) { + var commentRange = ts.getCommentRange(member); + var sourceMapRange = ts.getSourceMapRange(member); + var func = transformFunctionLikeToExpression(member, /*location*/ member, /*name*/ undefined); + ts.setEmitFlags(func, 49152 /* NoComments */); + ts.setSourceMapRange(func, sourceMapRange); + var statement = ts.createStatement(ts.createAssignment(ts.createMemberAccessForPropertyName(receiver, ts.visitNode(member.name, visitor, ts.isPropertyName), + /*location*/ member.name), func), + /*location*/ member); + ts.setOriginalNode(statement, member); + ts.setCommentRange(statement, commentRange); + // The location for the statement is used to emit comments only. + // No source map should be emitted for this statement to align with the + // old emitter. + ts.setEmitFlags(statement, 1536 /* NoSourceMap */); + return statement; + } + /** + * Transforms a set of related of get/set accessors into a statement for a class body function. + * + * @param receiver The receiver for the member. + * @param accessors The set of related get/set accessors. + */ + function transformAccessorsToStatement(receiver, accessors) { + var statement = ts.createStatement(transformAccessorsToExpression(receiver, accessors, /*startsOnNewLine*/ false), + /*location*/ ts.getSourceMapRange(accessors.firstAccessor)); + // The location for the statement is used to emit source maps only. + // No comments should be emitted for this statement to align with the + // old emitter. + ts.setEmitFlags(statement, 49152 /* NoComments */); + return statement; + } + /** + * Transforms a set of related get/set accessors into an expression for either a class + * body function or an ObjectLiteralExpression with computed properties. + * + * @param receiver The receiver for the member. + */ + function transformAccessorsToExpression(receiver, _a, startsOnNewLine) { + var firstAccessor = _a.firstAccessor, getAccessor = _a.getAccessor, setAccessor = _a.setAccessor; + // To align with source maps in the old emitter, the receiver and property name + // arguments are both mapped contiguously to the accessor name. + var target = ts.getMutableClone(receiver); + ts.setEmitFlags(target, 49152 /* NoComments */ | 1024 /* NoTrailingSourceMap */); + ts.setSourceMapRange(target, firstAccessor.name); + var propertyName = ts.createExpressionForPropertyName(ts.visitNode(firstAccessor.name, visitor, ts.isPropertyName)); + ts.setEmitFlags(propertyName, 49152 /* NoComments */ | 512 /* NoLeadingSourceMap */); + ts.setSourceMapRange(propertyName, firstAccessor.name); + var properties = []; + if (getAccessor) { + var getterFunction = transformFunctionLikeToExpression(getAccessor, /*location*/ undefined, /*name*/ undefined); + ts.setSourceMapRange(getterFunction, ts.getSourceMapRange(getAccessor)); + var getter = ts.createPropertyAssignment("get", getterFunction); + ts.setCommentRange(getter, ts.getCommentRange(getAccessor)); + properties.push(getter); + } + if (setAccessor) { + var setterFunction = transformFunctionLikeToExpression(setAccessor, /*location*/ undefined, /*name*/ undefined); + ts.setSourceMapRange(setterFunction, ts.getSourceMapRange(setAccessor)); + var setter = ts.createPropertyAssignment("set", setterFunction); + ts.setCommentRange(setter, ts.getCommentRange(setAccessor)); + properties.push(setter); + } + properties.push(ts.createPropertyAssignment("enumerable", ts.createLiteral(true)), ts.createPropertyAssignment("configurable", ts.createLiteral(true))); + var call = ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Object"), "defineProperty"), + /*typeArguments*/ undefined, [ + target, + propertyName, + ts.createObjectLiteral(properties, /*location*/ undefined, /*multiLine*/ true) + ]); + if (startsOnNewLine) { + call.startsOnNewLine = true; + } + return call; + } + /** + * Visits an ArrowFunction and transforms it into a FunctionExpression. + * + * @param node An ArrowFunction node. + */ + function visitArrowFunction(node) { + if (node.transformFlags & 8192 /* ContainsLexicalThis */) { + enableSubstitutionsForCapturedThis(); + } + var func = transformFunctionLikeToExpression(node, /*location*/ node, /*name*/ undefined); + ts.setEmitFlags(func, 256 /* CapturesThis */); + return func; + } + /** + * Visits a FunctionExpression node. + * + * @param node a FunctionExpression node. + */ + function visitFunctionExpression(node) { + return transformFunctionLikeToExpression(node, /*location*/ node, node.name); + } + /** + * Visits a FunctionDeclaration node. + * + * @param node a FunctionDeclaration node. + */ + function visitFunctionDeclaration(node) { + return ts.setOriginalNode(ts.createFunctionDeclaration( + /*decorators*/ undefined, node.modifiers, node.asteriskToken, node.name, + /*typeParameters*/ undefined, ts.visitNodes(node.parameters, visitor, ts.isParameter), + /*type*/ undefined, transformFunctionBody(node), + /*location*/ node), + /*original*/ node); + } + /** + * Transforms a function-like node into a FunctionExpression. + * + * @param node The function-like node to transform. + * @param location The source-map location for the new FunctionExpression. + * @param name The name of the new FunctionExpression. + */ + function transformFunctionLikeToExpression(node, location, name) { + var savedContainingNonArrowFunction = enclosingNonArrowFunction; + if (node.kind !== 180 /* ArrowFunction */) { + enclosingNonArrowFunction = node; + } + var expression = ts.setOriginalNode(ts.createFunctionExpression(node.asteriskToken, name, + /*typeParameters*/ undefined, ts.visitNodes(node.parameters, visitor, ts.isParameter), + /*type*/ undefined, saveStateAndInvoke(node, transformFunctionBody), location), + /*original*/ node); + enclosingNonArrowFunction = savedContainingNonArrowFunction; + return expression; + } + /** + * Transforms the body of a function-like node. + * + * @param node A function-like node. + */ + function transformFunctionBody(node) { + var multiLine = false; // indicates whether the block *must* be emitted as multiple lines + var singleLine = false; // indicates whether the block *may* be emitted as a single line + var statementsLocation; + var closeBraceLocation; + var statements = []; + var body = node.body; + var statementOffset; + startLexicalEnvironment(); + if (ts.isBlock(body)) { + // ensureUseStrict is false because no new prologue-directive should be added. + // addPrologueDirectives will simply put already-existing directives at the beginning of the target statement-array + statementOffset = ts.addPrologueDirectives(statements, body.statements, /*ensureUseStrict*/ false, visitor); + } + addCaptureThisForNodeIfNeeded(statements, node); + addDefaultValueAssignmentsIfNeeded(statements, node); + addRestParameterIfNeeded(statements, node, /*inConstructorWithSynthesizedSuper*/ false); + // If we added any generated statements, this must be a multi-line block. + if (!multiLine && statements.length > 0) { + multiLine = true; + } + if (ts.isBlock(body)) { + statementsLocation = body.statements; + ts.addRange(statements, ts.visitNodes(body.statements, visitor, ts.isStatement, statementOffset)); + // If the original body was a multi-line block, this must be a multi-line block. + if (!multiLine && body.multiLine) { + multiLine = true; } } - function emitForStatement(node) { - emitLoop(node, emitForStatementWorker); - } - function emitForStatementWorker(node, loop) { - var endPos = emitToken(86 /* ForKeyword */, node.pos); - write(" "); - endPos = emitToken(17 /* OpenParenToken */, endPos); - if (node.initializer && node.initializer.kind === 219 /* VariableDeclarationList */) { - var variableDeclarationList = node.initializer; - var startIsEmitted = tryEmitStartOfVariableDeclarationList(variableDeclarationList); - if (startIsEmitted) { - emitCommaList(variableDeclarationList.declarations); + else { + ts.Debug.assert(node.kind === 180 /* ArrowFunction */); + // To align with the old emitter, we use a synthetic end position on the location + // for the statement list we synthesize when we down-level an arrow function with + // an expression function body. This prevents both comments and source maps from + // being emitted for the end position only. + statementsLocation = ts.moveRangeEnd(body, -1); + var equalsGreaterThanToken = node.equalsGreaterThanToken; + if (!ts.nodeIsSynthesized(equalsGreaterThanToken) && !ts.nodeIsSynthesized(body)) { + if (ts.rangeEndIsOnSameLineAsRangeStart(equalsGreaterThanToken, body, currentSourceFile)) { + singleLine = true; } else { - emitVariableDeclarationListSkippingUninitializedEntries(variableDeclarationList); + multiLine = true; } } - else if (node.initializer) { - emit(node.initializer); - } - write(";"); - emitOptional(" ", node.condition); - write(";"); - emitOptional(" ", node.incrementor); - write(")"); - if (loop) { - emitConvertedLoopCall(loop, /*emitAsBlock*/ true); - } - else { - emitNormalLoopBody(node, /*emitAsEmbeddedStatement*/ true); - } + var expression = ts.visitNode(body, visitor, ts.isExpression); + var returnStatement = ts.createReturn(expression, /*location*/ body); + ts.setEmitFlags(returnStatement, 12288 /* NoTokenSourceMaps */ | 1024 /* NoTrailingSourceMap */ | 32768 /* NoTrailingComments */); + statements.push(returnStatement); + // To align with the source map emit for the old emitter, we set a custom + // source map location for the close brace. + closeBraceLocation = body; } - function emitForInOrForOfStatement(node) { - if (languageVersion < 2 /* ES6 */ && node.kind === 208 /* ForOfStatement */) { - emitLoop(node, emitDownLevelForOfStatementWorker); - } - else { - emitLoop(node, emitForInOrForOfStatementWorker); - } + var lexicalEnvironment = endLexicalEnvironment(); + ts.addRange(statements, lexicalEnvironment); + // If we added any final generated statements, this must be a multi-line block + if (!multiLine && lexicalEnvironment && lexicalEnvironment.length) { + multiLine = true; } - function emitForInOrForOfStatementWorker(node, loop) { - var endPos = emitToken(86 /* ForKeyword */, node.pos); - write(" "); - endPos = emitToken(17 /* OpenParenToken */, endPos); - if (node.initializer.kind === 219 /* VariableDeclarationList */) { - var variableDeclarationList = node.initializer; - if (variableDeclarationList.declarations.length >= 1) { - tryEmitStartOfVariableDeclarationList(variableDeclarationList); - emit(variableDeclarationList.declarations[0]); - } - } - else { - emit(node.initializer); - } - if (node.kind === 207 /* ForInStatement */) { - write(" in "); - } - else { - write(" of "); - } - emit(node.expression); - emitToken(18 /* CloseParenToken */, node.expression.end); - if (loop) { - emitConvertedLoopCall(loop, /*emitAsBlock*/ true); - } - else { - emitNormalLoopBody(node, /*emitAsEmbeddedStatement*/ true); + var block = ts.createBlock(ts.createNodeArray(statements, statementsLocation), node.body, multiLine); + if (!multiLine && singleLine) { + ts.setEmitFlags(block, 32 /* SingleLine */); + } + if (closeBraceLocation) { + ts.setTokenSourceMapRange(block, 16 /* CloseBraceToken */, closeBraceLocation); + } + ts.setOriginalNode(block, node.body); + return block; + } + /** + * Visits an ExpressionStatement that contains a destructuring assignment. + * + * @param node An ExpressionStatement node. + */ + function visitExpressionStatement(node) { + // If we are here it is most likely because our expression is a destructuring assignment. + switch (node.expression.kind) { + case 178 /* ParenthesizedExpression */: + return ts.updateStatement(node, visitParenthesizedExpression(node.expression, /*needsDestructuringValue*/ false)); + case 187 /* BinaryExpression */: + return ts.updateStatement(node, visitBinaryExpression(node.expression, /*needsDestructuringValue*/ false)); + } + return ts.visitEachChild(node, visitor, context); + } + /** + * Visits a ParenthesizedExpression that may contain a destructuring assignment. + * + * @param node A ParenthesizedExpression node. + * @param needsDestructuringValue A value indicating whether we need to hold onto the rhs + * of a destructuring assignment. + */ + function visitParenthesizedExpression(node, needsDestructuringValue) { + // If we are here it is most likely because our expression is a destructuring assignment. + if (needsDestructuringValue) { + switch (node.expression.kind) { + case 178 /* ParenthesizedExpression */: + return ts.createParen(visitParenthesizedExpression(node.expression, /*needsDestructuringValue*/ true), + /*location*/ node); + case 187 /* BinaryExpression */: + return ts.createParen(visitBinaryExpression(node.expression, /*needsDestructuringValue*/ true), + /*location*/ node); } } - function emitDownLevelForOfStatementWorker(node, loop) { - // The following ES6 code: - // - // for (let v of expr) { } - // - // should be emitted as - // - // for (let _i = 0, _a = expr; _i < _a.length; _i++) { - // let v = _a[_i]; - // } - // - // where _a and _i are temps emitted to capture the RHS and the counter, - // respectively. - // When the left hand side is an expression instead of a let declaration, - // the "let v" is not emitted. - // When the left hand side is a let/const, the v is renamed if there is - // another v in scope. - // Note that all assignments to the LHS are emitted in the body, including - // all destructuring. - // Note also that because an extra statement is needed to assign to the LHS, - // for-of bodies are always emitted as blocks. - var endPos = emitToken(86 /* ForKeyword */, node.pos); - write(" "); - endPos = emitToken(17 /* OpenParenToken */, endPos); - // Do not emit the LHS let declaration yet, because it might contain destructuring. - // Do not call recordTempDeclaration because we are declaring the temps - // right here. Recording means they will be declared later. - // In the case where the user wrote an identifier as the RHS, like this: - // - // for (let v of arr) { } - // - // we can't reuse 'arr' because it might be modified within the body of the loop. - var counter = createTempVariable(268435456 /* _i */); - var rhsReference = ts.createSynthesizedNode(69 /* Identifier */); - rhsReference.text = node.expression.kind === 69 /* Identifier */ ? - makeUniqueName(node.expression.text) : - makeTempVariableName(0 /* Auto */); - // This is the let keyword for the counter and rhsReference. The let keyword for - // the LHS will be emitted inside the body. - emitStart(node.expression); - write("var "); - // _i = 0 - emitNodeWithoutSourceMap(counter); - write(" = 0"); - emitEnd(node.expression); - // , _a = expr - write(", "); - emitStart(node.expression); - emitNodeWithoutSourceMap(rhsReference); - write(" = "); - emitNodeWithoutSourceMap(node.expression); - emitEnd(node.expression); - write("; "); - // _i < _a.length; - emitStart(node.expression); - emitNodeWithoutSourceMap(counter); - write(" < "); - emitNodeWithCommentsAndWithoutSourcemap(rhsReference); - write(".length"); - emitEnd(node.expression); - write("; "); - // _i++) - emitStart(node.expression); - emitNodeWithoutSourceMap(counter); - write("++"); - emitEnd(node.expression); - emitToken(18 /* CloseParenToken */, node.expression.end); - // Body - write(" {"); - writeLine(); - increaseIndent(); - // Initialize LHS - // let v = _a[_i]; - var rhsIterationValue = createElementAccessExpression(rhsReference, counter); - emitStart(node.initializer); - if (node.initializer.kind === 219 /* VariableDeclarationList */) { - write("var "); - var variableDeclarationList = node.initializer; - if (variableDeclarationList.declarations.length > 0) { - var declaration = variableDeclarationList.declarations[0]; - if (ts.isBindingPattern(declaration.name)) { - // This works whether the declaration is a var, let, or const. - // It will use rhsIterationValue _a[_i] as the initializer. - emitDestructuring(declaration, /*isAssignmentExpressionStatement*/ false, rhsIterationValue); + return ts.visitEachChild(node, visitor, context); + } + /** + * Visits a BinaryExpression that contains a destructuring assignment. + * + * @param node A BinaryExpression node. + * @param needsDestructuringValue A value indicating whether we need to hold onto the rhs + * of a destructuring assignment. + */ + function visitBinaryExpression(node, needsDestructuringValue) { + // If we are here it is because this is a destructuring assignment. + ts.Debug.assert(ts.isDestructuringAssignment(node)); + return ts.flattenDestructuringAssignment(context, node, needsDestructuringValue, hoistVariableDeclaration, visitor); + } + function visitVariableStatement(node) { + if (convertedLoopState && (ts.getCombinedNodeFlags(node.declarationList) & 3 /* BlockScoped */) == 0) { + // we are inside a converted loop - hoist variable declarations + var assignments = void 0; + for (var _i = 0, _a = node.declarationList.declarations; _i < _a.length; _i++) { + var decl = _a[_i]; + hoistVariableDeclarationDeclaredInConvertedLoop(convertedLoopState, decl); + if (decl.initializer) { + var assignment = void 0; + if (ts.isBindingPattern(decl.name)) { + assignment = ts.flattenVariableDestructuringToExpression(context, decl, hoistVariableDeclaration, /*nameSubstitution*/ undefined, visitor); } else { - // The following call does not include the initializer, so we have - // to emit it separately. - emitNodeWithCommentsAndWithoutSourcemap(declaration); - write(" = "); - emitNodeWithoutSourceMap(rhsIterationValue); + assignment = ts.createBinary(decl.name, 56 /* EqualsToken */, decl.initializer); } - } - else { - // It's an empty declaration list. This can only happen in an error case, if the user wrote - // for (let of []) {} - emitNodeWithoutSourceMap(createTempVariable(0 /* Auto */)); - write(" = "); - emitNodeWithoutSourceMap(rhsIterationValue); - } - } - else { - // Initializer is an expression. Emit the expression in the body, so that it's - // evaluated on every iteration. - var assignmentExpression = createBinaryExpression(node.initializer, 56 /* EqualsToken */, rhsIterationValue, /*startsOnNewLine*/ false); - if (node.initializer.kind === 170 /* ArrayLiteralExpression */ || node.initializer.kind === 171 /* ObjectLiteralExpression */) { - // This is a destructuring pattern, so call emitDestructuring instead of emit. Calling emit will not work, because it will cause - // the BinaryExpression to be passed in instead of the expression statement, which will cause emitDestructuring to crash. - emitDestructuring(assignmentExpression, /*isAssignmentExpressionStatement*/ true, /*value*/ undefined); - } - else { - emitNodeWithCommentsAndWithoutSourcemap(assignmentExpression); + (assignments || (assignments = [])).push(assignment); } } - emitEnd(node.initializer); - write(";"); - if (loop) { - writeLine(); - emitConvertedLoopCall(loop, /*emitAsBlock*/ false); + if (assignments) { + return ts.createStatement(ts.reduceLeft(assignments, function (acc, v) { return ts.createBinary(v, 24 /* CommaToken */, acc); }), node); } else { - emitNormalLoopBody(node, /*emitAsEmbeddedStatement*/ false); + // none of declarations has initializer - the entire variable statement can be deleted + return undefined; } - writeLine(); - decreaseIndent(); - write("}"); } - function emitBreakOrContinueStatement(node) { - if (convertedLoopState) { - // check if we can emit break\continue as is - // it is possible if either - // - break\continue is statement labeled and label is located inside the converted loop - // - break\continue is non-labeled and located in non-converted loop\switch statement - var jump = node.kind === 210 /* BreakStatement */ ? 2 /* Break */ : 4 /* Continue */; - var canUseBreakOrContinue = (node.label && convertedLoopState.labels && convertedLoopState.labels[node.label.text]) || - (!node.label && (convertedLoopState.allowedNonLabeledJumps & jump)); - if (!canUseBreakOrContinue) { - write("return "); - // explicit exit from loop -> copy out parameters - copyLoopOutParameters(convertedLoopState, 1 /* ToOutParameter */, /*emitAsStatements*/ false); - if (!node.label) { - if (node.kind === 210 /* BreakStatement */) { - convertedLoopState.nonLocalJumps |= 2 /* Break */; - write("\"break\";"); - } - else { - convertedLoopState.nonLocalJumps |= 4 /* Continue */; - // note: return value is emitted only to simplify debugging, call to converted loop body does not do any dispatching on it. - write("\"continue\";"); - } - } - else { - var labelMarker = void 0; - if (node.kind === 210 /* BreakStatement */) { - labelMarker = "break-" + node.label.text; - setLabeledJump(convertedLoopState, /*isBreak*/ true, node.label.text, labelMarker); - } - else { - labelMarker = "continue-" + node.label.text; - setLabeledJump(convertedLoopState, /*isBreak*/ false, node.label.text, labelMarker); - } - write("\"" + labelMarker + "\";"); - } - return; - } - } - emitToken(node.kind === 210 /* BreakStatement */ ? 70 /* BreakKeyword */ : 75 /* ContinueKeyword */, node.pos); - emitOptional(" ", node.label); - write(";"); + return ts.visitEachChild(node, visitor, context); + } + /** + * Visits a VariableDeclarationList that is block scoped (e.g. `let` or `const`). + * + * @param node A VariableDeclarationList node. + */ + function visitVariableDeclarationList(node) { + if (node.flags & 3 /* BlockScoped */) { + enableSubstitutionsForBlockScopedBindings(); + } + var declarations = ts.flatten(ts.map(node.declarations, node.flags & 1 /* Let */ + ? visitVariableDeclarationInLetDeclarationList + : visitVariableDeclaration)); + var declarationList = ts.createVariableDeclarationList(declarations, /*location*/ node); + ts.setOriginalNode(declarationList, node); + ts.setCommentRange(declarationList, node); + if (node.transformFlags & 2097152 /* ContainsBindingPattern */ + && (ts.isBindingPattern(node.declarations[0].name) + || ts.isBindingPattern(ts.lastOrUndefined(node.declarations).name))) { + // If the first or last declaration is a binding pattern, we need to modify + // the source map range for the declaration list. + var firstDeclaration = ts.firstOrUndefined(declarations); + var lastDeclaration = ts.lastOrUndefined(declarations); + ts.setSourceMapRange(declarationList, ts.createRange(firstDeclaration.pos, lastDeclaration.end)); + } + return declarationList; + } + /** + * Gets a value indicating whether we should emit an explicit initializer for a variable + * declaration in a `let` declaration list. + * + * @param node A VariableDeclaration node. + */ + function shouldEmitExplicitInitializerForLetDeclaration(node) { + // Nested let bindings might need to be initialized explicitly to preserve + // ES6 semantic: + // + // { let x = 1; } + // { let x; } // x here should be undefined. not 1 + // + // Top level bindings never collide with anything and thus don't require + // explicit initialization. As for nested let bindings there are two cases: + // + // - Nested let bindings that were not renamed definitely should be + // initialized explicitly: + // + // { let x = 1; } + // { let x; if (some-condition) { x = 1}; if (x) { /*1*/ } } + // + // Without explicit initialization code in /*1*/ can be executed even if + // some-condition is evaluated to false. + // + // - Renaming introduces fresh name that should not collide with any + // existing names, however renamed bindings sometimes also should be + // explicitly initialized. One particular case: non-captured binding + // declared inside loop body (but not in loop initializer): + // + // let x; + // for (;;) { + // let x; + // } + // + // In downlevel codegen inner 'x' will be renamed so it won't collide + // with outer 'x' however it will should be reset on every iteration as + // if it was declared anew. + // + // * Why non-captured binding? + // - Because if loop contains block scoped binding captured in some + // function then loop body will be rewritten to have a fresh scope + // on every iteration so everything will just work. + // + // * Why loop initializer is excluded? + // - Since we've introduced a fresh name it already will be undefined. + var flags = resolver.getNodeCheckFlags(node); + var isCapturedInFunction = flags & 131072 /* CapturedBlockScopedBinding */; + var isDeclaredInLoop = flags & 262144 /* BlockScopedBindingInLoop */; + var emittedAsTopLevel = ts.isBlockScopedContainerTopLevel(enclosingBlockScopeContainer) + || (isCapturedInFunction + && isDeclaredInLoop + && ts.isBlock(enclosingBlockScopeContainer) + && ts.isIterationStatement(enclosingBlockScopeContainerParent, /*lookInLabeledStatements*/ false)); + var emitExplicitInitializer = !emittedAsTopLevel + && enclosingBlockScopeContainer.kind !== 207 /* ForInStatement */ + && enclosingBlockScopeContainer.kind !== 208 /* ForOfStatement */ + && (!resolver.isDeclarationWithCollidingName(node) + || (isDeclaredInLoop + && !isCapturedInFunction + && !ts.isIterationStatement(enclosingBlockScopeContainer, /*lookInLabeledStatements*/ false))); + return emitExplicitInitializer; + } + /** + * Visits a VariableDeclaration in a `let` declaration list. + * + * @param node A VariableDeclaration node. + */ + function visitVariableDeclarationInLetDeclarationList(node) { + // For binding pattern names that lack initializers there is no point to emit + // explicit initializer since downlevel codegen for destructuring will fail + // in the absence of initializer so all binding elements will say uninitialized + var name = node.name; + if (ts.isBindingPattern(name)) { + return visitVariableDeclaration(node); } - function emitReturnStatement(node) { - if (convertedLoopState) { - convertedLoopState.nonLocalJumps |= 8 /* Return */; - write("return { value: "); - if (node.expression) { - emit(node.expression); - } - else { - write("void 0"); - } - write(" };"); - return; - } - emitToken(94 /* ReturnKeyword */, node.pos); - emitOptional(" ", node.expression); - write(";"); + if (!node.initializer && shouldEmitExplicitInitializerForLetDeclaration(node)) { + var clone_5 = ts.getMutableClone(node); + clone_5.initializer = ts.createVoidZero(); + return clone_5; } - function emitWithStatement(node) { - write("with ("); - emit(node.expression); - write(")"); - emitEmbeddedStatement(node.statement); + return ts.visitEachChild(node, visitor, context); + } + /** + * Visits a VariableDeclaration node with a binding pattern. + * + * @param node A VariableDeclaration node. + */ + function visitVariableDeclaration(node) { + // If we are here it is because the name contains a binding pattern. + if (ts.isBindingPattern(node.name)) { + var recordTempVariablesInLine = !enclosingVariableStatement + || !ts.hasModifier(enclosingVariableStatement, 1 /* Export */); + return ts.flattenVariableDestructuring(context, node, /*value*/ undefined, visitor, recordTempVariablesInLine ? undefined : hoistVariableDeclaration); } - function emitSwitchStatement(node) { - var endPos = emitToken(96 /* SwitchKeyword */, node.pos); - write(" "); - emitToken(17 /* OpenParenToken */, endPos); - emit(node.expression); - endPos = emitToken(18 /* CloseParenToken */, node.expression.end); - write(" "); - var saveAllowedNonLabeledJumps; - if (convertedLoopState) { - saveAllowedNonLabeledJumps = convertedLoopState.allowedNonLabeledJumps; - // for switch statement allow only non-labeled break - convertedLoopState.allowedNonLabeledJumps |= 2 /* Break */; - } - emitCaseBlock(node.caseBlock, endPos); - if (convertedLoopState) { - convertedLoopState.allowedNonLabeledJumps = saveAllowedNonLabeledJumps; + return ts.visitEachChild(node, visitor, context); + } + function visitLabeledStatement(node) { + if (convertedLoopState) { + if (!convertedLoopState.labels) { + convertedLoopState.labels = ts.createMap(); } + convertedLoopState.labels[node.label.text] = node.label.text; } - function emitCaseBlock(node, startPos) { - emitToken(15 /* OpenBraceToken */, startPos); - increaseIndent(); - emitLines(node.clauses); - decreaseIndent(); - writeLine(); - emitToken(16 /* CloseBraceToken */, node.clauses.end); - } - function nodeStartPositionsAreOnSameLine(node1, node2) { - return ts.getLineOfLocalPositionFromLineMap(currentLineMap, ts.skipTrivia(currentText, node1.pos)) === - ts.getLineOfLocalPositionFromLineMap(currentLineMap, ts.skipTrivia(currentText, node2.pos)); + var result; + if (ts.isIterationStatement(node.statement, /*lookInLabeledStatements*/ false) && shouldConvertIterationStatementBody(node.statement)) { + result = ts.visitNodes(ts.createNodeArray([node.statement]), visitor, ts.isStatement); } - function nodeEndPositionsAreOnSameLine(node1, node2) { - return ts.getLineOfLocalPositionFromLineMap(currentLineMap, node1.end) === - ts.getLineOfLocalPositionFromLineMap(currentLineMap, node2.end); + else { + result = ts.visitEachChild(node, visitor, context); } - function nodeEndIsOnSameLineAsNodeStart(node1, node2) { - return ts.getLineOfLocalPositionFromLineMap(currentLineMap, node1.end) === - ts.getLineOfLocalPositionFromLineMap(currentLineMap, ts.skipTrivia(currentText, node2.pos)); + if (convertedLoopState) { + convertedLoopState.labels[node.label.text] = undefined; } - function emitCaseOrDefaultClause(node) { - if (node.kind === 249 /* CaseClause */) { - write("case "); - emit(node.expression); - write(":"); + return result; + } + function visitDoStatement(node) { + return convertIterationStatementBodyIfNecessary(node); + } + function visitWhileStatement(node) { + return convertIterationStatementBodyIfNecessary(node); + } + function visitForStatement(node) { + return convertIterationStatementBodyIfNecessary(node); + } + function visitForInStatement(node) { + return convertIterationStatementBodyIfNecessary(node); + } + /** + * Visits a ForOfStatement and converts it into a compatible ForStatement. + * + * @param node A ForOfStatement. + */ + function visitForOfStatement(node) { + return convertIterationStatementBodyIfNecessary(node, convertForOfToFor); + } + function convertForOfToFor(node, convertedLoopBodyStatements) { + // The following ES6 code: + // + // for (let v of expr) { } + // + // should be emitted as + // + // for (var _i = 0, _a = expr; _i < _a.length; _i++) { + // var v = _a[_i]; + // } + // + // where _a and _i are temps emitted to capture the RHS and the counter, + // respectively. + // When the left hand side is an expression instead of a let declaration, + // the "let v" is not emitted. + // When the left hand side is a let/const, the v is renamed if there is + // another v in scope. + // Note that all assignments to the LHS are emitted in the body, including + // all destructuring. + // Note also that because an extra statement is needed to assign to the LHS, + // for-of bodies are always emitted as blocks. + var expression = ts.visitNode(node.expression, visitor, ts.isExpression); + var initializer = node.initializer; + var statements = []; + // In the case where the user wrote an identifier as the RHS, like this: + // + // for (let v of arr) { } + // + // we don't want to emit a temporary variable for the RHS, just use it directly. + var counter = ts.createLoopVariable(); + var rhsReference = expression.kind === 69 /* Identifier */ + ? ts.createUniqueName(expression.text) + : ts.createTempVariable(/*recordTempVariable*/ undefined); + // Initialize LHS + // var v = _a[_i]; + if (ts.isVariableDeclarationList(initializer)) { + if (initializer.flags & 3 /* BlockScoped */) { + enableSubstitutionsForBlockScopedBindings(); + } + var firstOriginalDeclaration = ts.firstOrUndefined(initializer.declarations); + if (firstOriginalDeclaration && ts.isBindingPattern(firstOriginalDeclaration.name)) { + // This works whether the declaration is a var, let, or const. + // It will use rhsIterationValue _a[_i] as the initializer. + var declarations = ts.flattenVariableDestructuring(context, firstOriginalDeclaration, ts.createElementAccess(rhsReference, counter), visitor); + var declarationList = ts.createVariableDeclarationList(declarations, /*location*/ initializer); + ts.setOriginalNode(declarationList, initializer); + // Adjust the source map range for the first declaration to align with the old + // emitter. + var firstDeclaration = declarations[0]; + var lastDeclaration = ts.lastOrUndefined(declarations); + ts.setSourceMapRange(declarationList, ts.createRange(firstDeclaration.pos, lastDeclaration.end)); + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, declarationList)); } else { - write("default:"); + // The following call does not include the initializer, so we have + // to emit it separately. + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(firstOriginalDeclaration ? firstOriginalDeclaration.name : ts.createTempVariable(/*recordTempVariable*/ undefined), + /*type*/ undefined, ts.createElementAccess(rhsReference, counter)) + ], /*location*/ ts.moveRangePos(initializer, -1)), + /*location*/ ts.moveRangeEnd(initializer, -1))); } - if (node.statements.length === 1 && nodeStartPositionsAreOnSameLine(node, node.statements[0])) { - write(" "); - emit(node.statements[0]); + } + else { + // Initializer is an expression. Emit the expression in the body, so that it's + // evaluated on every iteration. + var assignment = ts.createAssignment(initializer, ts.createElementAccess(rhsReference, counter)); + if (ts.isDestructuringAssignment(assignment)) { + // This is a destructuring pattern, so we flatten the destructuring instead. + statements.push(ts.createStatement(ts.flattenDestructuringAssignment(context, assignment, + /*needsValue*/ false, hoistVariableDeclaration, visitor))); } else { - increaseIndent(); - emitLines(node.statements); - decreaseIndent(); + // Currently there is not way to check that assignment is binary expression of destructing assignment + // so we have to cast never type to binaryExpression + assignment.end = initializer.end; + statements.push(ts.createStatement(assignment, /*location*/ ts.moveRangeEnd(initializer, -1))); } } - function emitThrowStatement(node) { - write("throw "); - emit(node.expression); - write(";"); + var bodyLocation; + var statementsLocation; + if (convertedLoopBodyStatements) { + ts.addRange(statements, convertedLoopBodyStatements); } - function emitTryStatement(node) { - write("try "); - emit(node.tryBlock); - emit(node.catchClause); - if (node.finallyBlock) { - writeLine(); - write("finally "); - emit(node.finallyBlock); + else { + var statement = ts.visitNode(node.statement, visitor, ts.isStatement); + if (ts.isBlock(statement)) { + ts.addRange(statements, statement.statements); + bodyLocation = statement; + statementsLocation = statement.statements; + } + else { + statements.push(statement); + } + } + // The old emitter does not emit source maps for the expression + ts.setEmitFlags(expression, 1536 /* NoSourceMap */ | ts.getEmitFlags(expression)); + // The old emitter does not emit source maps for the block. + // We add the location to preserve comments. + var body = ts.createBlock(ts.createNodeArray(statements, /*location*/ statementsLocation), + /*location*/ bodyLocation); + ts.setEmitFlags(body, 1536 /* NoSourceMap */ | 12288 /* NoTokenSourceMaps */); + var forStatement = ts.createFor(ts.createVariableDeclarationList([ + ts.createVariableDeclaration(counter, /*type*/ undefined, ts.createLiteral(0), /*location*/ ts.moveRangePos(node.expression, -1)), + ts.createVariableDeclaration(rhsReference, /*type*/ undefined, expression, /*location*/ node.expression) + ], /*location*/ node.expression), ts.createLessThan(counter, ts.createPropertyAccess(rhsReference, "length"), + /*location*/ node.expression), ts.createPostfixIncrement(counter, /*location*/ node.expression), body, + /*location*/ node); + // Disable trailing source maps for the OpenParenToken to align source map emit with the old emitter. + ts.setEmitFlags(forStatement, 8192 /* NoTokenTrailingSourceMaps */); + return forStatement; + } + /** + * Visits an ObjectLiteralExpression with computed propety names. + * + * @param node An ObjectLiteralExpression node. + */ + function visitObjectLiteralExpression(node) { + // We are here because a ComputedPropertyName was used somewhere in the expression. + var properties = node.properties; + var numProperties = properties.length; + // Find the first computed property. + // Everything until that point can be emitted as part of the initial object literal. + var numInitialProperties = numProperties; + for (var i = 0; i < numProperties; i++) { + var property = properties[i]; + if (property.transformFlags & 4194304 /* ContainsYield */ + || property.name.kind === 140 /* ComputedPropertyName */) { + numInitialProperties = i; + break; } } - function emitCatchClause(node) { - writeLine(); - var endPos = emitToken(72 /* CatchKeyword */, node.pos); - write(" "); - emitToken(17 /* OpenParenToken */, endPos); - emit(node.variableDeclaration); - emitToken(18 /* CloseParenToken */, node.variableDeclaration ? node.variableDeclaration.end : endPos); - write(" "); - emitBlock(node.block); - } - function emitDebuggerStatement(node) { - emitToken(76 /* DebuggerKeyword */, node.pos); - write(";"); + ts.Debug.assert(numInitialProperties !== numProperties); + // For computed properties, we need to create a unique handle to the object + // literal so we can modify it without risking internal assignments tainting the object. + var temp = ts.createTempVariable(hoistVariableDeclaration); + // Write out the first non-computed properties, then emit the rest through indexing on the temp variable. + var expressions = []; + var assignment = ts.createAssignment(temp, ts.setEmitFlags(ts.createObjectLiteral(ts.visitNodes(properties, visitor, ts.isObjectLiteralElementLike, 0, numInitialProperties), + /*location*/ undefined, node.multiLine), 524288 /* Indented */)); + if (node.multiLine) { + assignment.startsOnNewLine = true; } - function emitLabelAndColon(node) { - emit(node.label); - write(": "); + expressions.push(assignment); + addObjectLiteralMembers(expressions, node, temp, numInitialProperties); + // We need to clone the temporary identifier so that we can write it on a + // new line + expressions.push(node.multiLine ? ts.startOnNewLine(ts.getMutableClone(temp)) : temp); + return ts.inlineExpressions(expressions); + } + function shouldConvertIterationStatementBody(node) { + return (resolver.getNodeCheckFlags(node) & 65536 /* LoopWithCapturedBlockScopedBinding */) !== 0; + } + /** + * Records constituents of name for the given variable to be hoisted in the outer scope. + */ + function hoistVariableDeclarationDeclaredInConvertedLoop(state, node) { + if (!state.hoistedLocalVariables) { + state.hoistedLocalVariables = []; } - function emitLabeledStatement(node) { - if (!ts.isIterationStatement(node.statement, /* lookInLabeledStatements */ false) || !shouldConvertLoopBody(node.statement)) { - emitLabelAndColon(node); + visit(node.name); + function visit(node) { + if (node.kind === 69 /* Identifier */) { + state.hoistedLocalVariables.push(node); } - if (convertedLoopState) { - if (!convertedLoopState.labels) { - convertedLoopState.labels = ts.createMap(); + else { + for (var _i = 0, _a = node.elements; _i < _a.length; _i++) { + var element = _a[_i]; + if (!ts.isOmittedExpression(element)) { + visit(element.name); + } } - convertedLoopState.labels[node.label.text] = node.label.text; } - emit(node.statement); + } + } + function convertIterationStatementBodyIfNecessary(node, convert) { + if (!shouldConvertIterationStatementBody(node)) { + var saveAllowedNonLabeledJumps = void 0; if (convertedLoopState) { - convertedLoopState.labels[node.label.text] = undefined; + // we get here if we are trying to emit normal loop loop inside converted loop + // set allowedNonLabeledJumps to Break | Continue to mark that break\continue inside the loop should be emitted as is + saveAllowedNonLabeledJumps = convertedLoopState.allowedNonLabeledJumps; + convertedLoopState.allowedNonLabeledJumps = 2 /* Break */ | 4 /* Continue */; } - } - function getContainingModule(node) { - do { - node = node.parent; - } while (node && node.kind !== 225 /* ModuleDeclaration */); - return node; - } - function emitContainingModuleName(node) { - var container = getContainingModule(node); - write(container ? getGeneratedNameForNode(container) : "exports"); - } - function emitModuleMemberName(node) { - emitStart(node.name); - if (ts.getCombinedNodeFlags(node) & 1 /* Export */) { - var container = getContainingModule(node); - if (container) { - write(getGeneratedNameForNode(container)); - write("."); - } - else if (modulekind !== ts.ModuleKind.ES6 && modulekind !== ts.ModuleKind.System) { - write("exports."); - } + var result = convert ? convert(node, /*convertedLoopBodyStatements*/ undefined) : ts.visitEachChild(node, visitor, context); + if (convertedLoopState) { + convertedLoopState.allowedNonLabeledJumps = saveAllowedNonLabeledJumps; } - emitNodeWithCommentsAndWithoutSourcemap(node.name); - emitEnd(node.name); - } - function createVoidZero() { - var zero = ts.createSynthesizedNode(8 /* NumericLiteral */); - zero.text = "0"; - var result = ts.createSynthesizedNode(183 /* VoidExpression */); - result.expression = zero; return result; } - function emitEs6ExportDefaultCompat(node) { - if (node.parent.kind === 256 /* SourceFile */) { - ts.Debug.assert(!!(node.flags & 512 /* Default */) || node.kind === 235 /* ExportAssignment */); - // only allow export default at a source file level - if (modulekind === ts.ModuleKind.CommonJS || modulekind === ts.ModuleKind.AMD || modulekind === ts.ModuleKind.UMD) { - if (!isEs6Module) { - if (languageVersion !== 0 /* ES3 */) { - // default value of configurable, enumerable, writable are `false`. - write('Object.defineProperty(exports, "__esModule", { value: true });'); - writeLine(); - } - else { - write("exports.__esModule = true;"); - writeLine(); - } - } - } - } - } - function emitExportMemberAssignment(node) { - if (node.flags & 1 /* Export */) { - writeLine(); - emitStart(node); - // emit call to exporter only for top level nodes - if (modulekind === ts.ModuleKind.System && node.parent === currentSourceFile) { - // emit export default as - // export("default", ) - write(exportFunctionForFile + "(\""); - if (node.flags & 512 /* Default */) { - write("default"); - } - else { - emitNodeWithCommentsAndWithoutSourcemap(node.name); - } - write("\", "); - emitDeclarationName(node); - write(")"); - } - else { - if (node.flags & 512 /* Default */) { - emitEs6ExportDefaultCompat(node); - if (languageVersion === 0 /* ES3 */) { - write('exports["default"]'); - } - else { - write("exports.default"); - } - } - else { - emitModuleMemberName(node); - } - write(" = "); - emitDeclarationName(node); + var functionName = ts.createUniqueName("_loop"); + var loopInitializer; + switch (node.kind) { + case 206 /* ForStatement */: + case 207 /* ForInStatement */: + case 208 /* ForOfStatement */: + var initializer = node.initializer; + if (initializer && initializer.kind === 219 /* VariableDeclarationList */) { + loopInitializer = initializer; } - emitEnd(node); - write(";"); - } + break; } - function emitExportMemberAssignments(name) { - if (modulekind === ts.ModuleKind.System) { - return; + // variables that will be passed to the loop as parameters + var loopParameters = []; + // variables declared in the loop initializer that will be changed inside the loop + var loopOutParameters = []; + if (loopInitializer && (ts.getCombinedNodeFlags(loopInitializer) & 3 /* BlockScoped */)) { + for (var _i = 0, _a = loopInitializer.declarations; _i < _a.length; _i++) { + var decl = _a[_i]; + processLoopVariableDeclaration(decl, loopParameters, loopOutParameters); + } + } + var outerConvertedLoopState = convertedLoopState; + convertedLoopState = { loopOutParameters: loopOutParameters }; + if (outerConvertedLoopState) { + // convertedOuterLoopState !== undefined means that this converted loop is nested in another converted loop. + // if outer converted loop has already accumulated some state - pass it through + if (outerConvertedLoopState.argumentsName) { + // outer loop has already used 'arguments' so we've already have some name to alias it + // use the same name in all nested loops + convertedLoopState.argumentsName = outerConvertedLoopState.argumentsName; + } + if (outerConvertedLoopState.thisName) { + // outer loop has already used 'this' so we've already have some name to alias it + // use the same name in all nested loops + convertedLoopState.thisName = outerConvertedLoopState.thisName; + } + if (outerConvertedLoopState.hoistedLocalVariables) { + // we've already collected some non-block scoped variable declarations in enclosing loop + // use the same storage in nested loop + convertedLoopState.hoistedLocalVariables = outerConvertedLoopState.hoistedLocalVariables; + } + } + var loopBody = ts.visitNode(node.statement, visitor, ts.isStatement); + var currentState = convertedLoopState; + convertedLoopState = outerConvertedLoopState; + if (loopOutParameters.length) { + var statements_3 = ts.isBlock(loopBody) ? loopBody.statements.slice() : [loopBody]; + copyOutParameters(loopOutParameters, 1 /* ToOutParameter */, statements_3); + loopBody = ts.createBlock(statements_3, /*location*/ undefined, /*multiline*/ true); + } + if (!ts.isBlock(loopBody)) { + loopBody = ts.createBlock([loopBody], /*location*/ undefined, /*multiline*/ true); + } + var isAsyncBlockContainingAwait = enclosingNonArrowFunction + && (ts.getEmitFlags(enclosingNonArrowFunction) & 2097152 /* AsyncFunctionBody */) !== 0 + && (node.statement.transformFlags & 4194304 /* ContainsYield */) !== 0; + var loopBodyFlags = 0; + if (currentState.containsLexicalThis) { + loopBodyFlags |= 256 /* CapturesThis */; + } + if (isAsyncBlockContainingAwait) { + loopBodyFlags |= 2097152 /* AsyncFunctionBody */; + } + var convertedLoopVariable = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(functionName, + /*type*/ undefined, ts.setEmitFlags(ts.createFunctionExpression(isAsyncBlockContainingAwait ? ts.createToken(37 /* AsteriskToken */) : undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, loopParameters, + /*type*/ undefined, loopBody), loopBodyFlags)) + ])); + var statements = [convertedLoopVariable]; + var extraVariableDeclarations; + // propagate state from the inner loop to the outer loop if necessary + if (currentState.argumentsName) { + // if alias for arguments is set + if (outerConvertedLoopState) { + // pass it to outer converted loop + outerConvertedLoopState.argumentsName = currentState.argumentsName; } - if (!exportEquals && exportSpecifiers && name.text in exportSpecifiers) { - for (var _a = 0, _b = exportSpecifiers[name.text]; _a < _b.length; _a++) { - var specifier = _b[_a]; - writeLine(); - emitStart(specifier.name); - emitContainingModuleName(specifier); - write("."); - emitNodeWithCommentsAndWithoutSourcemap(specifier.name); - emitEnd(specifier.name); - write(" = "); - emitExpressionIdentifier(name); - write(";"); - } + else { + // this is top level converted loop and we need to create an alias for 'arguments' object + (extraVariableDeclarations || (extraVariableDeclarations = [])).push(ts.createVariableDeclaration(currentState.argumentsName, + /*type*/ undefined, ts.createIdentifier("arguments"))); } } - function emitExportSpecifierInSystemModule(specifier) { - ts.Debug.assert(modulekind === ts.ModuleKind.System); - if (!resolver.getReferencedValueDeclaration(specifier.propertyName || specifier.name) && !resolver.isValueAliasDeclaration(specifier)) { - return; + if (currentState.thisName) { + // if alias for this is set + if (outerConvertedLoopState) { + // pass it to outer converted loop + outerConvertedLoopState.thisName = currentState.thisName; } - writeLine(); - emitStart(specifier.name); - write(exportFunctionForFile + "(\""); - emitNodeWithCommentsAndWithoutSourcemap(specifier.name); - write("\", "); - emitExpressionIdentifier(specifier.propertyName || specifier.name); - write(")"); - emitEnd(specifier.name); - write(";"); - } - /** - * Emit an assignment to a given identifier, 'name', with a given expression, 'value'. - * @param name an identifier as a left-hand-side operand of the assignment - * @param value an expression as a right-hand-side operand of the assignment - * @param shouldEmitCommaBeforeAssignment a boolean indicating whether to prefix an assignment with comma - */ - function emitAssignment(name, value, shouldEmitCommaBeforeAssignment, nodeForSourceMap) { - if (shouldEmitCommaBeforeAssignment) { - write(", "); - } - var exportChanged = isNameOfExportedSourceLevelDeclarationInSystemExternalModule(name); - if (exportChanged) { - write(exportFunctionForFile + "(\""); - emitNodeWithCommentsAndWithoutSourcemap(name); - write("\", "); - } - var isVariableDeclarationOrBindingElement = name.parent && (name.parent.kind === 218 /* VariableDeclaration */ || name.parent.kind === 169 /* BindingElement */); - // If this is first var declaration, we need to start at var/let/const keyword instead - // otherwise use nodeForSourceMap as the start position - emitStart(isFirstVariableDeclaration(nodeForSourceMap) ? nodeForSourceMap.parent : nodeForSourceMap); - withTemporaryNoSourceMap(function () { - if (isVariableDeclarationOrBindingElement) { - emitModuleMemberName(name.parent); - } - else { - emit(name); - } - write(" = "); - emit(value); - }); - emitEnd(nodeForSourceMap, /*stopOverridingSpan*/ true); - if (exportChanged) { - write(")"); + else { + // this is top level converted loop so we need to create an alias for 'this' here + // NOTE: + // if converted loops were all nested in arrow function then we'll always emit '_this' so convertedLoopState.thisName will not be set. + // If it is set this means that all nested loops are not nested in arrow function and it is safe to capture 'this'. + (extraVariableDeclarations || (extraVariableDeclarations = [])).push(ts.createVariableDeclaration(currentState.thisName, + /*type*/ undefined, ts.createIdentifier("this"))); } } - /** - * Create temporary variable, emit an assignment of the variable the given expression - * @param expression an expression to assign to the newly created temporary variable - * @param canDefineTempVariablesInPlace a boolean indicating whether you can define the temporary variable at an assignment location - * @param shouldEmitCommaBeforeAssignment a boolean indicating whether an assignment should prefix with comma - */ - function emitTempVariableAssignment(expression, canDefineTempVariablesInPlace, shouldEmitCommaBeforeAssignment, sourceMapNode) { - var identifier = createTempVariable(0 /* Auto */); - if (!canDefineTempVariablesInPlace) { - recordTempDeclaration(identifier); - } - emitAssignment(identifier, expression, shouldEmitCommaBeforeAssignment, sourceMapNode || expression.parent); - return identifier; - } - function isFirstVariableDeclaration(root) { - return root.kind === 218 /* VariableDeclaration */ && - root.parent.kind === 219 /* VariableDeclarationList */ && - root.parent.declarations[0] === root; - } - function emitDestructuring(root, isAssignmentExpressionStatement, value) { - var emitCount = 0; - // An exported declaration is actually emitted as an assignment (to a property on the module object), so - // temporary variables in an exported declaration need to have real declarations elsewhere - // Also temporary variables should be explicitly allocated for source level declarations when module target is system - // because actual variable declarations are hoisted - var canDefineTempVariablesInPlace = false; - if (root.kind === 218 /* VariableDeclaration */) { - var isExported = ts.getCombinedNodeFlags(root) & 1 /* Export */; - var isSourceLevelForSystemModuleKind = shouldHoistDeclarationInSystemJsModule(root); - canDefineTempVariablesInPlace = !isExported && !isSourceLevelForSystemModuleKind; - } - else if (root.kind === 142 /* Parameter */) { - canDefineTempVariablesInPlace = true; - } - if (root.kind === 187 /* BinaryExpression */) { - emitAssignmentExpression(root); + if (currentState.hoistedLocalVariables) { + // if hoistedLocalVariables !== undefined this means that we've possibly collected some variable declarations to be hoisted later + if (outerConvertedLoopState) { + // pass them to outer converted loop + outerConvertedLoopState.hoistedLocalVariables = currentState.hoistedLocalVariables; } else { - ts.Debug.assert(!isAssignmentExpressionStatement); - // If first variable declaration of variable statement correct the start location - if (isFirstVariableDeclaration(root)) { - // Use emit location of "var " as next emit start entry - sourceMap.changeEmitSourcePos(); + if (!extraVariableDeclarations) { + extraVariableDeclarations = []; } - emitBindingElement(root, value); - } - /** - * Ensures that there exists a declared identifier whose value holds the given expression. - * This function is useful to ensure that the expression's value can be read from in subsequent expressions. - * Unless 'reuseIdentifierExpressions' is false, 'expr' will be returned if it is just an identifier. - * - * @param expr the expression whose value needs to be bound. - * @param reuseIdentifierExpressions true if identifier expressions can simply be returned; - * false if it is necessary to always emit an identifier. - */ - function ensureIdentifier(expr, reuseIdentifierExpressions, sourceMapNode) { - if (expr.kind === 69 /* Identifier */ && reuseIdentifierExpressions) { - return expr; + // hoist collected variable declarations + for (var name_36 in currentState.hoistedLocalVariables) { + var identifier = currentState.hoistedLocalVariables[name_36]; + extraVariableDeclarations.push(ts.createVariableDeclaration(identifier)); } - var identifier = emitTempVariableAssignment(expr, canDefineTempVariablesInPlace, emitCount > 0, sourceMapNode); - emitCount++; - return identifier; - } - function createDefaultValueCheck(value, defaultValue, sourceMapNode) { - // The value expression will be evaluated twice, so for anything but a simple identifier - // we need to generate a temporary variable - // If the temporary variable needs to be emitted use the source Map node for assignment of that statement - value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, sourceMapNode); - // Return the expression 'value === void 0 ? defaultValue : value' - var equals = ts.createSynthesizedNode(187 /* BinaryExpression */); - equals.left = value; - equals.operatorToken = ts.createSynthesizedNode(32 /* EqualsEqualsEqualsToken */); - equals.right = createVoidZero(); - return createConditionalExpression(equals, defaultValue, value); - } - function createConditionalExpression(condition, whenTrue, whenFalse) { - var cond = ts.createSynthesizedNode(188 /* ConditionalExpression */); - cond.condition = condition; - cond.questionToken = ts.createSynthesizedNode(53 /* QuestionToken */); - cond.whenTrue = whenTrue; - cond.colonToken = ts.createSynthesizedNode(54 /* ColonToken */); - cond.whenFalse = whenFalse; - return cond; - } - function createNumericLiteral(value) { - var node = ts.createSynthesizedNode(8 /* NumericLiteral */); - node.text = "" + value; - return node; } - function createPropertyAccessForDestructuringProperty(object, propName) { - var index; - var nameIsComputed = propName.kind === 140 /* ComputedPropertyName */; - if (nameIsComputed) { - // TODO to handle when we look into sourcemaps for computed properties, for now use propName - index = ensureIdentifier(propName.expression, /*reuseIdentifierExpressions*/ false, propName); - } - else { - // We create a synthetic copy of the identifier in order to avoid the rewriting that might - // otherwise occur when the identifier is emitted. - index = ts.createSynthesizedNode(propName.kind); - // We need to unescape identifier here because when parsing an identifier prefixing with "__" - // the parser need to append "_" in order to escape colliding with magic identifiers such as "__proto__" - // Therefore, in order to correctly emit identifiers that are written in original TypeScript file, - // we will unescapeIdentifier to remove additional underscore (if no underscore is added, the function will return original input string) - index.text = ts.unescapeIdentifier(propName.text); - } - return !nameIsComputed && index.kind === 69 /* Identifier */ - ? createPropertyAccessExpression(object, index) - : createElementAccessExpression(object, index); - } - function createSliceCall(value, sliceIndex) { - var call = ts.createSynthesizedNode(174 /* CallExpression */); - var sliceIdentifier = ts.createSynthesizedNode(69 /* Identifier */); - sliceIdentifier.text = "slice"; - call.expression = createPropertyAccessExpression(value, sliceIdentifier); - call.arguments = ts.createSynthesizedNodeArray(); - call.arguments[0] = createNumericLiteral(sliceIndex); - return call; - } - function emitObjectLiteralAssignment(target, value, sourceMapNode) { - var properties = target.properties; - if (properties.length !== 1) { - // For anything but a single element destructuring we need to generate a temporary - // to ensure value is evaluated exactly once. - // When doing so we want to highlight the passed in source map node since thats the one needing this temp assignment - value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, sourceMapNode); - } - for (var _a = 0, properties_5 = properties; _a < properties_5.length; _a++) { - var p = properties_5[_a]; - if (p.kind === 253 /* PropertyAssignment */ || p.kind === 254 /* ShorthandPropertyAssignment */) { - var propName = p.name; - var target_1 = p.kind === 254 /* ShorthandPropertyAssignment */ ? p : p.initializer || propName; - // Assignment for target = value.propName should highlight whole property, hence use p as source map node - emitDestructuringAssignment(target_1, createPropertyAccessForDestructuringProperty(value, propName), p); - } - } - } - function emitArrayLiteralAssignment(target, value, sourceMapNode) { - var elements = target.elements; - if (elements.length !== 1) { - // For anything but a single element destructuring we need to generate a temporary - // to ensure value is evaluated exactly once. - // When doing so we want to highlight the passed in source map node since thats the one needing this temp assignment - value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, sourceMapNode); - } - for (var i = 0; i < elements.length; i++) { - var e = elements[i]; - if (e.kind !== 193 /* OmittedExpression */) { - // Assignment for target = value.propName should highlight whole property, hence use e as source map node - if (e.kind !== 191 /* SpreadElementExpression */) { - emitDestructuringAssignment(e, createElementAccessExpression(value, createNumericLiteral(i)), e); - } - else if (i === elements.length - 1) { - emitDestructuringAssignment(e.expression, createSliceCall(value, i), e); - } - } - } - } - function emitDestructuringAssignment(target, value, sourceMapNode) { - // When emitting target = value use source map node to highlight, including any temporary assignments needed for this - if (target.kind === 254 /* ShorthandPropertyAssignment */) { - if (target.objectAssignmentInitializer) { - value = createDefaultValueCheck(value, target.objectAssignmentInitializer, sourceMapNode); - } - target = target.name; - } - else if (target.kind === 187 /* BinaryExpression */ && target.operatorToken.kind === 56 /* EqualsToken */) { - value = createDefaultValueCheck(value, target.right, sourceMapNode); - target = target.left; - } - if (target.kind === 171 /* ObjectLiteralExpression */) { - emitObjectLiteralAssignment(target, value, sourceMapNode); - } - else if (target.kind === 170 /* ArrayLiteralExpression */) { - emitArrayLiteralAssignment(target, value, sourceMapNode); - } - else { - emitAssignment(target, value, /*shouldEmitCommaBeforeAssignment*/ emitCount > 0, sourceMapNode); - emitCount++; - } + } + // add extra variables to hold out parameters if necessary + if (loopOutParameters.length) { + if (!extraVariableDeclarations) { + extraVariableDeclarations = []; } - function emitAssignmentExpression(root) { - var target = root.left; - var value = root.right; - if (ts.isEmptyObjectLiteralOrArrayLiteral(target)) { - emit(value); - } - else if (isAssignmentExpressionStatement) { - // Source map node for root.left = root.right is root - // but if root is synthetic, which could be in below case, use the target which is { a } - // for ({a} of {a: string}) { - // } - emitDestructuringAssignment(target, value, ts.nodeIsSynthesized(root) ? target : root); - } - else { - if (root.parent.kind !== 178 /* ParenthesizedExpression */) { - write("("); - } - // Temporary assignment needed to emit root should highlight whole binary expression - value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, root); - // Source map node for root.left = root.right is root - emitDestructuringAssignment(target, value, root); - write(", "); - emit(value); - if (root.parent.kind !== 178 /* ParenthesizedExpression */) { - write(")"); - } - } - } - function emitBindingElement(target, value) { - // Any temporary assignments needed to emit target = value should point to target - if (target.initializer) { - // Combine value and initializer - value = value ? createDefaultValueCheck(value, target.initializer, target) : target.initializer; - } - else if (!value) { - // Use 'void 0' in absence of value and initializer - value = createVoidZero(); - } - if (ts.isBindingPattern(target.name)) { - var pattern = target.name; - var elements = pattern.elements; - var numElements = elements.length; - if (numElements !== 1) { - // For anything other than a single-element destructuring we need to generate a temporary - // to ensure value is evaluated exactly once. Additionally, if we have zero elements - // we need to emit *something* to ensure that in case a 'var' keyword was already emitted, - // so in that case, we'll intentionally create that temporary. - value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ numElements !== 0, target); - } - for (var i = 0; i < numElements; i++) { - var element = elements[i]; - if (pattern.kind === 167 /* ObjectBindingPattern */) { - // Rewrite element to a declaration with an initializer that fetches property - var propName = element.propertyName || element.name; - emitBindingElement(element, createPropertyAccessForDestructuringProperty(value, propName)); - } - else if (element.kind !== 193 /* OmittedExpression */) { - if (!element.dotDotDotToken) { - // Rewrite element to a declaration that accesses array element at index i - emitBindingElement(element, createElementAccessExpression(value, createNumericLiteral(i))); - } - else if (i === numElements - 1) { - emitBindingElement(element, createSliceCall(value, i)); - } - } - } - } - else { - emitAssignment(target.name, value, /*shouldEmitCommaBeforeAssignment*/ emitCount > 0, target); - emitCount++; - } + for (var _b = 0, loopOutParameters_1 = loopOutParameters; _b < loopOutParameters_1.length; _b++) { + var outParam = loopOutParameters_1[_b]; + extraVariableDeclarations.push(ts.createVariableDeclaration(outParam.outParamName)); } } - function emitVariableDeclaration(node) { - if (ts.isBindingPattern(node.name)) { - var isExported = ts.getCombinedNodeFlags(node) & 1 /* Export */; - if (languageVersion >= 2 /* ES6 */ && (!isExported || modulekind === ts.ModuleKind.ES6)) { - // emit ES6 destructuring only if target module is ES6 or variable is not exported - // exported variables in CJS/AMD are prefixed with 'exports.' so result javascript { exports.toString } = 1; is illegal - var isTopLevelDeclarationInSystemModule = modulekind === ts.ModuleKind.System && - shouldHoistVariable(node, /*checkIfSourceFileLevelDecl*/ true); - if (isTopLevelDeclarationInSystemModule) { - // In System modules top level variables are hoisted - // so variable declarations with destructuring are turned into destructuring assignments. - // As a result, they will need parentheses to disambiguate object binding assignments from blocks. - write("("); - } - emit(node.name); - emitOptional(" = ", node.initializer); - if (isTopLevelDeclarationInSystemModule) { - write(")"); - } + // create variable statement to hold all introduced variable declarations + if (extraVariableDeclarations) { + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList(extraVariableDeclarations))); + } + var convertedLoopBodyStatements = generateCallToConvertedLoop(functionName, loopParameters, currentState, isAsyncBlockContainingAwait); + var loop; + if (convert) { + loop = convert(node, convertedLoopBodyStatements); + } + else { + loop = ts.getMutableClone(node); + // clean statement part + loop.statement = undefined; + // visit childnodes to transform initializer/condition/incrementor parts + loop = ts.visitEachChild(loop, visitor, context); + // set loop statement + loop.statement = ts.createBlock(convertedLoopBodyStatements, + /*location*/ undefined, + /*multiline*/ true); + // reset and re-aggregate the transform flags + loop.transformFlags = 0; + ts.aggregateTransformFlags(loop); + } + statements.push(currentParent.kind === 214 /* LabeledStatement */ + ? ts.createLabel(currentParent.label, loop) + : loop); + return statements; + } + function copyOutParameter(outParam, copyDirection) { + var source = copyDirection === 0 /* ToOriginal */ ? outParam.outParamName : outParam.originalName; + var target = copyDirection === 0 /* ToOriginal */ ? outParam.originalName : outParam.outParamName; + return ts.createBinary(target, 56 /* EqualsToken */, source); + } + function copyOutParameters(outParams, copyDirection, statements) { + for (var _i = 0, outParams_1 = outParams; _i < outParams_1.length; _i++) { + var outParam = outParams_1[_i]; + statements.push(ts.createStatement(copyOutParameter(outParam, copyDirection))); + } + } + function generateCallToConvertedLoop(loopFunctionExpressionName, parameters, state, isAsyncBlockContainingAwait) { + var outerConvertedLoopState = convertedLoopState; + var statements = []; + // loop is considered simple if it does not have any return statements or break\continue that transfer control outside of the loop + // simple loops are emitted as just 'loop()'; + // NOTE: if loop uses only 'continue' it still will be emitted as simple loop + var isSimpleLoop = !(state.nonLocalJumps & ~4 /* Continue */) && + !state.labeledNonLocalBreaks && + !state.labeledNonLocalContinues; + var call = ts.createCall(loopFunctionExpressionName, /*typeArguments*/ undefined, ts.map(parameters, function (p) { return p.name; })); + var callResult = isAsyncBlockContainingAwait ? ts.createYield(ts.createToken(37 /* AsteriskToken */), call) : call; + if (isSimpleLoop) { + statements.push(ts.createStatement(callResult)); + copyOutParameters(state.loopOutParameters, 0 /* ToOriginal */, statements); + } + else { + var loopResultName = ts.createUniqueName("state"); + var stateVariable = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(loopResultName, /*type*/ undefined, callResult)])); + statements.push(stateVariable); + copyOutParameters(state.loopOutParameters, 0 /* ToOriginal */, statements); + if (state.nonLocalJumps & 8 /* Return */) { + var returnStatement = void 0; + if (outerConvertedLoopState) { + outerConvertedLoopState.nonLocalJumps |= 8 /* Return */; + returnStatement = ts.createReturn(loopResultName); } else { - emitDestructuring(node, /*isAssignmentExpressionStatement*/ false); + returnStatement = ts.createReturn(ts.createPropertyAccess(loopResultName, "value")); } + statements.push(ts.createIf(ts.createBinary(ts.createTypeOf(loopResultName), 32 /* EqualsEqualsEqualsToken */, ts.createLiteral("object")), returnStatement)); } - else { - var initializer = node.initializer; - if (!initializer && - languageVersion < 2 /* ES6 */ && - // for names - binding patterns that lack initializer there is no point to emit explicit initializer - // since downlevel codegen for destructuring will fail in the absence of initializer so all binding elements will say uninitialized - node.name.kind === 69 /* Identifier */) { - var container = ts.getEnclosingBlockScopeContainer(node); - var flags = resolver.getNodeCheckFlags(node); - // nested let bindings might need to be initialized explicitly to preserve ES6 semantic - // { let x = 1; } - // { let x; } // x here should be undefined. not 1 - // NOTES: - // Top level bindings never collide with anything and thus don't require explicit initialization. - // As for nested let bindings there are two cases: - // - nested let bindings that were not renamed definitely should be initialized explicitly - // { let x = 1; } - // { let x; if (some-condition) { x = 1}; if (x) { /*1*/ } } - // Without explicit initialization code in /*1*/ can be executed even if some-condition is evaluated to false - // - renaming introduces fresh name that should not collide with any existing names, however renamed bindings sometimes also should be - // explicitly initialized. One particular case: non-captured binding declared inside loop body (but not in loop initializer) - // let x; - // for (;;) { - // let x; - // } - // in downlevel codegen inner 'x' will be renamed so it won't collide with outer 'x' however it will should be reset on every iteration - // as if it was declared anew. - // * Why non-captured binding - because if loop contains block scoped binding captured in some function then loop body will be rewritten - // to have a fresh scope on every iteration so everything will just work. - // * Why loop initializer is excluded - since we've introduced a fresh name it already will be undefined. - var isCapturedInFunction = flags & 131072 /* CapturedBlockScopedBinding */; - var isDeclaredInLoop = flags & 262144 /* BlockScopedBindingInLoop */; - var emittedAsTopLevel = ts.isBlockScopedContainerTopLevel(container) || - (isCapturedInFunction && isDeclaredInLoop && container.kind === 199 /* Block */ && ts.isIterationStatement(container.parent, /*lookInLabeledStatements*/ false)); - var emittedAsNestedLetDeclaration = ts.getCombinedNodeFlags(node) & 1024 /* Let */ && - !emittedAsTopLevel; - var emitExplicitInitializer = emittedAsNestedLetDeclaration && - container.kind !== 207 /* ForInStatement */ && - container.kind !== 208 /* ForOfStatement */ && - (!resolver.isDeclarationWithCollidingName(node) || - (isDeclaredInLoop && !isCapturedInFunction && !ts.isIterationStatement(container, /*lookInLabeledStatements*/ false))); - if (emitExplicitInitializer) { - initializer = createVoidZero(); - } - } - var exportChanged = isNameOfExportedSourceLevelDeclarationInSystemExternalModule(node.name); - if (exportChanged) { - write(exportFunctionForFile + "(\""); - emitNodeWithCommentsAndWithoutSourcemap(node.name); - write("\", "); - } - emitModuleMemberName(node); - emitOptional(" = ", initializer); - if (exportChanged) { - write(")"); - } - } - } - function emitExportVariableAssignments(node) { - if (node.kind === 193 /* OmittedExpression */) { - return; + if (state.nonLocalJumps & 2 /* Break */) { + statements.push(ts.createIf(ts.createBinary(loopResultName, 32 /* EqualsEqualsEqualsToken */, ts.createLiteral("break")), ts.createBreak())); } - var name = node.name; - if (name.kind === 69 /* Identifier */) { - emitExportMemberAssignments(name); + if (state.labeledNonLocalBreaks || state.labeledNonLocalContinues) { + var caseClauses = []; + processLabeledJumps(state.labeledNonLocalBreaks, /*isBreak*/ true, loopResultName, outerConvertedLoopState, caseClauses); + processLabeledJumps(state.labeledNonLocalContinues, /*isBreak*/ false, loopResultName, outerConvertedLoopState, caseClauses); + statements.push(ts.createSwitch(loopResultName, ts.createCaseBlock(caseClauses))); } - else if (ts.isBindingPattern(name)) { - ts.forEach(name.elements, emitExportVariableAssignments); + } + return statements; + } + function setLabeledJump(state, isBreak, labelText, labelMarker) { + if (isBreak) { + if (!state.labeledNonLocalBreaks) { + state.labeledNonLocalBreaks = ts.createMap(); + } + state.labeledNonLocalBreaks[labelText] = labelMarker; + } + else { + if (!state.labeledNonLocalContinues) { + state.labeledNonLocalContinues = ts.createMap(); } + state.labeledNonLocalContinues[labelText] = labelMarker; } - function isES6ExportedDeclaration(node) { - return !!(node.flags & 1 /* Export */) && - modulekind === ts.ModuleKind.ES6 && - node.parent.kind === 256 /* SourceFile */; + } + function processLabeledJumps(table, isBreak, loopResultName, outerLoop, caseClauses) { + if (!table) { + return; } - function emitVariableStatement(node) { - var startIsEmitted = false; - if (node.flags & 1 /* Export */) { - if (isES6ExportedDeclaration(node)) { - // Exported ES6 module member - write("export "); - startIsEmitted = tryEmitStartOfVariableDeclarationList(node.declarationList); - } + for (var labelText in table) { + var labelMarker = table[labelText]; + var statements = []; + // if there are no outer converted loop or outer label in question is located inside outer converted loop + // then emit labeled break\continue + // otherwise propagate pair 'label -> marker' to outer converted loop and emit 'return labelMarker' so outer loop can later decide what to do + if (!outerLoop || (outerLoop.labels && outerLoop.labels[labelText])) { + var label = ts.createIdentifier(labelText); + statements.push(isBreak ? ts.createBreak(label) : ts.createContinue(label)); } else { - startIsEmitted = tryEmitStartOfVariableDeclarationList(node.declarationList); + setLabeledJump(outerLoop, isBreak, labelText, labelMarker); + statements.push(ts.createReturn(loopResultName)); } - if (startIsEmitted) { - emitCommaList(node.declarationList.declarations); - write(";"); - } - else { - var atLeastOneItem = emitVariableDeclarationListSkippingUninitializedEntries(node.declarationList); - if (atLeastOneItem) { - write(";"); + caseClauses.push(ts.createCaseClause(ts.createLiteral(labelMarker), statements)); + } + } + function processLoopVariableDeclaration(decl, loopParameters, loopOutParameters) { + var name = decl.name; + if (ts.isBindingPattern(name)) { + for (var _i = 0, _a = name.elements; _i < _a.length; _i++) { + var element = _a[_i]; + if (!ts.isOmittedExpression(element)) { + processLoopVariableDeclaration(element, loopParameters, loopOutParameters); } } - if (modulekind !== ts.ModuleKind.ES6 && node.parent === currentSourceFile) { - ts.forEach(node.declarationList.declarations, emitExportVariableAssignments); + } + else { + loopParameters.push(ts.createParameter(name)); + if (resolver.getNodeCheckFlags(decl) & 2097152 /* NeedsLoopOutParameter */) { + var outParamName = ts.createUniqueName("out_" + name.text); + loopOutParameters.push({ originalName: name, outParamName: outParamName }); + } + } + } + /** + * Adds the members of an object literal to an array of expressions. + * + * @param expressions An array of expressions. + * @param node An ObjectLiteralExpression node. + * @param receiver The receiver for members of the ObjectLiteralExpression. + * @param numInitialNonComputedProperties The number of initial properties without + * computed property names. + */ + function addObjectLiteralMembers(expressions, node, receiver, start) { + var properties = node.properties; + var numProperties = properties.length; + for (var i = start; i < numProperties; i++) { + var property = properties[i]; + switch (property.kind) { + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + var accessors = ts.getAllAccessorDeclarations(node.properties, property); + if (property === accessors.firstAccessor) { + expressions.push(transformAccessorsToExpression(receiver, accessors, node.multiLine)); + } + break; + case 253 /* PropertyAssignment */: + expressions.push(transformPropertyAssignmentToExpression(node, property, receiver, node.multiLine)); + break; + case 254 /* ShorthandPropertyAssignment */: + expressions.push(transformShorthandPropertyAssignmentToExpression(node, property, receiver, node.multiLine)); + break; + case 147 /* MethodDeclaration */: + expressions.push(transformObjectLiteralMethodDeclarationToExpression(node, property, receiver, node.multiLine)); + break; + default: + ts.Debug.failBadSyntaxKind(node); + break; } } - function shouldEmitLeadingAndTrailingCommentsForVariableStatement(node) { - // If we're not exporting the variables, there's nothing special here. - // Always emit comments for these nodes. - if (!(node.flags & 1 /* Export */)) { - return true; + } + /** + * Transforms a PropertyAssignment node into an expression. + * + * @param node The ObjectLiteralExpression that contains the PropertyAssignment. + * @param property The PropertyAssignment node. + * @param receiver The receiver for the assignment. + */ + function transformPropertyAssignmentToExpression(node, property, receiver, startsOnNewLine) { + var expression = ts.createAssignment(ts.createMemberAccessForPropertyName(receiver, ts.visitNode(property.name, visitor, ts.isPropertyName)), ts.visitNode(property.initializer, visitor, ts.isExpression), + /*location*/ property); + if (startsOnNewLine) { + expression.startsOnNewLine = true; + } + return expression; + } + /** + * Transforms a ShorthandPropertyAssignment node into an expression. + * + * @param node The ObjectLiteralExpression that contains the ShorthandPropertyAssignment. + * @param property The ShorthandPropertyAssignment node. + * @param receiver The receiver for the assignment. + */ + function transformShorthandPropertyAssignmentToExpression(node, property, receiver, startsOnNewLine) { + var expression = ts.createAssignment(ts.createMemberAccessForPropertyName(receiver, ts.visitNode(property.name, visitor, ts.isPropertyName)), ts.getSynthesizedClone(property.name), + /*location*/ property); + if (startsOnNewLine) { + expression.startsOnNewLine = true; + } + return expression; + } + /** + * Transforms a MethodDeclaration of an ObjectLiteralExpression into an expression. + * + * @param node The ObjectLiteralExpression that contains the MethodDeclaration. + * @param method The MethodDeclaration node. + * @param receiver The receiver for the assignment. + */ + function transformObjectLiteralMethodDeclarationToExpression(node, method, receiver, startsOnNewLine) { + var expression = ts.createAssignment(ts.createMemberAccessForPropertyName(receiver, ts.visitNode(method.name, visitor, ts.isPropertyName)), transformFunctionLikeToExpression(method, /*location*/ method, /*name*/ undefined), + /*location*/ method); + if (startsOnNewLine) { + expression.startsOnNewLine = true; + } + return expression; + } + /** + * Visits a MethodDeclaration of an ObjectLiteralExpression and transforms it into a + * PropertyAssignment. + * + * @param node A MethodDeclaration node. + */ + function visitMethodDeclaration(node) { + // We should only get here for methods on an object literal with regular identifier names. + // Methods on classes are handled in visitClassDeclaration/visitClassExpression. + // Methods with computed property names are handled in visitObjectLiteralExpression. + ts.Debug.assert(!ts.isComputedPropertyName(node.name)); + var functionExpression = transformFunctionLikeToExpression(node, /*location*/ ts.moveRangePos(node, -1), /*name*/ undefined); + ts.setEmitFlags(functionExpression, 16384 /* NoLeadingComments */ | ts.getEmitFlags(functionExpression)); + return ts.createPropertyAssignment(node.name, functionExpression, + /*location*/ node); + } + /** + * Visits a ShorthandPropertyAssignment and transforms it into a PropertyAssignment. + * + * @param node A ShorthandPropertyAssignment node. + */ + function visitShorthandPropertyAssignment(node) { + return ts.createPropertyAssignment(node.name, ts.getSynthesizedClone(node.name), + /*location*/ node); + } + /** + * Visits a YieldExpression node. + * + * @param node A YieldExpression node. + */ + function visitYieldExpression(node) { + // `yield` expressions are transformed using the generators transformer. + return ts.visitEachChild(node, visitor, context); + } + /** + * Visits an ArrayLiteralExpression that contains a spread element. + * + * @param node An ArrayLiteralExpression node. + */ + function visitArrayLiteralExpression(node) { + // We are here because we contain a SpreadElementExpression. + return transformAndSpreadElements(node.elements, /*needsUniqueCopy*/ true, node.multiLine, /*hasTrailingComma*/ node.elements.hasTrailingComma); + } + /** + * Visits a CallExpression that contains either a spread element or `super`. + * + * @param node a CallExpression. + */ + function visitCallExpression(node) { + return visitCallExpressionWithPotentialCapturedThisAssignment(node, /*assignToCapturedThis*/ true); + } + function visitImmediateSuperCallInBody(node) { + return visitCallExpressionWithPotentialCapturedThisAssignment(node, /*assignToCapturedThis*/ false); + } + function visitCallExpressionWithPotentialCapturedThisAssignment(node, assignToCapturedThis) { + // We are here either because SuperKeyword was used somewhere in the expression, or + // because we contain a SpreadElementExpression. + var _a = ts.createCallBinding(node.expression, hoistVariableDeclaration), target = _a.target, thisArg = _a.thisArg; + if (node.expression.kind === 95 /* SuperKeyword */) { + ts.setEmitFlags(thisArg, 128 /* NoSubstitution */); + } + var resultingCall; + if (node.transformFlags & 262144 /* ContainsSpreadElementExpression */) { + // [source] + // f(...a, b) + // x.m(...a, b) + // super(...a, b) + // super.m(...a, b) // in static + // super.m(...a, b) // in instance + // + // [output] + // f.apply(void 0, a.concat([b])) + // (_a = x).m.apply(_a, a.concat([b])) + // _super.apply(this, a.concat([b])) + // _super.m.apply(this, a.concat([b])) + // _super.prototype.m.apply(this, a.concat([b])) + resultingCall = ts.createFunctionApply(ts.visitNode(target, visitor, ts.isExpression), ts.visitNode(thisArg, visitor, ts.isExpression), transformAndSpreadElements(node.arguments, /*needsUniqueCopy*/ false, /*multiLine*/ false, /*hasTrailingComma*/ false)); + } + else { + // [source] + // super(a) + // super.m(a) // in static + // super.m(a) // in instance + // + // [output] + // _super.call(this, a) + // _super.m.call(this, a) + // _super.prototype.m.call(this, a) + resultingCall = ts.createFunctionCall(ts.visitNode(target, visitor, ts.isExpression), ts.visitNode(thisArg, visitor, ts.isExpression), ts.visitNodes(node.arguments, visitor, ts.isExpression), + /*location*/ node); + } + if (node.expression.kind === 95 /* SuperKeyword */) { + var actualThis = ts.createThis(); + ts.setEmitFlags(actualThis, 128 /* NoSubstitution */); + var initializer = ts.createLogicalOr(resultingCall, actualThis); + return assignToCapturedThis + ? ts.createAssignment(ts.createIdentifier("_this"), initializer) + : initializer; + } + return resultingCall; + } + /** + * Visits a NewExpression that contains a spread element. + * + * @param node A NewExpression node. + */ + function visitNewExpression(node) { + // We are here because we contain a SpreadElementExpression. + ts.Debug.assert((node.transformFlags & 262144 /* ContainsSpreadElementExpression */) !== 0); + // [source] + // new C(...a) + // + // [output] + // new ((_a = C).bind.apply(_a, [void 0].concat(a)))() + var _a = ts.createCallBinding(ts.createPropertyAccess(node.expression, "bind"), hoistVariableDeclaration), target = _a.target, thisArg = _a.thisArg; + return ts.createNew(ts.createFunctionApply(ts.visitNode(target, visitor, ts.isExpression), thisArg, transformAndSpreadElements(ts.createNodeArray([ts.createVoidZero()].concat(node.arguments)), /*needsUniqueCopy*/ false, /*multiLine*/ false, /*hasTrailingComma*/ false)), + /*typeArguments*/ undefined, []); + } + /** + * Transforms an array of Expression nodes that contains a SpreadElementExpression. + * + * @param elements The array of Expression nodes. + * @param needsUniqueCopy A value indicating whether to ensure that the result is a fresh array. + * @param multiLine A value indicating whether the result should be emitted on multiple lines. + */ + function transformAndSpreadElements(elements, needsUniqueCopy, multiLine, hasTrailingComma) { + // [source] + // [a, ...b, c] + // + // [output] + // [a].concat(b, [c]) + // Map spans of spread expressions into their expressions and spans of other + // expressions into an array literal. + var numElements = elements.length; + var segments = ts.flatten(ts.spanMap(elements, partitionSpreadElement, function (partition, visitPartition, start, end) { + return visitPartition(partition, multiLine, hasTrailingComma && end === numElements); + })); + if (segments.length === 1) { + var firstElement = elements[0]; + return needsUniqueCopy && ts.isSpreadElementExpression(firstElement) && firstElement.expression.kind !== 170 /* ArrayLiteralExpression */ + ? ts.createArraySlice(segments[0]) + : segments[0]; + } + // Rewrite using the pattern .concat(, , ...) + return ts.createArrayConcat(segments.shift(), segments); + } + function partitionSpreadElement(node) { + return ts.isSpreadElementExpression(node) + ? visitSpanOfSpreadElements + : visitSpanOfNonSpreadElements; + } + function visitSpanOfSpreadElements(chunk, multiLine, hasTrailingComma) { + return ts.map(chunk, visitExpressionOfSpreadElement); + } + function visitSpanOfNonSpreadElements(chunk, multiLine, hasTrailingComma) { + return ts.createArrayLiteral(ts.visitNodes(ts.createNodeArray(chunk, /*location*/ undefined, hasTrailingComma), visitor, ts.isExpression), + /*location*/ undefined, multiLine); + } + /** + * Transforms the expression of a SpreadElementExpression node. + * + * @param node A SpreadElementExpression node. + */ + function visitExpressionOfSpreadElement(node) { + return ts.visitNode(node.expression, visitor, ts.isExpression); + } + /** + * Visits a template literal. + * + * @param node A template literal. + */ + function visitTemplateLiteral(node) { + return ts.createLiteral(node.text, /*location*/ node); + } + /** + * Visits a TaggedTemplateExpression node. + * + * @param node A TaggedTemplateExpression node. + */ + function visitTaggedTemplateExpression(node) { + // Visit the tag expression + var tag = ts.visitNode(node.tag, visitor, ts.isExpression); + // Allocate storage for the template site object + var temp = ts.createTempVariable(hoistVariableDeclaration); + // Build up the template arguments and the raw and cooked strings for the template. + var templateArguments = [temp]; + var cookedStrings = []; + var rawStrings = []; + var template = node.template; + if (ts.isNoSubstitutionTemplateLiteral(template)) { + cookedStrings.push(ts.createLiteral(template.text)); + rawStrings.push(getRawLiteral(template)); + } + else { + cookedStrings.push(ts.createLiteral(template.head.text)); + rawStrings.push(getRawLiteral(template.head)); + for (var _i = 0, _a = template.templateSpans; _i < _a.length; _i++) { + var templateSpan = _a[_i]; + cookedStrings.push(ts.createLiteral(templateSpan.literal.text)); + rawStrings.push(getRawLiteral(templateSpan.literal)); + templateArguments.push(ts.visitNode(templateSpan.expression, visitor, ts.isExpression)); + } + } + // NOTE: The parentheses here is entirely optional as we are now able to auto- + // parenthesize when rebuilding the tree. This should be removed in a + // future version. It is here for now to match our existing emit. + return ts.createParen(ts.inlineExpressions([ + ts.createAssignment(temp, ts.createArrayLiteral(cookedStrings)), + ts.createAssignment(ts.createPropertyAccess(temp, "raw"), ts.createArrayLiteral(rawStrings)), + ts.createCall(tag, /*typeArguments*/ undefined, templateArguments) + ])); + } + /** + * Creates an ES5 compatible literal from an ES6 template literal. + * + * @param node The ES6 template literal. + */ + function getRawLiteral(node) { + // Find original source text, since we need to emit the raw strings of the tagged template. + // The raw strings contain the (escaped) strings of what the user wrote. + // Examples: `\n` is converted to "\\n", a template string with a newline to "\n". + var text = ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node); + // text contains the original source, it will also contain quotes ("`"), dolar signs and braces ("${" and "}"), + // thus we need to remove those characters. + // First template piece starts with "`", others with "}" + // Last template piece ends with "`", others with "${" + var isLast = node.kind === 11 /* NoSubstitutionTemplateLiteral */ || node.kind === 14 /* TemplateTail */; + text = text.substring(1, text.length - (isLast ? 1 : 2)); + // Newline normalization: + // ES6 Spec 11.8.6.1 - Static Semantics of TV's and TRV's + // and LineTerminatorSequences are normalized to for both TV and TRV. + text = text.replace(/\r\n?/g, "\n"); + return ts.createLiteral(text, /*location*/ node); + } + /** + * Visits a TemplateExpression node. + * + * @param node A TemplateExpression node. + */ + function visitTemplateExpression(node) { + var expressions = []; + addTemplateHead(expressions, node); + addTemplateSpans(expressions, node); + // createAdd will check if each expression binds less closely than binary '+'. + // If it does, it wraps the expression in parentheses. Otherwise, something like + // `abc${ 1 << 2 }` + // becomes + // "abc" + 1 << 2 + "" + // which is really + // ("abc" + 1) << (2 + "") + // rather than + // "abc" + (1 << 2) + "" + var expression = ts.reduceLeft(expressions, ts.createAdd); + if (ts.nodeIsSynthesized(expression)) { + ts.setTextRange(expression, node); + } + return expression; + } + /** + * Gets a value indicating whether we need to include the head of a TemplateExpression. + * + * @param node A TemplateExpression node. + */ + function shouldAddTemplateHead(node) { + // If this expression has an empty head literal and the first template span has a non-empty + // literal, then emitting the empty head literal is not necessary. + // `${ foo } and ${ bar }` + // can be emitted as + // foo + " and " + bar + // This is because it is only required that one of the first two operands in the emit + // output must be a string literal, so that the other operand and all following operands + // are forced into strings. + // + // If the first template span has an empty literal, then the head must still be emitted. + // `${ foo }${ bar }` + // must still be emitted as + // "" + foo + bar + // There is always atleast one templateSpan in this code path, since + // NoSubstitutionTemplateLiterals are directly emitted via emitLiteral() + ts.Debug.assert(node.templateSpans.length !== 0); + return node.head.text.length !== 0 || node.templateSpans[0].literal.text.length === 0; + } + /** + * Adds the head of a TemplateExpression to an array of expressions. + * + * @param expressions An array of expressions. + * @param node A TemplateExpression node. + */ + function addTemplateHead(expressions, node) { + if (!shouldAddTemplateHead(node)) { + return; + } + expressions.push(ts.createLiteral(node.head.text)); + } + /** + * Visits and adds the template spans of a TemplateExpression to an array of expressions. + * + * @param expressions An array of expressions. + * @param node A TemplateExpression node. + */ + function addTemplateSpans(expressions, node) { + for (var _i = 0, _a = node.templateSpans; _i < _a.length; _i++) { + var span_6 = _a[_i]; + expressions.push(ts.visitNode(span_6.expression, visitor, ts.isExpression)); + // Only emit if the literal is non-empty. + // The binary '+' operator is left-associative, so the first string concatenation + // with the head will force the result up to this point to be a string. + // Emitting a '+ ""' has no semantic effect for middles and tails. + if (span_6.literal.text.length !== 0) { + expressions.push(ts.createLiteral(span_6.literal.text)); + } + } + } + /** + * Visits the `super` keyword + */ + function visitSuperKeyword(node) { + return enclosingNonAsyncFunctionBody + && ts.isClassElement(enclosingNonAsyncFunctionBody) + && !ts.hasModifier(enclosingNonAsyncFunctionBody, 32 /* Static */) + && currentParent.kind !== 174 /* CallExpression */ + ? ts.createPropertyAccess(ts.createIdentifier("_super"), "prototype") + : ts.createIdentifier("_super"); + } + function visitSourceFileNode(node) { + var _a = ts.span(node.statements, ts.isPrologueDirective), prologue = _a[0], remaining = _a[1]; + var statements = []; + startLexicalEnvironment(); + ts.addRange(statements, prologue); + addCaptureThisForNodeIfNeeded(statements, node); + ts.addRange(statements, ts.visitNodes(ts.createNodeArray(remaining), visitor, ts.isStatement)); + ts.addRange(statements, endLexicalEnvironment()); + var clone = ts.getMutableClone(node); + clone.statements = ts.createNodeArray(statements, /*location*/ node.statements); + return clone; + } + /** + * Called by the printer just before a node is printed. + * + * @param node The node to be printed. + */ + function onEmitNode(emitContext, node, emitCallback) { + var savedEnclosingFunction = enclosingFunction; + if (enabledSubstitutions & 1 /* CapturedThis */ && ts.isFunctionLike(node)) { + // If we are tracking a captured `this`, keep track of the enclosing function. + enclosingFunction = node; + } + previousOnEmitNode(emitContext, node, emitCallback); + enclosingFunction = savedEnclosingFunction; + } + /** + * Enables a more costly code path for substitutions when we determine a source file + * contains block-scoped bindings (e.g. `let` or `const`). + */ + function enableSubstitutionsForBlockScopedBindings() { + if ((enabledSubstitutions & 2 /* BlockScopedBindings */) === 0) { + enabledSubstitutions |= 2 /* BlockScopedBindings */; + context.enableSubstitution(69 /* Identifier */); + } + } + /** + * Enables a more costly code path for substitutions when we determine a source file + * contains a captured `this`. + */ + function enableSubstitutionsForCapturedThis() { + if ((enabledSubstitutions & 1 /* CapturedThis */) === 0) { + enabledSubstitutions |= 1 /* CapturedThis */; + context.enableSubstitution(97 /* ThisKeyword */); + context.enableEmitNotification(148 /* Constructor */); + context.enableEmitNotification(147 /* MethodDeclaration */); + context.enableEmitNotification(149 /* GetAccessor */); + context.enableEmitNotification(150 /* SetAccessor */); + context.enableEmitNotification(180 /* ArrowFunction */); + context.enableEmitNotification(179 /* FunctionExpression */); + context.enableEmitNotification(220 /* FunctionDeclaration */); + } + } + /** + * Hooks node substitutions. + * + * @param node The node to substitute. + * @param isExpression A value indicating whether the node is to be used in an expression + * position. + */ + function onSubstituteNode(emitContext, node) { + node = previousOnSubstituteNode(emitContext, node); + if (emitContext === 1 /* Expression */) { + return substituteExpression(node); + } + if (ts.isIdentifier(node)) { + return substituteIdentifier(node); + } + return node; + } + /** + * Hooks substitutions for non-expression identifiers. + */ + function substituteIdentifier(node) { + // Only substitute the identifier if we have enabled substitutions for block-scoped + // bindings. + if (enabledSubstitutions & 2 /* BlockScopedBindings */) { + var original = ts.getParseTreeNode(node, ts.isIdentifier); + if (original && isNameOfDeclarationWithCollidingName(original)) { + return ts.getGeneratedNameForNode(original); + } + } + return node; + } + /** + * Determines whether a name is the name of a declaration with a colliding name. + * NOTE: This function expects to be called with an original source tree node. + * + * @param node An original source tree node. + */ + function isNameOfDeclarationWithCollidingName(node) { + var parent = node.parent; + switch (parent.kind) { + case 169 /* BindingElement */: + case 221 /* ClassDeclaration */: + case 224 /* EnumDeclaration */: + case 218 /* VariableDeclaration */: + return parent.name === node + && resolver.isDeclarationWithCollidingName(parent); + } + return false; + } + /** + * Substitutes an expression. + * + * @param node An Expression node. + */ + function substituteExpression(node) { + switch (node.kind) { + case 69 /* Identifier */: + return substituteExpressionIdentifier(node); + case 97 /* ThisKeyword */: + return substituteThisKeyword(node); + } + return node; + } + /** + * Substitutes an expression identifier. + * + * @param node An Identifier node. + */ + function substituteExpressionIdentifier(node) { + if (enabledSubstitutions & 2 /* BlockScopedBindings */) { + var declaration = resolver.getReferencedDeclarationWithCollidingName(node); + if (declaration) { + return ts.getGeneratedNameForNode(declaration.name); + } + } + return node; + } + /** + * Substitutes `this` when contained within an arrow function. + * + * @param node The ThisKeyword node. + */ + function substituteThisKeyword(node) { + if (enabledSubstitutions & 1 /* CapturedThis */ + && enclosingFunction + && ts.getEmitFlags(enclosingFunction) & 256 /* CapturesThis */) { + return ts.createIdentifier("_this", /*location*/ node); + } + return node; + } + /** + * Gets the local name for a declaration for use in expressions. + * + * A local name will *never* be prefixed with an module or namespace export modifier like + * "exports.". + * + * @param node The declaration. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ + function getLocalName(node, allowComments, allowSourceMaps) { + return getDeclarationName(node, allowComments, allowSourceMaps, 262144 /* LocalName */); + } + /** + * Gets the name of a declaration, without source map or comments. + * + * @param node The declaration. + * @param allowComments Allow comments for the name. + */ + function getDeclarationName(node, allowComments, allowSourceMaps, emitFlags) { + if (node.name && !ts.isGeneratedIdentifier(node.name)) { + var name_37 = ts.getMutableClone(node.name); + emitFlags |= ts.getEmitFlags(node.name); + if (!allowSourceMaps) { + emitFlags |= 1536 /* NoSourceMap */; } - // If we are exporting, but it's a top-level ES6 module exports, - // we'll emit the declaration list verbatim, so emit comments too. - if (isES6ExportedDeclaration(node)) { - return true; + if (!allowComments) { + emitFlags |= 49152 /* NoComments */; } - // Otherwise, only emit if we have at least one initializer present. - for (var _a = 0, _b = node.declarationList.declarations; _a < _b.length; _a++) { - var declaration = _b[_a]; - if (declaration.initializer) { - return true; - } + if (emitFlags) { + ts.setEmitFlags(name_37, emitFlags); } + return name_37; + } + return ts.getGeneratedNameForNode(node); + } + function getClassMemberPrefix(node, member) { + var expression = getLocalName(node); + return ts.hasModifier(member, 32 /* Static */) ? expression : ts.createPropertyAccess(expression, "prototype"); + } + function hasSynthesizedDefaultSuperCall(constructor, hasExtendsClause) { + if (!constructor || !hasExtendsClause) { return false; } - function emitParameter(node) { - if (languageVersion < 2 /* ES6 */) { - if (ts.isBindingPattern(node.name)) { - var name_31 = createTempVariable(0 /* Auto */); - if (!tempParameters) { - tempParameters = []; - } - tempParameters.push(name_31); - emit(name_31); - } - else { - emit(node.name); - } - } - else { - if (node.dotDotDotToken) { - write("..."); - } - emit(node.name); - emitOptional(" = ", node.initializer); - } + var parameter = ts.singleOrUndefined(constructor.parameters); + if (!parameter || !ts.nodeIsSynthesized(parameter) || !parameter.dotDotDotToken) { + return false; } - function emitDefaultValueAssignments(node) { - if (languageVersion < 2 /* ES6 */) { - var tempIndex_1 = 0; - ts.forEach(node.parameters, function (parameter) { - // A rest parameter cannot have a binding pattern or an initializer, - // so let's just ignore it. - if (parameter.dotDotDotToken) { - return; - } - var paramName = parameter.name, initializer = parameter.initializer; - if (ts.isBindingPattern(paramName)) { - // In cases where a binding pattern is simply '[]' or '{}', - // we usually don't want to emit a var declaration; however, in the presence - // of an initializer, we must emit that expression to preserve side effects. - var hasBindingElements = paramName.elements.length > 0; - if (hasBindingElements || initializer) { - writeLine(); - write("var "); - if (hasBindingElements) { - emitDestructuring(parameter, /*isAssignmentExpressionStatement*/ false, tempParameters[tempIndex_1]); - } - else { - emit(tempParameters[tempIndex_1]); - write(" = "); - emit(initializer); - } - write(";"); - } - // Regardless of whether we will emit a var declaration for the binding pattern, we generate the temporary - // variable for the parameter (see: emitParameter) - tempIndex_1++; - } - else if (initializer) { - writeLine(); - emitStart(parameter); - write("if ("); - emitNodeWithoutSourceMap(paramName); - write(" === void 0)"); - emitEnd(parameter); - write(" { "); - emitStart(parameter); - emitNodeWithCommentsAndWithoutSourcemap(paramName); - write(" = "); - emitNodeWithCommentsAndWithoutSourcemap(initializer); - emitEnd(parameter); - write("; }"); - } - }); - } + var statement = ts.firstOrUndefined(constructor.body.statements); + if (!statement || !ts.nodeIsSynthesized(statement) || statement.kind !== 202 /* ExpressionStatement */) { + return false; } - function emitRestParameter(node) { - if (languageVersion < 2 /* ES6 */ && ts.hasDeclaredRestParameter(node)) { - var restParam = node.parameters[node.parameters.length - 1]; - // A rest parameter cannot have a binding pattern, so let's just ignore it if it does. - if (ts.isBindingPattern(restParam.name)) { - return; - } - var skipThisCount = node.parameters.length && node.parameters[0].name.originalKeywordKind === 97 /* ThisKeyword */ ? 1 : 0; - var restIndex = node.parameters.length - 1 - skipThisCount; - var tempName = createTempVariable(268435456 /* _i */).text; - writeLine(); - emitLeadingComments(restParam); - emitStart(restParam); - write("var "); - emitNodeWithCommentsAndWithoutSourcemap(restParam.name); - write(" = [];"); - emitEnd(restParam); - emitTrailingComments(restParam); - writeLine(); - write("for ("); - emitStart(restParam); - write("var " + tempName + " = " + restIndex + ";"); - emitEnd(restParam); - write(" "); - emitStart(restParam); - write(tempName + " < arguments.length;"); - emitEnd(restParam); - write(" "); - emitStart(restParam); - write(tempName + "++"); - emitEnd(restParam); - write(") {"); - increaseIndent(); - writeLine(); - emitStart(restParam); - emitNodeWithCommentsAndWithoutSourcemap(restParam.name); - write("[" + tempName + " - " + restIndex + "] = arguments[" + tempName + "];"); - emitEnd(restParam); - decreaseIndent(); - writeLine(); - write("}"); - } + var statementExpression = statement.expression; + if (!ts.nodeIsSynthesized(statementExpression) || statementExpression.kind !== 174 /* CallExpression */) { + return false; } - function emitAccessor(node) { - write(node.kind === 149 /* GetAccessor */ ? "get " : "set "); - emit(node.name); - emitSignatureAndBody(node); + var callTarget = statementExpression.expression; + if (!ts.nodeIsSynthesized(callTarget) || callTarget.kind !== 95 /* SuperKeyword */) { + return false; } - function shouldEmitAsArrowFunction(node) { - return node.kind === 180 /* ArrowFunction */ && languageVersion >= 2 /* ES6 */; + var callArgument = ts.singleOrUndefined(statementExpression.arguments); + if (!callArgument || !ts.nodeIsSynthesized(callArgument) || callArgument.kind !== 191 /* SpreadElementExpression */) { + return false; } - function emitDeclarationName(node) { - if (node.name) { - emitNodeWithCommentsAndWithoutSourcemap(node.name); - } - else { - write(getGeneratedNameForNode(node)); - } + var expression = callArgument.expression; + return ts.isIdentifier(expression) && expression === parameter.name; + } + } + ts.transformES6 = transformES6; +})(ts || (ts = {})); +/// +/// +// Transforms generator functions into a compatible ES5 representation with similar runtime +// semantics. This is accomplished by first transforming the body of each generator +// function into an intermediate representation that is the compiled into a JavaScript +// switch statement. +// +// Many functions in this transformer will contain comments indicating the expected +// intermediate representation. For illustrative purposes, the following intermediate +// language is used to define this intermediate representation: +// +// .nop - Performs no operation. +// .local NAME, ... - Define local variable declarations. +// .mark LABEL - Mark the location of a label. +// .br LABEL - Jump to a label. If jumping out of a protected +// region, all .finally blocks are executed. +// .brtrue LABEL, (x) - Jump to a label IIF the expression `x` is truthy. +// If jumping out of a protected region, all .finally +// blocks are executed. +// .brfalse LABEL, (x) - Jump to a label IIF the expression `x` is falsey. +// If jumping out of a protected region, all .finally +// blocks are executed. +// .yield (x) - Yield the value of the optional expression `x`. +// Resume at the next label. +// .yieldstar (x) - Delegate yield to the value of the optional +// expression `x`. Resume at the next label. +// NOTE: `x` must be an Iterator, not an Iterable. +// .loop CONTINUE, BREAK - Marks the beginning of a loop. Any "continue" or +// "break" abrupt completions jump to the CONTINUE or +// BREAK labels, respectively. +// .endloop - Marks the end of a loop. +// .with (x) - Marks the beginning of a WithStatement block, using +// the supplied expression. +// .endwith - Marks the end of a WithStatement. +// .switch - Marks the beginning of a SwitchStatement. +// .endswitch - Marks the end of a SwitchStatement. +// .labeled NAME - Marks the beginning of a LabeledStatement with the +// supplied name. +// .endlabeled - Marks the end of a LabeledStatement. +// .try TRY, CATCH, FINALLY, END - Marks the beginning of a protected region, and the +// labels for each block. +// .catch (x) - Marks the beginning of a catch block. +// .finally - Marks the beginning of a finally block. +// .endfinally - Marks the end of a finally block. +// .endtry - Marks the end of a protected region. +// .throw (x) - Throws the value of the expression `x`. +// .return (x) - Returns the value of the expression `x`. +// +// In addition, the illustrative intermediate representation introduces some special +// variables: +// +// %sent% - Either returns the next value sent to the generator, +// returns the result of a delegated yield, or throws +// the exception sent to the generator. +// %error% - Returns the value of the current exception in a +// catch block. +// +// This intermediate representation is then compiled into JavaScript syntax. The resulting +// compilation output looks something like the following: +// +// function f() { +// var /*locals*/; +// /*functions*/ +// return __generator(function (state) { +// switch (state.label) { +// /*cases per label*/ +// } +// }); +// } +// +// Each of the above instructions corresponds to JavaScript emit similar to the following: +// +// .local NAME | var NAME; +// -------------------------------|---------------------------------------------- +// .mark LABEL | case LABEL: +// -------------------------------|---------------------------------------------- +// .br LABEL | return [3 /*break*/, LABEL]; +// -------------------------------|---------------------------------------------- +// .brtrue LABEL, (x) | if (x) return [3 /*break*/, LABEL]; +// -------------------------------|---------------------------------------------- +// .brfalse LABEL, (x) | if (!(x)) return [3, /*break*/, LABEL]; +// -------------------------------|---------------------------------------------- +// .yield (x) | return [4 /*yield*/, x]; +// .mark RESUME | case RESUME: +// a = %sent%; | a = state.sent(); +// -------------------------------|---------------------------------------------- +// .yieldstar (x) | return [5 /*yield**/, x]; +// .mark RESUME | case RESUME: +// a = %sent%; | a = state.sent(); +// -------------------------------|---------------------------------------------- +// .with (_a) | with (_a) { +// a(); | a(); +// | } +// | state.label = LABEL; +// .mark LABEL | case LABEL: +// | with (_a) { +// b(); | b(); +// | } +// .endwith | +// -------------------------------|---------------------------------------------- +// | case 0: +// | state.trys = []; +// | ... +// .try TRY, CATCH, FINALLY, END | +// .mark TRY | case TRY: +// | state.trys.push([TRY, CATCH, FINALLY, END]); +// .nop | +// a(); | a(); +// .br END | return [3 /*break*/, END]; +// .catch (e) | +// .mark CATCH | case CATCH: +// | e = state.sent(); +// b(); | b(); +// .br END | return [3 /*break*/, END]; +// .finally | +// .mark FINALLY | case FINALLY: +// c(); | c(); +// .endfinally | return [7 /*endfinally*/]; +// .endtry | +// .mark END | case END: +/*@internal*/ +var ts; +(function (ts) { + var OpCode; + (function (OpCode) { + OpCode[OpCode["Nop"] = 0] = "Nop"; + OpCode[OpCode["Statement"] = 1] = "Statement"; + OpCode[OpCode["Assign"] = 2] = "Assign"; + OpCode[OpCode["Break"] = 3] = "Break"; + OpCode[OpCode["BreakWhenTrue"] = 4] = "BreakWhenTrue"; + OpCode[OpCode["BreakWhenFalse"] = 5] = "BreakWhenFalse"; + OpCode[OpCode["Yield"] = 6] = "Yield"; + OpCode[OpCode["YieldStar"] = 7] = "YieldStar"; + OpCode[OpCode["Return"] = 8] = "Return"; + OpCode[OpCode["Throw"] = 9] = "Throw"; + OpCode[OpCode["Endfinally"] = 10] = "Endfinally"; // Marks the end of a `finally` block + })(OpCode || (OpCode = {})); + // whether a generated code block is opening or closing at the current operation for a FunctionBuilder + var BlockAction; + (function (BlockAction) { + BlockAction[BlockAction["Open"] = 0] = "Open"; + BlockAction[BlockAction["Close"] = 1] = "Close"; + })(BlockAction || (BlockAction = {})); + // the kind for a generated code block in a FunctionBuilder + var CodeBlockKind; + (function (CodeBlockKind) { + CodeBlockKind[CodeBlockKind["Exception"] = 0] = "Exception"; + CodeBlockKind[CodeBlockKind["With"] = 1] = "With"; + CodeBlockKind[CodeBlockKind["Switch"] = 2] = "Switch"; + CodeBlockKind[CodeBlockKind["Loop"] = 3] = "Loop"; + CodeBlockKind[CodeBlockKind["Labeled"] = 4] = "Labeled"; + })(CodeBlockKind || (CodeBlockKind = {})); + // the state for a generated code exception block + var ExceptionBlockState; + (function (ExceptionBlockState) { + ExceptionBlockState[ExceptionBlockState["Try"] = 0] = "Try"; + ExceptionBlockState[ExceptionBlockState["Catch"] = 1] = "Catch"; + ExceptionBlockState[ExceptionBlockState["Finally"] = 2] = "Finally"; + ExceptionBlockState[ExceptionBlockState["Done"] = 3] = "Done"; + })(ExceptionBlockState || (ExceptionBlockState = {})); + // NOTE: changes to this enum should be reflected in the __generator helper. + var Instruction; + (function (Instruction) { + Instruction[Instruction["Next"] = 0] = "Next"; + Instruction[Instruction["Throw"] = 1] = "Throw"; + Instruction[Instruction["Return"] = 2] = "Return"; + Instruction[Instruction["Break"] = 3] = "Break"; + Instruction[Instruction["Yield"] = 4] = "Yield"; + Instruction[Instruction["YieldStar"] = 5] = "YieldStar"; + Instruction[Instruction["Catch"] = 6] = "Catch"; + Instruction[Instruction["Endfinally"] = 7] = "Endfinally"; + })(Instruction || (Instruction = {})); + var instructionNames = ts.createMap((_a = {}, + _a[2 /* Return */] = "return", + _a[3 /* Break */] = "break", + _a[4 /* Yield */] = "yield", + _a[5 /* YieldStar */] = "yield*", + _a[7 /* Endfinally */] = "endfinally", + _a)); + function transformGenerators(context) { + var startLexicalEnvironment = context.startLexicalEnvironment, endLexicalEnvironment = context.endLexicalEnvironment, hoistFunctionDeclaration = context.hoistFunctionDeclaration, hoistVariableDeclaration = context.hoistVariableDeclaration; + var compilerOptions = context.getCompilerOptions(); + var languageVersion = ts.getEmitScriptTarget(compilerOptions); + var resolver = context.getEmitResolver(); + var previousOnSubstituteNode = context.onSubstituteNode; + context.onSubstituteNode = onSubstituteNode; + var currentSourceFile; + var renamedCatchVariables; + var renamedCatchVariableDeclarations; + var inGeneratorFunctionBody; + var inStatementContainingYield; + // The following three arrays store information about generated code blocks. + // All three arrays are correlated by their index. This approach is used over allocating + // objects to store the same information to avoid GC overhead. + // + var blocks; // Information about the code block + var blockOffsets; // The operation offset at which a code block begins or ends + var blockActions; // Whether the code block is opened or closed + var blockStack; // A stack of currently open code blocks + // Labels are used to mark locations in the code that can be the target of a Break (jump) + // operation. These are translated into case clauses in a switch statement. + // The following two arrays are correlated by their index. This approach is used over + // allocating objects to store the same information to avoid GC overhead. + // + var labelOffsets; // The operation offset at which the label is defined. + var labelExpressions; // The NumericLiteral nodes bound to each label. + var nextLabelId = 1; // The next label id to use. + // Operations store information about generated code for the function body. This + // Includes things like statements, assignments, breaks (jumps), and yields. + // The following three arrays are correlated by their index. This approach is used over + // allocating objects to store the same information to avoid GC overhead. + // + var operations; // The operation to perform. + var operationArguments; // The arguments to the operation. + var operationLocations; // The source map location for the operation. + var state; // The name of the state object used by the generator at runtime. + // The following variables store information used by the `build` function: + // + var blockIndex = 0; // The index of the current block. + var labelNumber = 0; // The current label number. + var labelNumbers; + var lastOperationWasAbrupt; // Indicates whether the last operation was abrupt (break/continue). + var lastOperationWasCompletion; // Indicates whether the last operation was a completion (return/throw). + var clauses; // The case clauses generated for labels. + var statements; // The statements for the current label. + var exceptionBlockStack; // A stack of containing exception blocks. + var currentExceptionBlock; // The current exception block. + var withBlockStack; // A stack containing `with` blocks. + return transformSourceFile; + function transformSourceFile(node) { + if (ts.isDeclarationFile(node)) { + return node; } - function shouldEmitFunctionName(node) { - if (node.kind === 179 /* FunctionExpression */) { - // Emit name if one is present - return !!node.name; - } - if (node.kind === 220 /* FunctionDeclaration */) { - // Emit name if one is present, or emit generated name in down-level case (for export default case) - return !!node.name || modulekind !== ts.ModuleKind.ES6; - } - } - function emitFunctionDeclaration(node) { - if (ts.nodeIsMissing(node.body)) { - return emitCommentsOnNotEmittedNode(node); - } - // TODO (yuisu) : we should not have special cases to condition emitting comments - // but have one place to fix check for these conditions. - var kind = node.kind, parent = node.parent; - if (kind !== 147 /* MethodDeclaration */ && - kind !== 146 /* MethodSignature */ && - parent && - parent.kind !== 253 /* PropertyAssignment */ && - parent.kind !== 174 /* CallExpression */ && - parent.kind !== 170 /* ArrayLiteralExpression */) { - // 1. Methods will emit comments at their assignment declaration sites. - // - // 2. If the function is a property of object literal, emitting leading-comments - // is done by emitNodeWithoutSourceMap which then call this function. - // In particular, we would like to avoid emit comments twice in following case: - // - // var obj = { - // id: - // /*comment*/ () => void - // } - // - // 3. If the function is an argument in call expression, emitting of comments will be - // taken care of in emit list of arguments inside of 'emitCallExpression'. - // - // 4. If the function is in an array literal, 'emitLinePreservingList' will take care - // of leading comments. - emitLeadingComments(node); - } - emitStart(node); - // For targeting below es6, emit functions-like declaration including arrow function using function keyword. - // When targeting ES6, emit arrow function natively in ES6 by omitting function keyword and using fat arrow instead - if (!shouldEmitAsArrowFunction(node)) { - if (isES6ExportedDeclaration(node)) { - write("export "); - if (node.flags & 512 /* Default */) { - write("default "); - } - } - write("function"); - if (languageVersion >= 2 /* ES6 */ && node.asteriskToken) { - write("*"); - } - write(" "); - } - if (shouldEmitFunctionName(node)) { - emitDeclarationName(node); - } - emitSignatureAndBody(node); - if (modulekind !== ts.ModuleKind.ES6 && kind === 220 /* FunctionDeclaration */ && parent === currentSourceFile && node.name) { - emitExportMemberAssignments(node.name); - } - emitEnd(node); - if (kind !== 147 /* MethodDeclaration */ && - kind !== 146 /* MethodSignature */ && - kind !== 180 /* ArrowFunction */) { - emitTrailingComments(node); - } + if (node.transformFlags & 1024 /* ContainsGenerator */) { + currentSourceFile = node; + node = ts.visitEachChild(node, visitor, context); + currentSourceFile = undefined; } - function emitCaptureThisForNodeIfNecessary(node) { - if (resolver.getNodeCheckFlags(node) & 4 /* CaptureThis */) { - writeLine(); - emitStart(node); - write("var _this = this;"); - emitEnd(node); - } + return node; + } + /** + * Visits a node. + * + * @param node The node to visit. + */ + function visitor(node) { + var transformFlags = node.transformFlags; + if (inStatementContainingYield) { + return visitJavaScriptInStatementContainingYield(node); } - function emitSignatureParameters(node) { - increaseIndent(); - write("("); - if (node) { - var parameters = node.parameters; - var skipCount = node.parameters.length && node.parameters[0].name.originalKeywordKind === 97 /* ThisKeyword */ ? 1 : 0; - var omitCount = languageVersion < 2 /* ES6 */ && ts.hasDeclaredRestParameter(node) ? 1 : 0; - emitList(parameters, skipCount, parameters.length - omitCount - skipCount, /*multiLine*/ false, /*trailingComma*/ false); - } - write(")"); - decreaseIndent(); + else if (inGeneratorFunctionBody) { + return visitJavaScriptInGeneratorFunctionBody(node); } - function emitSignatureParametersForArrow(node) { - // Check whether the parameter list needs parentheses and preserve no-parenthesis - if (node.parameters.length === 1 && node.pos === node.parameters[0].pos) { - emit(node.parameters[0]); - return; - } - emitSignatureParameters(node); - } - function emitAsyncFunctionBodyForES6(node) { - var promiseConstructor = ts.getEntityNameFromTypeNode(node.type); - var isArrowFunction = node.kind === 180 /* ArrowFunction */; - var hasLexicalArguments = (resolver.getNodeCheckFlags(node) & 8192 /* CaptureArguments */) !== 0; - // An async function is emit as an outer function that calls an inner - // generator function. To preserve lexical bindings, we pass the current - // `this` and `arguments` objects to `__awaiter`. The generator function - // passed to `__awaiter` is executed inside of the callback to the - // promise constructor. - // - // The emit for an async arrow without a lexical `arguments` binding might be: - // - // // input - // let a = async (b) => { await b; } - // - // // output - // let a = (b) => __awaiter(this, void 0, void 0, function* () { - // yield b; - // }); - // - // The emit for an async arrow with a lexical `arguments` binding might be: - // - // // input - // let a = async (b) => { await arguments[0]; } - // - // // output - // let a = (b) => __awaiter(this, arguments, void 0, function* (arguments) { - // yield arguments[0]; - // }); - // - // The emit for an async function expression without a lexical `arguments` binding - // might be: - // - // // input - // let a = async function (b) { - // await b; - // } - // - // // output - // let a = function (b) { - // return __awaiter(this, void 0, void 0, function* () { - // yield b; - // }); - // } - // - // The emit for an async function expression with a lexical `arguments` binding - // might be: - // - // // input - // let a = async function (b) { - // await arguments[0]; - // } - // - // // output - // let a = function (b) { - // return __awaiter(this, arguments, void 0, function* (_arguments) { - // yield _arguments[0]; - // }); - // } - // - // The emit for an async function expression with a lexical `arguments` binding - // and a return type annotation might be: - // - // // input - // let a = async function (b): MyPromise { - // await arguments[0]; - // } - // - // // output - // let a = function (b) { - // return __awaiter(this, arguments, MyPromise, function* (_arguments) { - // yield _arguments[0]; - // }); - // } - // - // If this is not an async arrow, emit the opening brace of the function body - // and the start of the return statement. - if (!isArrowFunction) { - write(" {"); - increaseIndent(); - writeLine(); - if (resolver.getNodeCheckFlags(node) & 4096 /* AsyncMethodWithSuperBinding */) { - writeLines("\nconst _super = (function (geti, seti) {\n const cache = Object.create(null);\n return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });\n})(name => super[name], (name, value) => super[name] = value);"); - writeLine(); - } - else if (resolver.getNodeCheckFlags(node) & 2048 /* AsyncMethodWithSuper */) { - write("const _super = name => super[name];"); - writeLine(); - } - write("return"); - } - write(" __awaiter(this"); - if (hasLexicalArguments) { - write(", arguments, "); - } - else { - write(", void 0, "); - } - if (languageVersion >= 2 /* ES6 */ || !promiseConstructor) { - write("void 0"); - } - else { - emitEntityNameAsExpression(promiseConstructor, /*useFallback*/ false); - } - // Emit the call to __awaiter. - write(", function* ()"); - // Emit the signature and body for the inner generator function. - emitFunctionBody(node); - write(")"); - // If this is not an async arrow, emit the closing brace of the outer function body. - if (!isArrowFunction) { - write(";"); - decreaseIndent(); - writeLine(); - write("}"); - } + else if (transformFlags & 512 /* Generator */) { + return visitGenerator(node); } - function emitFunctionBody(node) { - if (!node.body) { - // There can be no body when there are parse errors. Just emit an empty block - // in that case. - write(" { }"); - } - else { - if (node.body.kind === 199 /* Block */) { - emitBlockFunctionBody(node, node.body); + else if (transformFlags & 1024 /* ContainsGenerator */) { + return ts.visitEachChild(node, visitor, context); + } + else { + return node; + } + } + /** + * Visits a node that is contained within a statement that contains yield. + * + * @param node The node to visit. + */ + function visitJavaScriptInStatementContainingYield(node) { + switch (node.kind) { + case 204 /* DoStatement */: + return visitDoStatement(node); + case 205 /* WhileStatement */: + return visitWhileStatement(node); + case 213 /* SwitchStatement */: + return visitSwitchStatement(node); + case 214 /* LabeledStatement */: + return visitLabeledStatement(node); + default: + return visitJavaScriptInGeneratorFunctionBody(node); + } + } + /** + * Visits a node that is contained within a generator function. + * + * @param node The node to visit. + */ + function visitJavaScriptInGeneratorFunctionBody(node) { + switch (node.kind) { + case 220 /* FunctionDeclaration */: + return visitFunctionDeclaration(node); + case 179 /* FunctionExpression */: + return visitFunctionExpression(node); + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + return visitAccessorDeclaration(node); + case 200 /* VariableStatement */: + return visitVariableStatement(node); + case 206 /* ForStatement */: + return visitForStatement(node); + case 207 /* ForInStatement */: + return visitForInStatement(node); + case 210 /* BreakStatement */: + return visitBreakStatement(node); + case 209 /* ContinueStatement */: + return visitContinueStatement(node); + case 211 /* ReturnStatement */: + return visitReturnStatement(node); + default: + if (node.transformFlags & 4194304 /* ContainsYield */) { + return visitJavaScriptContainingYield(node); + } + else if (node.transformFlags & (1024 /* ContainsGenerator */ | 8388608 /* ContainsHoistedDeclarationOrCompletion */)) { + return ts.visitEachChild(node, visitor, context); } else { - emitExpressionFunctionBody(node, node.body); + return node; } - } } - function emitSignatureAndBody(node) { - var saveConvertedLoopState = convertedLoopState; - var saveTempFlags = tempFlags; - var saveTempVariables = tempVariables; - var saveTempParameters = tempParameters; - convertedLoopState = undefined; - tempFlags = 0; - tempVariables = undefined; - tempParameters = undefined; - // When targeting ES6, emit arrow function natively in ES6 - if (shouldEmitAsArrowFunction(node)) { - emitSignatureParametersForArrow(node); - write(" =>"); - } - else { - emitSignatureParameters(node); - } - var isAsync = ts.isAsyncFunctionLike(node); - if (isAsync) { - emitAsyncFunctionBodyForES6(node); - } - else { - emitFunctionBody(node); - } - if (!isES6ExportedDeclaration(node)) { - emitExportMemberAssignment(node); - } - ts.Debug.assert(convertedLoopState === undefined); - convertedLoopState = saveConvertedLoopState; - tempFlags = saveTempFlags; - tempVariables = saveTempVariables; - tempParameters = saveTempParameters; - } - // Returns true if any preamble code was emitted. - function emitFunctionBodyPreamble(node) { - emitCaptureThisForNodeIfNecessary(node); - emitDefaultValueAssignments(node); - emitRestParameter(node); - } - function emitExpressionFunctionBody(node, body) { - if (languageVersion < 2 /* ES6 */ || node.flags & 256 /* Async */) { - emitDownLevelExpressionFunctionBody(node, body); - return; - } - // For es6 and higher we can emit the expression as is. However, in the case - // where the expression might end up looking like a block when emitted, we'll - // also wrap it in parentheses first. For example if you have: a => {} - // then we need to generate: a => ({}) - write(" "); - // Unwrap all type assertions. - var current = body; - while (current.kind === 177 /* TypeAssertionExpression */) { - current = current.expression; - } - emitParenthesizedIf(body, current.kind === 171 /* ObjectLiteralExpression */); + } + /** + * Visits a node that contains a YieldExpression. + * + * @param node The node to visit. + */ + function visitJavaScriptContainingYield(node) { + switch (node.kind) { + case 187 /* BinaryExpression */: + return visitBinaryExpression(node); + case 188 /* ConditionalExpression */: + return visitConditionalExpression(node); + case 190 /* YieldExpression */: + return visitYieldExpression(node); + case 170 /* ArrayLiteralExpression */: + return visitArrayLiteralExpression(node); + case 171 /* ObjectLiteralExpression */: + return visitObjectLiteralExpression(node); + case 173 /* ElementAccessExpression */: + return visitElementAccessExpression(node); + case 174 /* CallExpression */: + return visitCallExpression(node); + case 175 /* NewExpression */: + return visitNewExpression(node); + default: + return ts.visitEachChild(node, visitor, context); } - function emitDownLevelExpressionFunctionBody(node, body) { - write(" {"); - increaseIndent(); - var outPos = writer.getTextPos(); - emitDetachedCommentsAndUpdateCommentsInfo(node.body); - emitFunctionBodyPreamble(node); - var preambleEmitted = writer.getTextPos() !== outPos; - decreaseIndent(); - // If we didn't have to emit any preamble code, then attempt to keep the arrow - // function on one line. - if (!preambleEmitted && nodeStartPositionsAreOnSameLine(node, body)) { - write(" "); - emitStart(body); - write("return "); - emit(body); - emitEnd(body); - write(";"); - emitTempDeclarations(/*newLine*/ false); - write(" "); - } - else { - increaseIndent(); - writeLine(); - emitLeadingComments(node.body); - emitStart(body); - write("return "); - emit(body); - emitEnd(body); - write(";"); - emitTrailingComments(node.body); - emitTempDeclarations(/*newLine*/ true); - decreaseIndent(); - writeLine(); - } - emitStart(node.body); - write("}"); - emitEnd(node.body); + } + /** + * Visits a generator function. + * + * @param node The node to visit. + */ + function visitGenerator(node) { + switch (node.kind) { + case 220 /* FunctionDeclaration */: + return visitFunctionDeclaration(node); + case 179 /* FunctionExpression */: + return visitFunctionExpression(node); + default: + ts.Debug.failBadSyntaxKind(node); + return ts.visitEachChild(node, visitor, context); } - function emitBlockFunctionBody(node, body) { - write(" {"); - var initialTextPos = writer.getTextPos(); - increaseIndent(); - emitDetachedCommentsAndUpdateCommentsInfo(body.statements); - // Emit all the directive prologues (like "use strict"). These have to come before - // any other preamble code we write (like parameter initializers). - var startIndex = emitDirectivePrologues(body.statements, /*startWithNewLine*/ true); - emitFunctionBodyPreamble(node); - decreaseIndent(); - var preambleEmitted = writer.getTextPos() !== initialTextPos; - if (!preambleEmitted && nodeEndIsOnSameLineAsNodeStart(body, body)) { - for (var _a = 0, _b = body.statements; _a < _b.length; _a++) { - var statement = _b[_a]; - write(" "); - emit(statement); - } - emitTempDeclarations(/*newLine*/ false); - write(" "); - emitLeadingCommentsOfPosition(body.statements.end); - } - else { - increaseIndent(); - emitLinesStartingAt(body.statements, startIndex); - emitTempDeclarations(/*newLine*/ true); - writeLine(); - emitLeadingCommentsOfPosition(body.statements.end); - decreaseIndent(); - } - emitToken(16 /* CloseBraceToken */, body.statements.end); + } + /** + * Visits a function declaration. + * + * This will be called when one of the following conditions are met: + * - The function declaration is a generator function. + * - The function declaration is contained within the body of a generator function. + * + * @param node The node to visit. + */ + function visitFunctionDeclaration(node) { + // Currently, we only support generators that were originally async functions. + if (node.asteriskToken && ts.getEmitFlags(node) & 2097152 /* AsyncFunctionBody */) { + node = ts.setOriginalNode(ts.createFunctionDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, node.name, + /*typeParameters*/ undefined, node.parameters, + /*type*/ undefined, transformGeneratorFunctionBody(node.body), + /*location*/ node), node); } - /** - * Return the statement at a given index if it is a super-call statement - * @param ctor a constructor declaration - * @param index an index to constructor's body to check - */ - function getSuperCallAtGivenIndex(ctor, index) { - if (!ctor.body) { - return undefined; - } - var statements = ctor.body.statements; - if (!statements || index >= statements.length) { - return undefined; - } - var statement = statements[index]; - if (statement.kind === 202 /* ExpressionStatement */) { - return ts.isSuperCallExpression(statement.expression) ? statement : undefined; - } + else { + var savedInGeneratorFunctionBody = inGeneratorFunctionBody; + var savedInStatementContainingYield = inStatementContainingYield; + inGeneratorFunctionBody = false; + inStatementContainingYield = false; + node = ts.visitEachChild(node, visitor, context); + inGeneratorFunctionBody = savedInGeneratorFunctionBody; + inStatementContainingYield = savedInStatementContainingYield; + } + if (inGeneratorFunctionBody) { + // Function declarations in a generator function body are hoisted + // to the top of the lexical scope and elided from the current statement. + hoistFunctionDeclaration(node); + return undefined; } - function emitParameterPropertyAssignments(node) { - ts.forEach(node.parameters, function (param) { - if (param.flags & 92 /* ParameterPropertyModifier */) { - writeLine(); - emitStart(param); - emitStart(param.name); - write("this."); - emitNodeWithoutSourceMap(param.name); - emitEnd(param.name); - write(" = "); - emit(param.name); - write(";"); - emitEnd(param); - } - }); + else { + return node; } - function emitMemberAccessForPropertyName(memberName) { - // This does not emit source map because it is emitted by caller as caller - // is aware how the property name changes to the property access - // eg. public x = 10; becomes this.x and static x = 10 becomes className.x - if (memberName.kind === 9 /* StringLiteral */ || memberName.kind === 8 /* NumericLiteral */) { - write("["); - emitNodeWithCommentsAndWithoutSourcemap(memberName); - write("]"); - } - else if (memberName.kind === 140 /* ComputedPropertyName */) { - emitComputedPropertyName(memberName); - } - else { - write("."); - emitNodeWithCommentsAndWithoutSourcemap(memberName); - } + } + /** + * Visits a function expression. + * + * This will be called when one of the following conditions are met: + * - The function expression is a generator function. + * - The function expression is contained within the body of a generator function. + * + * @param node The node to visit. + */ + function visitFunctionExpression(node) { + // Currently, we only support generators that were originally async functions. + if (node.asteriskToken && ts.getEmitFlags(node) & 2097152 /* AsyncFunctionBody */) { + node = ts.setOriginalNode(ts.createFunctionExpression( + /*asteriskToken*/ undefined, node.name, + /*typeParameters*/ undefined, node.parameters, + /*type*/ undefined, transformGeneratorFunctionBody(node.body), + /*location*/ node), node); } - function getInitializedProperties(node, isStatic) { - var properties = []; - for (var _a = 0, _b = node.members; _a < _b.length; _a++) { - var member = _b[_a]; - if (member.kind === 145 /* PropertyDeclaration */ && isStatic === ((member.flags & 32 /* Static */) !== 0) && member.initializer) { - properties.push(member); - } - } - return properties; + else { + var savedInGeneratorFunctionBody = inGeneratorFunctionBody; + var savedInStatementContainingYield = inStatementContainingYield; + inGeneratorFunctionBody = false; + inStatementContainingYield = false; + node = ts.visitEachChild(node, visitor, context); + inGeneratorFunctionBody = savedInGeneratorFunctionBody; + inStatementContainingYield = savedInStatementContainingYield; } - function emitPropertyDeclarations(node, properties) { - for (var _a = 0, properties_6 = properties; _a < properties_6.length; _a++) { - var property = properties_6[_a]; - emitPropertyDeclaration(node, property); - } + return node; + } + /** + * Visits a get or set accessor declaration. + * + * This will be called when one of the following conditions are met: + * - The accessor is contained within the body of a generator function. + * + * @param node The node to visit. + */ + function visitAccessorDeclaration(node) { + var savedInGeneratorFunctionBody = inGeneratorFunctionBody; + var savedInStatementContainingYield = inStatementContainingYield; + inGeneratorFunctionBody = false; + inStatementContainingYield = false; + node = ts.visitEachChild(node, visitor, context); + inGeneratorFunctionBody = savedInGeneratorFunctionBody; + inStatementContainingYield = savedInStatementContainingYield; + return node; + } + /** + * Transforms the body of a generator function declaration. + * + * @param node The function body to transform. + */ + function transformGeneratorFunctionBody(body) { + // Save existing generator state + var statements = []; + var savedInGeneratorFunctionBody = inGeneratorFunctionBody; + var savedInStatementContainingYield = inStatementContainingYield; + var savedBlocks = blocks; + var savedBlockOffsets = blockOffsets; + var savedBlockActions = blockActions; + var savedLabelOffsets = labelOffsets; + var savedLabelExpressions = labelExpressions; + var savedNextLabelId = nextLabelId; + var savedOperations = operations; + var savedOperationArguments = operationArguments; + var savedOperationLocations = operationLocations; + var savedState = state; + // Initialize generator state + inGeneratorFunctionBody = true; + inStatementContainingYield = false; + blocks = undefined; + blockOffsets = undefined; + blockActions = undefined; + labelOffsets = undefined; + labelExpressions = undefined; + nextLabelId = 1; + operations = undefined; + operationArguments = undefined; + operationLocations = undefined; + state = ts.createTempVariable(/*recordTempVariable*/ undefined); + // Build the generator + startLexicalEnvironment(); + var statementOffset = ts.addPrologueDirectives(statements, body.statements, /*ensureUseStrict*/ false, visitor); + transformAndEmitStatements(body.statements, statementOffset); + var buildResult = build(); + ts.addRange(statements, endLexicalEnvironment()); + statements.push(ts.createReturn(buildResult)); + // Restore previous generator state + inGeneratorFunctionBody = savedInGeneratorFunctionBody; + inStatementContainingYield = savedInStatementContainingYield; + blocks = savedBlocks; + blockOffsets = savedBlockOffsets; + blockActions = savedBlockActions; + labelOffsets = savedLabelOffsets; + labelExpressions = savedLabelExpressions; + nextLabelId = savedNextLabelId; + operations = savedOperations; + operationArguments = savedOperationArguments; + operationLocations = savedOperationLocations; + state = savedState; + return ts.createBlock(statements, /*location*/ body, body.multiLine); + } + /** + * Visits a variable statement. + * + * This will be called when one of the following conditions are met: + * - The variable statement is contained within the body of a generator function. + * + * @param node The node to visit. + */ + function visitVariableStatement(node) { + if (node.transformFlags & 4194304 /* ContainsYield */) { + transformAndEmitVariableDeclarationList(node.declarationList); + return undefined; } - function emitPropertyDeclaration(node, property, receiver, isExpression) { - writeLine(); - emitLeadingComments(property); - emitStart(property); - emitStart(property.name); - if (receiver) { - write(receiver); + else { + // Do not hoist custom prologues. + if (ts.getEmitFlags(node) & 8388608 /* CustomPrologue */) { + return node; } - else { - if (property.flags & 32 /* Static */) { - emitDeclarationName(node); - } - else { - write("this"); - } + for (var _i = 0, _a = node.declarationList.declarations; _i < _a.length; _i++) { + var variable = _a[_i]; + hoistVariableDeclaration(variable.name); } - emitMemberAccessForPropertyName(property.name); - emitEnd(property.name); - write(" = "); - emit(property.initializer); - if (!isExpression) { - write(";"); + var variables = ts.getInitializedVariables(node.declarationList); + if (variables.length === 0) { + return undefined; } - emitEnd(property); - emitTrailingComments(property); + return ts.createStatement(ts.inlineExpressions(ts.map(variables, transformInitializedVariable))); } - function emitMemberFunctionsForES5AndLower(node) { - ts.forEach(node.members, function (member) { - if (member.kind === 198 /* SemicolonClassElement */) { - writeLine(); - write(";"); - } - else if (member.kind === 147 /* MethodDeclaration */ || node.kind === 146 /* MethodSignature */) { - if (!member.body) { - return emitCommentsOnNotEmittedNode(member); - } - writeLine(); - emitLeadingComments(member); - emitStart(member); - emitStart(member.name); - emitClassMemberPrefix(node, member); - emitMemberAccessForPropertyName(member.name); - emitEnd(member.name); - write(" = "); - emitFunctionDeclaration(member); - emitEnd(member); - write(";"); - emitTrailingComments(member); - } - else if (member.kind === 149 /* GetAccessor */ || member.kind === 150 /* SetAccessor */) { - var accessors = ts.getAllAccessorDeclarations(node.members, member); - if (member === accessors.firstAccessor) { - writeLine(); - emitStart(member); - write("Object.defineProperty("); - emitStart(member.name); - emitClassMemberPrefix(node, member); - write(", "); - emitExpressionForPropertyName(member.name); - emitEnd(member.name); - write(", {"); - increaseIndent(); - if (accessors.getAccessor) { - writeLine(); - emitLeadingComments(accessors.getAccessor); - write("get: "); - emitStart(accessors.getAccessor); - write("function "); - emitSignatureAndBody(accessors.getAccessor); - emitEnd(accessors.getAccessor); - emitTrailingComments(accessors.getAccessor); - write(","); - } - if (accessors.setAccessor) { - writeLine(); - emitLeadingComments(accessors.setAccessor); - write("set: "); - emitStart(accessors.setAccessor); - write("function "); - emitSignatureAndBody(accessors.setAccessor); - emitEnd(accessors.setAccessor); - emitTrailingComments(accessors.setAccessor); - write(","); - } - writeLine(); - write("enumerable: true,"); - writeLine(); - write("configurable: true"); - decreaseIndent(); - writeLine(); - write("});"); - emitEnd(member); - } - } - }); + } + /** + * Visits a binary expression. + * + * This will be called when one of the following conditions are met: + * - The node contains a YieldExpression. + * + * @param node The node to visit. + */ + function visitBinaryExpression(node) { + switch (ts.getExpressionAssociativity(node)) { + case 0 /* Left */: + return visitLeftAssociativeBinaryExpression(node); + case 1 /* Right */: + return visitRightAssociativeBinaryExpression(node); + default: + ts.Debug.fail("Unknown associativity."); } - function emitMemberFunctionsForES6AndHigher(node) { - for (var _a = 0, _b = node.members; _a < _b.length; _a++) { - var member = _b[_a]; - if ((member.kind === 147 /* MethodDeclaration */ || node.kind === 146 /* MethodSignature */) && !member.body) { - emitCommentsOnNotEmittedNode(member); - } - else if (member.kind === 147 /* MethodDeclaration */ || - member.kind === 149 /* GetAccessor */ || - member.kind === 150 /* SetAccessor */) { - writeLine(); - emitLeadingComments(member); - emitStart(member); - if (member.flags & 32 /* Static */) { - write("static "); - } - if (member.kind === 149 /* GetAccessor */) { - write("get "); - } - else if (member.kind === 150 /* SetAccessor */) { - write("set "); - } - if (member.asteriskToken) { - write("*"); - } - emit(member.name); - emitSignatureAndBody(member); - emitEnd(member); - emitTrailingComments(member); - } - else if (member.kind === 198 /* SemicolonClassElement */) { - writeLine(); - write(";"); - } - } + } + function isCompoundAssignment(kind) { + return kind >= 57 /* FirstCompoundAssignment */ + && kind <= 68 /* LastCompoundAssignment */; + } + function getOperatorForCompoundAssignment(kind) { + switch (kind) { + case 57 /* PlusEqualsToken */: return 35 /* PlusToken */; + case 58 /* MinusEqualsToken */: return 36 /* MinusToken */; + case 59 /* AsteriskEqualsToken */: return 37 /* AsteriskToken */; + case 60 /* AsteriskAsteriskEqualsToken */: return 38 /* AsteriskAsteriskToken */; + case 61 /* SlashEqualsToken */: return 39 /* SlashToken */; + case 62 /* PercentEqualsToken */: return 40 /* PercentToken */; + case 63 /* LessThanLessThanEqualsToken */: return 43 /* LessThanLessThanToken */; + case 64 /* GreaterThanGreaterThanEqualsToken */: return 44 /* GreaterThanGreaterThanToken */; + case 65 /* GreaterThanGreaterThanGreaterThanEqualsToken */: return 45 /* GreaterThanGreaterThanGreaterThanToken */; + case 66 /* AmpersandEqualsToken */: return 46 /* AmpersandToken */; + case 67 /* BarEqualsToken */: return 47 /* BarToken */; + case 68 /* CaretEqualsToken */: return 48 /* CaretToken */; } - function emitConstructor(node, baseTypeElement) { - var saveConvertedLoopState = convertedLoopState; - var saveTempFlags = tempFlags; - var saveTempVariables = tempVariables; - var saveTempParameters = tempParameters; - convertedLoopState = undefined; - tempFlags = 0; - tempVariables = undefined; - tempParameters = undefined; - emitConstructorWorker(node, baseTypeElement); - ts.Debug.assert(convertedLoopState === undefined); - convertedLoopState = saveConvertedLoopState; - tempFlags = saveTempFlags; - tempVariables = saveTempVariables; - tempParameters = saveTempParameters; - } - function emitConstructorWorker(node, baseTypeElement) { - // Check if we have property assignment inside class declaration. - // If there is property assignment, we need to emit constructor whether users define it or not - // If there is no property assignment, we can omit constructor if users do not define it - var hasInstancePropertyWithInitializer = false; - // Emit the constructor overload pinned comments - ts.forEach(node.members, function (member) { - if (member.kind === 148 /* Constructor */ && !member.body) { - emitCommentsOnNotEmittedNode(member); - } - // Check if there is any non-static property assignment - if (member.kind === 145 /* PropertyDeclaration */ && member.initializer && (member.flags & 32 /* Static */) === 0) { - hasInstancePropertyWithInitializer = true; - } - }); - var ctor = ts.getFirstConstructorWithBody(node); - // For target ES6 and above, if there is no user-defined constructor and there is no property assignment - // do not emit constructor in class declaration. - if (languageVersion >= 2 /* ES6 */ && !ctor && !hasInstancePropertyWithInitializer) { - return; - } - if (ctor) { - emitLeadingComments(ctor); - } - emitStart(ctor || node); - if (languageVersion < 2 /* ES6 */) { - write("function "); - emitDeclarationName(node); - emitSignatureParameters(ctor); - } - else { - write("constructor"); - if (ctor) { - emitSignatureParameters(ctor); - } - else { - // The ES2015 spec specifies in 14.5.14. Runtime Semantics: ClassDefinitionEvaluation: - // If constructor is empty, then - // If ClassHeritag_eopt is present and protoParent is not null, then - // Let constructor be the result of parsing the source text - // constructor(...args) { super (...args);} - // using the syntactic grammar with the goal symbol MethodDefinition[~Yield]. - // Else, - // Let constructor be the result of parsing the source text - // constructor( ){ } - // using the syntactic grammar with the goal symbol MethodDefinition[~Yield]. + } + /** + * Visits a right-associative binary expression containing `yield`. + * + * @param node The node to visit. + */ + function visitRightAssociativeBinaryExpression(node) { + var left = node.left, right = node.right; + if (containsYield(right)) { + var target = void 0; + switch (left.kind) { + case 172 /* PropertyAccessExpression */: + // [source] + // a.b = yield; // - // While we could emit the '...args' rest parameter, certain later tools in the pipeline might - // downlevel the '...args' portion less efficiently by naively copying the contents of 'arguments' to an array. - // Instead, we'll avoid using a rest parameter and spread into the super call as - // 'super(...arguments)' instead of 'super(...args)', as you can see below. - write("()"); - } - } - var startIndex = 0; - write(" {"); - increaseIndent(); - if (ctor) { - // Emit all the directive prologues (like "use strict"). These have to come before - // any other preamble code we write (like parameter initializers). - startIndex = emitDirectivePrologues(ctor.body.statements, /*startWithNewLine*/ true); - emitDetachedCommentsAndUpdateCommentsInfo(ctor.body.statements); + // [intermediate] + // .local _a + // _a = a; + // .yield resumeLabel + // .mark resumeLabel + // _a.b = %sent%; + target = ts.updatePropertyAccess(left, cacheExpression(ts.visitNode(left.expression, visitor, ts.isLeftHandSideExpression)), left.name); + break; + case 173 /* ElementAccessExpression */: + // [source] + // a[b] = yield; + // + // [intermediate] + // .local _a, _b + // _a = a; + // _b = b; + // .yield resumeLabel + // .mark resumeLabel + // _a[_b] = %sent%; + target = ts.updateElementAccess(left, cacheExpression(ts.visitNode(left.expression, visitor, ts.isLeftHandSideExpression)), cacheExpression(ts.visitNode(left.argumentExpression, visitor, ts.isExpression))); + break; + default: + target = ts.visitNode(left, visitor, ts.isExpression); + break; } - emitCaptureThisForNodeIfNecessary(node); - var superCall; - if (ctor) { - emitDefaultValueAssignments(ctor); - emitRestParameter(ctor); - if (baseTypeElement) { - superCall = getSuperCallAtGivenIndex(ctor, startIndex); - if (superCall) { - writeLine(); - emit(superCall); - } - } - emitParameterPropertyAssignments(ctor); + var operator = node.operatorToken.kind; + if (isCompoundAssignment(operator)) { + return ts.createBinary(target, 56 /* EqualsToken */, ts.createBinary(cacheExpression(target), getOperatorForCompoundAssignment(operator), ts.visitNode(right, visitor, ts.isExpression), node), node); } else { - if (baseTypeElement) { - writeLine(); - emitStart(baseTypeElement); - if (languageVersion < 2 /* ES6 */) { - write("_super.apply(this, arguments);"); - } - else { - // See comment above on using '...arguments' instead of '...args'. - write("super(...arguments);"); - } - emitEnd(baseTypeElement); - } - } - emitPropertyDeclarations(node, getInitializedProperties(node, /*isStatic*/ false)); - if (ctor) { - var statements = ctor.body.statements; - if (superCall) { - statements = statements.slice(1); - } - emitLinesStartingAt(statements, startIndex); + return ts.updateBinary(node, target, ts.visitNode(right, visitor, ts.isExpression)); } - emitTempDeclarations(/*newLine*/ true); - writeLine(); - if (ctor) { - emitLeadingCommentsOfPosition(ctor.body.statements.end); + } + return ts.visitEachChild(node, visitor, context); + } + function visitLeftAssociativeBinaryExpression(node) { + if (containsYield(node.right)) { + if (ts.isLogicalOperator(node.operatorToken.kind)) { + return visitLogicalBinaryExpression(node); } - decreaseIndent(); - emitToken(16 /* CloseBraceToken */, ctor ? ctor.body.statements.end : node.members.end); - emitEnd(ctor || node); - if (ctor) { - emitTrailingComments(ctor); + else if (node.operatorToken.kind === 24 /* CommaToken */) { + return visitCommaExpression(node); } + // [source] + // a() + (yield) + c() + // + // [intermediate] + // .local _a + // _a = a(); + // .yield resumeLabel + // _a + %sent% + c() + var clone_6 = ts.getMutableClone(node); + clone_6.left = cacheExpression(ts.visitNode(node.left, visitor, ts.isExpression)); + clone_6.right = ts.visitNode(node.right, visitor, ts.isExpression); + return clone_6; + } + return ts.visitEachChild(node, visitor, context); + } + /** + * Visits a logical binary expression containing `yield`. + * + * @param node A node to visit. + */ + function visitLogicalBinaryExpression(node) { + // Logical binary expressions (`&&` and `||`) are shortcutting expressions and need + // to be transformed as such: + // + // [source] + // x = a() && yield; + // + // [intermediate] + // .local _a + // _a = a(); + // .brfalse resultLabel, (_a) + // .yield resumeLabel + // .mark resumeLabel + // _a = %sent%; + // .mark resultLabel + // x = _a; + // + // [source] + // x = a() || yield; + // + // [intermediate] + // .local _a + // _a = a(); + // .brtrue resultLabel, (_a) + // .yield resumeLabel + // .mark resumeLabel + // _a = %sent%; + // .mark resultLabel + // x = _a; + var resultLabel = defineLabel(); + var resultLocal = declareLocal(); + emitAssignment(resultLocal, ts.visitNode(node.left, visitor, ts.isExpression), /*location*/ node.left); + if (node.operatorToken.kind === 51 /* AmpersandAmpersandToken */) { + // Logical `&&` shortcuts when the left-hand operand is falsey. + emitBreakWhenFalse(resultLabel, resultLocal, /*location*/ node.left); } - function emitClassExpression(node) { - return emitClassLikeDeclaration(node); - } - function emitClassDeclaration(node) { - return emitClassLikeDeclaration(node); + else { + // Logical `||` shortcuts when the left-hand operand is truthy. + emitBreakWhenTrue(resultLabel, resultLocal, /*location*/ node.left); } - function emitClassLikeDeclaration(node) { - if (languageVersion < 2 /* ES6 */) { - emitClassLikeDeclarationBelowES6(node); + emitAssignment(resultLocal, ts.visitNode(node.right, visitor, ts.isExpression), /*location*/ node.right); + markLabel(resultLabel); + return resultLocal; + } + /** + * Visits a comma expression containing `yield`. + * + * @param node The node to visit. + */ + function visitCommaExpression(node) { + // [source] + // x = a(), yield, b(); + // + // [intermediate] + // a(); + // .yield resumeLabel + // .mark resumeLabel + // x = %sent%, b(); + var pendingExpressions = []; + visit(node.left); + visit(node.right); + return ts.inlineExpressions(pendingExpressions); + function visit(node) { + if (ts.isBinaryExpression(node) && node.operatorToken.kind === 24 /* CommaToken */) { + visit(node.left); + visit(node.right); } else { - emitClassLikeDeclarationForES6AndHigher(node); - } - if (modulekind !== ts.ModuleKind.ES6 && node.parent === currentSourceFile && node.name) { - emitExportMemberAssignments(node.name); + if (containsYield(node) && pendingExpressions.length > 0) { + emitWorker(1 /* Statement */, [ts.createStatement(ts.inlineExpressions(pendingExpressions))]); + pendingExpressions = []; + } + pendingExpressions.push(ts.visitNode(node, visitor, ts.isExpression)); } } - function emitClassLikeDeclarationForES6AndHigher(node) { - var decoratedClassAlias; - var isHoistedDeclarationInSystemModule = shouldHoistDeclarationInSystemJsModule(node); - var isDecorated = ts.nodeIsDecorated(node); - var rewriteAsClassExpression = isDecorated || isHoistedDeclarationInSystemModule; - if (node.kind === 221 /* ClassDeclaration */) { - if (rewriteAsClassExpression) { - // When we emit an ES6 class that has a class decorator, we must tailor the - // emit to certain specific cases. - // - // In the simplest case, we emit the class declaration as a let declaration, and - // evaluate decorators after the close of the class body: - // - // TypeScript | Javascript - // --------------------------------|------------------------------------ - // @dec | let C = class C { - // class C { | } - // } | C = __decorate([dec], C); - // --------------------------------|------------------------------------ - // @dec | export let C = class C { - // export class C { | } - // } | C = __decorate([dec], C); - // --------------------------------------------------------------------- - // [Example 1] - // - // If a class declaration contains a reference to itself *inside* of the class body, - // this introduces two bindings to the class: One outside of the class body, and one - // inside of the class body. If we apply decorators as in [Example 1] above, there - // is the possibility that the decorator `dec` will return a new value for the - // constructor, which would result in the binding inside of the class no longer - // pointing to the same reference as the binding outside of the class. - // - // As a result, we must instead rewrite all references to the class *inside* of the - // class body to instead point to a local temporary alias for the class: - // - // TypeScript | Javascript - // --------------------------------|------------------------------------ - // @dec | let C_1 = class C { - // class C { | static x() { return C_1.y; } - // static x() { return C.y; } | } - // static y = 1; | let C = C_1; - // } | C.y = 1; - // | C = C_1 = __decorate([dec], C); - // --------------------------------|------------------------------------ - // @dec | let C_1 = class C { - // export class C { | static x() { return C_1.y; } - // static x() { return C.y; } | } - // static y = 1; | export let C = C_1; - // } | C.y = 1; - // | C = C_1 = __decorate([dec], C); - // --------------------------------------------------------------------- - // [Example 2] - // - // If a class declaration is the default export of a module, we instead emit - // the export after the decorated declaration: - // - // TypeScript | Javascript - // --------------------------------|------------------------------------ - // @dec | let default_1 = class { - // export default class { | } - // } | default_1 = __decorate([dec], default_1); - // | export default default_1; - // --------------------------------|------------------------------------ - // @dec | let C = class C { - // export default class { | } - // } | C = __decorate([dec], C); - // | export default C; - // --------------------------------------------------------------------- - // [Example 3] - // - // If the class declaration is the default export and a reference to itself - // inside of the class body, we must emit both an alias for the class *and* - // move the export after the declaration: - // - // TypeScript | Javascript - // --------------------------------|------------------------------------ - // @dec | let C_1 = class C { - // export default class C { | static x() { return C_1.y; } - // static x() { return C.y; } | }; - // static y = 1; | let C = C_1; - // } | C.y = 1; - // | C = C_1 = __decorate([dec], C); - // | export default C; - // --------------------------------------------------------------------- - // [Example 4] - // - // NOTE: we reuse the same rewriting logic for cases when targeting ES6 and module kind is System. - // Because of hoisting top level class declaration need to be emitted as class expressions. - // Double bind case is only required if node is decorated. - if (isDecorated && resolver.getNodeCheckFlags(node) & 524288 /* ClassWithBodyScopedClassBinding */) { - decoratedClassAlias = ts.unescapeIdentifier(makeUniqueName(node.name ? node.name.text : "default")); - decoratedClassAliases[ts.getNodeId(node)] = decoratedClassAlias; - } - if (isES6ExportedDeclaration(node) && !(node.flags & 512 /* Default */) && decoratedClassAlias === undefined) { - write("export "); - } - if (decoratedClassAlias !== undefined) { - write("let " + decoratedClassAlias); - } - else { - if (!isHoistedDeclarationInSystemModule) { - write("let "); - } - emitDeclarationName(node); - } - write(" = "); - } - else if (isES6ExportedDeclaration(node)) { - write("export "); - if (node.flags & 512 /* Default */) { - write("default "); - } + } + /** + * Visits a conditional expression containing `yield`. + * + * @param node The node to visit. + */ + function visitConditionalExpression(node) { + // [source] + // x = a() ? yield : b(); + // + // [intermediate] + // .local _a + // .brfalse whenFalseLabel, (a()) + // .yield resumeLabel + // .mark resumeLabel + // _a = %sent%; + // .br resultLabel + // .mark whenFalseLabel + // _a = b(); + // .mark resultLabel + // x = _a; + // We only need to perform a specific transformation if a `yield` expression exists + // in either the `whenTrue` or `whenFalse` branches. + // A `yield` in the condition will be handled by the normal visitor. + if (containsYield(node.whenTrue) || containsYield(node.whenFalse)) { + var whenFalseLabel = defineLabel(); + var resultLabel = defineLabel(); + var resultLocal = declareLocal(); + emitBreakWhenFalse(whenFalseLabel, ts.visitNode(node.condition, visitor, ts.isExpression), /*location*/ node.condition); + emitAssignment(resultLocal, ts.visitNode(node.whenTrue, visitor, ts.isExpression), /*location*/ node.whenTrue); + emitBreak(resultLabel); + markLabel(whenFalseLabel); + emitAssignment(resultLocal, ts.visitNode(node.whenFalse, visitor, ts.isExpression), /*location*/ node.whenFalse); + markLabel(resultLabel); + return resultLocal; + } + return ts.visitEachChild(node, visitor, context); + } + /** + * Visits a `yield` expression. + * + * @param node The node to visit. + */ + function visitYieldExpression(node) { + // [source] + // x = yield a(); + // + // [intermediate] + // .yield resumeLabel, (a()) + // .mark resumeLabel + // x = %sent%; + // NOTE: we are explicitly not handling YieldStar at this time. + var resumeLabel = defineLabel(); + var expression = ts.visitNode(node.expression, visitor, ts.isExpression); + if (node.asteriskToken) { + emitYieldStar(expression, /*location*/ node); + } + else { + emitYield(expression, /*location*/ node); + } + markLabel(resumeLabel); + return createGeneratorResume(); + } + /** + * Visits an ArrayLiteralExpression that contains a YieldExpression. + * + * @param node The node to visit. + */ + function visitArrayLiteralExpression(node) { + return visitElements(node.elements, node.multiLine); + } + /** + * Visits an array of expressions containing one or more YieldExpression nodes + * and returns an expression for the resulting value. + * + * @param elements The elements to visit. + * @param multiLine Whether array literals created should be emitted on multiple lines. + */ + function visitElements(elements, multiLine) { + // [source] + // ar = [1, yield, 2]; + // + // [intermediate] + // .local _a + // _a = [1]; + // .yield resumeLabel + // .mark resumeLabel + // ar = _a.concat([%sent%, 2]); + var numInitialElements = countInitialNodesWithoutYield(elements); + var temp = declareLocal(); + var hasAssignedTemp = false; + if (numInitialElements > 0) { + emitAssignment(temp, ts.createArrayLiteral(ts.visitNodes(elements, visitor, ts.isExpression, 0, numInitialElements))); + hasAssignedTemp = true; + } + var expressions = ts.reduceLeft(elements, reduceElement, [], numInitialElements); + return hasAssignedTemp + ? ts.createArrayConcat(temp, [ts.createArrayLiteral(expressions)]) + : ts.createArrayLiteral(expressions); + function reduceElement(expressions, element) { + if (containsYield(element) && expressions.length > 0) { + emitAssignment(temp, hasAssignedTemp + ? ts.createArrayConcat(temp, [ts.createArrayLiteral(expressions)]) + : ts.createArrayLiteral(expressions)); + hasAssignedTemp = true; + expressions = []; + } + expressions.push(ts.visitNode(element, visitor, ts.isExpression)); + return expressions; + } + } + function visitObjectLiteralExpression(node) { + // [source] + // o = { + // a: 1, + // b: yield, + // c: 2 + // }; + // + // [intermediate] + // .local _a + // _a = { + // a: 1 + // }; + // .yield resumeLabel + // .mark resumeLabel + // o = (_a.b = %sent%, + // _a.c = 2, + // _a); + var properties = node.properties; + var multiLine = node.multiLine; + var numInitialProperties = countInitialNodesWithoutYield(properties); + var temp = declareLocal(); + emitAssignment(temp, ts.createObjectLiteral(ts.visitNodes(properties, visitor, ts.isObjectLiteralElementLike, 0, numInitialProperties), + /*location*/ undefined, multiLine)); + var expressions = ts.reduceLeft(properties, reduceProperty, [], numInitialProperties); + expressions.push(multiLine ? ts.startOnNewLine(ts.getMutableClone(temp)) : temp); + return ts.inlineExpressions(expressions); + function reduceProperty(expressions, property) { + if (containsYield(property) && expressions.length > 0) { + emitStatement(ts.createStatement(ts.inlineExpressions(expressions))); + expressions = []; + } + var expression = ts.createExpressionForObjectLiteralElementLike(node, property, temp); + var visited = ts.visitNode(expression, visitor, ts.isExpression); + if (visited) { + if (multiLine) { + visited.startsOnNewLine = true; } + expressions.push(visited); } - // If the class has static properties, and it's a class expression, then we'll need - // to specialize the emit a bit. for a class expression of the form: - // - // (class C { static a = 1; static b = 2; ... }) + return expressions; + } + } + /** + * Visits an ElementAccessExpression that contains a YieldExpression. + * + * @param node The node to visit. + */ + function visitElementAccessExpression(node) { + if (containsYield(node.argumentExpression)) { + // [source] + // a = x[yield]; // - // We'll emit: + // [intermediate] + // .local _a + // _a = x; + // .yield resumeLabel + // .mark resumeLabel + // a = _a[%sent%] + var clone_7 = ts.getMutableClone(node); + clone_7.expression = cacheExpression(ts.visitNode(node.expression, visitor, ts.isLeftHandSideExpression)); + clone_7.argumentExpression = ts.visitNode(node.argumentExpression, visitor, ts.isExpression); + return clone_7; + } + return ts.visitEachChild(node, visitor, context); + } + function visitCallExpression(node) { + if (ts.forEach(node.arguments, containsYield)) { + // [source] + // a.b(1, yield, 2); // - // ((C_1 = class C { - // // Normal class body - // }, - // C_1.a = 1, - // C_1.b = 2, - // C_1)); - // var C_1; + // [intermediate] + // .local _a, _b, _c + // _b = (_a = a).b; + // _c = [1]; + // .yield resumeLabel + // .mark resumeLabel + // _b.apply(_a, _c.concat([%sent%, 2])); + var _a = ts.createCallBinding(node.expression, hoistVariableDeclaration, languageVersion, /*cacheIdentifiers*/ true), target = _a.target, thisArg = _a.thisArg; + return ts.setOriginalNode(ts.createFunctionApply(cacheExpression(ts.visitNode(target, visitor, ts.isLeftHandSideExpression)), thisArg, visitElements(node.arguments, /*multiLine*/ false), + /*location*/ node), node); + } + return ts.visitEachChild(node, visitor, context); + } + function visitNewExpression(node) { + if (ts.forEach(node.arguments, containsYield)) { + // [source] + // new a.b(1, yield, 2); // - // This keeps the expression as an expression, while ensuring that the static parts - // of it have been initialized by the time it is used. - var staticProperties = getInitializedProperties(node, /*isStatic*/ true); - var isClassExpressionWithStaticProperties = staticProperties.length > 0 && node.kind === 192 /* ClassExpression */; - var generatedName; - if (isClassExpressionWithStaticProperties) { - generatedName = node.name ? getGeneratedNameForNode(node.name) : makeUniqueName("classExpression"); - var synthesizedNode = ts.createSynthesizedNode(69 /* Identifier */); - synthesizedNode.text = generatedName; - recordTempDeclaration(synthesizedNode); - write("("); - increaseIndent(); - emit(synthesizedNode); - write(" = "); - } - write("class"); - // emit name if - // - node has a name - // - this is default export with static initializers - if (node.name || (node.flags & 512 /* Default */ && (staticProperties.length > 0 || modulekind !== ts.ModuleKind.ES6) && !rewriteAsClassExpression)) { - write(" "); - emitDeclarationName(node); - } - var baseTypeNode = ts.getClassExtendsHeritageClauseElement(node); - if (baseTypeNode) { - write(" extends "); - emit(baseTypeNode.expression); - } - write(" {"); - increaseIndent(); - writeLine(); - emitConstructor(node, baseTypeNode); - emitMemberFunctionsForES6AndHigher(node); - decreaseIndent(); - writeLine(); - emitToken(16 /* CloseBraceToken */, node.members.end); - if (rewriteAsClassExpression) { - if (decoratedClassAlias !== undefined) { - write(";"); - writeLine(); - if (isES6ExportedDeclaration(node) && !(node.flags & 512 /* Default */)) { - write("export "); - } - write("let "); - emitDeclarationName(node); - write(" = " + decoratedClassAlias); - } - decoratedClassAliases[ts.getNodeId(node)] = undefined; - write(";"); - } - // Emit static property assignment. Because classDeclaration is lexically evaluated, - // it is safe to emit static property assignment after classDeclaration - // From ES6 specification: - // HasLexicalDeclaration (N) : Determines if the argument identifier has a binding in this environment record that was created using - // a lexical declaration such as a LexicalDeclaration or a ClassDeclaration. - if (isClassExpressionWithStaticProperties) { - for (var _a = 0, staticProperties_1 = staticProperties; _a < staticProperties_1.length; _a++) { - var property = staticProperties_1[_a]; - write(","); - writeLine(); - emitPropertyDeclaration(node, property, /*receiver*/ generatedName, /*isExpression*/ true); - } - write(","); - writeLine(); - write(generatedName); - decreaseIndent(); - write(")"); - } - else { - writeLine(); - emitPropertyDeclarations(node, staticProperties); - emitDecoratorsOfClass(node, decoratedClassAlias); + // [intermediate] + // .local _a, _b, _c + // _b = (_a = a.b).bind; + // _c = [1]; + // .yield resumeLabel + // .mark resumeLabel + // new (_b.apply(_a, _c.concat([%sent%, 2]))); + var _a = ts.createCallBinding(ts.createPropertyAccess(node.expression, "bind"), hoistVariableDeclaration), target = _a.target, thisArg = _a.thisArg; + return ts.setOriginalNode(ts.createNew(ts.createFunctionApply(cacheExpression(ts.visitNode(target, visitor, ts.isExpression)), thisArg, visitElements(node.arguments, /*multiLine*/ false)), + /*typeArguments*/ undefined, [], + /*location*/ node), node); + } + return ts.visitEachChild(node, visitor, context); + } + function transformAndEmitStatements(statements, start) { + if (start === void 0) { start = 0; } + var numStatements = statements.length; + for (var i = start; i < numStatements; i++) { + transformAndEmitStatement(statements[i]); + } + } + function transformAndEmitEmbeddedStatement(node) { + if (ts.isBlock(node)) { + transformAndEmitStatements(node.statements); + } + else { + transformAndEmitStatement(node); + } + } + function transformAndEmitStatement(node) { + var savedInStatementContainingYield = inStatementContainingYield; + if (!inStatementContainingYield) { + inStatementContainingYield = containsYield(node); + } + transformAndEmitStatementWorker(node); + inStatementContainingYield = savedInStatementContainingYield; + } + function transformAndEmitStatementWorker(node) { + switch (node.kind) { + case 199 /* Block */: + return transformAndEmitBlock(node); + case 202 /* ExpressionStatement */: + return transformAndEmitExpressionStatement(node); + case 203 /* IfStatement */: + return transformAndEmitIfStatement(node); + case 204 /* DoStatement */: + return transformAndEmitDoStatement(node); + case 205 /* WhileStatement */: + return transformAndEmitWhileStatement(node); + case 206 /* ForStatement */: + return transformAndEmitForStatement(node); + case 207 /* ForInStatement */: + return transformAndEmitForInStatement(node); + case 209 /* ContinueStatement */: + return transformAndEmitContinueStatement(node); + case 210 /* BreakStatement */: + return transformAndEmitBreakStatement(node); + case 211 /* ReturnStatement */: + return transformAndEmitReturnStatement(node); + case 212 /* WithStatement */: + return transformAndEmitWithStatement(node); + case 213 /* SwitchStatement */: + return transformAndEmitSwitchStatement(node); + case 214 /* LabeledStatement */: + return transformAndEmitLabeledStatement(node); + case 215 /* ThrowStatement */: + return transformAndEmitThrowStatement(node); + case 216 /* TryStatement */: + return transformAndEmitTryStatement(node); + default: + return emitStatement(ts.visitNode(node, visitor, ts.isStatement, /*optional*/ true)); + } + } + function transformAndEmitBlock(node) { + if (containsYield(node)) { + transformAndEmitStatements(node.statements); + } + else { + emitStatement(ts.visitNode(node, visitor, ts.isStatement)); + } + } + function transformAndEmitExpressionStatement(node) { + emitStatement(ts.visitNode(node, visitor, ts.isStatement)); + } + function transformAndEmitVariableDeclarationList(node) { + for (var _i = 0, _a = node.declarations; _i < _a.length; _i++) { + var variable = _a[_i]; + hoistVariableDeclaration(variable.name); + } + var variables = ts.getInitializedVariables(node); + var numVariables = variables.length; + var variablesWritten = 0; + var pendingExpressions = []; + while (variablesWritten < numVariables) { + for (var i = variablesWritten; i < numVariables; i++) { + var variable = variables[i]; + if (containsYield(variable.initializer) && pendingExpressions.length > 0) { + break; + } + pendingExpressions.push(transformInitializedVariable(variable)); } - if (!(node.flags & 1 /* Export */)) { - return; + if (pendingExpressions.length) { + emitStatement(ts.createStatement(ts.inlineExpressions(pendingExpressions))); + variablesWritten += pendingExpressions.length; + pendingExpressions = []; } - if (modulekind !== ts.ModuleKind.ES6) { - emitExportMemberAssignment(node); + } + return undefined; + } + function transformInitializedVariable(node) { + return ts.createAssignment(ts.getSynthesizedClone(node.name), ts.visitNode(node.initializer, visitor, ts.isExpression)); + } + function transformAndEmitIfStatement(node) { + if (containsYield(node)) { + // [source] + // if (x) + // /*thenStatement*/ + // else + // /*elseStatement*/ + // + // [intermediate] + // .brfalse elseLabel, (x) + // /*thenStatement*/ + // .br endLabel + // .mark elseLabel + // /*elseStatement*/ + // .mark endLabel + if (containsYield(node.thenStatement) || containsYield(node.elseStatement)) { + var endLabel = defineLabel(); + var elseLabel = node.elseStatement ? defineLabel() : undefined; + emitBreakWhenFalse(node.elseStatement ? elseLabel : endLabel, ts.visitNode(node.expression, visitor, ts.isExpression)); + transformAndEmitEmbeddedStatement(node.thenStatement); + if (node.elseStatement) { + emitBreak(endLabel); + markLabel(elseLabel); + transformAndEmitEmbeddedStatement(node.elseStatement); + } + markLabel(endLabel); } else { - // If this is an exported class, but not on the top level (i.e. on an internal - // module), export it - if (node.flags & 512 /* Default */) { - // if this is a top level default export of decorated class, write the export after the declaration. - if (isDecorated) { - writeLine(); - write("export default "); - emitDeclarationName(node); - write(";"); - } - } - else if (node.parent.kind !== 256 /* SourceFile */) { - writeLine(); - emitStart(node); - emitModuleMemberName(node); - write(" = "); - emitDeclarationName(node); - emitEnd(node); - write(";"); - } + emitStatement(ts.visitNode(node, visitor, ts.isStatement)); } } - function emitClassLikeDeclarationBelowES6(node) { - var isES6ExportedClass = isES6ExportedDeclaration(node); - if (node.kind === 221 /* ClassDeclaration */) { - if (isES6ExportedClass && !(node.flags & 512 /* Default */)) { - write("export "); + else { + emitStatement(ts.visitNode(node, visitor, ts.isStatement)); + } + } + function transformAndEmitDoStatement(node) { + if (containsYield(node)) { + // [source] + // do { + // /*body*/ + // } + // while (i < 10); + // + // [intermediate] + // .loop conditionLabel, endLabel + // .mark loopLabel + // /*body*/ + // .mark conditionLabel + // .brtrue loopLabel, (i < 10) + // .endloop + // .mark endLabel + var conditionLabel = defineLabel(); + var loopLabel = defineLabel(); + beginLoopBlock(/*continueLabel*/ conditionLabel); + markLabel(loopLabel); + transformAndEmitEmbeddedStatement(node.statement); + markLabel(conditionLabel); + emitBreakWhenTrue(loopLabel, ts.visitNode(node.expression, visitor, ts.isExpression)); + endLoopBlock(); + } + else { + emitStatement(ts.visitNode(node, visitor, ts.isStatement)); + } + } + function visitDoStatement(node) { + if (inStatementContainingYield) { + beginScriptLoopBlock(); + node = ts.visitEachChild(node, visitor, context); + endLoopBlock(); + return node; + } + else { + return ts.visitEachChild(node, visitor, context); + } + } + function transformAndEmitWhileStatement(node) { + if (containsYield(node)) { + // [source] + // while (i < 10) { + // /*body*/ + // } + // + // [intermediate] + // .loop loopLabel, endLabel + // .mark loopLabel + // .brfalse endLabel, (i < 10) + // /*body*/ + // .br loopLabel + // .endloop + // .mark endLabel + var loopLabel = defineLabel(); + var endLabel = beginLoopBlock(loopLabel); + markLabel(loopLabel); + emitBreakWhenFalse(endLabel, ts.visitNode(node.expression, visitor, ts.isExpression)); + transformAndEmitEmbeddedStatement(node.statement); + emitBreak(loopLabel); + endLoopBlock(); + } + else { + emitStatement(ts.visitNode(node, visitor, ts.isStatement)); + } + } + function visitWhileStatement(node) { + if (inStatementContainingYield) { + beginScriptLoopBlock(); + node = ts.visitEachChild(node, visitor, context); + endLoopBlock(); + return node; + } + else { + return ts.visitEachChild(node, visitor, context); + } + } + function transformAndEmitForStatement(node) { + if (containsYield(node)) { + // [source] + // for (var i = 0; i < 10; i++) { + // /*body*/ + // } + // + // [intermediate] + // .local i + // i = 0; + // .loop incrementLabel, endLoopLabel + // .mark conditionLabel + // .brfalse endLoopLabel, (i < 10) + // /*body*/ + // .mark incrementLabel + // i++; + // .br conditionLabel + // .endloop + // .mark endLoopLabel + var conditionLabel = defineLabel(); + var incrementLabel = defineLabel(); + var endLabel = beginLoopBlock(incrementLabel); + if (node.initializer) { + var initializer = node.initializer; + if (ts.isVariableDeclarationList(initializer)) { + transformAndEmitVariableDeclarationList(initializer); } - // source file level classes in system modules are hoisted so 'var's for them are already defined - if (!shouldHoistDeclarationInSystemJsModule(node)) { - write("var "); + else { + emitStatement(ts.createStatement(ts.visitNode(initializer, visitor, ts.isExpression), + /*location*/ initializer)); } - emitDeclarationName(node); - write(" = "); } - write("(function ("); - var baseTypeNode = ts.getClassExtendsHeritageClauseElement(node); - if (baseTypeNode) { - write("_super"); - } - write(") {"); - var saveTempFlags = tempFlags; - var saveTempVariables = tempVariables; - var saveTempParameters = tempParameters; - var saveComputedPropertyNamesToGeneratedNames = computedPropertyNamesToGeneratedNames; - var saveConvertedLoopState = convertedLoopState; - convertedLoopState = undefined; - tempFlags = 0; - tempVariables = undefined; - tempParameters = undefined; - computedPropertyNamesToGeneratedNames = undefined; - increaseIndent(); - if (baseTypeNode) { - writeLine(); - emitStart(baseTypeNode); - write("__extends("); - emitDeclarationName(node); - write(", _super);"); - emitEnd(baseTypeNode); + markLabel(conditionLabel); + if (node.condition) { + emitBreakWhenFalse(endLabel, ts.visitNode(node.condition, visitor, ts.isExpression)); } - writeLine(); - emitConstructor(node, baseTypeNode); - emitMemberFunctionsForES5AndLower(node); - emitPropertyDeclarations(node, getInitializedProperties(node, /*isStatic*/ true)); - writeLine(); - emitDecoratorsOfClass(node, /*decoratedClassAlias*/ undefined); - writeLine(); - emitToken(16 /* CloseBraceToken */, node.members.end, function () { - write("return "); - emitDeclarationName(node); - }); - write(";"); - emitTempDeclarations(/*newLine*/ true); - ts.Debug.assert(convertedLoopState === undefined); - convertedLoopState = saveConvertedLoopState; - tempFlags = saveTempFlags; - tempVariables = saveTempVariables; - tempParameters = saveTempParameters; - computedPropertyNamesToGeneratedNames = saveComputedPropertyNamesToGeneratedNames; - decreaseIndent(); - writeLine(); - emitToken(16 /* CloseBraceToken */, node.members.end); - emitStart(node); - write("("); - if (baseTypeNode) { - emit(baseTypeNode.expression); + transformAndEmitEmbeddedStatement(node.statement); + markLabel(incrementLabel); + if (node.incrementor) { + emitStatement(ts.createStatement(ts.visitNode(node.incrementor, visitor, ts.isExpression), + /*location*/ node.incrementor)); } - write("))"); - if (node.kind === 221 /* ClassDeclaration */) { - write(";"); + emitBreak(conditionLabel); + endLoopBlock(); + } + else { + emitStatement(ts.visitNode(node, visitor, ts.isStatement)); + } + } + function visitForStatement(node) { + if (inStatementContainingYield) { + beginScriptLoopBlock(); + } + var initializer = node.initializer; + if (ts.isVariableDeclarationList(initializer)) { + for (var _i = 0, _a = initializer.declarations; _i < _a.length; _i++) { + var variable = _a[_i]; + hoistVariableDeclaration(variable.name); } - emitEnd(node); - if (node.kind === 221 /* ClassDeclaration */ && !isES6ExportedClass) { - emitExportMemberAssignment(node); + var variables = ts.getInitializedVariables(initializer); + node = ts.updateFor(node, variables.length > 0 + ? ts.inlineExpressions(ts.map(variables, transformInitializedVariable)) + : undefined, ts.visitNode(node.condition, visitor, ts.isExpression, /*optional*/ true), ts.visitNode(node.incrementor, visitor, ts.isExpression, /*optional*/ true), ts.visitNode(node.statement, visitor, ts.isStatement, /*optional*/ false, ts.liftToBlock)); + } + else { + node = ts.visitEachChild(node, visitor, context); + } + if (inStatementContainingYield) { + endLoopBlock(); + } + return node; + } + function transformAndEmitForInStatement(node) { + // TODO(rbuckton): Source map locations + if (containsYield(node)) { + // [source] + // for (var p in o) { + // /*body*/ + // } + // + // [intermediate] + // .local _a, _b, _i + // _a = []; + // for (_b in o) _a.push(_b); + // _i = 0; + // .loop incrementLabel, endLoopLabel + // .mark conditionLabel + // .brfalse endLoopLabel, (_i < _a.length) + // p = _a[_i]; + // /*body*/ + // .mark incrementLabel + // _b++; + // .br conditionLabel + // .endloop + // .mark endLoopLabel + var keysArray = declareLocal(); // _a + var key = declareLocal(); // _b + var keysIndex = ts.createLoopVariable(); // _i + var initializer = node.initializer; + hoistVariableDeclaration(keysIndex); + emitAssignment(keysArray, ts.createArrayLiteral()); + emitStatement(ts.createForIn(key, ts.visitNode(node.expression, visitor, ts.isExpression), ts.createStatement(ts.createCall(ts.createPropertyAccess(keysArray, "push"), + /*typeArguments*/ undefined, [key])))); + emitAssignment(keysIndex, ts.createLiteral(0)); + var conditionLabel = defineLabel(); + var incrementLabel = defineLabel(); + var endLabel = beginLoopBlock(incrementLabel); + markLabel(conditionLabel); + emitBreakWhenFalse(endLabel, ts.createLessThan(keysIndex, ts.createPropertyAccess(keysArray, "length"))); + var variable = void 0; + if (ts.isVariableDeclarationList(initializer)) { + for (var _i = 0, _a = initializer.declarations; _i < _a.length; _i++) { + var variable_1 = _a[_i]; + hoistVariableDeclaration(variable_1.name); + } + variable = ts.getSynthesizedClone(initializer.declarations[0].name); } - else if (isES6ExportedClass && (node.flags & 512 /* Default */)) { - writeLine(); - write("export default "); - emitDeclarationName(node); - write(";"); + else { + variable = ts.visitNode(initializer, visitor, ts.isExpression); + ts.Debug.assert(ts.isLeftHandSideExpression(variable)); } + emitAssignment(variable, ts.createElementAccess(keysArray, keysIndex)); + transformAndEmitEmbeddedStatement(node.statement); + markLabel(incrementLabel); + emitStatement(ts.createStatement(ts.createPostfixIncrement(keysIndex))); + emitBreak(conditionLabel); + endLoopBlock(); } - function emitClassMemberPrefix(node, member) { - emitDeclarationName(node); - if (!(member.flags & 32 /* Static */)) { - write(".prototype"); - } + else { + emitStatement(ts.visitNode(node, visitor, ts.isStatement)); } - function emitDecoratorsOfClass(node, decoratedClassAlias) { - emitDecoratorsOfMembers(node, /*staticFlag*/ 0); - emitDecoratorsOfMembers(node, 32 /* Static */); - emitDecoratorsOfConstructor(node, decoratedClassAlias); + } + function visitForInStatement(node) { + // [source] + // for (var x in a) { + // /*body*/ + // } + // + // [intermediate] + // .local x + // .loop + // for (x in a) { + // /*body*/ + // } + // .endloop + if (inStatementContainingYield) { + beginScriptLoopBlock(); } - function emitDecoratorsOfConstructor(node, decoratedClassAlias) { - var decorators = node.decorators; - var constructor = ts.getFirstConstructorWithBody(node); - var firstParameterDecorator = constructor && ts.forEach(constructor.parameters, function (parameter) { return parameter.decorators; }); - // skip decoration of the constructor if neither it nor its parameters are decorated - if (!decorators && !firstParameterDecorator) { - return; + var initializer = node.initializer; + if (ts.isVariableDeclarationList(initializer)) { + for (var _i = 0, _a = initializer.declarations; _i < _a.length; _i++) { + var variable = _a[_i]; + hoistVariableDeclaration(variable.name); } - // Emit the call to __decorate. Given the class: - // - // @dec - // class C { - // } - // - // The emit for the class is: - // - // C = __decorate([dec], C); - // - writeLine(); - emitStart(node.decorators || firstParameterDecorator); - emitDeclarationName(node); - if (decoratedClassAlias !== undefined) { - write(" = " + decoratedClassAlias); + node = ts.updateForIn(node, initializer.declarations[0].name, ts.visitNode(node.expression, visitor, ts.isExpression), ts.visitNode(node.statement, visitor, ts.isStatement, /*optional*/ false, ts.liftToBlock)); + } + else { + node = ts.visitEachChild(node, visitor, context); + } + if (inStatementContainingYield) { + endLoopBlock(); + } + return node; + } + function transformAndEmitContinueStatement(node) { + var label = findContinueTarget(node.label ? node.label.text : undefined); + ts.Debug.assert(label > 0, "Expected continue statment to point to a valid Label."); + emitBreak(label, /*location*/ node); + } + function visitContinueStatement(node) { + if (inStatementContainingYield) { + var label = findContinueTarget(node.label && node.label.text); + if (label > 0) { + return createInlineBreak(label, /*location*/ node); } - write(" = __decorate(["); - increaseIndent(); - writeLine(); - var decoratorCount = decorators ? decorators.length : 0; - var argumentsWritten = emitList(decorators, 0, decoratorCount, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ false, /*noTrailingNewLine*/ true, function (decorator) { return emit(decorator.expression); }); - if (firstParameterDecorator) { - argumentsWritten += emitDecoratorsOfParameters(constructor, /*leadingComma*/ argumentsWritten > 0); + } + return ts.visitEachChild(node, visitor, context); + } + function transformAndEmitBreakStatement(node) { + var label = findBreakTarget(node.label ? node.label.text : undefined); + ts.Debug.assert(label > 0, "Expected break statment to point to a valid Label."); + emitBreak(label, /*location*/ node); + } + function visitBreakStatement(node) { + if (inStatementContainingYield) { + var label = findBreakTarget(node.label && node.label.text); + if (label > 0) { + return createInlineBreak(label, /*location*/ node); } - emitSerializedTypeMetadata(node, /*leadingComma*/ argumentsWritten >= 0); - decreaseIndent(); - writeLine(); - write("], "); - emitDeclarationName(node); - write(")"); - emitEnd(node.decorators || firstParameterDecorator); - write(";"); - writeLine(); } - function emitDecoratorsOfMembers(node, staticFlag) { - for (var _a = 0, _b = node.members; _a < _b.length; _a++) { - var member = _b[_a]; - // only emit members in the correct group - if ((member.flags & 32 /* Static */) !== staticFlag) { - continue; - } - // skip members that cannot be decorated (such as the constructor) - if (!ts.nodeCanBeDecorated(member)) { - continue; - } - // skip an accessor declaration if it is not the first accessor - var decorators = void 0; - var functionLikeMember = void 0; - if (ts.isAccessor(member)) { - var accessors = ts.getAllAccessorDeclarations(node.members, member); - if (member !== accessors.firstAccessor) { - continue; - } - // get the decorators from the first accessor with decorators - decorators = accessors.firstAccessor.decorators; - if (!decorators && accessors.secondAccessor) { - decorators = accessors.secondAccessor.decorators; + return ts.visitEachChild(node, visitor, context); + } + function transformAndEmitReturnStatement(node) { + emitReturn(ts.visitNode(node.expression, visitor, ts.isExpression, /*optional*/ true), + /*location*/ node); + } + function visitReturnStatement(node) { + return createInlineReturn(ts.visitNode(node.expression, visitor, ts.isExpression, /*optional*/ true), + /*location*/ node); + } + function transformAndEmitWithStatement(node) { + if (containsYield(node)) { + // [source] + // with (x) { + // /*body*/ + // } + // + // [intermediate] + // .with (x) + // /*body*/ + // .endwith + beginWithBlock(cacheExpression(ts.visitNode(node.expression, visitor, ts.isExpression))); + transformAndEmitEmbeddedStatement(node.statement); + endWithBlock(); + } + else { + emitStatement(ts.visitNode(node, visitor, ts.isStatement)); + } + } + function transformAndEmitSwitchStatement(node) { + if (containsYield(node.caseBlock)) { + // [source] + // switch (x) { + // case a: + // /*caseStatements*/ + // case b: + // /*caseStatements*/ + // default: + // /*defaultStatements*/ + // } + // + // [intermediate] + // .local _a + // .switch endLabel + // _a = x; + // switch (_a) { + // case a: + // .br clauseLabels[0] + // } + // switch (_a) { + // case b: + // .br clauseLabels[1] + // } + // .br clauseLabels[2] + // .mark clauseLabels[0] + // /*caseStatements*/ + // .mark clauseLabels[1] + // /*caseStatements*/ + // .mark clauseLabels[2] + // /*caseStatements*/ + // .endswitch + // .mark endLabel + var caseBlock = node.caseBlock; + var numClauses = caseBlock.clauses.length; + var endLabel = beginSwitchBlock(); + var expression = cacheExpression(ts.visitNode(node.expression, visitor, ts.isExpression)); + // Create labels for each clause and find the index of the first default clause. + var clauseLabels = []; + var defaultClauseIndex = -1; + for (var i = 0; i < numClauses; i++) { + var clause = caseBlock.clauses[i]; + clauseLabels.push(defineLabel()); + if (clause.kind === 250 /* DefaultClause */ && defaultClauseIndex === -1) { + defaultClauseIndex = i; + } + } + // Emit switch statements for each run of case clauses either from the first case + // clause or the next case clause with a `yield` in its expression, up to the next + // case clause with a `yield` in its expression. + var clausesWritten = 0; + var pendingClauses = []; + while (clausesWritten < numClauses) { + var defaultClausesSkipped = 0; + for (var i = clausesWritten; i < numClauses; i++) { + var clause = caseBlock.clauses[i]; + if (clause.kind === 249 /* CaseClause */) { + var caseClause = clause; + if (containsYield(caseClause.expression) && pendingClauses.length > 0) { + break; + } + pendingClauses.push(ts.createCaseClause(ts.visitNode(caseClause.expression, visitor, ts.isExpression), [ + createInlineBreak(clauseLabels[i], /*location*/ caseClause.expression) + ])); } - // we only decorate parameters of the set accessor - functionLikeMember = accessors.setAccessor; - } - else { - decorators = member.decorators; - // we only decorate the parameters here if this is a method - if (member.kind === 147 /* MethodDeclaration */) { - functionLikeMember = member; + else { + defaultClausesSkipped++; } } - var firstParameterDecorator = functionLikeMember && ts.forEach(functionLikeMember.parameters, function (parameter) { return parameter.decorators; }); - // skip a member if it or any of its parameters are not decorated - if (!decorators && !firstParameterDecorator) { - continue; - } - // Emit the call to __decorate. Given the following: - // - // class C { - // @dec method(@dec2 x) {} - // @dec get accessor() {} - // @dec prop; - // } - // - // The emit for a method is: - // - // __decorate([ - // dec, - // __param(0, dec2), - // __metadata("design:type", Function), - // __metadata("design:paramtypes", [Object]), - // __metadata("design:returntype", void 0) - // ], C.prototype, "method", undefined); - // - // The emit for an accessor is: - // - // __decorate([ - // dec - // ], C.prototype, "accessor", undefined); - // - // The emit for a property is: - // - // __decorate([ - // dec - // ], C.prototype, "prop"); - // - writeLine(); - emitStart(decorators || firstParameterDecorator); - write("__decorate(["); - increaseIndent(); - writeLine(); - var decoratorCount = decorators ? decorators.length : 0; - var argumentsWritten = emitList(decorators, 0, decoratorCount, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ false, /*noTrailingNewLine*/ true, function (decorator) { return emit(decorator.expression); }); - if (firstParameterDecorator) { - argumentsWritten += emitDecoratorsOfParameters(functionLikeMember, argumentsWritten > 0); + if (pendingClauses.length) { + emitStatement(ts.createSwitch(expression, ts.createCaseBlock(pendingClauses))); + clausesWritten += pendingClauses.length; + pendingClauses = []; } - emitSerializedTypeMetadata(member, argumentsWritten > 0); - decreaseIndent(); - writeLine(); - write("], "); - emitClassMemberPrefix(node, member); - write(", "); - emitExpressionForPropertyName(member.name); - if (languageVersion > 0 /* ES3 */) { - if (member.kind !== 145 /* PropertyDeclaration */) { - // We emit `null` here to indicate to `__decorate` that it can invoke `Object.getOwnPropertyDescriptor` directly. - // We have this extra argument here so that we can inject an explicit property descriptor at a later date. - write(", null"); - } - else { - // We emit `void 0` here to indicate to `__decorate` that it can invoke `Object.defineProperty` directly, but that it - // should not invoke `Object.getOwnPropertyDescriptor`. - write(", void 0"); - } + if (defaultClausesSkipped > 0) { + clausesWritten += defaultClausesSkipped; + defaultClausesSkipped = 0; } - write(")"); - emitEnd(decorators || firstParameterDecorator); - write(";"); - writeLine(); } - } - function emitDecoratorsOfParameters(node, leadingComma) { - var argumentsWritten = 0; - if (node) { - var parameterIndex_1 = 0; - for (var _a = 0, _b = node.parameters; _a < _b.length; _a++) { - var parameter = _b[_a]; - if (ts.nodeIsDecorated(parameter)) { - var decorators = parameter.decorators; - argumentsWritten += emitList(decorators, 0, decorators.length, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ leadingComma, /*noTrailingNewLine*/ true, function (decorator) { - write("__param(" + parameterIndex_1 + ", "); - emit(decorator.expression); - write(")"); - }); - leadingComma = true; - } - parameterIndex_1++; - } + if (defaultClauseIndex >= 0) { + emitBreak(clauseLabels[defaultClauseIndex]); } - return argumentsWritten; - } - function shouldEmitTypeMetadata(node) { - // This method determines whether to emit the "design:type" metadata based on the node's kind. - // The caller should have already tested whether the node has decorators and whether the emitDecoratorMetadata - // compiler option is set. - switch (node.kind) { - case 147 /* MethodDeclaration */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 145 /* PropertyDeclaration */: - return true; + else { + emitBreak(endLabel); } - return false; - } - function shouldEmitReturnTypeMetadata(node) { - // This method determines whether to emit the "design:returntype" metadata based on the node's kind. - // The caller should have already tested whether the node has decorators and whether the emitDecoratorMetadata - // compiler option is set. - switch (node.kind) { - case 147 /* MethodDeclaration */: - return true; + for (var i = 0; i < numClauses; i++) { + markLabel(clauseLabels[i]); + transformAndEmitStatements(caseBlock.clauses[i].statements); } - return false; + endSwitchBlock(); } - function shouldEmitParamTypesMetadata(node) { - // This method determines whether to emit the "design:paramtypes" metadata based on the node's kind. - // The caller should have already tested whether the node has decorators and whether the emitDecoratorMetadata - // compiler option is set. - switch (node.kind) { - case 221 /* ClassDeclaration */: - case 147 /* MethodDeclaration */: - case 150 /* SetAccessor */: - return true; - } - return false; + else { + emitStatement(ts.visitNode(node, visitor, ts.isStatement)); + } + } + function visitSwitchStatement(node) { + if (inStatementContainingYield) { + beginScriptSwitchBlock(); + } + node = ts.visitEachChild(node, visitor, context); + if (inStatementContainingYield) { + endSwitchBlock(); } - /** Serializes the type of a declaration to an appropriate JS constructor value. Used by the __metadata decorator for a class member. */ - function emitSerializedTypeOfNode(node) { - // serialization of the type of a declaration uses the following rules: + return node; + } + function transformAndEmitLabeledStatement(node) { + if (containsYield(node)) { + // [source] + // x: { + // /*body*/ + // } // - // * The serialized type of a ClassDeclaration is "Function" - // * The serialized type of a ParameterDeclaration is the serialized type of its type annotation. - // * The serialized type of a PropertyDeclaration is the serialized type of its type annotation. - // * The serialized type of an AccessorDeclaration is the serialized type of the return type annotation of its getter or parameter type annotation of its setter. - // * The serialized type of any other FunctionLikeDeclaration is "Function". - // * The serialized type of any other node is "void 0". + // [intermediate] + // .labeled "x", endLabel + // /*body*/ + // .endlabeled + // .mark endLabel + beginLabeledBlock(node.label.text); + transformAndEmitEmbeddedStatement(node.statement); + endLabeledBlock(); + } + else { + emitStatement(ts.visitNode(node, visitor, ts.isStatement)); + } + } + function visitLabeledStatement(node) { + if (inStatementContainingYield) { + beginScriptLabeledBlock(node.label.text); + } + node = ts.visitEachChild(node, visitor, context); + if (inStatementContainingYield) { + endLabeledBlock(); + } + return node; + } + function transformAndEmitThrowStatement(node) { + emitThrow(ts.visitNode(node.expression, visitor, ts.isExpression), + /*location*/ node); + } + function transformAndEmitTryStatement(node) { + if (containsYield(node)) { + // [source] + // try { + // /*tryBlock*/ + // } + // catch (e) { + // /*catchBlock*/ + // } + // finally { + // /*finallyBlock*/ + // } // - // For rules on serializing type annotations, see `serializeTypeNode`. - switch (node.kind) { - case 221 /* ClassDeclaration */: - write("Function"); - return; - case 145 /* PropertyDeclaration */: - emitSerializedTypeNode(node.type); - return; - case 142 /* Parameter */: - emitSerializedTypeNode(node.type); - return; - case 149 /* GetAccessor */: - emitSerializedTypeNode(node.type); - return; - case 150 /* SetAccessor */: - emitSerializedTypeNode(ts.getSetAccessorTypeAnnotationNode(node)); - return; + // [intermediate] + // .local _a + // .try tryLabel, catchLabel, finallyLabel, endLabel + // .mark tryLabel + // .nop + // /*tryBlock*/ + // .br endLabel + // .catch + // .mark catchLabel + // _a = %error%; + // /*catchBlock*/ + // .br endLabel + // .finally + // .mark finallyLabel + // /*finallyBlock*/ + // .endfinally + // .endtry + // .mark endLabel + beginExceptionBlock(); + transformAndEmitEmbeddedStatement(node.tryBlock); + if (node.catchClause) { + beginCatchBlock(node.catchClause.variableDeclaration); + transformAndEmitEmbeddedStatement(node.catchClause.block); } - if (ts.isFunctionLike(node)) { - write("Function"); - return; + if (node.finallyBlock) { + beginFinallyBlock(); + transformAndEmitEmbeddedStatement(node.finallyBlock); } - write("void 0"); + endExceptionBlock(); } - function emitSerializedTypeNode(node) { - if (node) { - switch (node.kind) { - case 103 /* VoidKeyword */: - write("void 0"); - return; - case 164 /* ParenthesizedType */: - emitSerializedTypeNode(node.type); - return; - case 156 /* FunctionType */: - case 157 /* ConstructorType */: - write("Function"); - return; - case 160 /* ArrayType */: - case 161 /* TupleType */: - write("Array"); - return; - case 154 /* TypePredicate */: - case 120 /* BooleanKeyword */: - write("Boolean"); - return; - case 132 /* StringKeyword */: - case 166 /* LiteralType */: - write("String"); - return; - case 130 /* NumberKeyword */: - write("Number"); - return; - case 133 /* SymbolKeyword */: - write("Symbol"); - return; - case 155 /* TypeReference */: - emitSerializedTypeReferenceNode(node); - return; - case 158 /* TypeQuery */: - case 159 /* TypeLiteral */: - case 162 /* UnionType */: - case 163 /* IntersectionType */: - case 117 /* AnyKeyword */: - case 165 /* ThisType */: - break; - default: - ts.Debug.fail("Cannot serialize unexpected type node."); - break; - } - } - write("Object"); + else { + emitStatement(ts.visitEachChild(node, visitor, context)); } - /** Serializes a TypeReferenceNode to an appropriate JS constructor value. Used by the __metadata decorator. */ - function emitSerializedTypeReferenceNode(node) { - var location = node.parent; - while (ts.isDeclaration(location) || ts.isTypeNode(location)) { - location = location.parent; - } - // Clone the type name and parent it to a location outside of the current declaration. - var typeName = ts.cloneEntityName(node.typeName, location); - var result = resolver.getTypeReferenceSerializationKind(typeName); - switch (result) { - case ts.TypeReferenceSerializationKind.Unknown: - var temp = createAndRecordTempVariable(0 /* Auto */); - write("(typeof ("); - emitNodeWithoutSourceMap(temp); - write(" = "); - emitEntityNameAsExpression(typeName, /*useFallback*/ true); - write(") === 'function' && "); - emitNodeWithoutSourceMap(temp); - write(") || Object"); - break; - case ts.TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue: - emitEntityNameAsExpression(typeName, /*useFallback*/ false); - break; - case ts.TypeReferenceSerializationKind.VoidType: - write("void 0"); - break; - case ts.TypeReferenceSerializationKind.BooleanType: - write("Boolean"); - break; - case ts.TypeReferenceSerializationKind.NumberLikeType: - write("Number"); - break; - case ts.TypeReferenceSerializationKind.StringLikeType: - write("String"); - break; - case ts.TypeReferenceSerializationKind.ArrayLikeType: - write("Array"); - break; - case ts.TypeReferenceSerializationKind.ESSymbolType: - if (languageVersion < 2 /* ES6 */) { - write("typeof Symbol === 'function' ? Symbol : Object"); - } - else { - write("Symbol"); - } - break; - case ts.TypeReferenceSerializationKind.TypeWithCallSignature: - write("Function"); - break; - case ts.TypeReferenceSerializationKind.ObjectType: - write("Object"); - break; + } + function containsYield(node) { + return node && (node.transformFlags & 4194304 /* ContainsYield */) !== 0; + } + function countInitialNodesWithoutYield(nodes) { + var numNodes = nodes.length; + for (var i = 0; i < numNodes; i++) { + if (containsYield(nodes[i])) { + return i; } } - /** Serializes the parameter types of a function or the constructor of a class. Used by the __metadata decorator for a method or set accessor. */ - function emitSerializedParameterTypesOfNode(node) { - // serialization of parameter types uses the following rules: - // - // * If the declaration is a class, the parameters of the first constructor with a body are used. - // * If the declaration is function-like and has a body, the parameters of the function are used. - // - // For the rules on serializing the type of each parameter declaration, see `serializeTypeOfDeclaration`. - if (node) { - var valueDeclaration = void 0; - if (node.kind === 221 /* ClassDeclaration */) { - valueDeclaration = ts.getFirstConstructorWithBody(node); - } - else if (ts.isFunctionLike(node) && ts.nodeIsPresent(node.body)) { - valueDeclaration = node; - } - if (valueDeclaration) { - var parameters = valueDeclaration.parameters; - var skipThisCount = parameters.length && parameters[0].name.originalKeywordKind === 97 /* ThisKeyword */ ? 1 : 0; - var parameterCount = parameters.length; - if (parameterCount > skipThisCount) { - for (var i = skipThisCount; i < parameterCount; i++) { - if (i > skipThisCount) { - write(", "); - } - if (parameters[i].dotDotDotToken) { - var parameterType = parameters[i].type; - if (parameterType && parameterType.kind === 160 /* ArrayType */) { - parameterType = parameterType.elementType; - } - else if (parameterType && parameterType.kind === 155 /* TypeReference */ && parameterType.typeArguments && parameterType.typeArguments.length === 1) { - parameterType = parameterType.typeArguments[0]; - } - else { - parameterType = undefined; - } - emitSerializedTypeNode(parameterType); - } - else { - emitSerializedTypeOfNode(parameters[i]); - } - } + return -1; + } + function onSubstituteNode(emitContext, node) { + node = previousOnSubstituteNode(emitContext, node); + if (emitContext === 1 /* Expression */) { + return substituteExpression(node); + } + return node; + } + function substituteExpression(node) { + if (ts.isIdentifier(node)) { + return substituteExpressionIdentifier(node); + } + return node; + } + function substituteExpressionIdentifier(node) { + if (renamedCatchVariables && ts.hasProperty(renamedCatchVariables, node.text)) { + var original = ts.getOriginalNode(node); + if (ts.isIdentifier(original) && original.parent) { + var declaration = resolver.getReferencedValueDeclaration(original); + if (declaration) { + var name_38 = ts.getProperty(renamedCatchVariableDeclarations, String(ts.getOriginalNodeId(declaration))); + if (name_38) { + var clone_8 = ts.getMutableClone(name_38); + ts.setSourceMapRange(clone_8, node); + ts.setCommentRange(clone_8, node); + return clone_8; } } } } - /** Serializes the return type of function. Used by the __metadata decorator for a method. */ - function emitSerializedReturnTypeOfNode(node) { - if (node && ts.isFunctionLike(node)) { - if (node.type) { - emitSerializedTypeNode(node.type); - return; - } - else if (ts.isAsyncFunctionLike(node)) { - write("Promise"); - return; + return node; + } + function cacheExpression(node) { + var temp; + if (ts.isGeneratedIdentifier(node)) { + return node; + } + temp = ts.createTempVariable(hoistVariableDeclaration); + emitAssignment(temp, node, /*location*/ node); + return temp; + } + function declareLocal(name) { + var temp = name + ? ts.createUniqueName(name) + : ts.createTempVariable(/*recordTempVariable*/ undefined); + hoistVariableDeclaration(temp); + return temp; + } + /** + * Defines a label, uses as the target of a Break operation. + */ + function defineLabel() { + if (!labelOffsets) { + labelOffsets = []; + } + var label = nextLabelId; + nextLabelId++; + labelOffsets[label] = -1; + return label; + } + /** + * Marks the current operation with the specified label. + */ + function markLabel(label) { + ts.Debug.assert(labelOffsets !== undefined, "No labels were defined."); + labelOffsets[label] = operations ? operations.length : 0; + } + /** + * Begins a block operation (With, Break/Continue, Try/Catch/Finally) + * + * @param block Information about the block. + */ + function beginBlock(block) { + if (!blocks) { + blocks = []; + blockActions = []; + blockOffsets = []; + blockStack = []; + } + var index = blockActions.length; + blockActions[index] = 0 /* Open */; + blockOffsets[index] = operations ? operations.length : 0; + blocks[index] = block; + blockStack.push(block); + return index; + } + /** + * Ends the current block operation. + */ + function endBlock() { + var block = peekBlock(); + ts.Debug.assert(block !== undefined, "beginBlock was never called."); + var index = blockActions.length; + blockActions[index] = 1 /* Close */; + blockOffsets[index] = operations ? operations.length : 0; + blocks[index] = block; + blockStack.pop(); + return block; + } + /** + * Gets the current open block. + */ + function peekBlock() { + return ts.lastOrUndefined(blockStack); + } + /** + * Gets the kind of the current open block. + */ + function peekBlockKind() { + var block = peekBlock(); + return block && block.kind; + } + /** + * Begins a code block for a generated `with` statement. + * + * @param expression An identifier representing expression for the `with` block. + */ + function beginWithBlock(expression) { + var startLabel = defineLabel(); + var endLabel = defineLabel(); + markLabel(startLabel); + beginBlock({ + kind: 1 /* With */, + expression: expression, + startLabel: startLabel, + endLabel: endLabel + }); + } + /** + * Ends a code block for a generated `with` statement. + */ + function endWithBlock() { + ts.Debug.assert(peekBlockKind() === 1 /* With */); + var block = endBlock(); + markLabel(block.endLabel); + } + function isWithBlock(block) { + return block.kind === 1 /* With */; + } + /** + * Begins a code block for a generated `try` statement. + */ + function beginExceptionBlock() { + var startLabel = defineLabel(); + var endLabel = defineLabel(); + markLabel(startLabel); + beginBlock({ + kind: 0 /* Exception */, + state: 0 /* Try */, + startLabel: startLabel, + endLabel: endLabel + }); + emitNop(); + return endLabel; + } + /** + * Enters the `catch` clause of a generated `try` statement. + * + * @param variable The catch variable. + */ + function beginCatchBlock(variable) { + ts.Debug.assert(peekBlockKind() === 0 /* Exception */); + var text = variable.name.text; + var name = declareLocal(text); + if (!renamedCatchVariables) { + renamedCatchVariables = ts.createMap(); + renamedCatchVariableDeclarations = ts.createMap(); + context.enableSubstitution(69 /* Identifier */); + } + renamedCatchVariables[text] = true; + renamedCatchVariableDeclarations[ts.getOriginalNodeId(variable)] = name; + var exception = peekBlock(); + ts.Debug.assert(exception.state < 1 /* Catch */); + var endLabel = exception.endLabel; + emitBreak(endLabel); + var catchLabel = defineLabel(); + markLabel(catchLabel); + exception.state = 1 /* Catch */; + exception.catchVariable = name; + exception.catchLabel = catchLabel; + emitAssignment(name, ts.createCall(ts.createPropertyAccess(state, "sent"), /*typeArguments*/ undefined, [])); + emitNop(); + } + /** + * Enters the `finally` block of a generated `try` statement. + */ + function beginFinallyBlock() { + ts.Debug.assert(peekBlockKind() === 0 /* Exception */); + var exception = peekBlock(); + ts.Debug.assert(exception.state < 2 /* Finally */); + var endLabel = exception.endLabel; + emitBreak(endLabel); + var finallyLabel = defineLabel(); + markLabel(finallyLabel); + exception.state = 2 /* Finally */; + exception.finallyLabel = finallyLabel; + } + /** + * Ends the code block for a generated `try` statement. + */ + function endExceptionBlock() { + ts.Debug.assert(peekBlockKind() === 0 /* Exception */); + var exception = endBlock(); + var state = exception.state; + if (state < 2 /* Finally */) { + emitBreak(exception.endLabel); + } + else { + emitEndfinally(); + } + markLabel(exception.endLabel); + emitNop(); + exception.state = 3 /* Done */; + } + function isExceptionBlock(block) { + return block.kind === 0 /* Exception */; + } + /** + * Begins a code block that supports `break` or `continue` statements that are defined in + * the source tree and not from generated code. + * + * @param labelText Names from containing labeled statements. + */ + function beginScriptLoopBlock() { + beginBlock({ + kind: 3 /* Loop */, + isScript: true, + breakLabel: -1, + continueLabel: -1 + }); + } + /** + * Begins a code block that supports `break` or `continue` statements that are defined in + * generated code. Returns a label used to mark the operation to which to jump when a + * `break` statement targets this block. + * + * @param continueLabel A Label used to mark the operation to which to jump when a + * `continue` statement targets this block. + */ + function beginLoopBlock(continueLabel) { + var breakLabel = defineLabel(); + beginBlock({ + kind: 3 /* Loop */, + isScript: false, + breakLabel: breakLabel, + continueLabel: continueLabel + }); + return breakLabel; + } + /** + * Ends a code block that supports `break` or `continue` statements that are defined in + * generated code or in the source tree. + */ + function endLoopBlock() { + ts.Debug.assert(peekBlockKind() === 3 /* Loop */); + var block = endBlock(); + var breakLabel = block.breakLabel; + if (!block.isScript) { + markLabel(breakLabel); + } + } + /** + * Begins a code block that supports `break` statements that are defined in the source + * tree and not from generated code. + * + */ + function beginScriptSwitchBlock() { + beginBlock({ + kind: 2 /* Switch */, + isScript: true, + breakLabel: -1 + }); + } + /** + * Begins a code block that supports `break` statements that are defined in generated code. + * Returns a label used to mark the operation to which to jump when a `break` statement + * targets this block. + */ + function beginSwitchBlock() { + var breakLabel = defineLabel(); + beginBlock({ + kind: 2 /* Switch */, + isScript: false, + breakLabel: breakLabel + }); + return breakLabel; + } + /** + * Ends a code block that supports `break` statements that are defined in generated code. + */ + function endSwitchBlock() { + ts.Debug.assert(peekBlockKind() === 2 /* Switch */); + var block = endBlock(); + var breakLabel = block.breakLabel; + if (!block.isScript) { + markLabel(breakLabel); + } + } + function beginScriptLabeledBlock(labelText) { + beginBlock({ + kind: 4 /* Labeled */, + isScript: true, + labelText: labelText, + breakLabel: -1 + }); + } + function beginLabeledBlock(labelText) { + var breakLabel = defineLabel(); + beginBlock({ + kind: 4 /* Labeled */, + isScript: false, + labelText: labelText, + breakLabel: breakLabel + }); + } + function endLabeledBlock() { + ts.Debug.assert(peekBlockKind() === 4 /* Labeled */); + var block = endBlock(); + if (!block.isScript) { + markLabel(block.breakLabel); + } + } + /** + * Indicates whether the provided block supports `break` statements. + * + * @param block A code block. + */ + function supportsUnlabeledBreak(block) { + return block.kind === 2 /* Switch */ + || block.kind === 3 /* Loop */; + } + /** + * Indicates whether the provided block supports `break` statements with labels. + * + * @param block A code block. + */ + function supportsLabeledBreakOrContinue(block) { + return block.kind === 4 /* Labeled */; + } + /** + * Indicates whether the provided block supports `continue` statements. + * + * @param block A code block. + */ + function supportsUnlabeledContinue(block) { + return block.kind === 3 /* Loop */; + } + function hasImmediateContainingLabeledBlock(labelText, start) { + for (var j = start; j >= 0; j--) { + var containingBlock = blockStack[j]; + if (supportsLabeledBreakOrContinue(containingBlock)) { + if (containingBlock.labelText === labelText) { + return true; } } - write("void 0"); + else { + break; + } } - function emitSerializedTypeMetadata(node, writeComma) { - // This method emits the serialized type metadata for a decorator target. - // The caller should have already tested whether the node has decorators. - var argumentsWritten = 0; - if (compilerOptions.emitDecoratorMetadata) { - if (shouldEmitTypeMetadata(node)) { - if (writeComma) { - write(", "); - } - writeLine(); - write("__metadata('design:type', "); - emitSerializedTypeOfNode(node); - write(")"); - argumentsWritten++; - } - if (shouldEmitParamTypesMetadata(node)) { - if (writeComma || argumentsWritten) { - write(", "); - } - writeLine(); - write("__metadata('design:paramtypes', ["); - emitSerializedParameterTypesOfNode(node); - write("])"); - argumentsWritten++; + return false; + } + /** + * Finds the label that is the target for a `break` statement. + * + * @param labelText An optional name of a containing labeled statement. + */ + function findBreakTarget(labelText) { + ts.Debug.assert(blocks !== undefined); + if (labelText) { + for (var i = blockStack.length - 1; i >= 0; i--) { + var block = blockStack[i]; + if (supportsLabeledBreakOrContinue(block) && block.labelText === labelText) { + return block.breakLabel; } - if (shouldEmitReturnTypeMetadata(node)) { - if (writeComma || argumentsWritten) { - write(", "); - } - writeLine(); - write("__metadata('design:returntype', "); - emitSerializedReturnTypeOfNode(node); - write(")"); - argumentsWritten++; + else if (supportsUnlabeledBreak(block) && hasImmediateContainingLabeledBlock(labelText, i - 1)) { + return block.breakLabel; } } - return argumentsWritten; - } - function emitInterfaceDeclaration(node) { - emitCommentsOnNotEmittedNode(node); } - function shouldEmitEnumDeclaration(node) { - var isConstEnum = ts.isConst(node); - return !isConstEnum || compilerOptions.preserveConstEnums || compilerOptions.isolatedModules; - } - function emitEnumDeclaration(node) { - // const enums are completely erased during compilation. - if (!shouldEmitEnumDeclaration(node)) { - return; - } - if (!shouldHoistDeclarationInSystemJsModule(node)) { - // do not emit var if variable was already hoisted - var isES6ExportedEnum = isES6ExportedDeclaration(node); - if (!(node.flags & 1 /* Export */) || (isES6ExportedEnum && isFirstDeclarationOfKind(node, node.symbol && node.symbol.declarations, 224 /* EnumDeclaration */))) { - emitStart(node); - if (isES6ExportedEnum) { - write("export "); - } - write("var "); - emit(node.name); - emitEnd(node); - write(";"); + else { + for (var i = blockStack.length - 1; i >= 0; i--) { + var block = blockStack[i]; + if (supportsUnlabeledBreak(block)) { + return block.breakLabel; } } - writeLine(); - emitStart(node); - write("(function ("); - emitStart(node.name); - write(getGeneratedNameForNode(node)); - emitEnd(node.name); - write(") {"); - increaseIndent(); - emitLines(node.members); - decreaseIndent(); - writeLine(); - emitToken(16 /* CloseBraceToken */, node.members.end); - write(")("); - emitModuleMemberName(node); - write(" || ("); - emitModuleMemberName(node); - write(" = {}));"); - emitEnd(node); - if (!isES6ExportedDeclaration(node) && node.flags & 1 /* Export */ && !shouldHoistDeclarationInSystemJsModule(node)) { - // do not emit var if variable was already hoisted - writeLine(); - emitStart(node); - write("var "); - emit(node.name); - write(" = "); - emitModuleMemberName(node); - emitEnd(node); - write(";"); - } - if (modulekind !== ts.ModuleKind.ES6 && node.parent === currentSourceFile) { - if (modulekind === ts.ModuleKind.System && (node.flags & 1 /* Export */)) { - // write the call to exporter for enum - writeLine(); - write(exportFunctionForFile + "(\""); - emitDeclarationName(node); - write("\", "); - emitDeclarationName(node); - write(");"); + } + return 0; + } + /** + * Finds the label that is the target for a `continue` statement. + * + * @param labelText An optional name of a containing labeled statement. + */ + function findContinueTarget(labelText) { + ts.Debug.assert(blocks !== undefined); + if (labelText) { + for (var i = blockStack.length - 1; i >= 0; i--) { + var block = blockStack[i]; + if (supportsUnlabeledContinue(block) && hasImmediateContainingLabeledBlock(labelText, i - 1)) { + return block.continueLabel; } - emitExportMemberAssignments(node.name); } } - function emitEnumMember(node) { - var enumParent = node.parent; - emitStart(node); - write(getGeneratedNameForNode(enumParent)); - write("["); - write(getGeneratedNameForNode(enumParent)); - write("["); - emitExpressionForPropertyName(node.name); - write("] = "); - writeEnumMemberDeclarationValue(node); - write("] = "); - emitExpressionForPropertyName(node.name); - emitEnd(node); - write(";"); + else { + for (var i = blockStack.length - 1; i >= 0; i--) { + var block = blockStack[i]; + if (supportsUnlabeledContinue(block)) { + return block.continueLabel; + } + } } - function writeEnumMemberDeclarationValue(member) { - var value = resolver.getConstantValue(member); - if (value !== undefined) { - write(value.toString()); - return; + return 0; + } + /** + * Creates an expression that can be used to indicate the value for a label. + * + * @param label A label. + */ + function createLabel(label) { + if (label > 0) { + if (labelExpressions === undefined) { + labelExpressions = []; } - else if (member.initializer) { - emit(member.initializer); + var expression = ts.createSynthesizedNode(8 /* NumericLiteral */); + if (labelExpressions[label] === undefined) { + labelExpressions[label] = [expression]; } else { - write("undefined"); + labelExpressions[label].push(expression); } + return expression; } - function getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration) { - if (moduleDeclaration.body && moduleDeclaration.body.kind === 225 /* ModuleDeclaration */) { - var recursiveInnerModule = getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration.body); - return recursiveInnerModule || moduleDeclaration.body; - } + return ts.createNode(193 /* OmittedExpression */); + } + /** + * Creates a numeric literal for the provided instruction. + */ + function createInstruction(instruction) { + var literal = ts.createLiteral(instruction); + literal.trailingComment = instructionNames[instruction]; + return literal; + } + /** + * Creates a statement that can be used indicate a Break operation to the provided label. + * + * @param label A label. + * @param location An optional source map location for the statement. + */ + function createInlineBreak(label, location) { + ts.Debug.assert(label > 0, "Invalid label: " + label); + return ts.createReturn(ts.createArrayLiteral([ + createInstruction(3 /* Break */), + createLabel(label) + ]), location); + } + /** + * Creates a statement that can be used indicate a Return operation. + * + * @param expression The expression for the return statement. + * @param location An optional source map location for the statement. + */ + function createInlineReturn(expression, location) { + return ts.createReturn(ts.createArrayLiteral(expression + ? [createInstruction(2 /* Return */), expression] + : [createInstruction(2 /* Return */)]), location); + } + /** + * Creates an expression that can be used to resume from a Yield operation. + */ + function createGeneratorResume(location) { + return ts.createCall(ts.createPropertyAccess(state, "sent"), /*typeArguments*/ undefined, [], location); + } + /** + * Emits an empty instruction. + */ + function emitNop() { + emitWorker(0 /* Nop */); + } + /** + * Emits a Statement. + * + * @param node A statement. + */ + function emitStatement(node) { + if (node) { + emitWorker(1 /* Statement */, [node]); } - function shouldEmitModuleDeclaration(node) { - return ts.isInstantiatedModule(node, compilerOptions.preserveConstEnums || compilerOptions.isolatedModules); + else { + emitNop(); } - function isModuleMergedWithES6Class(node) { - return languageVersion === 2 /* ES6 */ && !!(resolver.getNodeCheckFlags(node) & 32768 /* LexicalModuleMergesWithClass */); + } + /** + * Emits an Assignment operation. + * + * @param left The left-hand side of the assignment. + * @param right The right-hand side of the assignment. + * @param location An optional source map location for the assignment. + */ + function emitAssignment(left, right, location) { + emitWorker(2 /* Assign */, [left, right], location); + } + /** + * Emits a Break operation to the specified label. + * + * @param label A label. + * @param location An optional source map location for the assignment. + */ + function emitBreak(label, location) { + emitWorker(3 /* Break */, [label], location); + } + /** + * Emits a Break operation to the specified label when a condition evaluates to a truthy + * value at runtime. + * + * @param label A label. + * @param condition The condition. + * @param location An optional source map location for the assignment. + */ + function emitBreakWhenTrue(label, condition, location) { + emitWorker(4 /* BreakWhenTrue */, [label, condition], location); + } + /** + * Emits a Break to the specified label when a condition evaluates to a falsey value at + * runtime. + * + * @param label A label. + * @param condition The condition. + * @param location An optional source map location for the assignment. + */ + function emitBreakWhenFalse(label, condition, location) { + emitWorker(5 /* BreakWhenFalse */, [label, condition], location); + } + /** + * Emits a YieldStar operation for the provided expression. + * + * @param expression An optional value for the yield operation. + * @param location An optional source map location for the assignment. + */ + function emitYieldStar(expression, location) { + emitWorker(7 /* YieldStar */, [expression], location); + } + /** + * Emits a Yield operation for the provided expression. + * + * @param expression An optional value for the yield operation. + * @param location An optional source map location for the assignment. + */ + function emitYield(expression, location) { + emitWorker(6 /* Yield */, [expression], location); + } + /** + * Emits a Return operation for the provided expression. + * + * @param expression An optional value for the operation. + * @param location An optional source map location for the assignment. + */ + function emitReturn(expression, location) { + emitWorker(8 /* Return */, [expression], location); + } + /** + * Emits a Throw operation for the provided expression. + * + * @param expression A value for the operation. + * @param location An optional source map location for the assignment. + */ + function emitThrow(expression, location) { + emitWorker(9 /* Throw */, [expression], location); + } + /** + * Emits an Endfinally operation. This is used to handle `finally` block semantics. + */ + function emitEndfinally() { + emitWorker(10 /* Endfinally */); + } + /** + * Emits an operation. + * + * @param code The OpCode for the operation. + * @param args The optional arguments for the operation. + */ + function emitWorker(code, args, location) { + if (operations === undefined) { + operations = []; + operationArguments = []; + operationLocations = []; } - function isFirstDeclarationOfKind(node, declarations, kind) { - return !ts.forEach(declarations, function (declaration) { return declaration.kind === kind && declaration.pos < node.pos; }); + if (labelOffsets === undefined) { + // mark entry point + markLabel(defineLabel()); } - function emitModuleDeclaration(node) { - // Emit only if this module is non-ambient. - var shouldEmit = shouldEmitModuleDeclaration(node); - if (!shouldEmit) { - return emitCommentsOnNotEmittedNode(node); - } - var hoistedInDeclarationScope = shouldHoistDeclarationInSystemJsModule(node); - var emitVarForModule = !hoistedInDeclarationScope && !isModuleMergedWithES6Class(node); - if (emitVarForModule) { - var isES6ExportedNamespace = isES6ExportedDeclaration(node); - if (!isES6ExportedNamespace || isFirstDeclarationOfKind(node, node.symbol && node.symbol.declarations, 225 /* ModuleDeclaration */)) { - emitStart(node); - if (isES6ExportedNamespace) { - write("export "); - } - write("var "); - emit(node.name); - write(";"); - emitEnd(node); - writeLine(); - } - } - emitStart(node); - write("(function ("); - emitStart(node.name); - write(getGeneratedNameForNode(node)); - emitEnd(node.name); - write(") "); - ts.Debug.assert(node.body !== undefined); // node.body must exist, as this is a non-ambient module - if (node.body.kind === 226 /* ModuleBlock */) { - var saveConvertedLoopState = convertedLoopState; - var saveTempFlags = tempFlags; - var saveTempVariables = tempVariables; - convertedLoopState = undefined; - tempFlags = 0; - tempVariables = undefined; - emit(node.body); - ts.Debug.assert(convertedLoopState === undefined); - convertedLoopState = saveConvertedLoopState; - tempFlags = saveTempFlags; - tempVariables = saveTempVariables; - } - else { - write("{"); - increaseIndent(); - emitCaptureThisForNodeIfNecessary(node); - writeLine(); - emit(node.body); - decreaseIndent(); - writeLine(); - var moduleBlock = getInnerMostModuleDeclarationFromDottedModule(node).body; - emitToken(16 /* CloseBraceToken */, moduleBlock.statements.end); - } - write(")("); - // write moduleDecl = containingModule.m only if it is not exported es6 module member - if ((node.flags & 1 /* Export */) && !isES6ExportedDeclaration(node)) { - emit(node.name); - write(" = "); - } - emitModuleMemberName(node); - write(" || ("); - emitModuleMemberName(node); - write(" = {}));"); - emitEnd(node); - if (!isES6ExportedDeclaration(node) && node.name.kind === 69 /* Identifier */ && node.parent === currentSourceFile) { - if (modulekind === ts.ModuleKind.System && (node.flags & 1 /* Export */)) { - writeLine(); - write(exportFunctionForFile + "(\""); - emitDeclarationName(node); - write("\", "); - emitDeclarationName(node); - write(");"); - } - emitExportMemberAssignments(node.name); + var operationIndex = operations.length; + operations[operationIndex] = code; + operationArguments[operationIndex] = args; + operationLocations[operationIndex] = location; + } + /** + * Builds the generator function body. + */ + function build() { + blockIndex = 0; + labelNumber = 0; + labelNumbers = undefined; + lastOperationWasAbrupt = false; + lastOperationWasCompletion = false; + clauses = undefined; + statements = undefined; + exceptionBlockStack = undefined; + currentExceptionBlock = undefined; + withBlockStack = undefined; + var buildResult = buildStatements(); + return ts.createCall(ts.createHelperName(currentSourceFile.externalHelpersModuleName, "__generator"), + /*typeArguments*/ undefined, [ + ts.createThis(), + ts.setEmitFlags(ts.createFunctionExpression( + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ts.createParameter(state)], + /*type*/ undefined, ts.createBlock(buildResult, + /*location*/ undefined, + /*multiLine*/ buildResult.length > 0)), 4194304 /* ReuseTempVariableScope */) + ]); + } + /** + * Builds the statements for the generator function body. + */ + function buildStatements() { + if (operations) { + for (var operationIndex = 0; operationIndex < operations.length; operationIndex++) { + writeOperation(operationIndex); } + flushFinalLabel(operations.length); } - /* - * Some bundlers (SystemJS builder) sometimes want to rename dependencies. - * Here we check if alternative name was provided for a given moduleName and return it if possible. - */ - function tryRenameExternalModule(moduleName) { - if (renamedDependencies && moduleName.text in renamedDependencies) { - return "\"" + renamedDependencies[moduleName.text] + "\""; - } - return undefined; + else { + flushFinalLabel(0); + } + if (clauses) { + var labelExpression = ts.createPropertyAccess(state, "label"); + var switchStatement = ts.createSwitch(labelExpression, ts.createCaseBlock(clauses)); + switchStatement.startsOnNewLine = true; + return [switchStatement]; + } + if (statements) { + return statements; + } + return []; + } + /** + * Flush the current label and advance to a new label. + */ + function flushLabel() { + if (!statements) { + return; } - function emitRequire(moduleName) { - if (moduleName.kind === 9 /* StringLiteral */) { - write("require("); - var text = tryRenameExternalModule(moduleName); - if (text) { - write(text); - } - else { - emitStart(moduleName); - emitLiteral(moduleName); - emitEnd(moduleName); - } - emitToken(18 /* CloseParenToken */, moduleName.end); - } - else { - write("require()"); - } + appendLabel(/*markLabelEnd*/ !lastOperationWasAbrupt); + lastOperationWasAbrupt = false; + lastOperationWasCompletion = false; + labelNumber++; + } + /** + * Flush the final label of the generator function body. + */ + function flushFinalLabel(operationIndex) { + if (isFinalLabelReachable(operationIndex)) { + tryEnterLabel(operationIndex); + withBlockStack = undefined; + writeReturn(/*expression*/ undefined, /*operationLocation*/ undefined); } - function getNamespaceDeclarationNode(node) { - if (node.kind === 229 /* ImportEqualsDeclaration */) { - return node; - } - var importClause = node.importClause; - if (importClause && importClause.namedBindings && importClause.namedBindings.kind === 232 /* NamespaceImport */) { - return importClause.namedBindings; - } + if (statements && clauses) { + appendLabel(/*markLabelEnd*/ false); } - function isDefaultImport(node) { - return node.kind === 230 /* ImportDeclaration */ && node.importClause && !!node.importClause.name; + updateLabelExpressions(); + } + /** + * Tests whether the final label of the generator function body + * is reachable by user code. + */ + function isFinalLabelReachable(operationIndex) { + // if the last operation was *not* a completion (return/throw) then + // the final label is reachable. + if (!lastOperationWasCompletion) { + return true; } - function emitExportImportAssignments(node) { - if (ts.isAliasSymbolDeclaration(node) && resolver.isValueAliasDeclaration(node)) { - emitExportMemberAssignments(node.name); - } - ts.forEachChild(node, emitExportImportAssignments); + // if there are no labels defined or referenced, then the final label is + // not reachable. + if (!labelOffsets || !labelExpressions) { + return false; } - function emitImportDeclaration(node) { - if (modulekind !== ts.ModuleKind.ES6) { - return emitExternalImportDeclaration(node); + // if the label for this offset is referenced, then the final label + // is reachable. + for (var label = 0; label < labelOffsets.length; label++) { + if (labelOffsets[label] === operationIndex && labelExpressions[label]) { + return true; } - // ES6 import - if (node.importClause) { - var shouldEmitDefaultBindings = resolver.isReferencedAliasDeclaration(node.importClause); - var shouldEmitNamedBindings = node.importClause.namedBindings && resolver.isReferencedAliasDeclaration(node.importClause.namedBindings, /* checkChildren */ true); - if (shouldEmitDefaultBindings || shouldEmitNamedBindings) { - write("import "); - emitStart(node.importClause); - if (shouldEmitDefaultBindings) { - emit(node.importClause.name); - if (shouldEmitNamedBindings) { - write(", "); - } - } - if (shouldEmitNamedBindings) { - emitLeadingComments(node.importClause.namedBindings); - emitStart(node.importClause.namedBindings); - if (node.importClause.namedBindings.kind === 232 /* NamespaceImport */) { - write("* as "); - emit(node.importClause.namedBindings.name); - } - else { - write("{ "); - emitExportOrImportSpecifierList(node.importClause.namedBindings.elements, resolver.isReferencedAliasDeclaration); - write(" }"); - } - emitEnd(node.importClause.namedBindings); - emitTrailingComments(node.importClause.namedBindings); - } - emitEnd(node.importClause); - write(" from "); - emit(node.moduleSpecifier); - write(";"); + } + return false; + } + /** + * Appends a case clause for the last label and sets the new label. + * + * @param markLabelEnd Indicates that the transition between labels was a fall-through + * from a previous case clause and the change in labels should be + * reflected on the `state` object. + */ + function appendLabel(markLabelEnd) { + if (!clauses) { + clauses = []; + } + if (statements) { + if (withBlockStack) { + // The previous label was nested inside one or more `with` blocks, so we + // surround the statements in generated `with` blocks to create the same environment. + for (var i = withBlockStack.length - 1; i >= 0; i--) { + var withBlock = withBlockStack[i]; + statements = [ts.createWith(withBlock.expression, ts.createBlock(statements))]; + } + } + if (currentExceptionBlock) { + // The previous label was nested inside of an exception block, so we must + // indicate entry into a protected region by pushing the label numbers + // for each block in the protected region. + var startLabel = currentExceptionBlock.startLabel, catchLabel = currentExceptionBlock.catchLabel, finallyLabel = currentExceptionBlock.finallyLabel, endLabel = currentExceptionBlock.endLabel; + statements.unshift(ts.createStatement(ts.createCall(ts.createPropertyAccess(ts.createPropertyAccess(state, "trys"), "push"), + /*typeArguments*/ undefined, [ + ts.createArrayLiteral([ + createLabel(startLabel), + createLabel(catchLabel), + createLabel(finallyLabel), + createLabel(endLabel) + ]) + ]))); + currentExceptionBlock = undefined; + } + if (markLabelEnd) { + // The case clause for the last label falls through to this label, so we + // add an assignment statement to reflect the change in labels. + statements.push(ts.createStatement(ts.createAssignment(ts.createPropertyAccess(state, "label"), ts.createLiteral(labelNumber + 1)))); + } + } + clauses.push(ts.createCaseClause(ts.createLiteral(labelNumber), statements || [])); + statements = undefined; + } + /** + * Tries to enter into a new label at the current operation index. + */ + function tryEnterLabel(operationIndex) { + if (!labelOffsets) { + return; + } + for (var label = 0; label < labelOffsets.length; label++) { + if (labelOffsets[label] === operationIndex) { + flushLabel(); + if (labelNumbers === undefined) { + labelNumbers = []; } - } - else { - write("import "); - emit(node.moduleSpecifier); - write(";"); - } - } - function emitExternalImportDeclaration(node) { - if (ts.contains(externalImports, node)) { - var isExportedImport = node.kind === 229 /* ImportEqualsDeclaration */ && (node.flags & 1 /* Export */) !== 0; - var namespaceDeclaration = getNamespaceDeclarationNode(node); - var varOrConst = (languageVersion <= 1 /* ES5 */) ? "var " : "const "; - if (modulekind !== ts.ModuleKind.AMD) { - emitLeadingComments(node); - emitStart(node); - if (namespaceDeclaration && !isDefaultImport(node)) { - // import x = require("foo") - // import * as x from "foo" - if (!isExportedImport) { - write(varOrConst); - } - ; - emitModuleMemberName(namespaceDeclaration); - write(" = "); - } - else { - // import "foo" - // import x from "foo" - // import { x, y } from "foo" - // import d, * as x from "foo" - // import d, { x, y } from "foo" - var isNakedImport = node.kind === 230 /* ImportDeclaration */ && !node.importClause; - if (!isNakedImport) { - write(varOrConst); - write(getGeneratedNameForNode(node)); - write(" = "); - } - } - emitRequire(ts.getExternalModuleName(node)); - if (namespaceDeclaration && isDefaultImport(node)) { - // import d, * as x from "foo" - write(", "); - emitModuleMemberName(namespaceDeclaration); - write(" = "); - write(getGeneratedNameForNode(node)); - } - write(";"); - emitEnd(node); - emitExportImportAssignments(node); - emitTrailingComments(node); + if (labelNumbers[labelNumber] === undefined) { + labelNumbers[labelNumber] = [label]; } else { - if (isExportedImport) { - emitModuleMemberName(namespaceDeclaration); - write(" = "); - emit(namespaceDeclaration.name); - write(";"); - } - else if (namespaceDeclaration && isDefaultImport(node)) { - // import d, * as x from "foo" - write(varOrConst); - emitModuleMemberName(namespaceDeclaration); - write(" = "); - write(getGeneratedNameForNode(node)); - write(";"); - } - emitExportImportAssignments(node); + labelNumbers[labelNumber].push(label); } } } - function emitImportEqualsDeclaration(node) { - if (ts.isExternalModuleImportEqualsDeclaration(node)) { - emitExternalImportDeclaration(node); - return; - } - // preserve old compiler's behavior: emit 'var' for import declaration (even if we do not consider them referenced) when - // - current file is not external module - // - import declaration is top level and target is value imported by entity name - if (resolver.isReferencedAliasDeclaration(node) || - (!isCurrentFileExternalModule && resolver.isTopLevelValueImportEqualsWithEntityName(node))) { - emitLeadingComments(node); - emitStart(node); - // variable declaration for import-equals declaration can be hoisted in system modules - // in this case 'var' should be omitted and emit should contain only initialization - var variableDeclarationIsHoisted = shouldHoistVariable(node, /*checkIfSourceFileLevelDecl*/ true); - // is it top level export import v = a.b.c in system module? - // if yes - it needs to be rewritten as exporter('v', v = a.b.c) - var isExported = isSourceFileLevelDeclarationInSystemJsModule(node, /*isExported*/ true); - if (!variableDeclarationIsHoisted) { - ts.Debug.assert(!isExported); - if (isES6ExportedDeclaration(node)) { - write("export "); - write("var "); - } - else if (!(node.flags & 1 /* Export */)) { - write("var "); - } - } - if (isExported) { - write(exportFunctionForFile + "(\""); - emitNodeWithoutSourceMap(node.name); - write("\", "); - } - emitModuleMemberName(node); - write(" = "); - emit(node.moduleReference); - if (isExported) { - write(")"); - } - write(";"); - emitEnd(node); - emitExportImportAssignments(node); - emitTrailingComments(node); - } - } - function emitExportDeclaration(node) { - ts.Debug.assert(modulekind !== ts.ModuleKind.System); - if (modulekind !== ts.ModuleKind.ES6) { - if (node.moduleSpecifier && (!node.exportClause || resolver.isValueAliasDeclaration(node))) { - emitStart(node); - var generatedName = getGeneratedNameForNode(node); - if (node.exportClause) { - // export { x, y, ... } from "foo" - if (modulekind !== ts.ModuleKind.AMD) { - write("var "); - write(generatedName); - write(" = "); - emitRequire(ts.getExternalModuleName(node)); - write(";"); - } - for (var _a = 0, _b = node.exportClause.elements; _a < _b.length; _a++) { - var specifier = _b[_a]; - if (resolver.isValueAliasDeclaration(specifier)) { - writeLine(); - emitStart(specifier); - emitContainingModuleName(specifier); - write("."); - emitNodeWithCommentsAndWithoutSourcemap(specifier.name); - write(" = "); - write(generatedName); - write("."); - emitNodeWithCommentsAndWithoutSourcemap(specifier.propertyName || specifier.name); - write(";"); - emitEnd(specifier); - } - } - } - else { - // export * from "foo" - if (hasExportStarsToExportValues && resolver.moduleExportsSomeValue(node.moduleSpecifier)) { - writeLine(); - write("__export("); - if (modulekind !== ts.ModuleKind.AMD) { - emitRequire(ts.getExternalModuleName(node)); - } - else { - write(generatedName); + } + /** + * Updates literal expressions for labels with actual label numbers. + */ + function updateLabelExpressions() { + if (labelExpressions !== undefined && labelNumbers !== undefined) { + for (var labelNumber_1 = 0; labelNumber_1 < labelNumbers.length; labelNumber_1++) { + var labels = labelNumbers[labelNumber_1]; + if (labels !== undefined) { + for (var _i = 0, labels_1 = labels; _i < labels_1.length; _i++) { + var label = labels_1[_i]; + var expressions = labelExpressions[label]; + if (expressions !== undefined) { + for (var _a = 0, expressions_1 = expressions; _a < expressions_1.length; _a++) { + var expression = expressions_1[_a]; + expression.text = String(labelNumber_1); } - write(");"); } } - emitEnd(node); - } - } - else { - if (!node.exportClause || resolver.isValueAliasDeclaration(node)) { - write("export "); - if (node.exportClause) { - // export { x, y, ... } - write("{ "); - emitExportOrImportSpecifierList(node.exportClause.elements, resolver.isValueAliasDeclaration); - write(" }"); - } - else { - write("*"); - } - if (node.moduleSpecifier) { - write(" from "); - emit(node.moduleSpecifier); - } - write(";"); } } } - function emitExportOrImportSpecifierList(specifiers, shouldEmit) { - ts.Debug.assert(modulekind === ts.ModuleKind.ES6); - var needsComma = false; - for (var _a = 0, specifiers_1 = specifiers; _a < specifiers_1.length; _a++) { - var specifier = specifiers_1[_a]; - if (shouldEmit(specifier)) { - if (needsComma) { - write(", "); - } - if (specifier.propertyName) { - emit(specifier.propertyName); - write(" as "); + } + /** + * Tries to enter or leave a code block. + */ + function tryEnterOrLeaveBlock(operationIndex) { + if (blocks) { + for (; blockIndex < blockActions.length && blockOffsets[blockIndex] <= operationIndex; blockIndex++) { + var block = blocks[blockIndex]; + var blockAction = blockActions[blockIndex]; + if (isExceptionBlock(block)) { + if (blockAction === 0 /* Open */) { + if (!exceptionBlockStack) { + exceptionBlockStack = []; + } + if (!statements) { + statements = []; + } + exceptionBlockStack.push(currentExceptionBlock); + currentExceptionBlock = block; } - emit(specifier.name); - needsComma = true; - } - } - } - function emitExportAssignment(node) { - if (!node.isExportEquals && resolver.isValueAliasDeclaration(node)) { - if (modulekind === ts.ModuleKind.ES6) { - writeLine(); - emitStart(node); - write("export default "); - var expression = node.expression; - emit(expression); - if (expression.kind !== 220 /* FunctionDeclaration */ && - expression.kind !== 221 /* ClassDeclaration */) { - write(";"); + else if (blockAction === 1 /* Close */) { + currentExceptionBlock = exceptionBlockStack.pop(); } - emitEnd(node); } - else { - writeLine(); - emitStart(node); - if (modulekind === ts.ModuleKind.System) { - write(exportFunctionForFile + "(\"default\","); - emit(node.expression); - write(")"); - } - else { - emitEs6ExportDefaultCompat(node); - emitContainingModuleName(node); - if (languageVersion === 0 /* ES3 */) { - write('["default"] = '); + else if (isWithBlock(block)) { + if (blockAction === 0 /* Open */) { + if (!withBlockStack) { + withBlockStack = []; } - else { - write(".default = "); - } - emit(node.expression); + withBlockStack.push(block); + } + else if (blockAction === 1 /* Close */) { + withBlockStack.pop(); } - write(";"); - emitEnd(node); } } } - function collectExternalModuleInfo(sourceFile) { - externalImports = []; - exportSpecifiers = ts.createMap(); - exportEquals = undefined; - hasExportStarsToExportValues = false; - for (var _a = 0, _b = sourceFile.statements; _a < _b.length; _a++) { - var node = _b[_a]; - switch (node.kind) { - case 230 /* ImportDeclaration */: - if (!node.importClause || - resolver.isReferencedAliasDeclaration(node.importClause, /*checkChildren*/ true)) { - // import "mod" - // import x from "mod" where x is referenced - // import * as x from "mod" where x is referenced - // import { x, y } from "mod" where at least one import is referenced - externalImports.push(node); - } - break; - case 229 /* ImportEqualsDeclaration */: - if (node.moduleReference.kind === 240 /* ExternalModuleReference */ && resolver.isReferencedAliasDeclaration(node)) { - // import x = require("mod") where x is referenced - externalImports.push(node); - } - break; - case 236 /* ExportDeclaration */: - if (node.moduleSpecifier) { - if (!node.exportClause) { - // export * from "mod" - if (resolver.moduleExportsSomeValue(node.moduleSpecifier)) { - externalImports.push(node); - hasExportStarsToExportValues = true; - } - } - else if (resolver.isValueAliasDeclaration(node)) { - // export { x, y } from "mod" where at least one export is a value symbol - externalImports.push(node); - } - } - else { - // export { x, y } - for (var _c = 0, _d = node.exportClause.elements; _c < _d.length; _c++) { - var specifier = _d[_c]; - var name_32 = (specifier.propertyName || specifier.name).text; - ts.multiMapAdd(exportSpecifiers, name_32, specifier); - } - } - break; - case 235 /* ExportAssignment */: - if (node.isExportEquals && !exportEquals) { - // export = x - exportEquals = node; - } - break; - } - } + } + /** + * Writes an operation as a statement to the current label's statement list. + * + * @param operation The OpCode of the operation + */ + function writeOperation(operationIndex) { + tryEnterLabel(operationIndex); + tryEnterOrLeaveBlock(operationIndex); + // early termination, nothing else to process in this label + if (lastOperationWasAbrupt) { + return; } - function emitExportStarHelper() { - if (hasExportStarsToExportValues) { - writeLine(); - write("function __export(m) {"); - increaseIndent(); - writeLine(); - write("for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];"); - decreaseIndent(); - writeLine(); - write("}"); - } + lastOperationWasAbrupt = false; + lastOperationWasCompletion = false; + var opcode = operations[operationIndex]; + if (opcode === 0 /* Nop */) { + return; } - function getLocalNameForExternalImport(node) { - var namespaceDeclaration = getNamespaceDeclarationNode(node); - if (namespaceDeclaration && !isDefaultImport(node)) { - return ts.getTextOfNodeFromSourceText(currentText, namespaceDeclaration.name); - } - if (node.kind === 230 /* ImportDeclaration */ && node.importClause) { - return getGeneratedNameForNode(node); + else if (opcode === 10 /* Endfinally */) { + return writeEndfinally(); + } + var args = operationArguments[operationIndex]; + if (opcode === 1 /* Statement */) { + return writeStatement(args[0]); + } + var location = operationLocations[operationIndex]; + switch (opcode) { + case 2 /* Assign */: + return writeAssign(args[0], args[1], location); + case 3 /* Break */: + return writeBreak(args[0], location); + case 4 /* BreakWhenTrue */: + return writeBreakWhenTrue(args[0], args[1], location); + case 5 /* BreakWhenFalse */: + return writeBreakWhenFalse(args[0], args[1], location); + case 6 /* Yield */: + return writeYield(args[0], location); + case 7 /* YieldStar */: + return writeYieldStar(args[0], location); + case 8 /* Return */: + return writeReturn(args[0], location); + case 9 /* Throw */: + return writeThrow(args[0], location); + } + } + /** + * Writes a statement to the current label's statement list. + * + * @param statement A statement to write. + */ + function writeStatement(statement) { + if (statement) { + if (!statements) { + statements = [statement]; } - if (node.kind === 236 /* ExportDeclaration */ && node.moduleSpecifier) { - return getGeneratedNameForNode(node); + else { + statements.push(statement); } } - function getExternalModuleNameText(importNode, emitRelativePathAsModuleName) { - if (emitRelativePathAsModuleName) { - var name_33 = getExternalModuleNameFromDeclaration(host, resolver, importNode); - if (name_33) { - return "\"" + name_33 + "\""; - } + } + /** + * Writes an Assign operation to the current label's statement list. + * + * @param left The left-hand side of the assignment. + * @param right The right-hand side of the assignment. + * @param operationLocation The source map location for the operation. + */ + function writeAssign(left, right, operationLocation) { + writeStatement(ts.createStatement(ts.createAssignment(left, right), operationLocation)); + } + /** + * Writes a Throw operation to the current label's statement list. + * + * @param expression The value to throw. + * @param operationLocation The source map location for the operation. + */ + function writeThrow(expression, operationLocation) { + lastOperationWasAbrupt = true; + lastOperationWasCompletion = true; + writeStatement(ts.createThrow(expression, operationLocation)); + } + /** + * Writes a Return operation to the current label's statement list. + * + * @param expression The value to return. + * @param operationLocation The source map location for the operation. + */ + function writeReturn(expression, operationLocation) { + lastOperationWasAbrupt = true; + lastOperationWasCompletion = true; + writeStatement(ts.createReturn(ts.createArrayLiteral(expression + ? [createInstruction(2 /* Return */), expression] + : [createInstruction(2 /* Return */)]), operationLocation)); + } + /** + * Writes a Break operation to the current label's statement list. + * + * @param label The label for the Break. + * @param operationLocation The source map location for the operation. + */ + function writeBreak(label, operationLocation) { + lastOperationWasAbrupt = true; + writeStatement(ts.createReturn(ts.createArrayLiteral([ + createInstruction(3 /* Break */), + createLabel(label) + ]), operationLocation)); + } + /** + * Writes a BreakWhenTrue operation to the current label's statement list. + * + * @param label The label for the Break. + * @param condition The condition for the Break. + * @param operationLocation The source map location for the operation. + */ + function writeBreakWhenTrue(label, condition, operationLocation) { + writeStatement(ts.createIf(condition, ts.createReturn(ts.createArrayLiteral([ + createInstruction(3 /* Break */), + createLabel(label) + ]), operationLocation))); + } + /** + * Writes a BreakWhenFalse operation to the current label's statement list. + * + * @param label The label for the Break. + * @param condition The condition for the Break. + * @param operationLocation The source map location for the operation. + */ + function writeBreakWhenFalse(label, condition, operationLocation) { + writeStatement(ts.createIf(ts.createLogicalNot(condition), ts.createReturn(ts.createArrayLiteral([ + createInstruction(3 /* Break */), + createLabel(label) + ]), operationLocation))); + } + /** + * Writes a Yield operation to the current label's statement list. + * + * @param expression The expression to yield. + * @param operationLocation The source map location for the operation. + */ + function writeYield(expression, operationLocation) { + lastOperationWasAbrupt = true; + writeStatement(ts.createReturn(ts.createArrayLiteral(expression + ? [createInstruction(4 /* Yield */), expression] + : [createInstruction(4 /* Yield */)]), operationLocation)); + } + /** + * Writes a YieldStar instruction to the current label's statement list. + * + * @param expression The expression to yield. + * @param operationLocation The source map location for the operation. + */ + function writeYieldStar(expression, operationLocation) { + lastOperationWasAbrupt = true; + writeStatement(ts.createReturn(ts.createArrayLiteral([ + createInstruction(5 /* YieldStar */), + expression + ]), operationLocation)); + } + /** + * Writes an Endfinally instruction to the current label's statement list. + */ + function writeEndfinally() { + lastOperationWasAbrupt = true; + writeStatement(ts.createReturn(ts.createArrayLiteral([ + createInstruction(7 /* Endfinally */) + ]))); + } + } + ts.transformGenerators = transformGenerators; + var _a; +})(ts || (ts = {})); +/// +/// +/*@internal*/ +var ts; +(function (ts) { + function transformModule(context) { + var transformModuleDelegates = ts.createMap((_a = {}, + _a[ts.ModuleKind.None] = transformCommonJSModule, + _a[ts.ModuleKind.CommonJS] = transformCommonJSModule, + _a[ts.ModuleKind.AMD] = transformAMDModule, + _a[ts.ModuleKind.UMD] = transformUMDModule, + _a)); + var startLexicalEnvironment = context.startLexicalEnvironment, endLexicalEnvironment = context.endLexicalEnvironment, hoistVariableDeclaration = context.hoistVariableDeclaration; + var compilerOptions = context.getCompilerOptions(); + var resolver = context.getEmitResolver(); + var host = context.getEmitHost(); + var languageVersion = ts.getEmitScriptTarget(compilerOptions); + var moduleKind = ts.getEmitModuleKind(compilerOptions); + var previousOnSubstituteNode = context.onSubstituteNode; + var previousOnEmitNode = context.onEmitNode; + context.onSubstituteNode = onSubstituteNode; + context.onEmitNode = onEmitNode; + context.enableSubstitution(69 /* Identifier */); + context.enableSubstitution(187 /* BinaryExpression */); + context.enableSubstitution(185 /* PrefixUnaryExpression */); + context.enableSubstitution(186 /* PostfixUnaryExpression */); + context.enableSubstitution(254 /* ShorthandPropertyAssignment */); + context.enableEmitNotification(256 /* SourceFile */); + var currentSourceFile; + var externalImports; + var exportSpecifiers; + var exportEquals; + var bindingNameExportSpecifiersMap; + // Subset of exportSpecifiers that is a binding-name. + // This is to reduce amount of memory we have to keep around even after we done with module-transformer + var bindingNameExportSpecifiersForFileMap = ts.createMap(); + var hasExportStarsToExportValues; + return transformSourceFile; + /** + * Transforms the module aspects of a SourceFile. + * + * @param node The SourceFile node. + */ + function transformSourceFile(node) { + if (ts.isDeclarationFile(node)) { + return node; + } + if (ts.isExternalModule(node) || compilerOptions.isolatedModules) { + currentSourceFile = node; + // Collect information about the external module. + (_a = ts.collectExternalModuleInfo(node, resolver), externalImports = _a.externalImports, exportSpecifiers = _a.exportSpecifiers, exportEquals = _a.exportEquals, hasExportStarsToExportValues = _a.hasExportStarsToExportValues, _a); + // Perform the transformation. + var transformModule_1 = transformModuleDelegates[moduleKind] || transformModuleDelegates[ts.ModuleKind.None]; + var updated = transformModule_1(node); + ts.aggregateTransformFlags(updated); + currentSourceFile = undefined; + externalImports = undefined; + exportSpecifiers = undefined; + exportEquals = undefined; + hasExportStarsToExportValues = false; + return updated; + } + return node; + var _a; + } + /** + * Transforms a SourceFile into a CommonJS module. + * + * @param node The SourceFile node. + */ + function transformCommonJSModule(node) { + startLexicalEnvironment(); + var statements = []; + var statementOffset = ts.addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, visitor); + ts.addRange(statements, ts.visitNodes(node.statements, visitor, ts.isStatement, statementOffset)); + ts.addRange(statements, endLexicalEnvironment()); + addExportEqualsIfNeeded(statements, /*emitAsReturn*/ false); + var updated = updateSourceFile(node, statements); + if (hasExportStarsToExportValues) { + ts.setEmitFlags(updated, 2 /* EmitExportStar */ | ts.getEmitFlags(node)); + } + return updated; + } + /** + * Transforms a SourceFile into an AMD module. + * + * @param node The SourceFile node. + */ + function transformAMDModule(node) { + var define = ts.createIdentifier("define"); + var moduleName = ts.tryGetModuleNameFromFile(node, host, compilerOptions); + return transformAsynchronousModule(node, define, moduleName, /*includeNonAmdDependencies*/ true); + } + /** + * Transforms a SourceFile into a UMD module. + * + * @param node The SourceFile node. + */ + function transformUMDModule(node) { + var define = ts.createIdentifier("define"); + ts.setEmitFlags(define, 16 /* UMDDefine */); + return transformAsynchronousModule(node, define, /*moduleName*/ undefined, /*includeNonAmdDependencies*/ false); + } + /** + * Transforms a SourceFile into an AMD or UMD module. + * + * @param node The SourceFile node. + * @param define The expression used to define the module. + * @param moduleName An expression for the module name, if available. + * @param includeNonAmdDependencies A value indicating whether to incldue any non-AMD dependencies. + */ + function transformAsynchronousModule(node, define, moduleName, includeNonAmdDependencies) { + // An AMD define function has the following shape: + // + // define(id?, dependencies?, factory); + // + // This has the shape of the following: + // + // define(name, ["module1", "module2"], function (module1Alias) { ... } + // + // The location of the alias in the parameter list in the factory function needs to + // match the position of the module name in the dependency list. + // + // To ensure this is true in cases of modules with no aliases, e.g.: + // + // import "module" + // + // or + // + // /// + // + // we need to add modules without alias names to the end of the dependencies list + var _a = collectAsynchronousDependencies(node, includeNonAmdDependencies), aliasedModuleNames = _a.aliasedModuleNames, unaliasedModuleNames = _a.unaliasedModuleNames, importAliasNames = _a.importAliasNames; + // Create an updated SourceFile: + // + // define(moduleName?, ["module1", "module2"], function ... + return updateSourceFile(node, [ + ts.createStatement(ts.createCall(define, + /*typeArguments*/ undefined, (moduleName ? [moduleName] : []).concat([ + // Add the dependency array argument: + // + // ["require", "exports", module1", "module2", ...] + ts.createArrayLiteral([ + ts.createLiteral("require"), + ts.createLiteral("exports") + ].concat(aliasedModuleNames, unaliasedModuleNames)), + // Add the module body function argument: + // + // function (require, exports, module1, module2) ... + ts.createFunctionExpression( + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ + ts.createParameter("require"), + ts.createParameter("exports") + ].concat(importAliasNames), + /*type*/ undefined, transformAsynchronousModuleBody(node)) + ]))) + ]); + } + /** + * Transforms a SourceFile into an AMD or UMD module body. + * + * @param node The SourceFile node. + */ + function transformAsynchronousModuleBody(node) { + startLexicalEnvironment(); + var statements = []; + var statementOffset = ts.addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, visitor); + // Visit each statement of the module body. + ts.addRange(statements, ts.visitNodes(node.statements, visitor, ts.isStatement, statementOffset)); + // End the lexical environment for the module body + // and merge any new lexical declarations. + ts.addRange(statements, endLexicalEnvironment()); + // Append the 'export =' statement if provided. + addExportEqualsIfNeeded(statements, /*emitAsReturn*/ true); + var body = ts.createBlock(statements, /*location*/ undefined, /*multiLine*/ true); + if (hasExportStarsToExportValues) { + // If we have any `export * from ...` declarations + // we need to inform the emitter to add the __export helper. + ts.setEmitFlags(body, 2 /* EmitExportStar */); + } + return body; + } + function addExportEqualsIfNeeded(statements, emitAsReturn) { + if (exportEquals && resolver.isValueAliasDeclaration(exportEquals)) { + if (emitAsReturn) { + var statement = ts.createReturn(exportEquals.expression, + /*location*/ exportEquals); + ts.setEmitFlags(statement, 12288 /* NoTokenSourceMaps */ | 49152 /* NoComments */); + statements.push(statement); } - var moduleName = ts.getExternalModuleName(importNode); - if (moduleName.kind === 9 /* StringLiteral */) { - return tryRenameExternalModule(moduleName) || getLiteralText(moduleName); + else { + var statement = ts.createStatement(ts.createAssignment(ts.createPropertyAccess(ts.createIdentifier("module"), "exports"), exportEquals.expression), + /*location*/ exportEquals); + ts.setEmitFlags(statement, 49152 /* NoComments */); + statements.push(statement); } + } + } + /** + * Visits a node at the top level of the source file. + * + * @param node The node. + */ + function visitor(node) { + switch (node.kind) { + case 230 /* ImportDeclaration */: + return visitImportDeclaration(node); + case 229 /* ImportEqualsDeclaration */: + return visitImportEqualsDeclaration(node); + case 236 /* ExportDeclaration */: + return visitExportDeclaration(node); + case 235 /* ExportAssignment */: + return visitExportAssignment(node); + case 200 /* VariableStatement */: + return visitVariableStatement(node); + case 220 /* FunctionDeclaration */: + return visitFunctionDeclaration(node); + case 221 /* ClassDeclaration */: + return visitClassDeclaration(node); + case 202 /* ExpressionStatement */: + return visitExpressionStatement(node); + default: + // This visitor does not descend into the tree, as export/import statements + // are only transformed at the top level of a file. + return node; + } + } + /** + * Visits an ImportDeclaration node. + * + * @param node The ImportDeclaration node. + */ + function visitImportDeclaration(node) { + if (!ts.contains(externalImports, node)) { return undefined; } - function emitVariableDeclarationsForImports() { - if (externalImports.length === 0) { - return; + var statements = []; + var namespaceDeclaration = ts.getNamespaceDeclarationNode(node); + if (moduleKind !== ts.ModuleKind.AMD) { + if (!node.importClause) { + // import "mod"; + statements.push(ts.createStatement(createRequireCall(node), + /*location*/ node)); } - writeLine(); - var started = false; - for (var _a = 0, externalImports_1 = externalImports; _a < externalImports_1.length; _a++) { - var importNode = externalImports_1[_a]; - // do not create variable declaration for exports and imports that lack import clause - var skipNode = importNode.kind === 236 /* ExportDeclaration */ || - (importNode.kind === 230 /* ImportDeclaration */ && !importNode.importClause); - if (skipNode) { - continue; - } - if (!started) { - write("var "); - started = true; + else { + var variables = []; + if (namespaceDeclaration && !ts.isDefaultImport(node)) { + // import * as n from "mod"; + variables.push(ts.createVariableDeclaration(ts.getSynthesizedClone(namespaceDeclaration.name), + /*type*/ undefined, createRequireCall(node))); } else { - write(", "); - } - write(getLocalNameForExternalImport(importNode)); - } - if (started) { - write(";"); - } + // import d from "mod"; + // import { x, y } from "mod"; + // import d, { x, y } from "mod"; + // import d, * as n from "mod"; + variables.push(ts.createVariableDeclaration(ts.getGeneratedNameForNode(node), + /*type*/ undefined, createRequireCall(node))); + if (namespaceDeclaration && ts.isDefaultImport(node)) { + variables.push(ts.createVariableDeclaration(ts.getSynthesizedClone(namespaceDeclaration.name), + /*type*/ undefined, ts.getGeneratedNameForNode(node))); + } + } + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createConstDeclarationList(variables), + /*location*/ node)); + } + } + else if (namespaceDeclaration && ts.isDefaultImport(node)) { + // import d, * as n from "mod"; + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(ts.getSynthesizedClone(namespaceDeclaration.name), + /*type*/ undefined, ts.getGeneratedNameForNode(node), + /*location*/ node) + ]))); + } + addExportImportAssignments(statements, node); + return ts.singleOrMany(statements); + } + function visitImportEqualsDeclaration(node) { + if (!ts.contains(externalImports, node)) { + return undefined; } - function emitLocalStorageForExportedNamesIfNecessary(exportedDeclarations) { - // when resolving exports local exported entries/indirect exported entries in the module - // should always win over entries with similar names that were added via star exports - // to support this we store names of local/indirect exported entries in a set. - // this set is used to filter names brought by star exports. - if (!hasExportStarsToExportValues) { - // local names set is needed only in presence of star exports - return undefined; - } - // local names set should only be added if we have anything exported - if (!exportedDeclarations && !ts.someProperties(exportSpecifiers)) { - // no exported declarations (export var ...) or export specifiers (export {x}) - // check if we have any non star export declarations. - var hasExportDeclarationWithExportClause = false; - for (var _a = 0, externalImports_2 = externalImports; _a < externalImports_2.length; _a++) { - var externalImport = externalImports_2[_a]; - if (externalImport.kind === 236 /* ExportDeclaration */ && externalImport.exportClause) { - hasExportDeclarationWithExportClause = true; - break; - } - } - if (!hasExportDeclarationWithExportClause) { - // we still need to emit exportStar helper - return emitExportStarFunction(/*localNames*/ undefined); - } - } - var exportedNamesStorageRef = makeUniqueName("exportedNames"); - writeLine(); - write("var " + exportedNamesStorageRef + " = {"); - increaseIndent(); - var started = false; - if (exportedDeclarations) { - for (var i = 0; i < exportedDeclarations.length; i++) { - // write name of exported declaration, i.e 'export var x...' - writeExportedName(exportedDeclarations[i]); - } + // Set emitFlags on the name of the importEqualsDeclaration + // This is so the printer will not substitute the identifier + ts.setEmitFlags(node.name, 128 /* NoSubstitution */); + var statements = []; + if (moduleKind !== ts.ModuleKind.AMD) { + if (ts.hasModifier(node, 1 /* Export */)) { + statements.push(ts.createStatement(createExportAssignment(node.name, createRequireCall(node)), + /*location*/ node)); } - if (exportSpecifiers) { - for (var n in exportSpecifiers) { - for (var _b = 0, _c = exportSpecifiers[n]; _b < _c.length; _b++) { - var specifier = _c[_b]; - // write name of export specified, i.e. 'export {x}' - writeExportedName(specifier.name); - } - } + else { + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(ts.getSynthesizedClone(node.name), + /*type*/ undefined, createRequireCall(node)) + ], + /*location*/ undefined, + /*flags*/ languageVersion >= 2 /* ES6 */ ? 2 /* Const */ : 0 /* None */), + /*location*/ node)); } - for (var _d = 0, externalImports_3 = externalImports; _d < externalImports_3.length; _d++) { - var externalImport = externalImports_3[_d]; - if (externalImport.kind !== 236 /* ExportDeclaration */) { - continue; - } - var exportDecl = externalImport; - if (!exportDecl.exportClause) { - // export * from ... - continue; - } - for (var _e = 0, _f = exportDecl.exportClause.elements; _e < _f.length; _e++) { - var element = _f[_e]; - // write name of indirectly exported entry, i.e. 'export {x} from ...' - writeExportedName(element.name || element.propertyName); - } + } + else { + if (ts.hasModifier(node, 1 /* Export */)) { + statements.push(ts.createStatement(createExportAssignment(node.name, node.name), + /*location*/ node)); } - decreaseIndent(); - writeLine(); - write("};"); - return emitExportStarFunction(exportedNamesStorageRef); - function emitExportStarFunction(localNames) { - var exportStarFunction = makeUniqueName("exportStar"); - writeLine(); - // define an export star helper function - write("function " + exportStarFunction + "(m) {"); - increaseIndent(); - writeLine(); - write("var exports = {};"); - writeLine(); - write("for(var n in m) {"); - increaseIndent(); - writeLine(); - write("if (n !== \"default\""); - if (localNames) { - write("&& !" + localNames + ".hasOwnProperty(n)"); - } - write(") exports[n] = m[n];"); - decreaseIndent(); - writeLine(); - write("}"); - writeLine(); - write(exportFunctionForFile + "(exports);"); - decreaseIndent(); - writeLine(); - write("}"); - return exportStarFunction; + } + addExportImportAssignments(statements, node); + return statements; + } + function visitExportDeclaration(node) { + if (!ts.contains(externalImports, node)) { + return undefined; + } + var generatedName = ts.getGeneratedNameForNode(node); + if (node.exportClause) { + var statements = []; + // export { x, y } from "mod"; + if (moduleKind !== ts.ModuleKind.AMD) { + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(generatedName, + /*type*/ undefined, createRequireCall(node)) + ]), + /*location*/ node)); + } + for (var _i = 0, _a = node.exportClause.elements; _i < _a.length; _i++) { + var specifier = _a[_i]; + if (resolver.isValueAliasDeclaration(specifier)) { + var exportedValue = ts.createPropertyAccess(generatedName, specifier.propertyName || specifier.name); + statements.push(ts.createStatement(createExportAssignment(specifier.name, exportedValue), + /*location*/ specifier)); + } + } + return ts.singleOrMany(statements); + } + else if (resolver.moduleExportsSomeValue(node.moduleSpecifier)) { + // export * from "mod"; + return ts.createStatement(ts.createCall(ts.createIdentifier("__export"), + /*typeArguments*/ undefined, [ + moduleKind !== ts.ModuleKind.AMD + ? createRequireCall(node) + : generatedName + ]), + /*location*/ node); + } + } + function visitExportAssignment(node) { + if (!node.isExportEquals) { + if (ts.nodeIsSynthesized(node) || resolver.isValueAliasDeclaration(node)) { + var statements = []; + addExportDefault(statements, node.expression, /*location*/ node); + return statements; } - function writeExportedName(node) { - // do not record default exports - // they are local to module and never overwritten (explicitly skipped) by star export - if (node.kind !== 69 /* Identifier */ && node.flags & 512 /* Default */) { - return; - } - if (started) { - write(","); - } - else { - started = true; - } - writeLine(); - write("'"); - if (node.kind === 69 /* Identifier */) { - emitNodeWithCommentsAndWithoutSourcemap(node); - } - else { - emitDeclarationName(node); - } - write("': true"); - } - } - function processTopLevelVariableAndFunctionDeclarations(node) { - // per ES6 spec: - // 15.2.1.16.4 ModuleDeclarationInstantiation() Concrete Method - // - var declarations are initialized to undefined - 14.a.ii - // - function/generator declarations are instantiated - 16.a.iv - // this means that after module is instantiated but before its evaluation - // exported functions are already accessible at import sites - // in theory we should hoist only exported functions and its dependencies - // in practice to simplify things we'll hoist all source level functions and variable declaration - // including variables declarations for module and class declarations - var hoistedVars; - var hoistedFunctionDeclarations; - var exportedDeclarations; - visit(node); - if (hoistedVars) { - writeLine(); - write("var "); - var seen = ts.createMap(); - for (var i = 0; i < hoistedVars.length; i++) { - var local = hoistedVars[i]; - var name_34 = local.kind === 69 /* Identifier */ - ? local - : local.name; - if (name_34) { - // do not emit duplicate entries (in case of declaration merging) in the list of hoisted variables - var text = ts.unescapeIdentifier(name_34.text); - if (text in seen) { - continue; - } - else { - seen[text] = text; - } - } - if (i !== 0) { - write(", "); - } - if (local.kind === 221 /* ClassDeclaration */ || local.kind === 225 /* ModuleDeclaration */ || local.kind === 224 /* EnumDeclaration */) { - emitDeclarationName(local); - } - else { - emit(local); - } - var flags = ts.getCombinedNodeFlags(local.kind === 69 /* Identifier */ ? local.parent : local); - if (flags & 1 /* Export */) { - if (!exportedDeclarations) { - exportedDeclarations = []; - } - exportedDeclarations.push(local); - } - } - write(";"); + } + return undefined; + } + function addExportDefault(statements, expression, location) { + tryAddExportDefaultCompat(statements); + statements.push(ts.createStatement(createExportAssignment(ts.createIdentifier("default"), expression), location)); + } + function tryAddExportDefaultCompat(statements) { + var original = ts.getOriginalNode(currentSourceFile); + ts.Debug.assert(original.kind === 256 /* SourceFile */); + if (!original.symbol.exports["___esModule"]) { + if (languageVersion === 0 /* ES3 */) { + statements.push(ts.createStatement(createExportAssignment(ts.createIdentifier("__esModule"), ts.createLiteral(true)))); } - if (hoistedFunctionDeclarations) { - for (var _a = 0, hoistedFunctionDeclarations_1 = hoistedFunctionDeclarations; _a < hoistedFunctionDeclarations_1.length; _a++) { - var f = hoistedFunctionDeclarations_1[_a]; - writeLine(); - emit(f); - if (f.flags & 1 /* Export */) { - if (!exportedDeclarations) { - exportedDeclarations = []; - } - exportedDeclarations.push(f); - } - } + else { + statements.push(ts.createStatement(ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Object"), "defineProperty"), + /*typeArguments*/ undefined, [ + ts.createIdentifier("exports"), + ts.createLiteral("__esModule"), + ts.createObjectLiteral([ + ts.createPropertyAssignment("value", ts.createLiteral(true)) + ]) + ]))); } - return exportedDeclarations; - function visit(node) { - if (node.flags & 2 /* Ambient */) { - return; - } - if (node.kind === 220 /* FunctionDeclaration */) { - if (!hoistedFunctionDeclarations) { - hoistedFunctionDeclarations = []; - } - hoistedFunctionDeclarations.push(node); - return; - } - if (node.kind === 221 /* ClassDeclaration */) { - if (!hoistedVars) { - hoistedVars = []; - } - hoistedVars.push(node); - return; - } - if (node.kind === 224 /* EnumDeclaration */) { - if (shouldEmitEnumDeclaration(node)) { - if (!hoistedVars) { - hoistedVars = []; - } - hoistedVars.push(node); - } - return; - } - if (node.kind === 225 /* ModuleDeclaration */) { - if (shouldEmitModuleDeclaration(node)) { - if (!hoistedVars) { - hoistedVars = []; - } - hoistedVars.push(node); - } - return; - } - if (node.kind === 218 /* VariableDeclaration */ || node.kind === 169 /* BindingElement */) { - if (shouldHoistVariable(node, /*checkIfSourceFileLevelDecl*/ false)) { - var name_35 = node.name; - if (name_35.kind === 69 /* Identifier */) { - if (!hoistedVars) { - hoistedVars = []; - } - hoistedVars.push(name_35); - } - else { - ts.forEachChild(name_35, visit); - } - } - return; - } - if (ts.isInternalModuleImportEqualsDeclaration(node) && resolver.isValueAliasDeclaration(node)) { - if (!hoistedVars) { - hoistedVars = []; - } - hoistedVars.push(node.name); - return; - } - if (ts.isBindingPattern(node)) { - ts.forEach(node.elements, visit); - return; - } - if (!ts.isDeclaration(node)) { - ts.forEachChild(node, visit); - } + } + } + function addExportImportAssignments(statements, node) { + if (ts.isImportEqualsDeclaration(node)) { + addExportMemberAssignments(statements, node.name); + } + else { + var names = ts.reduceEachChild(node, collectExportMembers, []); + for (var _i = 0, names_1 = names; _i < names_1.length; _i++) { + var name_39 = names_1[_i]; + addExportMemberAssignments(statements, name_39); } } - function shouldHoistVariable(node, checkIfSourceFileLevelDecl) { - if (checkIfSourceFileLevelDecl && !shouldHoistDeclarationInSystemJsModule(node)) { - return false; + } + function collectExportMembers(names, node) { + if (ts.isAliasSymbolDeclaration(node) && resolver.isValueAliasDeclaration(node) && ts.isDeclaration(node)) { + var name_40 = node.name; + if (ts.isIdentifier(name_40)) { + names.push(name_40); } - // hoist variable if - // - it is not block scoped - // - it is top level block scoped - // if block scoped variables are nested in some another block then - // no other functions can use them except ones that are defined at least in the same block - return (ts.getCombinedNodeFlags(node) & 3072 /* BlockScoped */) === 0 || - ts.getEnclosingBlockScopeContainer(node).kind === 256 /* SourceFile */; - } - function isCurrentFileSystemExternalModule() { - return modulekind === ts.ModuleKind.System && isCurrentFileExternalModule; - } - function emitSystemModuleBody(node, dependencyGroups, startIndex) { - // shape of the body in system modules: - // function (exports) { - // - // - // - // return { - // setters: [ - // - // ], - // execute: function() { - // - // } - // } - // - // } - // I.e: - // import {x} from 'file1' - // var y = 1; - // export function foo() { return y + x(); } - // console.log(y); - // will be transformed to - // function(exports) { - // var file1; // local alias - // var y; - // function foo() { return y + file1.x(); } - // exports("foo", foo); - // return { - // setters: [ - // function(v) { file1 = v } - // ], - // execute(): function() { - // y = 1; - // console.log(y); - // } - // }; - // } - emitVariableDeclarationsForImports(); - writeLine(); - var exportedDeclarations = processTopLevelVariableAndFunctionDeclarations(node); - var exportStarFunction = emitLocalStorageForExportedNamesIfNecessary(exportedDeclarations); - writeLine(); - write("return {"); - increaseIndent(); - writeLine(); - emitSetters(exportStarFunction, dependencyGroups); - writeLine(); - emitExecute(node, startIndex); - decreaseIndent(); - writeLine(); - write("}"); // return - emitTempDeclarations(/*newLine*/ true); } - function emitSetters(exportStarFunction, dependencyGroups) { - write("setters:["); - for (var i = 0; i < dependencyGroups.length; i++) { - if (i !== 0) { - write(","); - } - writeLine(); - increaseIndent(); - var group = dependencyGroups[i]; - // derive a unique name for parameter from the first named entry in the group - var parameterName = makeUniqueName(ts.forEach(group, getLocalNameForExternalImport) || ""); - write("function (" + parameterName + ") {"); - increaseIndent(); - for (var _a = 0, group_1 = group; _a < group_1.length; _a++) { - var entry = group_1[_a]; - var importVariableName = getLocalNameForExternalImport(entry) || ""; - switch (entry.kind) { - case 230 /* ImportDeclaration */: - if (!entry.importClause) { - // 'import "..."' case - // module is imported only for side-effects, no emit required - break; - } - // fall-through - case 229 /* ImportEqualsDeclaration */: - ts.Debug.assert(importVariableName !== ""); - writeLine(); - // save import into the local - write(importVariableName + " = " + parameterName + ";"); - writeLine(); - break; - case 236 /* ExportDeclaration */: - ts.Debug.assert(importVariableName !== ""); - if (entry.exportClause) { - // export {a, b as c} from 'foo' - // emit as: - // exports_({ - // "a": _["a"], - // "c": _["b"] - // }); - writeLine(); - write(exportFunctionForFile + "({"); - writeLine(); - increaseIndent(); - for (var i_1 = 0, len = entry.exportClause.elements.length; i_1 < len; i_1++) { - if (i_1 !== 0) { - write(","); - writeLine(); - } - var e = entry.exportClause.elements[i_1]; - write("\""); - emitNodeWithCommentsAndWithoutSourcemap(e.name); - write("\": " + parameterName + "[\""); - emitNodeWithCommentsAndWithoutSourcemap(e.propertyName || e.name); - write("\"]"); - } - decreaseIndent(); - writeLine(); - write("});"); - } - else { - // collectExternalModuleInfo prefilters star exports to keep only ones that export values - // this means that check 'resolver.moduleExportsSomeValue' is redundant and can be omitted here - writeLine(); - // export * from 'foo' - // emit as: - // exportStar(_foo); - write(exportStarFunction + "(" + parameterName + ");"); - } - writeLine(); - break; - } - } - decreaseIndent(); - write("}"); - decreaseIndent(); + return ts.reduceEachChild(node, collectExportMembers, names); + } + function addExportMemberAssignments(statements, name) { + if (!exportEquals && exportSpecifiers && ts.hasProperty(exportSpecifiers, name.text)) { + for (var _i = 0, _a = exportSpecifiers[name.text]; _i < _a.length; _i++) { + var specifier = _a[_i]; + statements.push(ts.startOnNewLine(ts.createStatement(createExportAssignment(specifier.name, name), + /*location*/ specifier.name))); } - write("],"); } - function emitExecute(node, startIndex) { - write("execute: function() {"); - increaseIndent(); - writeLine(); - for (var i = startIndex; i < node.statements.length; i++) { - var statement = node.statements[i]; - switch (statement.kind) { - // - function declarations are not emitted because they were already hoisted - // - import declarations are not emitted since they are already handled in setters - // - export declarations with module specifiers are not emitted since they were already written in setters - // - export declarations without module specifiers are emitted preserving the order - case 220 /* FunctionDeclaration */: - case 230 /* ImportDeclaration */: - continue; - case 236 /* ExportDeclaration */: - if (!statement.moduleSpecifier) { - for (var _a = 0, _b = statement.exportClause.elements; _a < _b.length; _a++) { - var element = _b[_a]; - // write call to exporter function for every export specifier in exports list - emitExportSpecifierInSystemModule(element); - } - } - continue; - case 229 /* ImportEqualsDeclaration */: - if (!ts.isInternalModuleImportEqualsDeclaration(statement)) { - // - import equals declarations that import external modules are not emitted - continue; - } - // fall-though for import declarations that import internal modules - default: - writeLine(); - emit(statement); - } + } + function addExportMemberAssignment(statements, node) { + if (ts.hasModifier(node, 512 /* Default */)) { + addExportDefault(statements, getDeclarationName(node), /*location*/ node); + } + else { + statements.push(createExportStatement(node.name, ts.setEmitFlags(ts.getSynthesizedClone(node.name), 262144 /* LocalName */), /*location*/ node)); + } + } + function visitVariableStatement(node) { + // If the variable is for a generated declaration, + // we should maintain it and just strip off the 'export' modifier if necessary. + var originalKind = ts.getOriginalNode(node).kind; + if (originalKind === 225 /* ModuleDeclaration */ || + originalKind === 224 /* EnumDeclaration */ || + originalKind === 221 /* ClassDeclaration */) { + if (!ts.hasModifier(node, 1 /* Export */)) { + return node; } - decreaseIndent(); - writeLine(); - write("}"); // execute - } - function writeModuleName(node, emitRelativePathAsModuleName) { - var moduleName = node.moduleName; - if (moduleName || (emitRelativePathAsModuleName && (moduleName = getResolvedExternalModuleName(host, node)))) { - write("\"" + moduleName + "\", "); - } - } - function emitSystemModule(node, emitRelativePathAsModuleName) { - collectExternalModuleInfo(node); - // System modules has the following shape - // System.register(['dep-1', ... 'dep-n'], function(exports) {/* module body function */}) - // 'exports' here is a function 'exports(name: string, value: T): T' that is used to publish exported values. - // 'exports' returns its 'value' argument so in most cases expressions - // that mutate exported values can be rewritten as: - // expr -> exports('name', expr). - // The only exception in this rule is postfix unary operators, - // see comment to 'emitPostfixUnaryExpression' for more details - ts.Debug.assert(!exportFunctionForFile); - // make sure that name of 'exports' function does not conflict with existing identifiers - exportFunctionForFile = makeUniqueName("exports"); - contextObjectForFile = makeUniqueName("context"); - writeLine(); - write("System.register("); - writeModuleName(node, emitRelativePathAsModuleName); - write("["); - var groupIndices = ts.createMap(); - var dependencyGroups = []; - for (var i = 0; i < externalImports.length; i++) { - var text = getExternalModuleNameText(externalImports[i], emitRelativePathAsModuleName); - if (text === undefined) { - continue; - } - // text should be quoted string - // for deduplication purposes in key remove leading and trailing quotes so 'a' and "a" will be considered the same - var key = text.substr(1, text.length - 2); - if (key in groupIndices) { - // deduplicate/group entries in dependency list by the dependency name - var groupIndex = groupIndices[key]; - dependencyGroups[groupIndex].push(externalImports[i]); - continue; - } - else { - groupIndices[key] = dependencyGroups.length; - dependencyGroups.push([externalImports[i]]); - } - if (i !== 0) { - write(", "); - } - write(text); + return ts.setOriginalNode(ts.createVariableStatement( + /*modifiers*/ undefined, node.declarationList), node); + } + var resultStatements = []; + // If we're exporting these variables, then these just become assignments to 'exports.blah'. + // We only want to emit assignments for variables with initializers. + if (ts.hasModifier(node, 1 /* Export */)) { + var variables = ts.getInitializedVariables(node.declarationList); + if (variables.length > 0) { + var inlineAssignments = ts.createStatement(ts.inlineExpressions(ts.map(variables, transformInitializedVariable)), node); + resultStatements.push(inlineAssignments); } - write("], function(" + exportFunctionForFile + ", " + contextObjectForFile + ") {"); - writeLine(); - increaseIndent(); - var startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ true, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict); - writeLine(); - write("var __moduleName = " + contextObjectForFile + " && " + contextObjectForFile + ".id;"); - writeLine(); - emitEmitHelpers(node); - emitCaptureThisForNodeIfNecessary(node); - emitSystemModuleBody(node, dependencyGroups, startIndex); - decreaseIndent(); - writeLine(); - write("});"); - } - function getAMDDependencyNames(node, includeNonAmdDependencies, emitRelativePathAsModuleName) { - // names of modules with corresponding parameter in the factory function - var aliasedModuleNames = []; - // names of modules with no corresponding parameters in factory function - var unaliasedModuleNames = []; - var importAliasNames = []; // names of the parameters in the factory function; these - // parameters need to match the indexes of the corresponding - // module names in aliasedModuleNames. - // Fill in amd-dependency tags - for (var _a = 0, _b = node.amdDependencies; _a < _b.length; _a++) { - var amdDependency = _b[_a]; - if (amdDependency.name) { - aliasedModuleNames.push('"' + amdDependency.path + '"'); - importAliasNames.push(amdDependency.name); - } - else { - unaliasedModuleNames.push('"' + amdDependency.path + '"'); + } + else { + resultStatements.push(node); + } + // While we might not have been exported here, each variable might have been exported + // later on in an export specifier (e.g. `export {foo as blah, bar}`). + for (var _i = 0, _a = node.declarationList.declarations; _i < _a.length; _i++) { + var decl = _a[_i]; + addExportMemberAssignmentsForBindingName(resultStatements, decl.name); + } + return resultStatements; + } + /** + * Creates appropriate assignments for each binding identifier that is exported in an export specifier, + * and inserts it into 'resultStatements'. + */ + function addExportMemberAssignmentsForBindingName(resultStatements, name) { + if (ts.isBindingPattern(name)) { + for (var _i = 0, _a = name.elements; _i < _a.length; _i++) { + var element = _a[_i]; + if (!ts.isOmittedExpression(element)) { + addExportMemberAssignmentsForBindingName(resultStatements, element.name); } } - for (var _c = 0, externalImports_4 = externalImports; _c < externalImports_4.length; _c++) { - var importNode = externalImports_4[_c]; - // Find the name of the external module - var externalModuleName = getExternalModuleNameText(importNode, emitRelativePathAsModuleName); - // Find the name of the module alias, if there is one - var importAliasName = getLocalNameForExternalImport(importNode); - if (includeNonAmdDependencies && importAliasName) { - aliasedModuleNames.push(externalModuleName); - importAliasNames.push(importAliasName); - } - else { - unaliasedModuleNames.push(externalModuleName); + } + else { + if (!exportEquals && exportSpecifiers && ts.hasProperty(exportSpecifiers, name.text)) { + var sourceFileId = ts.getOriginalNodeId(currentSourceFile); + if (!bindingNameExportSpecifiersForFileMap[sourceFileId]) { + bindingNameExportSpecifiersForFileMap[sourceFileId] = ts.createMap(); } + bindingNameExportSpecifiersForFileMap[sourceFileId][name.text] = exportSpecifiers[name.text]; + addExportMemberAssignments(resultStatements, name); } - return { aliasedModuleNames: aliasedModuleNames, unaliasedModuleNames: unaliasedModuleNames, importAliasNames: importAliasNames }; } - function emitAMDDependencies(node, includeNonAmdDependencies, emitRelativePathAsModuleName) { - // An AMD define function has the following shape: - // define(id?, dependencies?, factory); - // - // This has the shape of - // define(name, ["module1", "module2"], function (module1Alias) { - // The location of the alias in the parameter list in the factory function needs to - // match the position of the module name in the dependency list. - // - // To ensure this is true in cases of modules with no aliases, e.g.: - // `import "module"` or `` - // we need to add modules without alias names to the end of the dependencies list - var dependencyNames = getAMDDependencyNames(node, includeNonAmdDependencies, emitRelativePathAsModuleName); - emitAMDDependencyList(dependencyNames); - write(", "); - emitAMDFactoryHeader(dependencyNames); + } + function transformInitializedVariable(node) { + var name = node.name; + if (ts.isBindingPattern(name)) { + return ts.flattenVariableDestructuringToExpression(context, node, hoistVariableDeclaration, getModuleMemberName, visitor); } - function emitAMDDependencyList(_a) { - var aliasedModuleNames = _a.aliasedModuleNames, unaliasedModuleNames = _a.unaliasedModuleNames; - write('["require", "exports"'); - if (aliasedModuleNames.length) { - write(", "); - write(aliasedModuleNames.join(", ")); - } - if (unaliasedModuleNames.length) { - write(", "); - write(unaliasedModuleNames.join(", ")); + else { + return ts.createAssignment(getModuleMemberName(name), ts.visitNode(node.initializer, visitor, ts.isExpression)); + } + } + function visitFunctionDeclaration(node) { + var statements = []; + var name = node.name || ts.getGeneratedNameForNode(node); + if (ts.hasModifier(node, 1 /* Export */)) { + statements.push(ts.setOriginalNode(ts.createFunctionDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, node.asteriskToken, name, + /*typeParameters*/ undefined, node.parameters, + /*type*/ undefined, node.body, + /*location*/ node), + /*original*/ node)); + addExportMemberAssignment(statements, node); + } + else { + statements.push(node); + } + if (node.name) { + addExportMemberAssignments(statements, node.name); + } + return ts.singleOrMany(statements); + } + function visitClassDeclaration(node) { + var statements = []; + var name = node.name || ts.getGeneratedNameForNode(node); + if (ts.hasModifier(node, 1 /* Export */)) { + statements.push(ts.setOriginalNode(ts.createClassDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, name, + /*typeParameters*/ undefined, node.heritageClauses, node.members, + /*location*/ node), + /*original*/ node)); + addExportMemberAssignment(statements, node); + } + else { + statements.push(node); + } + // Decorators end up creating a series of assignment expressions which overwrite + // the local binding that we export, so we need to defer from exporting decorated classes + // until the decoration assignments take place. We do this when visiting expression-statements. + if (node.name && !(node.decorators && node.decorators.length)) { + addExportMemberAssignments(statements, node.name); + } + return ts.singleOrMany(statements); + } + function visitExpressionStatement(node) { + var original = ts.getOriginalNode(node); + var origKind = original.kind; + if (origKind === 224 /* EnumDeclaration */ || origKind === 225 /* ModuleDeclaration */) { + return visitExpressionStatementForEnumOrNamespaceDeclaration(node, original); + } + else if (origKind === 221 /* ClassDeclaration */) { + // The decorated assignment for a class name may need to be transformed. + var classDecl = original; + if (classDecl.name) { + var statements = [node]; + addExportMemberAssignments(statements, classDecl.name); + return statements; } - write("]"); } - function emitAMDFactoryHeader(_a) { - var importAliasNames = _a.importAliasNames; - write("function (require, exports"); - if (importAliasNames.length) { - write(", "); - write(importAliasNames.join(", ")); + return node; + } + function visitExpressionStatementForEnumOrNamespaceDeclaration(node, original) { + var statements = [node]; + // Preserve old behavior for enums in which a variable statement is emitted after the body itself. + if (ts.hasModifier(original, 1 /* Export */) && + original.kind === 224 /* EnumDeclaration */ && + ts.isFirstDeclarationOfKind(original, 224 /* EnumDeclaration */)) { + addVarForExportedEnumOrNamespaceDeclaration(statements, original); + } + addExportMemberAssignments(statements, original.name); + return statements; + } + /** + * Adds a trailing VariableStatement for an enum or module declaration. + */ + function addVarForExportedEnumOrNamespaceDeclaration(statements, node) { + var transformedStatement = ts.createVariableStatement( + /*modifiers*/ undefined, [ts.createVariableDeclaration(getDeclarationName(node), + /*type*/ undefined, ts.createPropertyAccess(ts.createIdentifier("exports"), getDeclarationName(node)))], + /*location*/ node); + ts.setEmitFlags(transformedStatement, 49152 /* NoComments */); + statements.push(transformedStatement); + } + function getDeclarationName(node) { + return node.name ? ts.getSynthesizedClone(node.name) : ts.getGeneratedNameForNode(node); + } + function onEmitNode(emitContext, node, emitCallback) { + if (node.kind === 256 /* SourceFile */) { + bindingNameExportSpecifiersMap = bindingNameExportSpecifiersForFileMap[ts.getOriginalNodeId(node)]; + previousOnEmitNode(emitContext, node, emitCallback); + bindingNameExportSpecifiersMap = undefined; + } + else { + previousOnEmitNode(emitContext, node, emitCallback); + } + } + /** + * Hooks node substitutions. + * + * @param node The node to substitute. + * @param isExpression A value indicating whether the node is to be used in an expression + * position. + */ + function onSubstituteNode(emitContext, node) { + node = previousOnSubstituteNode(emitContext, node); + if (emitContext === 1 /* Expression */) { + return substituteExpression(node); + } + else if (ts.isShorthandPropertyAssignment(node)) { + return substituteShorthandPropertyAssignment(node); + } + return node; + } + function substituteShorthandPropertyAssignment(node) { + var name = node.name; + var exportedOrImportedName = substituteExpressionIdentifier(name); + if (exportedOrImportedName !== name) { + // A shorthand property with an assignment initializer is probably part of a + // destructuring assignment + if (node.objectAssignmentInitializer) { + var initializer = ts.createAssignment(exportedOrImportedName, node.objectAssignmentInitializer); + return ts.createPropertyAssignment(name, initializer, /*location*/ node); } - write(") {"); + return ts.createPropertyAssignment(name, exportedOrImportedName, /*location*/ node); } - function emitAMDModule(node, emitRelativePathAsModuleName) { - emitEmitHelpers(node); - collectExternalModuleInfo(node); - writeLine(); - write("define("); - writeModuleName(node, emitRelativePathAsModuleName); - emitAMDDependencies(node, /*includeNonAmdDependencies*/ true, emitRelativePathAsModuleName); - increaseIndent(); - var startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ true, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict); - emitExportStarHelper(); - emitCaptureThisForNodeIfNecessary(node); - emitLinesStartingAt(node.statements, startIndex); - emitExportEquals(/*emitAsReturn*/ true); - emitTempDeclarations(/*newLine*/ true); - decreaseIndent(); - writeLine(); - write("});"); - } - function emitCommonJSModule(node) { - var startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ false, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict); - emitEmitHelpers(node); - collectExternalModuleInfo(node); - emitExportStarHelper(); - emitCaptureThisForNodeIfNecessary(node); - emitLinesStartingAt(node.statements, startIndex); - emitExportEquals(/*emitAsReturn*/ false); - emitTempDeclarations(/*newLine*/ true); - } - function emitUMDModule(node) { - emitEmitHelpers(node); - collectExternalModuleInfo(node); - var dependencyNames = getAMDDependencyNames(node, /*includeNonAmdDependencies*/ false); - // Module is detected first to support Browserify users that load into a browser with an AMD loader - writeLines("(function (factory) {\n if (typeof module === 'object' && typeof module.exports === 'object') {\n var v = factory(require, exports); if (v !== undefined) module.exports = v;\n }\n else if (typeof define === 'function' && define.amd) {\n define("); - emitAMDDependencyList(dependencyNames); - write(", factory);"); - writeLines(" }\n})("); - emitAMDFactoryHeader(dependencyNames); - increaseIndent(); - var startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ true, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict); - emitExportStarHelper(); - emitCaptureThisForNodeIfNecessary(node); - emitLinesStartingAt(node.statements, startIndex); - emitExportEquals(/*emitAsReturn*/ true); - emitTempDeclarations(/*newLine*/ true); - decreaseIndent(); - writeLine(); - write("});"); + return node; + } + function substituteExpression(node) { + switch (node.kind) { + case 69 /* Identifier */: + return substituteExpressionIdentifier(node); + case 187 /* BinaryExpression */: + return substituteBinaryExpression(node); + case 186 /* PostfixUnaryExpression */: + case 185 /* PrefixUnaryExpression */: + return substituteUnaryExpression(node); } - function emitES6Module(node) { - externalImports = undefined; - exportSpecifiers = undefined; - exportEquals = undefined; - hasExportStarsToExportValues = false; - var startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ false); - emitEmitHelpers(node); - emitCaptureThisForNodeIfNecessary(node); - emitLinesStartingAt(node.statements, startIndex); - emitTempDeclarations(/*newLine*/ true); - // Emit exportDefault if it exists will happen as part - // or normal statement emit. - } - function emitExportEquals(emitAsReturn) { - if (exportEquals && resolver.isValueAliasDeclaration(exportEquals)) { - writeLine(); - emitStart(exportEquals); - write(emitAsReturn ? "return " : "module.exports = "); - emit(exportEquals.expression); - write(";"); - emitEnd(exportEquals); + return node; + } + function substituteExpressionIdentifier(node) { + return trySubstituteExportedName(node) + || trySubstituteImportedName(node) + || node; + } + function substituteBinaryExpression(node) { + var left = node.left; + // If the left-hand-side of the binaryExpression is an identifier and its is export through export Specifier + if (ts.isIdentifier(left) && ts.isAssignmentOperator(node.operatorToken.kind)) { + if (bindingNameExportSpecifiersMap && ts.hasProperty(bindingNameExportSpecifiersMap, left.text)) { + ts.setEmitFlags(node, 128 /* NoSubstitution */); + var nestedExportAssignment = void 0; + for (var _i = 0, _a = bindingNameExportSpecifiersMap[left.text]; _i < _a.length; _i++) { + var specifier = _a[_i]; + nestedExportAssignment = nestedExportAssignment ? + createExportAssignment(specifier.name, nestedExportAssignment) : + createExportAssignment(specifier.name, node); + } + return nestedExportAssignment; + } + } + return node; + } + function substituteUnaryExpression(node) { + // Because how the compiler only parse plusplus and minusminus to be either prefixUnaryExpression or postFixUnaryExpression depended on where they are + // We don't need to check that the operator has SyntaxKind.plusplus or SyntaxKind.minusminus + var operator = node.operator; + var operand = node.operand; + if (ts.isIdentifier(operand) && bindingNameExportSpecifiersForFileMap) { + if (bindingNameExportSpecifiersMap && ts.hasProperty(bindingNameExportSpecifiersMap, operand.text)) { + ts.setEmitFlags(node, 128 /* NoSubstitution */); + var transformedUnaryExpression = void 0; + if (node.kind === 186 /* PostfixUnaryExpression */) { + transformedUnaryExpression = ts.createBinary(operand, ts.createNode(operator === 41 /* PlusPlusToken */ ? 57 /* PlusEqualsToken */ : 58 /* MinusEqualsToken */), ts.createLiteral(1), + /*location*/ node); + // We have to set no substitution flag here to prevent visit the binary expression and substitute it again as we will preform all necessary substitution in here + ts.setEmitFlags(transformedUnaryExpression, 128 /* NoSubstitution */); + } + var nestedExportAssignment = void 0; + for (var _i = 0, _a = bindingNameExportSpecifiersMap[operand.text]; _i < _a.length; _i++) { + var specifier = _a[_i]; + nestedExportAssignment = nestedExportAssignment ? + createExportAssignment(specifier.name, nestedExportAssignment) : + createExportAssignment(specifier.name, transformedUnaryExpression || node); + } + return nestedExportAssignment; } } - function emitJsxElement(node) { - switch (compilerOptions.jsx) { - case 2 /* React */: - jsxEmitReact(node); - break; - case 1 /* Preserve */: - // Fall back to preserve if None was specified (we'll error earlier) - default: - jsxEmitPreserve(node); - break; + return node; + } + function trySubstituteExportedName(node) { + var emitFlags = ts.getEmitFlags(node); + if ((emitFlags & 262144 /* LocalName */) === 0) { + var container = resolver.getReferencedExportContainer(node, (emitFlags & 131072 /* ExportName */) !== 0); + if (container) { + if (container.kind === 256 /* SourceFile */) { + return ts.createPropertyAccess(ts.createIdentifier("exports"), ts.getSynthesizedClone(node), + /*location*/ node); + } } } - function trimReactWhitespaceAndApplyEntities(node) { - var result = undefined; - var text = ts.getTextOfNode(node, /*includeTrivia*/ true); - var firstNonWhitespace = 0; - var lastNonWhitespace = -1; - // JSX trims whitespace at the end and beginning of lines, except that the - // start/end of a tag is considered a start/end of a line only if that line is - // on the same line as the closing tag. See examples in tests/cases/conformance/jsx/tsxReactEmitWhitespace.tsx - for (var i = 0; i < text.length; i++) { - var c = text.charCodeAt(i); - if (ts.isLineBreak(c)) { - if (firstNonWhitespace !== -1 && (lastNonWhitespace - firstNonWhitespace + 1 > 0)) { - var part = text.substr(firstNonWhitespace, lastNonWhitespace - firstNonWhitespace + 1); - result = (result ? result + "\" + ' ' + \"" : "") + ts.escapeString(part); + return undefined; + } + function trySubstituteImportedName(node) { + if ((ts.getEmitFlags(node) & 262144 /* LocalName */) === 0) { + var declaration = resolver.getReferencedImportDeclaration(node); + if (declaration) { + if (ts.isImportClause(declaration)) { + if (languageVersion >= 1 /* ES5 */) { + return ts.createPropertyAccess(ts.getGeneratedNameForNode(declaration.parent), ts.createIdentifier("default"), + /*location*/ node); } - firstNonWhitespace = -1; - } - else if (!ts.isWhiteSpaceSingleLine(c)) { - lastNonWhitespace = i; - if (firstNonWhitespace === -1) { - firstNonWhitespace = i; + else { + // TODO: ES3 transform to handle x.default -> x["default"] + return ts.createElementAccess(ts.getGeneratedNameForNode(declaration.parent), ts.createLiteral("default"), + /*location*/ node); } } - } - if (firstNonWhitespace !== -1) { - var part = text.substr(firstNonWhitespace); - result = (result ? result + "\" + ' ' + \"" : "") + ts.escapeString(part); - } - if (result) { - // Replace entities like   - result = result.replace(/&(\w+);/g, function (s, m) { - if (entities[m] !== undefined) { - var ch = String.fromCharCode(entities[m]); - // " needs to be escaped - return ch === '"' ? "\\\"" : ch; + else if (ts.isImportSpecifier(declaration)) { + var name_41 = declaration.propertyName || declaration.name; + if (name_41.originalKeywordKind === 77 /* DefaultKeyword */ && languageVersion <= 0 /* ES3 */) { + // TODO: ES3 transform to handle x.default -> x["default"] + return ts.createElementAccess(ts.getGeneratedNameForNode(declaration.parent.parent.parent), ts.createLiteral(name_41.text), + /*location*/ node); } else { - return s; + return ts.createPropertyAccess(ts.getGeneratedNameForNode(declaration.parent.parent.parent), ts.getSynthesizedClone(name_41), + /*location*/ node); } - }); + } } - return result; } - function isJsxChildEmittable(child) { - if (child.kind === 248 /* JsxExpression */) { - // Don't emit empty expressions - return !!child.expression; + return undefined; + } + function getModuleMemberName(name) { + return ts.createPropertyAccess(ts.createIdentifier("exports"), name, + /*location*/ name); + } + function createRequireCall(importNode) { + var moduleName = ts.getExternalModuleNameLiteral(importNode, currentSourceFile, host, resolver, compilerOptions); + var args = []; + if (ts.isDefined(moduleName)) { + args.push(moduleName); + } + return ts.createCall(ts.createIdentifier("require"), /*typeArguments*/ undefined, args); + } + function createExportStatement(name, value, location) { + var statement = ts.createStatement(createExportAssignment(name, value)); + statement.startsOnNewLine = true; + if (location) { + ts.setSourceMapRange(statement, location); + } + return statement; + } + function createExportAssignment(name, value) { + return ts.createAssignment(name.originalKeywordKind === 77 /* DefaultKeyword */ && languageVersion === 0 /* ES3 */ + ? ts.createElementAccess(ts.createIdentifier("exports"), ts.createLiteral(name.text)) + : ts.createPropertyAccess(ts.createIdentifier("exports"), ts.getSynthesizedClone(name)), value); + } + function collectAsynchronousDependencies(node, includeNonAmdDependencies) { + // names of modules with corresponding parameter in the factory function + var aliasedModuleNames = []; + // names of modules with no corresponding parameters in factory function + var unaliasedModuleNames = []; + // names of the parameters in the factory function; these + // parameters need to match the indexes of the corresponding + // module names in aliasedModuleNames. + var importAliasNames = []; + // Fill in amd-dependency tags + for (var _i = 0, _a = node.amdDependencies; _i < _a.length; _i++) { + var amdDependency = _a[_i]; + if (amdDependency.name) { + aliasedModuleNames.push(ts.createLiteral(amdDependency.path)); + importAliasNames.push(ts.createParameter(amdDependency.name)); } - else if (child.kind === 244 /* JsxText */) { - // Don't emit empty strings - return !!getTextToEmit(child); + else { + unaliasedModuleNames.push(ts.createLiteral(amdDependency.path)); + } + } + for (var _b = 0, externalImports_1 = externalImports; _b < externalImports_1.length; _b++) { + var importNode = externalImports_1[_b]; + // Find the name of the external module + var externalModuleName = ts.getExternalModuleNameLiteral(importNode, currentSourceFile, host, resolver, compilerOptions); + // Find the name of the module alias, if there is one + var importAliasName = ts.getLocalNameForExternalImport(importNode, currentSourceFile); + if (includeNonAmdDependencies && importAliasName) { + // Set emitFlags on the name of the classDeclaration + // This is so that when printer will not substitute the identifier + ts.setEmitFlags(importAliasName, 128 /* NoSubstitution */); + aliasedModuleNames.push(externalModuleName); + importAliasNames.push(ts.createParameter(importAliasName)); } - return true; - } - ; - function getTextToEmit(node) { - switch (compilerOptions.jsx) { - case 2 /* React */: - var text = trimReactWhitespaceAndApplyEntities(node); - if (text === undefined || text.length === 0) { - return undefined; - } - else { - return text; - } - case 1 /* Preserve */: - default: - return ts.getTextOfNode(node, /*includeTrivia*/ true); + else { + unaliasedModuleNames.push(externalModuleName); } } - function emitJsxText(node) { - switch (compilerOptions.jsx) { - case 2 /* React */: - write('"'); - write(trimReactWhitespaceAndApplyEntities(node)); - write('"'); - break; - case 1 /* Preserve */: - default: - writer.writeLiteral(ts.getTextOfNode(node, /*includeTrivia*/ true)); - break; - } + return { aliasedModuleNames: aliasedModuleNames, unaliasedModuleNames: unaliasedModuleNames, importAliasNames: importAliasNames }; + } + function updateSourceFile(node, statements) { + var updated = ts.getMutableClone(node); + updated.statements = ts.createNodeArray(statements, node.statements); + return updated; + } + var _a; + } + ts.transformModule = transformModule; +})(ts || (ts = {})); +/// +/// +/*@internal*/ +var ts; +(function (ts) { + function transformSystemModule(context) { + var startLexicalEnvironment = context.startLexicalEnvironment, endLexicalEnvironment = context.endLexicalEnvironment, hoistVariableDeclaration = context.hoistVariableDeclaration, hoistFunctionDeclaration = context.hoistFunctionDeclaration; + var compilerOptions = context.getCompilerOptions(); + var resolver = context.getEmitResolver(); + var host = context.getEmitHost(); + var languageVersion = ts.getEmitScriptTarget(compilerOptions); + var previousOnSubstituteNode = context.onSubstituteNode; + var previousOnEmitNode = context.onEmitNode; + context.onSubstituteNode = onSubstituteNode; + context.onEmitNode = onEmitNode; + context.enableSubstitution(69 /* Identifier */); + context.enableSubstitution(187 /* BinaryExpression */); + context.enableSubstitution(185 /* PrefixUnaryExpression */); + context.enableSubstitution(186 /* PostfixUnaryExpression */); + context.enableEmitNotification(256 /* SourceFile */); + var exportFunctionForFileMap = []; + var currentSourceFile; + var externalImports; + var exportSpecifiers; + var exportEquals; + var hasExportStarsToExportValues; + var exportFunctionForFile; + var contextObjectForFile; + var exportedLocalNames; + var exportedFunctionDeclarations; + var enclosingBlockScopedContainer; + var currentParent; + var currentNode; + return transformSourceFile; + function transformSourceFile(node) { + if (ts.isDeclarationFile(node)) { + return node; } - function emitJsxExpression(node) { - if (node.expression) { - switch (compilerOptions.jsx) { - case 1 /* Preserve */: - default: - write("{"); - emit(node.expression); - write("}"); - break; - case 2 /* React */: - emit(node.expression); - break; - } - } + if (ts.isExternalModule(node) || compilerOptions.isolatedModules) { + currentSourceFile = node; + currentNode = node; + // Perform the transformation. + var updated = transformSystemModuleWorker(node); + ts.aggregateTransformFlags(updated); + currentSourceFile = undefined; + externalImports = undefined; + exportSpecifiers = undefined; + exportEquals = undefined; + hasExportStarsToExportValues = false; + exportFunctionForFile = undefined; + contextObjectForFile = undefined; + exportedLocalNames = undefined; + exportedFunctionDeclarations = undefined; + return updated; } - function isUseStrictPrologue(node) { - return node.expression.text === "use strict"; + return node; + } + function transformSystemModuleWorker(node) { + // System modules have the following shape: + // + // System.register(['dep-1', ... 'dep-n'], function(exports) {/* module body function */}) + // + // The parameter 'exports' here is a callback '(name: string, value: T) => T' that + // is used to publish exported values. 'exports' returns its 'value' argument so in + // most cases expressions that mutate exported values can be rewritten as: + // + // expr -> exports('name', expr) + // + // The only exception in this rule is postfix unary operators, + // see comment to 'substitutePostfixUnaryExpression' for more details + ts.Debug.assert(!exportFunctionForFile); + // Collect information about the external module and dependency groups. + (_a = ts.collectExternalModuleInfo(node, resolver), externalImports = _a.externalImports, exportSpecifiers = _a.exportSpecifiers, exportEquals = _a.exportEquals, hasExportStarsToExportValues = _a.hasExportStarsToExportValues, _a); + // Make sure that the name of the 'exports' function does not conflict with + // existing identifiers. + exportFunctionForFile = ts.createUniqueName("exports"); + contextObjectForFile = ts.createUniqueName("context"); + exportFunctionForFileMap[ts.getOriginalNodeId(node)] = exportFunctionForFile; + var dependencyGroups = collectDependencyGroups(externalImports); + var statements = []; + // Add the body of the module. + addSystemModuleBody(statements, node, dependencyGroups); + var moduleName = ts.tryGetModuleNameFromFile(node, host, compilerOptions); + var dependencies = ts.createArrayLiteral(ts.map(dependencyGroups, getNameOfDependencyGroup)); + var body = ts.createFunctionExpression( + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ + ts.createParameter(exportFunctionForFile), + ts.createParameter(contextObjectForFile) + ], + /*type*/ undefined, ts.setEmitFlags(ts.createBlock(statements, /*location*/ undefined, /*multiLine*/ true), 1 /* EmitEmitHelpers */)); + // Write the call to `System.register` + // Clear the emit-helpers flag for later passes since we'll have already used it in the module body + // So the helper will be emit at the correct position instead of at the top of the source-file + return updateSourceFile(node, [ + ts.createStatement(ts.createCall(ts.createPropertyAccess(ts.createIdentifier("System"), "register"), + /*typeArguments*/ undefined, moduleName + ? [moduleName, dependencies, body] + : [dependencies, body])) + ], /*nodeEmitFlags*/ ~1 /* EmitEmitHelpers */ & ts.getEmitFlags(node)); + var _a; + } + /** + * Adds the statements for the module body function for the source file. + * + * @param statements The output statements for the module body. + * @param node The source file for the module. + * @param statementOffset The offset at which to begin visiting the statements of the SourceFile. + */ + function addSystemModuleBody(statements, node, dependencyGroups) { + // Shape of the body in system modules: + // + // function (exports) { + // + // + // + // return { + // setters: [ + // + // ], + // execute: function() { + // + // } + // } + // + // } + // + // i.e: + // + // import {x} from 'file1' + // var y = 1; + // export function foo() { return y + x(); } + // console.log(y); + // + // Will be transformed to: + // + // function(exports) { + // var file_1; // local alias + // var y; + // function foo() { return y + file_1.x(); } + // exports("foo", foo); + // return { + // setters: [ + // function(v) { file_1 = v } + // ], + // execute(): function() { + // y = 1; + // console.log(y); + // } + // }; + // } + // We start a new lexical environment in this function body, but *not* in the + // body of the execute function. This allows us to emit temporary declarations + // only in the outer module body and not in the inner one. + startLexicalEnvironment(); + // Add any prologue directives. + var statementOffset = ts.addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, visitSourceElement); + // var __moduleName = context_1 && context_1.id; + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration("__moduleName", + /*type*/ undefined, ts.createLogicalAnd(contextObjectForFile, ts.createPropertyAccess(contextObjectForFile, "id"))) + ]))); + // Visit the statements of the source file, emitting any transformations into + // the `executeStatements` array. We do this *before* we fill the `setters` array + // as we both emit transformations as well as aggregate some data used when creating + // setters. This allows us to reduce the number of times we need to loop through the + // statements of the source file. + var executeStatements = ts.visitNodes(node.statements, visitSourceElement, ts.isStatement, statementOffset); + // We emit the lexical environment (hoisted variables and function declarations) + // early to align roughly with our previous emit output. + // Two key differences in this approach are: + // - Temporary variables will appear at the top rather than at the bottom of the file + // - Calls to the exporter for exported function declarations are grouped after + // the declarations. + ts.addRange(statements, endLexicalEnvironment()); + // Emit early exports for function declarations. + ts.addRange(statements, exportedFunctionDeclarations); + var exportStarFunction = addExportStarIfNeeded(statements); + statements.push(ts.createReturn(ts.setMultiLine(ts.createObjectLiteral([ + ts.createPropertyAssignment("setters", generateSetters(exportStarFunction, dependencyGroups)), + ts.createPropertyAssignment("execute", ts.createFunctionExpression( + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, + /*parameters*/ [], + /*type*/ undefined, ts.createBlock(executeStatements, + /*location*/ undefined, + /*multiLine*/ true))) + ]), + /*multiLine*/ true))); + } + function addExportStarIfNeeded(statements) { + if (!hasExportStarsToExportValues) { + return; } - function ensureUseStrictPrologue(startWithNewLine, writeUseStrict) { - if (writeUseStrict) { - if (startWithNewLine) { - writeLine(); + // when resolving exports local exported entries/indirect exported entries in the module + // should always win over entries with similar names that were added via star exports + // to support this we store names of local/indirect exported entries in a set. + // this set is used to filter names brought by star expors. + // local names set should only be added if we have anything exported + if (!exportedLocalNames && ts.isEmpty(exportSpecifiers)) { + // no exported declarations (export var ...) or export specifiers (export {x}) + // check if we have any non star export declarations. + var hasExportDeclarationWithExportClause = false; + for (var _i = 0, externalImports_2 = externalImports; _i < externalImports_2.length; _i++) { + var externalImport = externalImports_2[_i]; + if (externalImport.kind === 236 /* ExportDeclaration */ && externalImport.exportClause) { + hasExportDeclarationWithExportClause = true; + break; } - write("\"use strict\";"); } - } - function emitDirectivePrologues(statements, startWithNewLine, ensureUseStrict) { - var foundUseStrict = false; - for (var i = 0; i < statements.length; i++) { - if (ts.isPrologueDirective(statements[i])) { - if (isUseStrictPrologue(statements[i])) { - foundUseStrict = true; - } - if (startWithNewLine || i > 0) { - writeLine(); - } - emit(statements[i]); - } - else { - ensureUseStrictPrologue(startWithNewLine || i > 0, !foundUseStrict && ensureUseStrict); - // return index of the first non prologue directive - return i; - } + if (!hasExportDeclarationWithExportClause) { + // we still need to emit exportStar helper + return addExportStarFunction(statements, /*localNames*/ undefined); } - ensureUseStrictPrologue(startWithNewLine, !foundUseStrict && ensureUseStrict); - return statements.length; } - function writeLines(text) { - var lines = text.split(/\r\n|\r|\n/g); - for (var i = 0; i < lines.length; i++) { - var line = lines[i]; - if (line.length) { - writeLine(); - write(line); - } + var exportedNames = []; + if (exportedLocalNames) { + for (var _a = 0, exportedLocalNames_1 = exportedLocalNames; _a < exportedLocalNames_1.length; _a++) { + var exportedLocalName = exportedLocalNames_1[_a]; + // write name of exported declaration, i.e 'export var x...' + exportedNames.push(ts.createPropertyAssignment(ts.createLiteral(exportedLocalName.text), ts.createLiteral(true))); } } - function emitEmitHelpers(node) { - // Only emit helpers if the user did not say otherwise. - if (!compilerOptions.noEmitHelpers) { - // Only Emit __extends function when target ES5. - // For target ES6 and above, we can emit classDeclaration as is. - if (languageVersion < 2 /* ES6 */ && !extendsEmitted && node.flags & 262144 /* HasClassExtends */) { - writeLines(extendsHelper); - extendsEmitted = true; - } - if (compilerOptions.jsx !== 1 /* Preserve */ && !assignEmitted && (node.flags & 1073741824 /* HasJsxSpreadAttribute */)) { - writeLines(assignHelper); - assignEmitted = true; - } - if (!decorateEmitted && node.flags & 524288 /* HasDecorators */) { - writeLines(decorateHelper); - if (compilerOptions.emitDecoratorMetadata) { - writeLines(metadataHelper); - } - decorateEmitted = true; - } - if (!paramEmitted && node.flags & 1048576 /* HasParamDecorators */) { - writeLines(paramHelper); - paramEmitted = true; - } - if (!awaiterEmitted && node.flags & 2097152 /* HasAsyncFunctions */) { - writeLines(awaiterHelper); - awaiterEmitted = true; - } + for (var _b = 0, externalImports_3 = externalImports; _b < externalImports_3.length; _b++) { + var externalImport = externalImports_3[_b]; + if (externalImport.kind !== 236 /* ExportDeclaration */) { + continue; } - } - function emitSourceFileNode(node) { - // Start new file on new line - writeLine(); - emitShebang(); - emitDetachedCommentsAndUpdateCommentsInfo(node); - if (ts.isExternalModule(node) || compilerOptions.isolatedModules) { - if (isOwnFileEmit || (!ts.isExternalModule(node) && compilerOptions.isolatedModules)) { - var emitModule = moduleEmitDelegates[modulekind] || moduleEmitDelegates[ts.ModuleKind.CommonJS]; - emitModule(node); - } - else { - bundleEmitDelegates[modulekind](node, /*emitRelativePathAsModuleName*/ true); - } + var exportDecl = externalImport; + if (!exportDecl.exportClause) { + // export * from ... + continue; } - else { - // emit prologue directives prior to __extends - var startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ false); - externalImports = undefined; - exportSpecifiers = undefined; - exportEquals = undefined; - hasExportStarsToExportValues = false; - emitEmitHelpers(node); - emitCaptureThisForNodeIfNecessary(node); - emitLinesStartingAt(node.statements, startIndex); - emitTempDeclarations(/*newLine*/ true); - } - emitLeadingComments(node.endOfFileToken); - } - function emit(node) { - emitNodeConsideringCommentsOption(node, emitNodeWithSourceMap); - } - function emitNodeWithCommentsAndWithoutSourcemap(node) { - emitNodeConsideringCommentsOption(node, emitNodeWithoutSourceMap); - } - function emitNodeConsideringCommentsOption(node, emitNodeConsideringSourcemap) { - if (node) { - if (node.flags & 2 /* Ambient */) { - return emitCommentsOnNotEmittedNode(node); - } - if (isSpecializedCommentHandling(node)) { - // This is the node that will handle its own comments and sourcemap - return emitNodeWithoutSourceMap(node); - } - var emitComments_1 = shouldEmitLeadingAndTrailingComments(node); - if (emitComments_1) { - emitLeadingComments(node); - } - emitNodeConsideringSourcemap(node); - if (emitComments_1) { - emitTrailingComments(node); - } + for (var _c = 0, _d = exportDecl.exportClause.elements; _c < _d.length; _c++) { + var element = _d[_c]; + // write name of indirectly exported entry, i.e. 'export {x} from ...' + exportedNames.push(ts.createPropertyAssignment(ts.createLiteral((element.name || element.propertyName).text), ts.createLiteral(true))); } } - function emitNodeWithSourceMap(node) { - if (node) { - emitStart(node); - emitNodeWithoutSourceMap(node); - emitEnd(node); + var exportedNamesStorageRef = ts.createUniqueName("exportedNames"); + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(exportedNamesStorageRef, + /*type*/ undefined, ts.createObjectLiteral(exportedNames, /*location*/ undefined, /*multiline*/ true)) + ]))); + return addExportStarFunction(statements, exportedNamesStorageRef); + } + /** + * Emits a setter callback for each dependency group. + * @param write The callback used to write each callback. + */ + function generateSetters(exportStarFunction, dependencyGroups) { + var setters = []; + for (var _i = 0, dependencyGroups_1 = dependencyGroups; _i < dependencyGroups_1.length; _i++) { + var group = dependencyGroups_1[_i]; + // derive a unique name for parameter from the first named entry in the group + var localName = ts.forEach(group.externalImports, function (i) { return ts.getLocalNameForExternalImport(i, currentSourceFile); }); + var parameterName = localName ? ts.getGeneratedNameForNode(localName) : ts.createUniqueName(""); + var statements = []; + for (var _a = 0, _b = group.externalImports; _a < _b.length; _a++) { + var entry = _b[_a]; + var importVariableName = ts.getLocalNameForExternalImport(entry, currentSourceFile); + switch (entry.kind) { + case 230 /* ImportDeclaration */: + if (!entry.importClause) { + // 'import "..."' case + // module is imported only for side-effects, no emit required + break; + } + // fall-through + case 229 /* ImportEqualsDeclaration */: + ts.Debug.assert(importVariableName !== undefined); + // save import into the local + statements.push(ts.createStatement(ts.createAssignment(importVariableName, parameterName))); + break; + case 236 /* ExportDeclaration */: + ts.Debug.assert(importVariableName !== undefined); + if (entry.exportClause) { + // export {a, b as c} from 'foo' + // + // emit as: + // + // exports_({ + // "a": _["a"], + // "c": _["b"] + // }); + var properties = []; + for (var _c = 0, _d = entry.exportClause.elements; _c < _d.length; _c++) { + var e = _d[_c]; + properties.push(ts.createPropertyAssignment(ts.createLiteral(e.name.text), ts.createElementAccess(parameterName, ts.createLiteral((e.propertyName || e.name).text)))); + } + statements.push(ts.createStatement(ts.createCall(exportFunctionForFile, + /*typeArguments*/ undefined, [ts.createObjectLiteral(properties, /*location*/ undefined, /*multiline*/ true)]))); + } + else { + // export * from 'foo' + // + // emit as: + // + // exportStar(foo_1_1); + statements.push(ts.createStatement(ts.createCall(exportStarFunction, + /*typeArguments*/ undefined, [parameterName]))); + } + break; + } } + setters.push(ts.createFunctionExpression( + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ts.createParameter(parameterName)], + /*type*/ undefined, ts.createBlock(statements, /*location*/ undefined, /*multiLine*/ true))); } - function emitNodeWithoutSourceMap(node) { - if (node) { - emitJavaScriptWorker(node); - } + return ts.createArrayLiteral(setters, /*location*/ undefined, /*multiLine*/ true); + } + function visitSourceElement(node) { + switch (node.kind) { + case 230 /* ImportDeclaration */: + return visitImportDeclaration(node); + case 229 /* ImportEqualsDeclaration */: + return visitImportEqualsDeclaration(node); + case 236 /* ExportDeclaration */: + return visitExportDeclaration(node); + case 235 /* ExportAssignment */: + return visitExportAssignment(node); + default: + return visitNestedNode(node); + } + } + function visitNestedNode(node) { + var savedEnclosingBlockScopedContainer = enclosingBlockScopedContainer; + var savedCurrentParent = currentParent; + var savedCurrentNode = currentNode; + var currentGrandparent = currentParent; + currentParent = currentNode; + currentNode = node; + if (currentParent && ts.isBlockScope(currentParent, currentGrandparent)) { + enclosingBlockScopedContainer = currentParent; + } + var result = visitNestedNodeWorker(node); + enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer; + currentParent = savedCurrentParent; + currentNode = savedCurrentNode; + return result; + } + function visitNestedNodeWorker(node) { + switch (node.kind) { + case 200 /* VariableStatement */: + return visitVariableStatement(node); + case 220 /* FunctionDeclaration */: + return visitFunctionDeclaration(node); + case 221 /* ClassDeclaration */: + return visitClassDeclaration(node); + case 206 /* ForStatement */: + return visitForStatement(node); + case 207 /* ForInStatement */: + return visitForInStatement(node); + case 208 /* ForOfStatement */: + return visitForOfStatement(node); + case 204 /* DoStatement */: + return visitDoStatement(node); + case 205 /* WhileStatement */: + return visitWhileStatement(node); + case 214 /* LabeledStatement */: + return visitLabeledStatement(node); + case 212 /* WithStatement */: + return visitWithStatement(node); + case 213 /* SwitchStatement */: + return visitSwitchStatement(node); + case 227 /* CaseBlock */: + return visitCaseBlock(node); + case 249 /* CaseClause */: + return visitCaseClause(node); + case 250 /* DefaultClause */: + return visitDefaultClause(node); + case 216 /* TryStatement */: + return visitTryStatement(node); + case 252 /* CatchClause */: + return visitCatchClause(node); + case 199 /* Block */: + return visitBlock(node); + case 202 /* ExpressionStatement */: + return visitExpressionStatement(node); + default: + return node; } - function changeSourceMapEmit(writer) { - sourceMap = writer; - emitStart = writer.emitStart; - emitEnd = writer.emitEnd; - emitPos = writer.emitPos; - setSourceFile = writer.setSourceFile; + } + function visitImportDeclaration(node) { + if (node.importClause && ts.contains(externalImports, node)) { + hoistVariableDeclaration(ts.getLocalNameForExternalImport(node, currentSourceFile)); } - function withTemporaryNoSourceMap(callback) { - var prevSourceMap = sourceMap; - setSourceMapWriterEmit(ts.getNullSourceMapWriter()); - callback(); - setSourceMapWriterEmit(prevSourceMap); + return undefined; + } + function visitImportEqualsDeclaration(node) { + if (ts.contains(externalImports, node)) { + hoistVariableDeclaration(ts.getLocalNameForExternalImport(node, currentSourceFile)); } - function isSpecializedCommentHandling(node) { - switch (node.kind) { - // All of these entities are emitted in a specialized fashion. As such, we allow - // the specialized methods for each to handle the comments on the nodes. - case 222 /* InterfaceDeclaration */: - case 220 /* FunctionDeclaration */: - case 230 /* ImportDeclaration */: - case 229 /* ImportEqualsDeclaration */: - case 223 /* TypeAliasDeclaration */: - case 235 /* ExportAssignment */: - return true; - } + // NOTE(rbuckton): Do we support export import = require('') in System? + return undefined; + } + function visitExportDeclaration(node) { + if (!node.moduleSpecifier) { + var statements = []; + ts.addRange(statements, ts.map(node.exportClause.elements, visitExportSpecifier)); + return statements; } - function shouldEmitLeadingAndTrailingComments(node) { - switch (node.kind) { - case 200 /* VariableStatement */: - return shouldEmitLeadingAndTrailingCommentsForVariableStatement(node); - case 225 /* ModuleDeclaration */: - // Only emit the leading/trailing comments for a module if we're actually - // emitting the module as well. - return shouldEmitModuleDeclaration(node); - case 224 /* EnumDeclaration */: - // Only emit the leading/trailing comments for an enum if we're actually - // emitting the module as well. - return shouldEmitEnumDeclaration(node); - } - // If the node is emitted in specialized fashion, dont emit comments as this node will handle - // emitting comments when emitting itself - ts.Debug.assert(!isSpecializedCommentHandling(node)); - // If this is the expression body of an arrow function that we're down-leveling, - // then we don't want to emit comments when we emit the body. It will have already - // been taken care of when we emitted the 'return' statement for the function - // expression body. - if (node.kind !== 199 /* Block */ && - node.parent && - node.parent.kind === 180 /* ArrowFunction */ && - node.parent.body === node && - languageVersion <= 1 /* ES5 */) { - return false; - } - // Emit comments for everything else. - return true; + return undefined; + } + function visitExportSpecifier(specifier) { + if (resolver.getReferencedValueDeclaration(specifier.propertyName || specifier.name) + || resolver.isValueAliasDeclaration(specifier)) { + recordExportName(specifier.name); + return createExportStatement(specifier.name, specifier.propertyName || specifier.name); } - function emitJavaScriptWorker(node) { - // Check if the node can be emitted regardless of the ScriptTarget - switch (node.kind) { - case 69 /* Identifier */: - return emitIdentifier(node); - case 142 /* Parameter */: - return emitParameter(node); - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - return emitMethod(node); - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - return emitAccessor(node); - case 97 /* ThisKeyword */: - return emitThis(node); - case 95 /* SuperKeyword */: - return emitSuper(node); - case 93 /* NullKeyword */: - return write("null"); - case 99 /* TrueKeyword */: - return write("true"); - case 84 /* FalseKeyword */: - return write("false"); - case 8 /* NumericLiteral */: - case 9 /* StringLiteral */: - case 10 /* RegularExpressionLiteral */: - case 11 /* NoSubstitutionTemplateLiteral */: - case 12 /* TemplateHead */: - case 13 /* TemplateMiddle */: - case 14 /* TemplateTail */: - return emitLiteral(node); - case 189 /* TemplateExpression */: - return emitTemplateExpression(node); - case 197 /* TemplateSpan */: - return emitTemplateSpan(node); - case 241 /* JsxElement */: - case 242 /* JsxSelfClosingElement */: - return emitJsxElement(node); - case 244 /* JsxText */: - return emitJsxText(node); - case 248 /* JsxExpression */: - return emitJsxExpression(node); - case 139 /* QualifiedName */: - return emitQualifiedName(node); - case 167 /* ObjectBindingPattern */: - return emitObjectBindingPattern(node); - case 168 /* ArrayBindingPattern */: - return emitArrayBindingPattern(node); - case 169 /* BindingElement */: - return emitBindingElement(node); - case 170 /* ArrayLiteralExpression */: - return emitArrayLiteral(node); - case 171 /* ObjectLiteralExpression */: - return emitObjectLiteral(node); - case 253 /* PropertyAssignment */: - return emitPropertyAssignment(node); - case 254 /* ShorthandPropertyAssignment */: - return emitShorthandPropertyAssignment(node); - case 140 /* ComputedPropertyName */: - return emitComputedPropertyName(node); - case 172 /* PropertyAccessExpression */: - return emitPropertyAccess(node); - case 173 /* ElementAccessExpression */: - return emitIndexedAccess(node); - case 174 /* CallExpression */: - return emitCallExpression(node); - case 175 /* NewExpression */: - return emitNewExpression(node); - case 176 /* TaggedTemplateExpression */: - return emitTaggedTemplateExpression(node); - case 177 /* TypeAssertionExpression */: - case 195 /* AsExpression */: - case 196 /* NonNullExpression */: - return emit(node.expression); - case 178 /* ParenthesizedExpression */: - return emitParenExpression(node); - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - case 180 /* ArrowFunction */: - return emitFunctionDeclaration(node); - case 181 /* DeleteExpression */: - return emitDeleteExpression(node); - case 182 /* TypeOfExpression */: - return emitTypeOfExpression(node); - case 183 /* VoidExpression */: - return emitVoidExpression(node); - case 184 /* AwaitExpression */: - return emitAwaitExpression(node); - case 185 /* PrefixUnaryExpression */: - return emitPrefixUnaryExpression(node); - case 186 /* PostfixUnaryExpression */: - return emitPostfixUnaryExpression(node); - case 187 /* BinaryExpression */: - return emitBinaryExpression(node); - case 188 /* ConditionalExpression */: - return emitConditionalExpression(node); - case 191 /* SpreadElementExpression */: - return emitSpreadElementExpression(node); - case 190 /* YieldExpression */: - return emitYieldExpression(node); - case 193 /* OmittedExpression */: - return; - case 199 /* Block */: - case 226 /* ModuleBlock */: - return emitBlock(node); - case 200 /* VariableStatement */: - return emitVariableStatement(node); - case 201 /* EmptyStatement */: - return write(";"); - case 202 /* ExpressionStatement */: - return emitExpressionStatement(node); - case 203 /* IfStatement */: - return emitIfStatement(node); - case 204 /* DoStatement */: - return emitDoStatement(node); - case 205 /* WhileStatement */: - return emitWhileStatement(node); - case 206 /* ForStatement */: - return emitForStatement(node); - case 208 /* ForOfStatement */: - case 207 /* ForInStatement */: - return emitForInOrForOfStatement(node); - case 209 /* ContinueStatement */: - case 210 /* BreakStatement */: - return emitBreakOrContinueStatement(node); - case 211 /* ReturnStatement */: - return emitReturnStatement(node); - case 212 /* WithStatement */: - return emitWithStatement(node); - case 213 /* SwitchStatement */: - return emitSwitchStatement(node); - case 249 /* CaseClause */: - case 250 /* DefaultClause */: - return emitCaseOrDefaultClause(node); - case 214 /* LabeledStatement */: - return emitLabeledStatement(node); - case 215 /* ThrowStatement */: - return emitThrowStatement(node); - case 216 /* TryStatement */: - return emitTryStatement(node); - case 252 /* CatchClause */: - return emitCatchClause(node); - case 217 /* DebuggerStatement */: - return emitDebuggerStatement(node); - case 218 /* VariableDeclaration */: - return emitVariableDeclaration(node); - case 192 /* ClassExpression */: - return emitClassExpression(node); - case 221 /* ClassDeclaration */: - return emitClassDeclaration(node); - case 222 /* InterfaceDeclaration */: - return emitInterfaceDeclaration(node); - case 224 /* EnumDeclaration */: - return emitEnumDeclaration(node); - case 255 /* EnumMember */: - return emitEnumMember(node); - case 225 /* ModuleDeclaration */: - return emitModuleDeclaration(node); - case 230 /* ImportDeclaration */: - return emitImportDeclaration(node); - case 229 /* ImportEqualsDeclaration */: - return emitImportEqualsDeclaration(node); - case 236 /* ExportDeclaration */: - return emitExportDeclaration(node); - case 235 /* ExportAssignment */: - return emitExportAssignment(node); - case 256 /* SourceFile */: - return emitSourceFileNode(node); + return undefined; + } + function visitExportAssignment(node) { + if (!node.isExportEquals) { + if (ts.nodeIsSynthesized(node) || resolver.isValueAliasDeclaration(node)) { + return createExportStatement(ts.createLiteral("default"), node.expression); } } - function hasDetachedComments(pos) { - return detachedCommentsInfo !== undefined && ts.lastOrUndefined(detachedCommentsInfo).nodePos === pos; + return undefined; + } + /** + * Visits a variable statement, hoisting declared names to the top-level module body. + * Each declaration is rewritten into an assignment expression. + * + * @param node The variable statement to visit. + */ + function visitVariableStatement(node) { + // hoist only non-block scoped declarations or block scoped declarations parented by source file + var shouldHoist = ((ts.getCombinedNodeFlags(ts.getOriginalNode(node.declarationList)) & 3 /* BlockScoped */) == 0) || + enclosingBlockScopedContainer.kind === 256 /* SourceFile */; + if (!shouldHoist) { + return node; } - function getLeadingCommentsWithoutDetachedComments() { - // get the leading comments from detachedPos - var leadingComments = ts.getLeadingCommentRanges(currentText, ts.lastOrUndefined(detachedCommentsInfo).detachedCommentEndPos); - if (detachedCommentsInfo.length - 1) { - detachedCommentsInfo.pop(); - } - else { - detachedCommentsInfo = undefined; + var isExported = ts.hasModifier(node, 1 /* Export */); + var expressions = []; + for (var _i = 0, _a = node.declarationList.declarations; _i < _a.length; _i++) { + var variable = _a[_i]; + var visited = transformVariable(variable, isExported); + if (visited) { + expressions.push(visited); } - return leadingComments; } - /** - * Determine if the given comment is a triple-slash - * - * @return true if the comment is a triple-slash comment else false - **/ - function isTripleSlashComment(comment) { - // Verify this is /// comment, but do the regexp match only when we first can find /// in the comment text - // so that we don't end up computing comment string and doing match for all // comments - if (currentText.charCodeAt(comment.pos + 1) === 47 /* slash */ && - comment.pos + 2 < comment.end && - currentText.charCodeAt(comment.pos + 2) === 47 /* slash */) { - var textSubStr = currentText.substring(comment.pos, comment.end); - return textSubStr.match(ts.fullTripleSlashReferencePathRegEx) || - textSubStr.match(ts.fullTripleSlashAMDReferencePathRegEx) ? - true : false; - } - return false; + if (expressions.length) { + return ts.createStatement(ts.inlineExpressions(expressions), node); } - function getLeadingCommentsToEmit(node) { - // Emit the leading comments only if the parent's pos doesn't match because parent should take care of emitting these comments - if (node.parent) { - if (node.parent.kind === 256 /* SourceFile */ || node.pos !== node.parent.pos) { - if (hasDetachedComments(node.pos)) { - // get comments without detached comments - return getLeadingCommentsWithoutDetachedComments(); - } - else { - // get the leading comments from the node - return ts.getLeadingCommentRangesOfNodeFromText(node, currentText); - } - } - } + return undefined; + } + /** + * Transforms a VariableDeclaration into one or more assignment expressions. + * + * @param node The VariableDeclaration to transform. + * @param isExported A value used to indicate whether the containing statement was exported. + */ + function transformVariable(node, isExported) { + // Hoist any bound names within the declaration. + hoistBindingElement(node, isExported); + if (!node.initializer) { + // If the variable has no initializer, ignore it. + return; } - function getTrailingCommentsToEmit(node) { - // Emit the trailing comments only if the parent's pos doesn't match because parent should take care of emitting these comments - if (node.parent) { - if (node.parent.kind === 256 /* SourceFile */ || node.end !== node.parent.end) { - return ts.getTrailingCommentRanges(currentText, node.end); - } - } + var name = node.name; + if (ts.isIdentifier(name)) { + // If the variable has an IdentifierName, write out an assignment expression in its place. + return ts.createAssignment(name, node.initializer); } - /** - * Emit comments associated with node that will not be emitted into JS file - */ - function emitCommentsOnNotEmittedNode(node) { - emitLeadingCommentsWorker(node, /*isEmittedNode*/ false); + else { + // If the variable has a BindingPattern, flatten the variable into multiple assignment expressions. + return ts.flattenVariableDestructuringToExpression(context, node, hoistVariableDeclaration); } - function emitLeadingComments(node) { - return emitLeadingCommentsWorker(node, /*isEmittedNode*/ true); + } + /** + * Visits a FunctionDeclaration, hoisting it to the outer module body function. + * + * @param node The function declaration to visit. + */ + function visitFunctionDeclaration(node) { + if (ts.hasModifier(node, 1 /* Export */)) { + // If the function is exported, ensure it has a name and rewrite the function without any export flags. + var name_42 = node.name || ts.getGeneratedNameForNode(node); + var newNode = ts.createFunctionDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, node.asteriskToken, name_42, + /*typeParameters*/ undefined, node.parameters, + /*type*/ undefined, node.body, + /*location*/ node); + // Record a declaration export in the outer module body function. + recordExportedFunctionDeclaration(node); + if (!ts.hasModifier(node, 512 /* Default */)) { + recordExportName(name_42); + } + ts.setOriginalNode(newNode, node); + node = newNode; + } + // Hoist the function declaration to the outer module body function. + hoistFunctionDeclaration(node); + return undefined; + } + function visitExpressionStatement(node) { + var originalNode = ts.getOriginalNode(node); + if ((originalNode.kind === 225 /* ModuleDeclaration */ || originalNode.kind === 224 /* EnumDeclaration */) && ts.hasModifier(originalNode, 1 /* Export */)) { + var name_43 = getDeclarationName(originalNode); + // We only need to hoistVariableDeclaration for EnumDeclaration + // as ModuleDeclaration is already hoisted when the transformer call visitVariableStatement + // which then call transformsVariable for each declaration in declarationList + if (originalNode.kind === 224 /* EnumDeclaration */) { + hoistVariableDeclaration(name_43); + } + return [ + node, + createExportStatement(name_43, name_43) + ]; } - function emitLeadingCommentsWorker(node, isEmittedNode) { - if (compilerOptions.removeComments) { - return; - } - var leadingComments; - if (isEmittedNode) { - leadingComments = getLeadingCommentsToEmit(node); - } - else { - // If the node will not be emitted in JS, remove all the comments(normal, pinned and ///) associated with the node, - // unless it is a triple slash comment at the top of the file. - // For Example: - // /// - // declare var x; - // /// - // interface F {} - // The first /// will NOT be removed while the second one will be removed even though both node will not be emitted - if (node.pos === 0) { - leadingComments = ts.filter(getLeadingCommentsToEmit(node), isTripleSlashComment); - } - } - ts.emitNewLineBeforeLeadingComments(currentLineMap, writer, node, leadingComments); - // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space - ts.emitComments(currentText, currentLineMap, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment); - } - function emitTrailingComments(node) { - if (compilerOptions.removeComments) { - return; + return node; + } + /** + * Visits a ClassDeclaration, hoisting its name to the outer module body function. + * + * @param node The class declaration to visit. + */ + function visitClassDeclaration(node) { + // Hoist the name of the class declaration to the outer module body function. + var name = getDeclarationName(node); + hoistVariableDeclaration(name); + var statements = []; + // Rewrite the class declaration into an assignment of a class expression. + statements.push(ts.createStatement(ts.createAssignment(name, ts.createClassExpression( + /*modifiers*/ undefined, node.name, + /*typeParameters*/ undefined, node.heritageClauses, node.members, + /*location*/ node)), + /*location*/ node)); + // If the class was exported, write a declaration export to the inner module body function. + if (ts.hasModifier(node, 1 /* Export */)) { + if (!ts.hasModifier(node, 512 /* Default */)) { + recordExportName(name); + } + statements.push(createDeclarationExport(node)); + } + return statements; + } + function shouldHoistLoopInitializer(node) { + return ts.isVariableDeclarationList(node) && (ts.getCombinedNodeFlags(node) & 3 /* BlockScoped */) === 0; + } + /** + * Visits the body of a ForStatement to hoist declarations. + * + * @param node The statement to visit. + */ + function visitForStatement(node) { + var initializer = node.initializer; + if (shouldHoistLoopInitializer(initializer)) { + var expressions = []; + for (var _i = 0, _a = initializer.declarations; _i < _a.length; _i++) { + var variable = _a[_i]; + var visited = transformVariable(variable, /*isExported*/ false); + if (visited) { + expressions.push(visited); + } } - // Emit the trailing comments only if the parent's end doesn't match - var trailingComments = getTrailingCommentsToEmit(node); - // trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/ - ts.emitComments(currentText, currentLineMap, writer, trailingComments, /*trailingSeparator*/ false, newLine, writeComment); + ; + return ts.createFor(expressions.length + ? ts.inlineExpressions(expressions) + : ts.createSynthesizedNode(193 /* OmittedExpression */), node.condition, node.incrementor, ts.visitNode(node.statement, visitNestedNode, ts.isStatement), + /*location*/ node); } - /** - * Emit trailing comments at the position. The term trailing comment is used here to describe following comment: - * x, /comment1/ y - * ^ => pos; the function will emit "comment1" in the emitJS - */ - function emitTrailingCommentsOfPosition(pos) { - if (compilerOptions.removeComments) { - return; - } - var trailingComments = ts.getTrailingCommentRanges(currentText, pos); - // trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/ - ts.emitComments(currentText, currentLineMap, writer, trailingComments, /*trailingSeparator*/ true, newLine, writeComment); + else { + return ts.visitEachChild(node, visitNestedNode, context); } - function emitLeadingCommentsOfPositionWorker(pos) { - if (compilerOptions.removeComments) { - return; - } - var leadingComments; - if (hasDetachedComments(pos)) { - // get comments without detached comments - leadingComments = getLeadingCommentsWithoutDetachedComments(); - } - else { - // get the leading comments from the node - leadingComments = ts.getLeadingCommentRanges(currentText, pos); - } - ts.emitNewLineBeforeLeadingComments(currentLineMap, writer, { pos: pos, end: pos }, leadingComments); - // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space - ts.emitComments(currentText, currentLineMap, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment); + } + /** + * Transforms and hoists the declaration list of a ForInStatement or ForOfStatement into an expression. + * + * @param node The decalaration list to transform. + */ + function transformForBinding(node) { + var firstDeclaration = ts.firstOrUndefined(node.declarations); + hoistBindingElement(firstDeclaration, /*isExported*/ false); + var name = firstDeclaration.name; + return ts.isIdentifier(name) + ? name + : ts.flattenVariableDestructuringToExpression(context, firstDeclaration, hoistVariableDeclaration); + } + /** + * Visits the body of a ForInStatement to hoist declarations. + * + * @param node The statement to visit. + */ + function visitForInStatement(node) { + var initializer = node.initializer; + if (shouldHoistLoopInitializer(initializer)) { + var updated = ts.getMutableClone(node); + updated.initializer = transformForBinding(initializer); + updated.statement = ts.visitNode(node.statement, visitNestedNode, ts.isStatement, /*optional*/ false, ts.liftToBlock); + return updated; } - function emitDetachedCommentsAndUpdateCommentsInfo(node) { - var currentDetachedCommentInfo = ts.emitDetachedComments(currentText, currentLineMap, writer, writeComment, node, newLine, compilerOptions.removeComments); - if (currentDetachedCommentInfo) { - if (detachedCommentsInfo) { - detachedCommentsInfo.push(currentDetachedCommentInfo); - } - else { - detachedCommentsInfo = [currentDetachedCommentInfo]; - } - } + else { + return ts.visitEachChild(node, visitNestedNode, context); } - function writeComment(text, lineMap, writer, comment, newLine) { - emitPos(comment.pos); - ts.writeCommentRange(text, lineMap, writer, comment, newLine); - emitPos(comment.end); + } + /** + * Visits the body of a ForOfStatement to hoist declarations. + * + * @param node The statement to visit. + */ + function visitForOfStatement(node) { + var initializer = node.initializer; + if (shouldHoistLoopInitializer(initializer)) { + var updated = ts.getMutableClone(node); + updated.initializer = transformForBinding(initializer); + updated.statement = ts.visitNode(node.statement, visitNestedNode, ts.isStatement, /*optional*/ false, ts.liftToBlock); + return updated; } - function emitShebang() { - var shebang = ts.getShebang(currentText); - if (shebang) { - write(shebang); - writeLine(); - } + else { + return ts.visitEachChild(node, visitNestedNode, context); } - var _a, _b; } - function emitFile(_a, sourceFiles, isBundledEmit) { - var jsFilePath = _a.jsFilePath, sourceMapFilePath = _a.sourceMapFilePath, declarationFilePath = _a.declarationFilePath; - // Make sure not to write js File and source map file if any of them cannot be written - if (!host.isEmitBlocked(jsFilePath) && !compilerOptions.noEmit) { - emitJavaScript(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit); + /** + * Visits the body of a DoStatement to hoist declarations. + * + * @param node The statement to visit. + */ + function visitDoStatement(node) { + var statement = ts.visitNode(node.statement, visitNestedNode, ts.isStatement, /*optional*/ false, ts.liftToBlock); + if (statement !== node.statement) { + var updated = ts.getMutableClone(node); + updated.statement = statement; + return updated; } - else { - emitSkipped = true; + return node; + } + /** + * Visits the body of a WhileStatement to hoist declarations. + * + * @param node The statement to visit. + */ + function visitWhileStatement(node) { + var statement = ts.visitNode(node.statement, visitNestedNode, ts.isStatement, /*optional*/ false, ts.liftToBlock); + if (statement !== node.statement) { + var updated = ts.getMutableClone(node); + updated.statement = statement; + return updated; } - if (declarationFilePath) { - emitSkipped = ts.writeDeclarationFile(declarationFilePath, sourceFiles, isBundledEmit, host, resolver, emitterDiagnostics) || emitSkipped; + return node; + } + /** + * Visits the body of a LabeledStatement to hoist declarations. + * + * @param node The statement to visit. + */ + function visitLabeledStatement(node) { + var statement = ts.visitNode(node.statement, visitNestedNode, ts.isStatement, /*optional*/ false, ts.liftToBlock); + if (statement !== node.statement) { + var updated = ts.getMutableClone(node); + updated.statement = statement; + return updated; } - if (!emitSkipped && emittedFilesList) { - emittedFilesList.push(jsFilePath); - if (sourceMapFilePath) { - emittedFilesList.push(sourceMapFilePath); - } - if (declarationFilePath) { - emittedFilesList.push(declarationFilePath); - } + return node; + } + /** + * Visits the body of a WithStatement to hoist declarations. + * + * @param node The statement to visit. + */ + function visitWithStatement(node) { + var statement = ts.visitNode(node.statement, visitNestedNode, ts.isStatement, /*optional*/ false, ts.liftToBlock); + if (statement !== node.statement) { + var updated = ts.getMutableClone(node); + updated.statement = statement; + return updated; } + return node; } - } - ts.emitFiles = emitFiles; -})(ts || (ts = {})); -/// -/// -/// -var ts; -(function (ts) { - /** The version of the TypeScript compiler release */ - ts.version = "2.1.0"; - var emptyArray = []; - function findConfigFile(searchPath, fileExists) { - while (true) { - var fileName = ts.combinePaths(searchPath, "tsconfig.json"); - if (fileExists(fileName)) { - return fileName; + /** + * Visits the body of a SwitchStatement to hoist declarations. + * + * @param node The statement to visit. + */ + function visitSwitchStatement(node) { + var caseBlock = ts.visitNode(node.caseBlock, visitNestedNode, ts.isCaseBlock); + if (caseBlock !== node.caseBlock) { + var updated = ts.getMutableClone(node); + updated.caseBlock = caseBlock; + return updated; } - var parentPath = ts.getDirectoryPath(searchPath); - if (parentPath === searchPath) { - break; + return node; + } + /** + * Visits the body of a CaseBlock to hoist declarations. + * + * @param node The node to visit. + */ + function visitCaseBlock(node) { + var clauses = ts.visitNodes(node.clauses, visitNestedNode, ts.isCaseOrDefaultClause); + if (clauses !== node.clauses) { + var updated = ts.getMutableClone(node); + updated.clauses = clauses; + return updated; } - searchPath = parentPath; + return node; } - return undefined; - } - ts.findConfigFile = findConfigFile; - function resolveTripleslashReference(moduleName, containingFile) { - var basePath = ts.getDirectoryPath(containingFile); - var referencedFileName = ts.isRootedDiskPath(moduleName) ? moduleName : ts.combinePaths(basePath, moduleName); - return ts.normalizePath(referencedFileName); - } - ts.resolveTripleslashReference = resolveTripleslashReference; - /* @internal */ - function computeCommonSourceDirectoryOfFilenames(fileNames, currentDirectory, getCanonicalFileName) { - var commonPathComponents; - var failed = ts.forEach(fileNames, function (sourceFile) { - // Each file contributes into common source file path - var sourcePathComponents = ts.getNormalizedPathComponents(sourceFile, currentDirectory); - sourcePathComponents.pop(); // The base file name is not part of the common directory path - if (!commonPathComponents) { - // first file - commonPathComponents = sourcePathComponents; - return; + /** + * Visits the body of a CaseClause to hoist declarations. + * + * @param node The clause to visit. + */ + function visitCaseClause(node) { + var statements = ts.visitNodes(node.statements, visitNestedNode, ts.isStatement); + if (statements !== node.statements) { + var updated = ts.getMutableClone(node); + updated.statements = statements; + return updated; } - for (var i = 0, n = Math.min(commonPathComponents.length, sourcePathComponents.length); i < n; i++) { - if (getCanonicalFileName(commonPathComponents[i]) !== getCanonicalFileName(sourcePathComponents[i])) { - if (i === 0) { - // Failed to find any common path component - return true; - } - // New common path found that is 0 -> i-1 - commonPathComponents.length = i; - break; - } + return node; + } + /** + * Visits the body of a DefaultClause to hoist declarations. + * + * @param node The clause to visit. + */ + function visitDefaultClause(node) { + return ts.visitEachChild(node, visitNestedNode, context); + } + /** + * Visits the body of a TryStatement to hoist declarations. + * + * @param node The statement to visit. + */ + function visitTryStatement(node) { + return ts.visitEachChild(node, visitNestedNode, context); + } + /** + * Visits the body of a CatchClause to hoist declarations. + * + * @param node The clause to visit. + */ + function visitCatchClause(node) { + var block = ts.visitNode(node.block, visitNestedNode, ts.isBlock); + if (block !== node.block) { + var updated = ts.getMutableClone(node); + updated.block = block; + return updated; } - // If the sourcePathComponents was shorter than the commonPathComponents, truncate to the sourcePathComponents - if (sourcePathComponents.length < commonPathComponents.length) { - commonPathComponents.length = sourcePathComponents.length; + return node; + } + /** + * Visits the body of a Block to hoist declarations. + * + * @param node The block to visit. + */ + function visitBlock(node) { + return ts.visitEachChild(node, visitNestedNode, context); + } + // + // Substitutions + // + function onEmitNode(emitContext, node, emitCallback) { + if (node.kind === 256 /* SourceFile */) { + exportFunctionForFile = exportFunctionForFileMap[ts.getOriginalNodeId(node)]; + previousOnEmitNode(emitContext, node, emitCallback); + exportFunctionForFile = undefined; + } + else { + previousOnEmitNode(emitContext, node, emitCallback); } - }); - // A common path can not be found when paths span multiple drives on windows, for example - if (failed) { - return ""; } - if (!commonPathComponents) { - return currentDirectory; + /** + * Hooks node substitutions. + * + * @param node The node to substitute. + * @param isExpression A value indicating whether the node is to be used in an expression + * position. + */ + function onSubstituteNode(emitContext, node) { + node = previousOnSubstituteNode(emitContext, node); + if (emitContext === 1 /* Expression */) { + return substituteExpression(node); + } + return node; } - return ts.getNormalizedPathFromPathComponents(commonPathComponents); - } - ts.computeCommonSourceDirectoryOfFilenames = computeCommonSourceDirectoryOfFilenames; - function trace(host, message) { - host.trace(ts.formatMessage.apply(undefined, arguments)); - } - function isTraceEnabled(compilerOptions, host) { - return compilerOptions.traceResolution && host.trace !== undefined; - } - /* @internal */ - function hasZeroOrOneAsteriskCharacter(str) { - var seenAsterisk = false; - for (var i = 0; i < str.length; i++) { - if (str.charCodeAt(i) === 42 /* asterisk */) { - if (!seenAsterisk) { - seenAsterisk = true; - } - else { - // have already seen asterisk - return false; + /** + * Substitute the expression, if necessary. + * + * @param node The node to substitute. + */ + function substituteExpression(node) { + switch (node.kind) { + case 69 /* Identifier */: + return substituteExpressionIdentifier(node); + case 187 /* BinaryExpression */: + return substituteBinaryExpression(node); + case 185 /* PrefixUnaryExpression */: + case 186 /* PostfixUnaryExpression */: + return substituteUnaryExpression(node); + } + return node; + } + /** + * Substitution for identifiers exported at the top level of a module. + */ + function substituteExpressionIdentifier(node) { + var importDeclaration = resolver.getReferencedImportDeclaration(node); + if (importDeclaration) { + var importBinding = createImportBinding(importDeclaration); + if (importBinding) { + return importBinding; } } + return node; } - return true; - } - ts.hasZeroOrOneAsteriskCharacter = hasZeroOrOneAsteriskCharacter; - function createResolvedModule(resolvedFileName, isExternalLibraryImport, failedLookupLocations) { - return { resolvedModule: resolvedFileName ? { resolvedFileName: resolvedFileName, isExternalLibraryImport: isExternalLibraryImport } : undefined, failedLookupLocations: failedLookupLocations }; - } - function moduleHasNonRelativeName(moduleName) { - return !(ts.isRootedDiskPath(moduleName) || ts.isExternalModuleNameRelative(moduleName)); - } - function tryReadTypesSection(packageJsonPath, baseDirectory, state) { - var jsonContent = readJson(packageJsonPath, state.host); - function tryReadFromField(fieldName) { - if (ts.hasProperty(jsonContent, fieldName)) { - var typesFile = jsonContent[fieldName]; - if (typeof typesFile === "string") { - var typesFilePath_1 = ts.normalizePath(ts.combinePaths(baseDirectory, typesFile)); - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.package_json_has_0_field_1_that_references_2, fieldName, typesFile, typesFilePath_1); + function substituteBinaryExpression(node) { + if (ts.isAssignmentOperator(node.operatorToken.kind)) { + return substituteAssignmentExpression(node); + } + return node; + } + function substituteAssignmentExpression(node) { + ts.setEmitFlags(node, 128 /* NoSubstitution */); + var left = node.left; + switch (left.kind) { + case 69 /* Identifier */: + var exportDeclaration = resolver.getReferencedExportContainer(left); + if (exportDeclaration) { + return createExportExpression(left, node); } - return typesFilePath_1; - } - else { - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, fieldName, typeof typesFile); + break; + case 171 /* ObjectLiteralExpression */: + case 170 /* ArrayLiteralExpression */: + if (hasExportedReferenceInDestructuringPattern(left)) { + return substituteDestructuring(node); } - } + break; } + return node; } - var typesFilePath = tryReadFromField("typings") || tryReadFromField("types"); - if (typesFilePath) { - return typesFilePath; + function isExportedBinding(name) { + var container = resolver.getReferencedExportContainer(name); + return container && container.kind === 256 /* SourceFile */; } - // Use the main module for inferring types if no types package specified and the allowJs is set - if (state.compilerOptions.allowJs && jsonContent.main && typeof jsonContent.main === "string") { - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.No_types_specified_in_package_json_but_allowJs_is_set_so_returning_main_value_of_0, jsonContent.main); + function hasExportedReferenceInDestructuringPattern(node) { + switch (node.kind) { + case 69 /* Identifier */: + return isExportedBinding(node); + case 171 /* ObjectLiteralExpression */: + for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { + var property = _a[_i]; + if (hasExportedReferenceInObjectDestructuringElement(property)) { + return true; + } + } + break; + case 170 /* ArrayLiteralExpression */: + for (var _b = 0, _c = node.elements; _b < _c.length; _b++) { + var element = _c[_b]; + if (hasExportedReferenceInArrayDestructuringElement(element)) { + return true; + } + } + break; } - var mainFilePath = ts.normalizePath(ts.combinePaths(baseDirectory, jsonContent.main)); - return mainFilePath; + return false; } - return undefined; - } - function readJson(path, host) { - try { - var jsonText = host.readFile(path); - return jsonText ? JSON.parse(jsonText) : {}; + function hasExportedReferenceInObjectDestructuringElement(node) { + if (ts.isShorthandPropertyAssignment(node)) { + return isExportedBinding(node.name); + } + else if (ts.isPropertyAssignment(node)) { + return hasExportedReferenceInDestructuringElement(node.initializer); + } + else { + return false; + } } - catch (e) { - // gracefully handle if readFile fails or returns not JSON - return {}; + function hasExportedReferenceInArrayDestructuringElement(node) { + if (ts.isSpreadElementExpression(node)) { + var expression = node.expression; + return ts.isIdentifier(expression) && isExportedBinding(expression); + } + else { + return hasExportedReferenceInDestructuringElement(node); + } } - } - var typeReferenceExtensions = [".d.ts"]; - function getEffectiveTypeRoots(options, host) { - if (options.typeRoots) { - return options.typeRoots; + function hasExportedReferenceInDestructuringElement(node) { + if (ts.isBinaryExpression(node)) { + var left = node.left; + return node.operatorToken.kind === 56 /* EqualsToken */ + && isDestructuringPattern(left) + && hasExportedReferenceInDestructuringPattern(left); + } + else if (ts.isIdentifier(node)) { + return isExportedBinding(node); + } + else if (ts.isSpreadElementExpression(node)) { + var expression = node.expression; + return ts.isIdentifier(expression) && isExportedBinding(expression); + } + else if (isDestructuringPattern(node)) { + return hasExportedReferenceInDestructuringPattern(node); + } + else { + return false; + } } - var currentDirectory; - if (options.configFilePath) { - currentDirectory = ts.getDirectoryPath(options.configFilePath); + function isDestructuringPattern(node) { + var kind = node.kind; + return kind === 69 /* Identifier */ + || kind === 171 /* ObjectLiteralExpression */ + || kind === 170 /* ArrayLiteralExpression */; + } + function substituteDestructuring(node) { + return ts.flattenDestructuringAssignment(context, node, /*needsValue*/ true, hoistVariableDeclaration); + } + function substituteUnaryExpression(node) { + var operand = node.operand; + var operator = node.operator; + var substitute = ts.isIdentifier(operand) && + (node.kind === 186 /* PostfixUnaryExpression */ || + (node.kind === 185 /* PrefixUnaryExpression */ && (operator === 41 /* PlusPlusToken */ || operator === 42 /* MinusMinusToken */))); + if (substitute) { + var exportDeclaration = resolver.getReferencedExportContainer(operand); + if (exportDeclaration) { + var expr = ts.createPrefix(node.operator, operand, node); + ts.setEmitFlags(expr, 128 /* NoSubstitution */); + var call = createExportExpression(operand, expr); + if (node.kind === 185 /* PrefixUnaryExpression */) { + return call; + } + else { + // export function returns the value that was passes as the second argument + // however for postfix unary expressions result value should be the value before modification. + // emit 'x++' as '(export('x', ++x) - 1)' and 'x--' as '(export('x', --x) + 1)' + return operator === 41 /* PlusPlusToken */ + ? ts.createSubtract(call, ts.createLiteral(1)) + : ts.createAdd(call, ts.createLiteral(1)); + } + } + } + return node; } - else if (host.getCurrentDirectory) { - currentDirectory = host.getCurrentDirectory(); + /** + * Gets a name to use for a DeclarationStatement. + * @param node The declaration statement. + */ + function getDeclarationName(node) { + return node.name ? ts.getSynthesizedClone(node.name) : ts.getGeneratedNameForNode(node); + } + function addExportStarFunction(statements, localNames) { + var exportStarFunction = ts.createUniqueName("exportStar"); + var m = ts.createIdentifier("m"); + var n = ts.createIdentifier("n"); + var exports = ts.createIdentifier("exports"); + var condition = ts.createStrictInequality(n, ts.createLiteral("default")); + if (localNames) { + condition = ts.createLogicalAnd(condition, ts.createLogicalNot(ts.createHasOwnProperty(localNames, n))); + } + statements.push(ts.createFunctionDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, exportStarFunction, + /*typeParameters*/ undefined, [ts.createParameter(m)], + /*type*/ undefined, ts.createBlock([ + ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(exports, + /*type*/ undefined, ts.createObjectLiteral([])) + ])), + ts.createForIn(ts.createVariableDeclarationList([ + ts.createVariableDeclaration(n, /*type*/ undefined) + ]), m, ts.createBlock([ + ts.setEmitFlags(ts.createIf(condition, ts.createStatement(ts.createAssignment(ts.createElementAccess(exports, n), ts.createElementAccess(m, n)))), 32 /* SingleLine */) + ])), + ts.createStatement(ts.createCall(exportFunctionForFile, + /*typeArguments*/ undefined, [exports])) + ], + /*location*/ undefined, + /*multiline*/ true))); + return exportStarFunction; } - return currentDirectory && getDefaultTypeRoots(currentDirectory, host); - } - /** - * Returns the path to every node_modules/@types directory from some ancestor directory. - * Returns undefined if there are none. - */ - function getDefaultTypeRoots(currentDirectory, host) { - if (!host.directoryExists) { - return [ts.combinePaths(currentDirectory, "node_modules")]; + /** + * Creates a call to the current file's export function to export a value. + * @param name The bound name of the export. + * @param value The exported value. + */ + function createExportExpression(name, value) { + var exportName = ts.isIdentifier(name) ? ts.createLiteral(name.text) : name; + return ts.createCall(exportFunctionForFile, /*typeArguments*/ undefined, [exportName, value]); } - var typeRoots; - while (true) { - var atTypes = ts.combinePaths(currentDirectory, nodeModulesAtTypes); - if (host.directoryExists(atTypes)) { - (typeRoots || (typeRoots = [])).push(atTypes); + /** + * Creates a call to the current file's export function to export a value. + * @param name The bound name of the export. + * @param value The exported value. + */ + function createExportStatement(name, value) { + return ts.createStatement(createExportExpression(name, value)); + } + /** + * Creates a call to the current file's export function to export a declaration. + * @param node The declaration to export. + */ + function createDeclarationExport(node) { + var declarationName = getDeclarationName(node); + var exportName = ts.hasModifier(node, 512 /* Default */) ? ts.createLiteral("default") : declarationName; + return createExportStatement(exportName, declarationName); + } + function createImportBinding(importDeclaration) { + var importAlias; + var name; + if (ts.isImportClause(importDeclaration)) { + importAlias = ts.getGeneratedNameForNode(importDeclaration.parent); + name = ts.createIdentifier("default"); + } + else if (ts.isImportSpecifier(importDeclaration)) { + importAlias = ts.getGeneratedNameForNode(importDeclaration.parent.parent.parent); + name = importDeclaration.propertyName || importDeclaration.name; } - var parent_15 = ts.getDirectoryPath(currentDirectory); - if (parent_15 === currentDirectory) { - break; + else { + return undefined; } - currentDirectory = parent_15; - } - return typeRoots; - } - var nodeModulesAtTypes = ts.combinePaths("node_modules", "@types"); - /** - * @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. - * This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups - * is assumed to be the same as root directory of the project. - */ - function resolveTypeReferenceDirective(typeReferenceDirectiveName, containingFile, options, host) { - var traceEnabled = isTraceEnabled(options, host); - var moduleResolutionState = { - compilerOptions: options, - host: host, - skipTsx: true, - traceEnabled: traceEnabled - }; - var typeRoots = getEffectiveTypeRoots(options, host); - if (traceEnabled) { - if (containingFile === undefined) { - if (typeRoots === undefined) { - trace(host, ts.Diagnostics.Resolving_type_reference_directive_0_containing_file_not_set_root_directory_not_set, typeReferenceDirectiveName); - } - else { - trace(host, ts.Diagnostics.Resolving_type_reference_directive_0_containing_file_not_set_root_directory_1, typeReferenceDirectiveName, typeRoots); - } + if (name.originalKeywordKind && languageVersion === 0 /* ES3 */) { + return ts.createElementAccess(importAlias, ts.createLiteral(name.text)); } else { - if (typeRoots === undefined) { - trace(host, ts.Diagnostics.Resolving_type_reference_directive_0_containing_file_1_root_directory_not_set, typeReferenceDirectiveName, containingFile); + return ts.createPropertyAccess(importAlias, ts.getSynthesizedClone(name)); + } + } + function collectDependencyGroups(externalImports) { + var groupIndices = ts.createMap(); + var dependencyGroups = []; + for (var i = 0; i < externalImports.length; i++) { + var externalImport = externalImports[i]; + var externalModuleName = ts.getExternalModuleNameLiteral(externalImport, currentSourceFile, host, resolver, compilerOptions); + var text = externalModuleName.text; + if (ts.hasProperty(groupIndices, text)) { + // deduplicate/group entries in dependency list by the dependency name + var groupIndex = groupIndices[text]; + dependencyGroups[groupIndex].externalImports.push(externalImport); + continue; } else { - trace(host, ts.Diagnostics.Resolving_type_reference_directive_0_containing_file_1_root_directory_2, typeReferenceDirectiveName, containingFile, typeRoots); + groupIndices[text] = dependencyGroups.length; + dependencyGroups.push({ + name: externalModuleName, + externalImports: [externalImport] + }); } } + return dependencyGroups; } - var failedLookupLocations = []; - // Check primary library paths - if (typeRoots && typeRoots.length) { - if (traceEnabled) { - trace(host, ts.Diagnostics.Resolving_with_primary_search_path_0, typeRoots.join(", ")); + function getNameOfDependencyGroup(dependencyGroup) { + return dependencyGroup.name; + } + function recordExportName(name) { + if (!exportedLocalNames) { + exportedLocalNames = []; } - var primarySearchPaths = typeRoots; - for (var _i = 0, primarySearchPaths_1 = primarySearchPaths; _i < primarySearchPaths_1.length; _i++) { - var typeRoot = primarySearchPaths_1[_i]; - var candidate = ts.combinePaths(typeRoot, typeReferenceDirectiveName); - var candidateDirectory = ts.getDirectoryPath(candidate); - var resolvedFile_1 = loadNodeModuleFromDirectory(typeReferenceExtensions, candidate, failedLookupLocations, !directoryProbablyExists(candidateDirectory, host), moduleResolutionState); - if (resolvedFile_1) { - if (traceEnabled) { - trace(host, ts.Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, resolvedFile_1, true); - } - return { - resolvedTypeReferenceDirective: { primary: true, resolvedFileName: resolvedFile_1 }, - failedLookupLocations: failedLookupLocations - }; - } + exportedLocalNames.push(name); + } + function recordExportedFunctionDeclaration(node) { + if (!exportedFunctionDeclarations) { + exportedFunctionDeclarations = []; } + exportedFunctionDeclarations.push(createDeclarationExport(node)); } - else { - if (traceEnabled) { - trace(host, ts.Diagnostics.Root_directory_cannot_be_determined_skipping_primary_search_paths); + function hoistBindingElement(node, isExported) { + if (ts.isOmittedExpression(node)) { + return; + } + var name = node.name; + if (ts.isIdentifier(name)) { + hoistVariableDeclaration(ts.getSynthesizedClone(name)); + if (isExported) { + recordExportName(name); + } + } + else if (ts.isBindingPattern(name)) { + ts.forEach(name.elements, isExported ? hoistExportedBindingElement : hoistNonExportedBindingElement); } } - var resolvedFile; - var initialLocationForSecondaryLookup; - if (containingFile) { - initialLocationForSecondaryLookup = ts.getDirectoryPath(containingFile); + function hoistExportedBindingElement(node) { + hoistBindingElement(node, /*isExported*/ true); } - if (initialLocationForSecondaryLookup !== undefined) { - // check secondary locations - if (traceEnabled) { - trace(host, ts.Diagnostics.Looking_up_in_node_modules_folder_initial_location_0, initialLocationForSecondaryLookup); + function hoistNonExportedBindingElement(node) { + hoistBindingElement(node, /*isExported*/ false); + } + function updateSourceFile(node, statements, nodeEmitFlags) { + var updated = ts.getMutableClone(node); + updated.statements = ts.createNodeArray(statements, node.statements); + ts.setEmitFlags(updated, nodeEmitFlags); + return updated; + } + } + ts.transformSystemModule = transformSystemModule; +})(ts || (ts = {})); +/// +/// +/*@internal*/ +var ts; +(function (ts) { + function transformES6Module(context) { + var compilerOptions = context.getCompilerOptions(); + var resolver = context.getEmitResolver(); + var currentSourceFile; + return transformSourceFile; + function transformSourceFile(node) { + if (ts.isDeclarationFile(node)) { + return node; } - resolvedFile = loadModuleFromNodeModules(typeReferenceDirectiveName, initialLocationForSecondaryLookup, failedLookupLocations, moduleResolutionState); - if (traceEnabled) { - if (resolvedFile) { - trace(host, ts.Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, resolvedFile, false); - } - else { - trace(host, ts.Diagnostics.Type_reference_directive_0_was_not_resolved, typeReferenceDirectiveName); - } + if (ts.isExternalModule(node) || compilerOptions.isolatedModules) { + currentSourceFile = node; + return ts.visitEachChild(node, visitor, context); } + return node; } - else { - if (traceEnabled) { - trace(host, ts.Diagnostics.Containing_file_is_not_specified_and_root_directory_cannot_be_determined_skipping_lookup_in_node_modules_folder); + function visitor(node) { + switch (node.kind) { + case 230 /* ImportDeclaration */: + return visitImportDeclaration(node); + case 229 /* ImportEqualsDeclaration */: + return visitImportEqualsDeclaration(node); + case 231 /* ImportClause */: + return visitImportClause(node); + case 233 /* NamedImports */: + case 232 /* NamespaceImport */: + return visitNamedBindings(node); + case 234 /* ImportSpecifier */: + return visitImportSpecifier(node); + case 235 /* ExportAssignment */: + return visitExportAssignment(node); + case 236 /* ExportDeclaration */: + return visitExportDeclaration(node); + case 237 /* NamedExports */: + return visitNamedExports(node); + case 238 /* ExportSpecifier */: + return visitExportSpecifier(node); } + return node; } - return { - resolvedTypeReferenceDirective: resolvedFile - ? { primary: false, resolvedFileName: resolvedFile } - : undefined, - failedLookupLocations: failedLookupLocations - }; - } - ts.resolveTypeReferenceDirective = resolveTypeReferenceDirective; - function resolveModuleName(moduleName, containingFile, compilerOptions, host) { - var traceEnabled = isTraceEnabled(compilerOptions, host); - if (traceEnabled) { - trace(host, ts.Diagnostics.Resolving_module_0_from_1, moduleName, containingFile); + function visitExportAssignment(node) { + if (node.isExportEquals) { + return undefined; // do not emit export equals for ES6 + } + var original = ts.getOriginalNode(node); + return ts.nodeIsSynthesized(original) || resolver.isValueAliasDeclaration(original) ? node : undefined; } - var moduleResolution = compilerOptions.moduleResolution; - if (moduleResolution === undefined) { - moduleResolution = ts.getEmitModuleKind(compilerOptions) === ts.ModuleKind.CommonJS ? ts.ModuleResolutionKind.NodeJs : ts.ModuleResolutionKind.Classic; - if (traceEnabled) { - trace(host, ts.Diagnostics.Module_resolution_kind_is_not_specified_using_0, ts.ModuleResolutionKind[moduleResolution]); + function visitExportDeclaration(node) { + if (!node.exportClause) { + return resolver.moduleExportsSomeValue(node.moduleSpecifier) ? node : undefined; + } + if (!resolver.isValueAliasDeclaration(node)) { + return undefined; + } + var newExportClause = ts.visitNode(node.exportClause, visitor, ts.isNamedExports, /*optional*/ true); + if (node.exportClause === newExportClause) { + return node; } + return newExportClause + ? ts.createExportDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, newExportClause, node.moduleSpecifier) + : undefined; } - else { - if (traceEnabled) { - trace(host, ts.Diagnostics.Explicitly_specified_module_resolution_kind_Colon_0, ts.ModuleResolutionKind[moduleResolution]); + function visitNamedExports(node) { + var newExports = ts.visitNodes(node.elements, visitor, ts.isExportSpecifier); + if (node.elements === newExports) { + return node; } + return newExports.length ? ts.createNamedExports(newExports) : undefined; } - var result; - switch (moduleResolution) { - case ts.ModuleResolutionKind.NodeJs: - result = nodeModuleNameResolver(moduleName, containingFile, compilerOptions, host); - break; - case ts.ModuleResolutionKind.Classic: - result = classicNameResolver(moduleName, containingFile, compilerOptions, host); - break; + function visitExportSpecifier(node) { + return resolver.isValueAliasDeclaration(node) ? node : undefined; } - if (traceEnabled) { - if (result.resolvedModule) { - trace(host, ts.Diagnostics.Module_name_0_was_successfully_resolved_to_1, moduleName, result.resolvedModule.resolvedFileName); + function visitImportEqualsDeclaration(node) { + return !ts.isExternalModuleImportEqualsDeclaration(node) || resolver.isReferencedAliasDeclaration(node) ? node : undefined; + } + function visitImportDeclaration(node) { + if (node.importClause) { + var newImportClause = ts.visitNode(node.importClause, visitor, ts.isImportClause); + if (!newImportClause.name && !newImportClause.namedBindings) { + return undefined; + } + else if (newImportClause !== node.importClause) { + return ts.createImportDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, newImportClause, node.moduleSpecifier); + } + } + return node; + } + function visitImportClause(node) { + var newDefaultImport = node.name; + if (!resolver.isReferencedAliasDeclaration(node)) { + newDefaultImport = undefined; + } + var newNamedBindings = ts.visitNode(node.namedBindings, visitor, ts.isNamedImportBindings, /*optional*/ true); + return newDefaultImport !== node.name || newNamedBindings !== node.namedBindings + ? ts.createImportClause(newDefaultImport, newNamedBindings) + : node; + } + function visitNamedBindings(node) { + if (node.kind === 232 /* NamespaceImport */) { + return resolver.isReferencedAliasDeclaration(node) ? node : undefined; } else { - trace(host, ts.Diagnostics.Module_name_0_was_not_resolved, moduleName); + var newNamedImportElements = ts.visitNodes(node.elements, visitor, ts.isImportSpecifier); + if (!newNamedImportElements || newNamedImportElements.length == 0) { + return undefined; + } + if (newNamedImportElements === node.elements) { + return node; + } + return ts.createNamedImports(newNamedImportElements); } } - return result; + function visitImportSpecifier(node) { + return resolver.isReferencedAliasDeclaration(node) ? node : undefined; + } } - ts.resolveModuleName = resolveModuleName; + ts.transformES6Module = transformES6Module; +})(ts || (ts = {})); +/// +/// +/// +/// +/// +/// +/// +/// +/// +/* @internal */ +var ts; +(function (ts) { + var moduleTransformerMap = ts.createMap((_a = {}, + _a[ts.ModuleKind.ES6] = ts.transformES6Module, + _a[ts.ModuleKind.System] = ts.transformSystemModule, + _a[ts.ModuleKind.AMD] = ts.transformModule, + _a[ts.ModuleKind.CommonJS] = ts.transformModule, + _a[ts.ModuleKind.UMD] = ts.transformModule, + _a[ts.ModuleKind.None] = ts.transformModule, + _a)); + var SyntaxKindFeatureFlags; + (function (SyntaxKindFeatureFlags) { + SyntaxKindFeatureFlags[SyntaxKindFeatureFlags["Substitution"] = 1] = "Substitution"; + SyntaxKindFeatureFlags[SyntaxKindFeatureFlags["EmitNotifications"] = 2] = "EmitNotifications"; + })(SyntaxKindFeatureFlags || (SyntaxKindFeatureFlags = {})); + function getTransformers(compilerOptions) { + var jsx = compilerOptions.jsx; + var languageVersion = ts.getEmitScriptTarget(compilerOptions); + var moduleKind = ts.getEmitModuleKind(compilerOptions); + var transformers = []; + transformers.push(ts.transformTypeScript); + transformers.push(moduleTransformerMap[moduleKind] || moduleTransformerMap[ts.ModuleKind.None]); + if (jsx === 2 /* React */) { + transformers.push(ts.transformJsx); + } + transformers.push(ts.transformES7); + if (languageVersion < 2 /* ES6 */) { + transformers.push(ts.transformES6); + transformers.push(ts.transformGenerators); + } + return transformers; + } + ts.getTransformers = getTransformers; /** - * Any module resolution kind can be augmented with optional settings: 'baseUrl', 'paths' and 'rootDirs' - they are used to - * mitigate differences between design time structure of the project and its runtime counterpart so the same import name - * can be resolved successfully by TypeScript compiler and runtime module loader. - * If these settings are set then loading procedure will try to use them to resolve module name and it can of failure it will - * fallback to standard resolution routine. - * - * - baseUrl - this setting controls how non-relative module names are resolved. If this setting is specified then non-relative - * names will be resolved relative to baseUrl: i.e. if baseUrl is '/a/b' then candidate location to resolve module name 'c/d' will - * be '/a/b/c/d' - * - paths - this setting can only be used when baseUrl is specified. allows to tune how non-relative module names - * will be resolved based on the content of the module name. - * Structure of 'paths' compiler options - * 'paths': { - * pattern-1: [...substitutions], - * pattern-2: [...substitutions], - * ... - * pattern-n: [...substitutions] - * } - * Pattern here is a string that can contain zero or one '*' character. During module resolution module name will be matched against - * all patterns in the list. Matching for patterns that don't contain '*' means that module name must be equal to pattern respecting the case. - * If pattern contains '*' then to match pattern "*" module name must start with the and end with . - * denotes part of the module name between and . - * If module name can be matches with multiple patterns then pattern with the longest prefix will be picked. - * After selecting pattern we'll use list of substitutions to get candidate locations of the module and the try to load module - * from the candidate location. - * Substitution is a string that can contain zero or one '*'. To get candidate location from substitution we'll pick every - * substitution in the list and replace '*' with string. If candidate location is not rooted it - * will be converted to absolute using baseUrl. - * For example: - * baseUrl: /a/b/c - * "paths": { - * // match all module names - * "*": [ - * "*", // use matched name as is, - * // will be looked as /a/b/c/ - * - * "folder1/*" // substitution will convert matched name to 'folder1/', - * // since it is not rooted then final candidate location will be /a/b/c/folder1/ - * ], - * // match module names that start with 'components/' - * "components/*": [ "/root/components/*" ] // substitution will convert /components/folder1/ to '/root/components/folder1/', - * // it is rooted so it will be final candidate location - * } + * Transforms an array of SourceFiles by passing them through each transformer. * - * 'rootDirs' allows the project to be spreaded across multiple locations and resolve modules with relative names as if - * they were in the same location. For example lets say there are two files - * '/local/src/content/file1.ts' - * '/shared/components/contracts/src/content/protocols/file2.ts' - * After bundling content of '/shared/components/contracts/src' will be merged with '/local/src' so - * if file1 has the following import 'import {x} from "./protocols/file2"' it will be resolved successfully in runtime. - * 'rootDirs' provides the way to tell compiler that in order to get the whole project it should behave as if content of all - * root dirs were merged together. - * I.e. for the example above 'rootDirs' will have two entries: [ '/local/src', '/shared/components/contracts/src' ]. - * Compiler will first convert './protocols/file2' into absolute path relative to the location of containing file: - * '/local/src/content/protocols/file2' and try to load it - failure. - * Then it will search 'rootDirs' looking for a longest matching prefix of this absolute path and if such prefix is found - absolute path will - * be converted to a path relative to found rootDir entry './content/protocols/file2' (*). As a last step compiler will check all remaining - * entries in 'rootDirs', use them to build absolute path out of (*) and try to resolve module from this location. + * @param resolver The emit resolver provided by the checker. + * @param host The emit host. + * @param sourceFiles An array of source files + * @param transforms An array of Transformers. */ - function tryLoadModuleUsingOptionalResolutionSettings(moduleName, containingDirectory, loader, failedLookupLocations, supportedExtensions, state) { - if (moduleHasNonRelativeName(moduleName)) { - return tryLoadModuleUsingBaseUrl(moduleName, loader, failedLookupLocations, supportedExtensions, state); + function transformFiles(resolver, host, sourceFiles, transformers) { + var lexicalEnvironmentVariableDeclarationsStack = []; + var lexicalEnvironmentFunctionDeclarationsStack = []; + var enabledSyntaxKindFeatures = new Array(289 /* Count */); + var lexicalEnvironmentStackOffset = 0; + var hoistedVariableDeclarations; + var hoistedFunctionDeclarations; + var lexicalEnvironmentDisabled; + // The transformation context is provided to each transformer as part of transformer + // initialization. + var context = { + getCompilerOptions: function () { return host.getCompilerOptions(); }, + getEmitResolver: function () { return resolver; }, + getEmitHost: function () { return host; }, + hoistVariableDeclaration: hoistVariableDeclaration, + hoistFunctionDeclaration: hoistFunctionDeclaration, + startLexicalEnvironment: startLexicalEnvironment, + endLexicalEnvironment: endLexicalEnvironment, + onSubstituteNode: function (emitContext, node) { return node; }, + enableSubstitution: enableSubstitution, + isSubstitutionEnabled: isSubstitutionEnabled, + onEmitNode: function (node, emitContext, emitCallback) { return emitCallback(node, emitContext); }, + enableEmitNotification: enableEmitNotification, + isEmitNotificationEnabled: isEmitNotificationEnabled + }; + // Chain together and initialize each transformer. + var transformation = ts.chain.apply(void 0, transformers)(context); + // Transform each source file. + var transformed = ts.map(sourceFiles, transformSourceFile); + // Disable modification of the lexical environment. + lexicalEnvironmentDisabled = true; + return { + transformed: transformed, + emitNodeWithSubstitution: emitNodeWithSubstitution, + emitNodeWithNotification: emitNodeWithNotification + }; + /** + * Transforms a source file. + * + * @param sourceFile The source file to transform. + */ + function transformSourceFile(sourceFile) { + if (ts.isDeclarationFile(sourceFile)) { + return sourceFile; + } + return transformation(sourceFile); } - else { - return tryLoadModuleUsingRootDirs(moduleName, containingDirectory, loader, failedLookupLocations, supportedExtensions, state); + /** + * Enables expression substitutions in the pretty printer for the provided SyntaxKind. + */ + function enableSubstitution(kind) { + enabledSyntaxKindFeatures[kind] |= 1 /* Substitution */; } - } - function tryLoadModuleUsingRootDirs(moduleName, containingDirectory, loader, failedLookupLocations, supportedExtensions, state) { - if (!state.compilerOptions.rootDirs) { - return undefined; + /** + * Determines whether expression substitutions are enabled for the provided node. + */ + function isSubstitutionEnabled(node) { + return (enabledSyntaxKindFeatures[node.kind] & 1 /* Substitution */) !== 0 + && (ts.getEmitFlags(node) & 128 /* NoSubstitution */) === 0; } - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.rootDirs_option_is_set_using_it_to_resolve_relative_module_name_0, moduleName); + /** + * Emits a node with possible substitution. + * + * @param emitContext The current emit context. + * @param node The node to emit. + * @param emitCallback The callback used to emit the node or its substitute. + */ + function emitNodeWithSubstitution(emitContext, node, emitCallback) { + if (node) { + if (isSubstitutionEnabled(node)) { + var substitute = context.onSubstituteNode(emitContext, node); + if (substitute && substitute !== node) { + emitCallback(emitContext, substitute); + return; + } + } + emitCallback(emitContext, node); + } } - var candidate = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName)); - var matchedRootDir; - var matchedNormalizedPrefix; - for (var _i = 0, _a = state.compilerOptions.rootDirs; _i < _a.length; _i++) { - var rootDir = _a[_i]; - // rootDirs are expected to be absolute - // in case of tsconfig.json this will happen automatically - compiler will expand relative names - // using location of tsconfig.json as base location - var normalizedRoot = ts.normalizePath(rootDir); - if (!ts.endsWith(normalizedRoot, ts.directorySeparator)) { - normalizedRoot += ts.directorySeparator; + /** + * Enables before/after emit notifications in the pretty printer for the provided SyntaxKind. + */ + function enableEmitNotification(kind) { + enabledSyntaxKindFeatures[kind] |= 2 /* EmitNotifications */; + } + /** + * Determines whether before/after emit notifications should be raised in the pretty + * printer when it emits a node. + */ + function isEmitNotificationEnabled(node) { + return (enabledSyntaxKindFeatures[node.kind] & 2 /* EmitNotifications */) !== 0 + || (ts.getEmitFlags(node) & 64 /* AdviseOnEmitNode */) !== 0; + } + /** + * Emits a node with possible emit notification. + * + * @param emitContext The current emit context. + * @param node The node to emit. + * @param emitCallback The callback used to emit the node. + */ + function emitNodeWithNotification(emitContext, node, emitCallback) { + if (node) { + if (isEmitNotificationEnabled(node)) { + context.onEmitNode(emitContext, node, emitCallback); + } + else { + emitCallback(emitContext, node); + } } - var isLongestMatchingPrefix = ts.startsWith(candidate, normalizedRoot) && - (matchedNormalizedPrefix === undefined || matchedNormalizedPrefix.length < normalizedRoot.length); - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Checking_if_0_is_the_longest_matching_prefix_for_1_2, normalizedRoot, candidate, isLongestMatchingPrefix); + } + /** + * Records a hoisted variable declaration for the provided name within a lexical environment. + */ + function hoistVariableDeclaration(name) { + ts.Debug.assert(!lexicalEnvironmentDisabled, "Cannot modify the lexical environment during the print phase."); + var decl = ts.createVariableDeclaration(name); + if (!hoistedVariableDeclarations) { + hoistedVariableDeclarations = [decl]; } - if (isLongestMatchingPrefix) { - matchedNormalizedPrefix = normalizedRoot; - matchedRootDir = rootDir; + else { + hoistedVariableDeclarations.push(decl); } } - if (matchedNormalizedPrefix) { - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Longest_matching_prefix_for_0_is_1, candidate, matchedNormalizedPrefix); + /** + * Records a hoisted function declaration within a lexical environment. + */ + function hoistFunctionDeclaration(func) { + ts.Debug.assert(!lexicalEnvironmentDisabled, "Cannot modify the lexical environment during the print phase."); + if (!hoistedFunctionDeclarations) { + hoistedFunctionDeclarations = [func]; } - var suffix = candidate.substr(matchedNormalizedPrefix.length); - // first - try to load from a initial location - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Loading_0_from_the_root_dir_1_candidate_location_2, suffix, matchedNormalizedPrefix, candidate); + else { + hoistedFunctionDeclarations.push(func); } - var resolvedFileName = loader(candidate, supportedExtensions, failedLookupLocations, !directoryProbablyExists(containingDirectory, state.host), state); - if (resolvedFileName) { - return resolvedFileName; + } + /** + * Starts a new lexical environment. Any existing hoisted variable or function declarations + * are pushed onto a stack, and the related storage variables are reset. + */ + function startLexicalEnvironment() { + ts.Debug.assert(!lexicalEnvironmentDisabled, "Cannot start a lexical environment during the print phase."); + // Save the current lexical environment. Rather than resizing the array we adjust the + // stack size variable. This allows us to reuse existing array slots we've + // already allocated between transformations to avoid allocation and GC overhead during + // transformation. + lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset] = hoistedVariableDeclarations; + lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset] = hoistedFunctionDeclarations; + lexicalEnvironmentStackOffset++; + hoistedVariableDeclarations = undefined; + hoistedFunctionDeclarations = undefined; + } + /** + * Ends a lexical environment. The previous set of hoisted declarations are restored and + * any hoisted declarations added in this environment are returned. + */ + function endLexicalEnvironment() { + ts.Debug.assert(!lexicalEnvironmentDisabled, "Cannot end a lexical environment during the print phase."); + var statements; + if (hoistedVariableDeclarations || hoistedFunctionDeclarations) { + if (hoistedFunctionDeclarations) { + statements = hoistedFunctionDeclarations.slice(); + } + if (hoistedVariableDeclarations) { + var statement = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList(hoistedVariableDeclarations)); + if (!statements) { + statements = [statement]; + } + else { + statements.push(statement); + } + } } - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Trying_other_entries_in_rootDirs); + // Restore the previous lexical environment. + lexicalEnvironmentStackOffset--; + hoistedVariableDeclarations = lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset]; + hoistedFunctionDeclarations = lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset]; + return statements; + } + } + ts.transformFiles = transformFiles; + var _a; +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + // Used for initialize lastEncodedSourceMapSpan and reset lastEncodedSourceMapSpan when updateLastEncodedAndRecordedSpans + var defaultLastEncodedSourceMapSpan = { + emittedLine: 1, + emittedColumn: 1, + sourceLine: 1, + sourceColumn: 1, + sourceIndex: 0 + }; + function createSourceMapWriter(host, writer) { + var compilerOptions = host.getCompilerOptions(); + var extendedDiagnostics = compilerOptions.extendedDiagnostics; + var currentSourceFile; + var currentSourceText; + var sourceMapDir; // The directory in which sourcemap will be + // Current source map file and its index in the sources list + var sourceMapSourceIndex; + // Last recorded and encoded spans + var lastRecordedSourceMapSpan; + var lastEncodedSourceMapSpan; + var lastEncodedNameIndex; + // Source map data + var sourceMapData; + var disabled = !(compilerOptions.sourceMap || compilerOptions.inlineSourceMap); + return { + initialize: initialize, + reset: reset, + getSourceMapData: function () { return sourceMapData; }, + setSourceFile: setSourceFile, + emitPos: emitPos, + emitNodeWithSourceMap: emitNodeWithSourceMap, + emitTokenWithSourceMap: emitTokenWithSourceMap, + getText: getText, + getSourceMappingURL: getSourceMappingURL, + }; + /** + * Initialize the SourceMapWriter for a new output file. + * + * @param filePath The path to the generated output file. + * @param sourceMapFilePath The path to the output source map file. + * @param sourceFiles The input source files for the program. + * @param isBundledEmit A value indicating whether the generated output file is a bundle. + */ + function initialize(filePath, sourceMapFilePath, sourceFiles, isBundledEmit) { + if (disabled) { + return; + } + if (sourceMapData) { + reset(); + } + currentSourceFile = undefined; + currentSourceText = undefined; + // Current source map file and its index in the sources list + sourceMapSourceIndex = -1; + // Last recorded and encoded spans + lastRecordedSourceMapSpan = undefined; + lastEncodedSourceMapSpan = defaultLastEncodedSourceMapSpan; + lastEncodedNameIndex = 0; + // Initialize source map data + sourceMapData = { + sourceMapFilePath: sourceMapFilePath, + jsSourceMappingURL: !compilerOptions.inlineSourceMap ? ts.getBaseFileName(ts.normalizeSlashes(sourceMapFilePath)) : undefined, + sourceMapFile: ts.getBaseFileName(ts.normalizeSlashes(filePath)), + sourceMapSourceRoot: compilerOptions.sourceRoot || "", + sourceMapSources: [], + inputSourceFileNames: [], + sourceMapNames: [], + sourceMapMappings: "", + sourceMapSourcesContent: compilerOptions.inlineSources ? [] : undefined, + sourceMapDecodedMappings: [] + }; + // Normalize source root and make sure it has trailing "/" so that it can be used to combine paths with the + // relative paths of the sources list in the sourcemap + sourceMapData.sourceMapSourceRoot = ts.normalizeSlashes(sourceMapData.sourceMapSourceRoot); + if (sourceMapData.sourceMapSourceRoot.length && sourceMapData.sourceMapSourceRoot.charCodeAt(sourceMapData.sourceMapSourceRoot.length - 1) !== 47 /* slash */) { + sourceMapData.sourceMapSourceRoot += ts.directorySeparator; } - // then try to resolve using remaining entries in rootDirs - for (var _b = 0, _c = state.compilerOptions.rootDirs; _b < _c.length; _b++) { - var rootDir = _c[_b]; - if (rootDir === matchedRootDir) { - // skip the initially matched entry - continue; + if (compilerOptions.mapRoot) { + sourceMapDir = ts.normalizeSlashes(compilerOptions.mapRoot); + if (!isBundledEmit) { + ts.Debug.assert(sourceFiles.length === 1); + // For modules or multiple emit files the mapRoot will have directory structure like the sources + // So if src\a.ts and src\lib\b.ts are compiled together user would be moving the maps into mapRoot\a.js.map and mapRoot\lib\b.js.map + sourceMapDir = ts.getDirectoryPath(ts.getSourceFilePathInNewDir(sourceFiles[0], host, sourceMapDir)); } - var candidate_1 = ts.combinePaths(ts.normalizePath(rootDir), suffix); - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Loading_0_from_the_root_dir_1_candidate_location_2, suffix, rootDir, candidate_1); + if (!ts.isRootedDiskPath(sourceMapDir) && !ts.isUrl(sourceMapDir)) { + // The relative paths are relative to the common directory + sourceMapDir = ts.combinePaths(host.getCommonSourceDirectory(), sourceMapDir); + sourceMapData.jsSourceMappingURL = ts.getRelativePathToDirectoryOrUrl(ts.getDirectoryPath(ts.normalizePath(filePath)), // get the relative sourceMapDir path based on jsFilePath + ts.combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL), // this is where user expects to see sourceMap + host.getCurrentDirectory(), host.getCanonicalFileName, + /*isAbsolutePathAnUrl*/ true); } - var baseDirectory = ts.getDirectoryPath(candidate_1); - var resolvedFileName_1 = loader(candidate_1, supportedExtensions, failedLookupLocations, !directoryProbablyExists(baseDirectory, state.host), state); - if (resolvedFileName_1) { - return resolvedFileName_1; + else { + sourceMapData.jsSourceMappingURL = ts.combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL); } } - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Module_resolution_using_rootDirs_has_failed); + else { + sourceMapDir = ts.getDirectoryPath(ts.normalizePath(filePath)); } } - return undefined; - } - function tryLoadModuleUsingBaseUrl(moduleName, loader, failedLookupLocations, supportedExtensions, state) { - if (!state.compilerOptions.baseUrl) { - return undefined; - } - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.baseUrl_option_is_set_to_0_using_this_value_to_resolve_non_relative_module_name_1, state.compilerOptions.baseUrl, moduleName); - } - // string is for exact match - var matchedPattern = undefined; - if (state.compilerOptions.paths) { - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.paths_option_is_specified_looking_for_a_pattern_to_match_module_name_0, moduleName); + /** + * Reset the SourceMapWriter to an empty state. + */ + function reset() { + if (disabled) { + return; } - matchedPattern = matchPatternOrExact(ts.getOwnKeys(state.compilerOptions.paths), moduleName); + currentSourceFile = undefined; + sourceMapDir = undefined; + sourceMapSourceIndex = undefined; + lastRecordedSourceMapSpan = undefined; + lastEncodedSourceMapSpan = undefined; + lastEncodedNameIndex = undefined; + sourceMapData = undefined; } - if (matchedPattern) { - var matchedStar = typeof matchedPattern === "string" ? undefined : matchedText(matchedPattern, moduleName); - var matchedPatternText = typeof matchedPattern === "string" ? matchedPattern : patternText(matchedPattern); - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Module_name_0_matched_pattern_1, moduleName, matchedPatternText); + // Encoding for sourcemap span + function encodeLastRecordedSourceMapSpan() { + if (!lastRecordedSourceMapSpan || lastRecordedSourceMapSpan === lastEncodedSourceMapSpan) { + return; } - for (var _i = 0, _a = state.compilerOptions.paths[matchedPatternText]; _i < _a.length; _i++) { - var subst = _a[_i]; - var path = matchedStar ? subst.replace("*", matchedStar) : subst; - var candidate = ts.normalizePath(ts.combinePaths(state.compilerOptions.baseUrl, path)); - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Trying_substitution_0_candidate_module_location_Colon_1, subst, path); + var prevEncodedEmittedColumn = lastEncodedSourceMapSpan.emittedColumn; + // Line/Comma delimiters + if (lastEncodedSourceMapSpan.emittedLine === lastRecordedSourceMapSpan.emittedLine) { + // Emit comma to separate the entry + if (sourceMapData.sourceMapMappings) { + sourceMapData.sourceMapMappings += ","; } - var resolvedFileName = loader(candidate, supportedExtensions, failedLookupLocations, !directoryProbablyExists(ts.getDirectoryPath(candidate), state.host), state); - if (resolvedFileName) { - return resolvedFileName; + } + else { + // Emit line delimiters + for (var encodedLine = lastEncodedSourceMapSpan.emittedLine; encodedLine < lastRecordedSourceMapSpan.emittedLine; encodedLine++) { + sourceMapData.sourceMapMappings += ";"; } + prevEncodedEmittedColumn = 1; } - return undefined; - } - else { - var candidate = ts.normalizePath(ts.combinePaths(state.compilerOptions.baseUrl, moduleName)); - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Resolving_module_name_0_relative_to_base_url_1_2, moduleName, state.compilerOptions.baseUrl, candidate); + // 1. Relative Column 0 based + sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.emittedColumn - prevEncodedEmittedColumn); + // 2. Relative sourceIndex + sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceIndex - lastEncodedSourceMapSpan.sourceIndex); + // 3. Relative sourceLine 0 based + sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceLine - lastEncodedSourceMapSpan.sourceLine); + // 4. Relative sourceColumn 0 based + sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceColumn - lastEncodedSourceMapSpan.sourceColumn); + // 5. Relative namePosition 0 based + if (lastRecordedSourceMapSpan.nameIndex >= 0) { + ts.Debug.assert(false, "We do not support name index right now, Make sure to update updateLastEncodedAndRecordedSpans when we start using this"); + sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.nameIndex - lastEncodedNameIndex); + lastEncodedNameIndex = lastRecordedSourceMapSpan.nameIndex; } - return loader(candidate, supportedExtensions, failedLookupLocations, !directoryProbablyExists(ts.getDirectoryPath(candidate), state.host), state); + lastEncodedSourceMapSpan = lastRecordedSourceMapSpan; + sourceMapData.sourceMapDecodedMappings.push(lastEncodedSourceMapSpan); } - } - /** - * patternStrings contains both pattern strings (containing "*") and regular strings. - * Return an exact match if possible, or a pattern match, or undefined. - * (These are verified by verifyCompilerOptions to have 0 or 1 "*" characters.) - */ - function matchPatternOrExact(patternStrings, candidate) { - var patterns = []; - for (var _i = 0, patternStrings_1 = patternStrings; _i < patternStrings_1.length; _i++) { - var patternString = patternStrings_1[_i]; - var pattern = tryParsePattern(patternString); - if (pattern) { - patterns.push(pattern); - } - else if (patternString === candidate) { - // pattern was matched as is - no need to search further - return patternString; + /** + * Emits a mapping. + * + * If the position is synthetic (undefined or a negative value), no mapping will be + * created. + * + * @param pos The position. + */ + function emitPos(pos) { + if (disabled || ts.positionIsSynthesized(pos)) { + return; } - } - return findBestPatternMatch(patterns, function (_) { return _; }, candidate); - } - function patternText(_a) { - var prefix = _a.prefix, suffix = _a.suffix; - return prefix + "*" + suffix; - } - /** - * Given that candidate matches pattern, returns the text matching the '*'. - * E.g.: matchedText(tryParsePattern("foo*baz"), "foobarbaz") === "bar" - */ - function matchedText(pattern, candidate) { - ts.Debug.assert(isPatternMatch(pattern, candidate)); - return candidate.substr(pattern.prefix.length, candidate.length - pattern.suffix.length); - } - /** Return the object corresponding to the best pattern to match `candidate`. */ - /* @internal */ - function findBestPatternMatch(values, getPattern, candidate) { - var matchedValue = undefined; - // use length of prefix as betterness criteria - var longestMatchPrefixLength = -1; - for (var _i = 0, values_1 = values; _i < values_1.length; _i++) { - var v = values_1[_i]; - var pattern = getPattern(v); - if (isPatternMatch(pattern, candidate) && pattern.prefix.length > longestMatchPrefixLength) { - longestMatchPrefixLength = pattern.prefix.length; - matchedValue = v; + if (extendedDiagnostics) { + ts.performance.mark("beforeSourcemap"); } - } - return matchedValue; - } - ts.findBestPatternMatch = findBestPatternMatch; - function isPatternMatch(_a, candidate) { - var prefix = _a.prefix, suffix = _a.suffix; - return candidate.length >= prefix.length + suffix.length && - ts.startsWith(candidate, prefix) && - ts.endsWith(candidate, suffix); - } - /* @internal */ - function tryParsePattern(pattern) { - // This should be verified outside of here and a proper error thrown. - ts.Debug.assert(hasZeroOrOneAsteriskCharacter(pattern)); - var indexOfStar = pattern.indexOf("*"); - return indexOfStar === -1 ? undefined : { - prefix: pattern.substr(0, indexOfStar), - suffix: pattern.substr(indexOfStar + 1) - }; - } - ts.tryParsePattern = tryParsePattern; - function nodeModuleNameResolver(moduleName, containingFile, compilerOptions, host) { - var containingDirectory = ts.getDirectoryPath(containingFile); - var supportedExtensions = ts.getSupportedExtensions(compilerOptions); - var traceEnabled = isTraceEnabled(compilerOptions, host); - var failedLookupLocations = []; - var state = { compilerOptions: compilerOptions, host: host, traceEnabled: traceEnabled, skipTsx: false }; - var resolvedFileName = tryLoadModuleUsingOptionalResolutionSettings(moduleName, containingDirectory, nodeLoadModuleByRelativeName, failedLookupLocations, supportedExtensions, state); - var isExternalLibraryImport = false; - if (!resolvedFileName) { - if (moduleHasNonRelativeName(moduleName)) { - if (traceEnabled) { - trace(host, ts.Diagnostics.Loading_module_0_from_node_modules_folder, moduleName); - } - resolvedFileName = loadModuleFromNodeModules(moduleName, containingDirectory, failedLookupLocations, state); - isExternalLibraryImport = resolvedFileName !== undefined; + var sourceLinePos = ts.getLineAndCharacterOfPosition(currentSourceFile, pos); + // Convert the location to be one-based. + sourceLinePos.line++; + sourceLinePos.character++; + var emittedLine = writer.getLine(); + var emittedColumn = writer.getColumn(); + // If this location wasn't recorded or the location in source is going backwards, record the span + if (!lastRecordedSourceMapSpan || + lastRecordedSourceMapSpan.emittedLine !== emittedLine || + lastRecordedSourceMapSpan.emittedColumn !== emittedColumn || + (lastRecordedSourceMapSpan.sourceIndex === sourceMapSourceIndex && + (lastRecordedSourceMapSpan.sourceLine > sourceLinePos.line || + (lastRecordedSourceMapSpan.sourceLine === sourceLinePos.line && lastRecordedSourceMapSpan.sourceColumn > sourceLinePos.character)))) { + // Encode the last recordedSpan before assigning new + encodeLastRecordedSourceMapSpan(); + // New span + lastRecordedSourceMapSpan = { + emittedLine: emittedLine, + emittedColumn: emittedColumn, + sourceLine: sourceLinePos.line, + sourceColumn: sourceLinePos.character, + sourceIndex: sourceMapSourceIndex + }; } else { - var candidate = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName)); - resolvedFileName = nodeLoadModuleByRelativeName(candidate, supportedExtensions, failedLookupLocations, /*onlyRecordFailures*/ false, state); + // Take the new pos instead since there is no change in emittedLine and column since last location + lastRecordedSourceMapSpan.sourceLine = sourceLinePos.line; + lastRecordedSourceMapSpan.sourceColumn = sourceLinePos.character; + lastRecordedSourceMapSpan.sourceIndex = sourceMapSourceIndex; } - } - if (resolvedFileName && host.realpath) { - var originalFileName = resolvedFileName; - resolvedFileName = ts.normalizePath(host.realpath(resolvedFileName)); - if (traceEnabled) { - trace(host, ts.Diagnostics.Resolving_real_path_for_0_result_1, originalFileName, resolvedFileName); + if (extendedDiagnostics) { + ts.performance.mark("afterSourcemap"); + ts.performance.measure("Source Map", "beforeSourcemap", "afterSourcemap"); } } - return createResolvedModule(resolvedFileName, isExternalLibraryImport, failedLookupLocations); - } - ts.nodeModuleNameResolver = nodeModuleNameResolver; - function nodeLoadModuleByRelativeName(candidate, supportedExtensions, failedLookupLocations, onlyRecordFailures, state) { - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Loading_module_as_file_Slash_folder_candidate_module_location_0, candidate); - } - var resolvedFileName = loadModuleFromFile(candidate, supportedExtensions, failedLookupLocations, onlyRecordFailures, state); - return resolvedFileName || loadNodeModuleFromDirectory(supportedExtensions, candidate, failedLookupLocations, onlyRecordFailures, state); - } - /* @internal */ - function directoryProbablyExists(directoryName, host) { - // if host does not support 'directoryExists' assume that directory will exist - return !host.directoryExists || host.directoryExists(directoryName); - } - ts.directoryProbablyExists = directoryProbablyExists; - /** - * @param {boolean} onlyRecordFailures - if true then function won't try to actually load files but instead record all attempts as failures. This flag is necessary - * in cases when we know upfront that all load attempts will fail (because containing folder does not exists) however we still need to record all failed lookup locations. - */ - function loadModuleFromFile(candidate, extensions, failedLookupLocation, onlyRecordFailures, state) { - // First, try adding an extension. An import of "foo" could be matched by a file "foo.ts", or "foo.js" by "foo.js.ts" - var resolvedByAddingExtension = tryAddingExtensions(candidate, extensions, failedLookupLocation, onlyRecordFailures, state); - if (resolvedByAddingExtension) { - return resolvedByAddingExtension; - } - // If that didn't work, try stripping a ".js" or ".jsx" extension and replacing it with a TypeScript one; - // e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts" - if (ts.hasJavaScriptFileExtension(candidate)) { - var extensionless = ts.removeFileExtension(candidate); - if (state.traceEnabled) { - var extension = candidate.substring(extensionless.length); - trace(state.host, ts.Diagnostics.File_name_0_has_a_1_extension_stripping_it, candidate, extension); + /** + * Emits a node with possible leading and trailing source maps. + * + * @param node The node to emit. + * @param emitCallback The callback used to emit the node. + */ + function emitNodeWithSourceMap(emitContext, node, emitCallback) { + if (disabled) { + return emitCallback(emitContext, node); } - return tryAddingExtensions(extensionless, extensions, failedLookupLocation, onlyRecordFailures, state); - } - } - /** Try to return an existing file that adds one of the `extensions` to `candidate`. */ - function tryAddingExtensions(candidate, extensions, failedLookupLocation, onlyRecordFailures, state) { - if (!onlyRecordFailures) { - // check if containing folder exists - if it doesn't then just record failures for all supported extensions without disk probing - var directory = ts.getDirectoryPath(candidate); - if (directory) { - onlyRecordFailures = !directoryProbablyExists(directory, state.host); + if (node) { + var emitNode = node.emitNode; + var emitFlags = emitNode && emitNode.flags; + var _a = emitNode && emitNode.sourceMapRange || node, pos = _a.pos, end = _a.end; + if (node.kind !== 287 /* NotEmittedStatement */ + && (emitFlags & 512 /* NoLeadingSourceMap */) === 0 + && pos >= 0) { + emitPos(ts.skipTrivia(currentSourceText, pos)); + } + if (emitFlags & 2048 /* NoNestedSourceMaps */) { + disabled = true; + emitCallback(emitContext, node); + disabled = false; + } + else { + emitCallback(emitContext, node); + } + if (node.kind !== 287 /* NotEmittedStatement */ + && (emitFlags & 1024 /* NoTrailingSourceMap */) === 0 + && end >= 0) { + emitPos(end); + } } } - return ts.forEach(extensions, function (ext) { - return !(state.skipTsx && ts.isJsxOrTsxExtension(ext)) && tryFile(candidate + ext, failedLookupLocation, onlyRecordFailures, state); - }); - } - /** Return the file if it exists. */ - function tryFile(fileName, failedLookupLocation, onlyRecordFailures, state) { - if (!onlyRecordFailures && state.host.fileExists(fileName)) { - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.File_0_exist_use_it_as_a_name_resolution_result, fileName); + /** + * Emits a token of a node with possible leading and trailing source maps. + * + * @param node The node containing the token. + * @param token The token to emit. + * @param tokenStartPos The start pos of the token. + * @param emitCallback The callback used to emit the token. + */ + function emitTokenWithSourceMap(node, token, tokenPos, emitCallback) { + if (disabled) { + return emitCallback(token, tokenPos); } - return fileName; - } - else { - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.File_0_does_not_exist, fileName); + var emitNode = node && node.emitNode; + var emitFlags = emitNode && emitNode.flags; + var range = emitNode && emitNode.tokenSourceMapRanges && emitNode.tokenSourceMapRanges[token]; + tokenPos = ts.skipTrivia(currentSourceText, range ? range.pos : tokenPos); + if ((emitFlags & 4096 /* NoTokenLeadingSourceMaps */) === 0 && tokenPos >= 0) { + emitPos(tokenPos); } - failedLookupLocation.push(fileName); - return undefined; - } - } - function loadNodeModuleFromDirectory(extensions, candidate, failedLookupLocation, onlyRecordFailures, state) { - var packageJsonPath = pathToPackageJson(candidate); - var directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, state.host); - if (directoryExists && state.host.fileExists(packageJsonPath)) { - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Found_package_json_at_0, packageJsonPath); + tokenPos = emitCallback(token, tokenPos); + if (range) + tokenPos = range.end; + if ((emitFlags & 8192 /* NoTokenTrailingSourceMaps */) === 0 && tokenPos >= 0) { + emitPos(tokenPos); } - var typesFile = tryReadTypesSection(packageJsonPath, candidate, state); - if (typesFile) { - var onlyRecordFailures_1 = !directoryProbablyExists(ts.getDirectoryPath(typesFile), state.host); - // A package.json "typings" may specify an exact filename, or may choose to omit an extension. - var result = tryFile(typesFile, failedLookupLocation, onlyRecordFailures_1, state) || - tryAddingExtensions(typesFile, extensions, failedLookupLocation, onlyRecordFailures_1, state); - if (result) { - return result; - } + return tokenPos; + } + /** + * Set the current source file. + * + * @param sourceFile The source file. + */ + function setSourceFile(sourceFile) { + if (disabled) { + return; } - else { - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.package_json_does_not_have_types_field); + currentSourceFile = sourceFile; + currentSourceText = currentSourceFile.text; + // Add the file to tsFilePaths + // If sourceroot option: Use the relative path corresponding to the common directory path + // otherwise source locations relative to map file location + var sourcesDirectoryPath = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir; + var source = ts.getRelativePathToDirectoryOrUrl(sourcesDirectoryPath, currentSourceFile.fileName, host.getCurrentDirectory(), host.getCanonicalFileName, + /*isAbsolutePathAnUrl*/ true); + sourceMapSourceIndex = ts.indexOf(sourceMapData.sourceMapSources, source); + if (sourceMapSourceIndex === -1) { + sourceMapSourceIndex = sourceMapData.sourceMapSources.length; + sourceMapData.sourceMapSources.push(source); + // The one that can be used from program to get the actual source file + sourceMapData.inputSourceFileNames.push(currentSourceFile.fileName); + if (compilerOptions.inlineSources) { + sourceMapData.sourceMapSourcesContent.push(currentSourceFile.text); } } } - else { - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.File_0_does_not_exist, packageJsonPath); + /** + * Gets the text for the source map. + */ + function getText() { + if (disabled) { + return; } - // record package json as one of failed lookup locations - in the future if this file will appear it will invalidate resolution results - failedLookupLocation.push(packageJsonPath); - } - return loadModuleFromFile(ts.combinePaths(candidate, "index"), extensions, failedLookupLocation, !directoryExists, state); - } - function pathToPackageJson(directory) { - return ts.combinePaths(directory, "package.json"); - } - function loadModuleFromNodeModulesFolder(moduleName, directory, failedLookupLocations, state) { - var nodeModulesFolder = ts.combinePaths(directory, "node_modules"); - var nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, state.host); - var candidate = ts.normalizePath(ts.combinePaths(nodeModulesFolder, moduleName)); - var supportedExtensions = ts.getSupportedExtensions(state.compilerOptions); - var result = loadModuleFromFile(candidate, supportedExtensions, failedLookupLocations, !nodeModulesFolderExists, state); - if (result) { - return result; - } - result = loadNodeModuleFromDirectory(supportedExtensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state); - if (result) { - return result; + encodeLastRecordedSourceMapSpan(); + return ts.stringify({ + version: 3, + file: sourceMapData.sourceMapFile, + sourceRoot: sourceMapData.sourceMapSourceRoot, + sources: sourceMapData.sourceMapSources, + names: sourceMapData.sourceMapNames, + mappings: sourceMapData.sourceMapMappings, + sourcesContent: sourceMapData.sourceMapSourcesContent, + }); } - } - function loadModuleFromNodeModules(moduleName, directory, failedLookupLocations, state) { - directory = ts.normalizeSlashes(directory); - while (true) { - var baseName = ts.getBaseFileName(directory); - if (baseName !== "node_modules") { - // Try to load source from the package - var packageResult = loadModuleFromNodeModulesFolder(moduleName, directory, failedLookupLocations, state); - if (packageResult && ts.hasTypeScriptFileExtension(packageResult)) { - // Always prefer a TypeScript (.ts, .tsx, .d.ts) file shipped with the package - return packageResult; - } - else { - // Else prefer a types package over non-TypeScript results (e.g. JavaScript files) - var typesResult = loadModuleFromNodeModulesFolder(ts.combinePaths("@types", moduleName), directory, failedLookupLocations, state); - if (typesResult || packageResult) { - return typesResult || packageResult; - } - } + /** + * Gets the SourceMappingURL for the source map. + */ + function getSourceMappingURL() { + if (disabled) { + return; } - var parentPath = ts.getDirectoryPath(directory); - if (parentPath === directory) { - break; + if (compilerOptions.inlineSourceMap) { + // Encode the sourceMap into the sourceMap url + var base64SourceMapText = ts.convertToBase64(getText()); + return sourceMapData.jsSourceMappingURL = "data:application/json;base64," + base64SourceMapText; + } + else { + return sourceMapData.jsSourceMappingURL; } - directory = parentPath; } - return undefined; } - function classicNameResolver(moduleName, containingFile, compilerOptions, host) { - var traceEnabled = isTraceEnabled(compilerOptions, host); - var state = { compilerOptions: compilerOptions, host: host, traceEnabled: traceEnabled, skipTsx: !compilerOptions.jsx }; - var failedLookupLocations = []; - var supportedExtensions = ts.getSupportedExtensions(compilerOptions); - var containingDirectory = ts.getDirectoryPath(containingFile); - var resolvedFileName = tryLoadModuleUsingOptionalResolutionSettings(moduleName, containingDirectory, loadModuleFromFile, failedLookupLocations, supportedExtensions, state); - if (resolvedFileName) { - return createResolvedModule(resolvedFileName, /*isExternalLibraryImport*/ false, failedLookupLocations); + ts.createSourceMapWriter = createSourceMapWriter; + var base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + function base64FormatEncode(inValue) { + if (inValue < 64) { + return base64Chars.charAt(inValue); } - var referencedSourceFile; - if (moduleHasNonRelativeName(moduleName)) { - while (true) { - var searchName = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName)); - referencedSourceFile = loadModuleFromFile(searchName, supportedExtensions, failedLookupLocations, /*onlyRecordFailures*/ false, state); - if (referencedSourceFile) { - break; - } - var parentPath = ts.getDirectoryPath(containingDirectory); - if (parentPath === containingDirectory) { - break; - } - containingDirectory = parentPath; - } + throw TypeError(inValue + ": not a 64 based value"); + } + function base64VLQFormatEncode(inValue) { + // Add a new least significant bit that has the sign of the value. + // if negative number the least significant bit that gets added to the number has value 1 + // else least significant bit value that gets added is 0 + // eg. -1 changes to binary : 01 [1] => 3 + // +1 changes to binary : 01 [0] => 2 + if (inValue < 0) { + inValue = ((-inValue) << 1) + 1; } else { - var candidate = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName)); - referencedSourceFile = loadModuleFromFile(candidate, supportedExtensions, failedLookupLocations, /*onlyRecordFailures*/ false, state); + inValue = inValue << 1; } - return referencedSourceFile - ? { resolvedModule: { resolvedFileName: referencedSourceFile }, failedLookupLocations: failedLookupLocations } - : { resolvedModule: undefined, failedLookupLocations: failedLookupLocations }; + // Encode 5 bits at a time starting from least significant bits + var encodedStr = ""; + do { + var currentDigit = inValue & 31; // 11111 + inValue = inValue >> 5; + if (inValue > 0) { + // There are still more digits to decode, set the msb (6th bit) + currentDigit = currentDigit | 32; + } + encodedStr = encodedStr + base64FormatEncode(currentDigit); + } while (inValue > 0); + return encodedStr; } - ts.classicNameResolver = classicNameResolver; - function createCompilerHost(options, setParentNodes) { - var existingDirectories = ts.createMap(); - function getCanonicalFileName(fileName) { - // if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form. - // otherwise use toLowerCase as a canonical form. - return ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); - } - // returned by CScript sys environment - var unsupportedFileEncodingErrorCode = -2147024809; - function getSourceFile(fileName, languageVersion, onError) { - var text; - try { - ts.performance.mark("beforeIORead"); - text = ts.sys.readFile(fileName, options.charset); - ts.performance.mark("afterIORead"); - ts.performance.measure("I/O Read", "beforeIORead", "afterIORead"); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + function createCommentWriter(host, writer, sourceMap) { + var compilerOptions = host.getCompilerOptions(); + var extendedDiagnostics = compilerOptions.extendedDiagnostics; + var newLine = host.getNewLine(); + var emitPos = sourceMap.emitPos; + var containerPos = -1; + var containerEnd = -1; + var declarationListContainerEnd = -1; + var currentSourceFile; + var currentText; + var currentLineMap; + var detachedCommentsInfo; + var hasWrittenComment = false; + var disabled = compilerOptions.removeComments; + return { + reset: reset, + setSourceFile: setSourceFile, + emitNodeWithComments: emitNodeWithComments, + emitBodyWithDetachedComments: emitBodyWithDetachedComments, + emitTrailingCommentsOfPosition: emitTrailingCommentsOfPosition, + }; + function emitNodeWithComments(emitContext, node, emitCallback) { + if (disabled) { + emitCallback(emitContext, node); + return; } - catch (e) { - if (onError) { - onError(e.number === unsupportedFileEncodingErrorCode - ? ts.createCompilerDiagnostic(ts.Diagnostics.Unsupported_file_encoding).messageText - : e.message); + if (node) { + var _a = ts.getCommentRange(node), pos = _a.pos, end = _a.end; + var emitFlags = ts.getEmitFlags(node); + if ((pos < 0 && end < 0) || (pos === end)) { + // Both pos and end are synthesized, so just emit the node without comments. + if (emitFlags & 65536 /* NoNestedComments */) { + disabled = true; + emitCallback(emitContext, node); + disabled = false; + } + else { + emitCallback(emitContext, node); + } + } + else { + if (extendedDiagnostics) { + ts.performance.mark("preEmitNodeWithComment"); + } + var isEmittedNode = node.kind !== 287 /* NotEmittedStatement */; + var skipLeadingComments = pos < 0 || (emitFlags & 16384 /* NoLeadingComments */) !== 0; + var skipTrailingComments = end < 0 || (emitFlags & 32768 /* NoTrailingComments */) !== 0; + // Emit leading comments if the position is not synthesized and the node + // has not opted out from emitting leading comments. + if (!skipLeadingComments) { + emitLeadingComments(pos, isEmittedNode); + } + // Save current container state on the stack. + var savedContainerPos = containerPos; + var savedContainerEnd = containerEnd; + var savedDeclarationListContainerEnd = declarationListContainerEnd; + if (!skipLeadingComments) { + containerPos = pos; + } + if (!skipTrailingComments) { + containerEnd = end; + // To avoid invalid comment emit in a down-level binding pattern, we + // keep track of the last declaration list container's end + if (node.kind === 219 /* VariableDeclarationList */) { + declarationListContainerEnd = end; + } + } + if (extendedDiagnostics) { + ts.performance.measure("commentTime", "preEmitNodeWithComment"); + } + if (emitFlags & 65536 /* NoNestedComments */) { + disabled = true; + emitCallback(emitContext, node); + disabled = false; + } + else { + emitCallback(emitContext, node); + } + if (extendedDiagnostics) { + ts.performance.mark("beginEmitNodeWithComment"); + } + // Restore previous container state. + containerPos = savedContainerPos; + containerEnd = savedContainerEnd; + declarationListContainerEnd = savedDeclarationListContainerEnd; + // Emit trailing comments if the position is not synthesized and the node + // has not opted out from emitting leading comments and is an emitted node. + if (!skipTrailingComments && isEmittedNode) { + emitTrailingComments(end); + } + if (extendedDiagnostics) { + ts.performance.measure("commentTime", "beginEmitNodeWithComment"); + } } - text = ""; } - return text !== undefined ? ts.createSourceFile(fileName, text, languageVersion, setParentNodes) : undefined; } - function directoryExists(directoryPath) { - if (directoryPath in existingDirectories) { - return true; + function emitBodyWithDetachedComments(node, detachedRange, emitCallback) { + if (extendedDiagnostics) { + ts.performance.mark("preEmitBodyWithDetachedComments"); } - if (ts.sys.directoryExists(directoryPath)) { - existingDirectories[directoryPath] = true; - return true; + var pos = detachedRange.pos, end = detachedRange.end; + var emitFlags = ts.getEmitFlags(node); + var skipLeadingComments = pos < 0 || (emitFlags & 16384 /* NoLeadingComments */) !== 0; + var skipTrailingComments = disabled || end < 0 || (emitFlags & 32768 /* NoTrailingComments */) !== 0; + if (!skipLeadingComments) { + emitDetachedCommentsAndUpdateCommentsInfo(detachedRange); } - return false; - } - function ensureDirectoriesExist(directoryPath) { - if (directoryPath.length > ts.getRootLength(directoryPath) && !directoryExists(directoryPath)) { - var parentDirectory = ts.getDirectoryPath(directoryPath); - ensureDirectoriesExist(parentDirectory); - ts.sys.createDirectory(directoryPath); + if (extendedDiagnostics) { + ts.performance.measure("commentTime", "preEmitBodyWithDetachedComments"); } - } - var outputFingerprints; - function writeFileIfUpdated(fileName, data, writeByteOrderMark) { - if (!outputFingerprints) { - outputFingerprints = ts.createMap(); + if (emitFlags & 65536 /* NoNestedComments */ && !disabled) { + disabled = true; + emitCallback(node); + disabled = false; } - var hash = ts.sys.createHash(data); - var mtimeBefore = ts.sys.getModifiedTime(fileName); - if (mtimeBefore && fileName in outputFingerprints) { - var fingerprint = outputFingerprints[fileName]; - // If output has not been changed, and the file has no external modification - if (fingerprint.byteOrderMark === writeByteOrderMark && - fingerprint.hash === hash && - fingerprint.mtime.getTime() === mtimeBefore.getTime()) { - return; - } + else { + emitCallback(node); } - ts.sys.writeFile(fileName, data, writeByteOrderMark); - var mtimeAfter = ts.sys.getModifiedTime(fileName); - outputFingerprints[fileName] = { - hash: hash, - byteOrderMark: writeByteOrderMark, - mtime: mtimeAfter - }; - } - function writeFile(fileName, data, writeByteOrderMark, onError) { - try { - ts.performance.mark("beforeIOWrite"); - ensureDirectoriesExist(ts.getDirectoryPath(ts.normalizePath(fileName))); - if (ts.isWatchSet(options) && ts.sys.createHash && ts.sys.getModifiedTime) { - writeFileIfUpdated(fileName, data, writeByteOrderMark); - } - else { - ts.sys.writeFile(fileName, data, writeByteOrderMark); - } - ts.performance.mark("afterIOWrite"); - ts.performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite"); + if (extendedDiagnostics) { + ts.performance.mark("beginEmitBodyWithDetachedCommetns"); } - catch (e) { - if (onError) { - onError(e.message); - } + if (!skipTrailingComments) { + emitLeadingComments(detachedRange.end, /*isEmittedNode*/ true); + } + if (extendedDiagnostics) { + ts.performance.measure("commentTime", "beginEmitBodyWithDetachedCommetns"); } } - function getDefaultLibLocation() { - return ts.getDirectoryPath(ts.normalizePath(ts.sys.getExecutingFilePath())); + function emitLeadingComments(pos, isEmittedNode) { + hasWrittenComment = false; + if (isEmittedNode) { + forEachLeadingCommentToEmit(pos, emitLeadingComment); + } + else if (pos === 0) { + // If the node will not be emitted in JS, remove all the comments(normal, pinned and ///) associated with the node, + // unless it is a triple slash comment at the top of the file. + // For Example: + // /// + // declare var x; + // /// + // interface F {} + // The first /// will NOT be removed while the second one will be removed even though both node will not be emitted + forEachLeadingCommentToEmit(pos, emitTripleSlashLeadingComment); + } } - var newLine = ts.getNewLineCharacter(options); - var realpath = ts.sys.realpath && (function (path) { return ts.sys.realpath(path); }); - return { - getSourceFile: getSourceFile, - getDefaultLibLocation: getDefaultLibLocation, - getDefaultLibFileName: function (options) { return ts.combinePaths(getDefaultLibLocation(), ts.getDefaultLibFileName(options)); }, - writeFile: writeFile, - getCurrentDirectory: ts.memoize(function () { return ts.sys.getCurrentDirectory(); }), - useCaseSensitiveFileNames: function () { return ts.sys.useCaseSensitiveFileNames; }, - getCanonicalFileName: getCanonicalFileName, - getNewLine: function () { return newLine; }, - fileExists: function (fileName) { return ts.sys.fileExists(fileName); }, - readFile: function (fileName) { return ts.sys.readFile(fileName); }, - trace: function (s) { return ts.sys.write(s + newLine); }, - directoryExists: function (directoryName) { return ts.sys.directoryExists(directoryName); }, - getDirectories: function (path) { return ts.sys.getDirectories(path); }, - realpath: realpath - }; - } - ts.createCompilerHost = createCompilerHost; - function getPreEmitDiagnostics(program, sourceFile, cancellationToken) { - var diagnostics = program.getOptionsDiagnostics(cancellationToken).concat(program.getSyntacticDiagnostics(sourceFile, cancellationToken), program.getGlobalDiagnostics(cancellationToken), program.getSemanticDiagnostics(sourceFile, cancellationToken)); - if (program.getCompilerOptions().declaration) { - diagnostics = diagnostics.concat(program.getDeclarationDiagnostics(sourceFile, cancellationToken)); + function emitTripleSlashLeadingComment(commentPos, commentEnd, kind, hasTrailingNewLine, rangePos) { + if (isTripleSlashComment(commentPos, commentEnd)) { + emitLeadingComment(commentPos, commentEnd, kind, hasTrailingNewLine, rangePos); + } } - return ts.sortAndDeduplicateDiagnostics(diagnostics); - } - ts.getPreEmitDiagnostics = getPreEmitDiagnostics; - function formatDiagnostics(diagnostics, host) { - var output = ""; - for (var _i = 0, diagnostics_2 = diagnostics; _i < diagnostics_2.length; _i++) { - var diagnostic = diagnostics_2[_i]; - if (diagnostic.file) { - var _a = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start), line = _a.line, character = _a.character; - var fileName = diagnostic.file.fileName; - var relativeFileName = ts.convertToRelativePath(fileName, host.getCurrentDirectory(), function (fileName) { return host.getCanonicalFileName(fileName); }); - output += relativeFileName + "(" + (line + 1) + "," + (character + 1) + "): "; + function emitLeadingComment(commentPos, commentEnd, kind, hasTrailingNewLine, rangePos) { + if (!hasWrittenComment) { + ts.emitNewLineBeforeLeadingCommentOfPosition(currentLineMap, writer, rangePos, commentPos); + hasWrittenComment = true; + } + // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space + emitPos(commentPos); + ts.writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine); + emitPos(commentEnd); + if (hasTrailingNewLine) { + writer.writeLine(); + } + else { + writer.write(" "); } - var category = ts.DiagnosticCategory[diagnostic.category].toLowerCase(); - output += category + " TS" + diagnostic.code + ": " + flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine()) + host.getNewLine(); } - return output; - } - ts.formatDiagnostics = formatDiagnostics; - function flattenDiagnosticMessageText(messageText, newLine) { - if (typeof messageText === "string") { - return messageText; + function emitTrailingComments(pos) { + forEachTrailingCommentToEmit(pos, emitTrailingComment); } - else { - var diagnosticChain = messageText; - var result = ""; - var indent = 0; - while (diagnosticChain) { - if (indent) { - result += newLine; - for (var i = 0; i < indent; i++) { - result += " "; - } - } - result += diagnosticChain.messageText; - indent++; - diagnosticChain = diagnosticChain.next; + function emitTrailingComment(commentPos, commentEnd, kind, hasTrailingNewLine) { + // trailing comments are emitted at space/*trailing comment1 */space/*trailing comment2*/ + if (!writer.isAtStartOfLine()) { + writer.write(" "); + } + emitPos(commentPos); + ts.writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine); + emitPos(commentEnd); + if (hasTrailingNewLine) { + writer.writeLine(); } - return result; - } - } - ts.flattenDiagnosticMessageText = flattenDiagnosticMessageText; - function loadWithLocalCache(names, containingFile, loader) { - if (names.length === 0) { - return []; } - var resolutions = []; - var cache = ts.createMap(); - for (var _i = 0, names_1 = names; _i < names_1.length; _i++) { - var name_36 = names_1[_i]; - var result = name_36 in cache - ? cache[name_36] - : cache[name_36] = loader(name_36, containingFile); - resolutions.push(result); + function emitTrailingCommentsOfPosition(pos) { + if (disabled) { + return; + } + if (extendedDiagnostics) { + ts.performance.mark("beforeEmitTrailingCommentsOfPosition"); + } + forEachTrailingCommentToEmit(pos, emitTrailingCommentOfPosition); + if (extendedDiagnostics) { + ts.performance.measure("commentTime", "beforeEmitTrailingCommentsOfPosition"); + } } - return resolutions; - } - /** - * Given a set of options, returns the set of type directive names - * that should be included for this program automatically. - * This list could either come from the config file, - * or from enumerating the types root + initial secondary types lookup location. - * More type directives might appear in the program later as a result of loading actual source files; - * this list is only the set of defaults that are implicitly included. - */ - function getAutomaticTypeDirectiveNames(options, host) { - // Use explicit type list from tsconfig.json - if (options.types) { - return options.types; + function emitTrailingCommentOfPosition(commentPos, commentEnd, kind, hasTrailingNewLine) { + // trailing comments of a position are emitted at /*trailing comment1 */space/*trailing comment*/space + emitPos(commentPos); + ts.writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine); + emitPos(commentEnd); + if (hasTrailingNewLine) { + writer.writeLine(); + } + else { + writer.write(" "); + } } - // Walk the primary type lookup locations - var result = []; - if (host.directoryExists && host.getDirectories) { - var typeRoots = getEffectiveTypeRoots(options, host); - if (typeRoots) { - for (var _i = 0, typeRoots_1 = typeRoots; _i < typeRoots_1.length; _i++) { - var root = typeRoots_1[_i]; - if (host.directoryExists(root)) { - for (var _a = 0, _b = host.getDirectories(root); _a < _b.length; _a++) { - var typeDirectivePath = _b[_a]; - var normalized = ts.normalizePath(typeDirectivePath); - var packageJsonPath = pathToPackageJson(ts.combinePaths(root, normalized)); - // tslint:disable-next-line:no-null-keyword - var isNotNeededPackage = host.fileExists(packageJsonPath) && readJson(packageJsonPath, host).typings === null; - if (!isNotNeededPackage) { - // Return just the type directive names - result.push(ts.getBaseFileName(normalized)); - } - } - } + function forEachLeadingCommentToEmit(pos, cb) { + // Emit the leading comments only if the container's pos doesn't match because the container should take care of emitting these comments + if (containerPos === -1 || pos !== containerPos) { + if (hasDetachedComments(pos)) { + forEachLeadingCommentWithoutDetachedComments(cb); + } + else { + ts.forEachLeadingCommentRange(currentText, pos, cb, /*state*/ pos); } } } - return result; - } - ts.getAutomaticTypeDirectiveNames = getAutomaticTypeDirectiveNames; - function createProgram(rootNames, options, host, oldProgram) { - var program; - var files = []; - var commonSourceDirectory; - var diagnosticsProducingTypeChecker; - var noDiagnosticsTypeChecker; - var classifiableNames; - var resolvedTypeReferenceDirectives = ts.createMap(); - var fileProcessingDiagnostics = ts.createDiagnosticCollection(); - // The below settings are to track if a .js file should be add to the program if loaded via searching under node_modules. - // This works as imported modules are discovered recursively in a depth first manner, specifically: - // - For each root file, findSourceFile is called. - // - This calls processImportedModules for each module imported in the source file. - // - This calls resolveModuleNames, and then calls findSourceFile for each resolved module. - // As all these operations happen - and are nested - within the createProgram call, they close over the below variables. - // The current resolution depth is tracked by incrementing/decrementing as the depth first search progresses. - var maxNodeModulesJsDepth = typeof options.maxNodeModuleJsDepth === "number" ? options.maxNodeModuleJsDepth : 0; - var currentNodeModulesDepth = 0; - // If a module has some of its imports skipped due to being at the depth limit under node_modules, then track - // this, as it may be imported at a shallower depth later, and then it will need its skipped imports processed. - var modulesWithElidedImports = ts.createMap(); - // Track source files that are source files found by searching under node_modules, as these shouldn't be compiled. - var sourceFilesFoundSearchingNodeModules = ts.createMap(); - ts.performance.mark("beforeProgram"); - host = host || createCompilerHost(options); - var skipDefaultLib = options.noLib; - var programDiagnostics = ts.createDiagnosticCollection(); - var currentDirectory = host.getCurrentDirectory(); - var supportedExtensions = ts.getSupportedExtensions(options); - // Map storing if there is emit blocking diagnostics for given input - var hasEmitBlockingDiagnostics = ts.createFileMap(getCanonicalFileName); - var resolveModuleNamesWorker; - if (host.resolveModuleNames) { - resolveModuleNamesWorker = function (moduleNames, containingFile) { return host.resolveModuleNames(moduleNames, containingFile); }; + function forEachTrailingCommentToEmit(end, cb) { + // Emit the trailing comments only if the container's end doesn't match because the container should take care of emitting these comments + if (containerEnd === -1 || (end !== containerEnd && end !== declarationListContainerEnd)) { + ts.forEachTrailingCommentRange(currentText, end, cb); + } } - else { - var loader_1 = function (moduleName, containingFile) { return resolveModuleName(moduleName, containingFile, options, host).resolvedModule; }; - resolveModuleNamesWorker = function (moduleNames, containingFile) { return loadWithLocalCache(moduleNames, containingFile, loader_1); }; + function reset() { + currentSourceFile = undefined; + currentText = undefined; + currentLineMap = undefined; + detachedCommentsInfo = undefined; } - var resolveTypeReferenceDirectiveNamesWorker; - if (host.resolveTypeReferenceDirectives) { - resolveTypeReferenceDirectiveNamesWorker = function (typeDirectiveNames, containingFile) { return host.resolveTypeReferenceDirectives(typeDirectiveNames, containingFile); }; + function setSourceFile(sourceFile) { + currentSourceFile = sourceFile; + currentText = currentSourceFile.text; + currentLineMap = ts.getLineStarts(currentSourceFile); + detachedCommentsInfo = undefined; } - else { - var loader_2 = function (typesRef, containingFile) { return resolveTypeReferenceDirective(typesRef, containingFile, options, host).resolvedTypeReferenceDirective; }; - resolveTypeReferenceDirectiveNamesWorker = function (typeReferenceDirectiveNames, containingFile) { return loadWithLocalCache(typeReferenceDirectiveNames, containingFile, loader_2); }; + function hasDetachedComments(pos) { + return detachedCommentsInfo !== undefined && ts.lastOrUndefined(detachedCommentsInfo).nodePos === pos; } - var filesByName = ts.createFileMap(); - // stores 'filename -> file association' ignoring case - // used to track cases when two file names differ only in casing - var filesByNameIgnoreCase = host.useCaseSensitiveFileNames() ? ts.createFileMap(function (fileName) { return fileName.toLowerCase(); }) : undefined; - if (!tryReuseStructureFromOldProgram()) { - ts.forEach(rootNames, function (name) { return processRootFile(name, /*isDefaultLib*/ false); }); - // load type declarations specified via 'types' argument or implicitly from types/ and node_modules/@types folders - var typeReferences = getAutomaticTypeDirectiveNames(options, host); - if (typeReferences) { - // This containingFilename needs to match with the one used in managed-side - var containingFilename = ts.combinePaths(host.getCurrentDirectory(), "__inferred type names__.ts"); - var resolutions = resolveTypeReferenceDirectiveNamesWorker(typeReferences, containingFilename); - for (var i = 0; i < typeReferences.length; i++) { - processTypeReferenceDirective(typeReferences[i], resolutions[i]); - } + function forEachLeadingCommentWithoutDetachedComments(cb) { + // get the leading comments from detachedPos + var pos = ts.lastOrUndefined(detachedCommentsInfo).detachedCommentEndPos; + if (detachedCommentsInfo.length - 1) { + detachedCommentsInfo.pop(); } - // Do not process the default library if: - // - The '--noLib' flag is used. - // - A 'no-default-lib' reference comment is encountered in - // processing the root files. - if (!skipDefaultLib) { - // If '--lib' is not specified, include default library file according to '--target' - // otherwise, using options specified in '--lib' instead of '--target' default library file - if (!options.lib) { - processRootFile(host.getDefaultLibFileName(options), /*isDefaultLib*/ true); - } - else { - var libDirectory_1 = host.getDefaultLibLocation ? host.getDefaultLibLocation() : ts.getDirectoryPath(host.getDefaultLibFileName(options)); - ts.forEach(options.lib, function (libFileName) { - processRootFile(ts.combinePaths(libDirectory_1, libFileName), /*isDefaultLib*/ true); - }); - } + else { + detachedCommentsInfo = undefined; } + ts.forEachLeadingCommentRange(currentText, pos, cb, /*state*/ pos); } - // unconditionally set oldProgram to undefined to prevent it from being captured in closure - oldProgram = undefined; - program = { - getRootFileNames: function () { return rootNames; }, - getSourceFile: getSourceFile, - getSourceFileByPath: getSourceFileByPath, - getSourceFiles: function () { return files; }, - getCompilerOptions: function () { return options; }, - getSyntacticDiagnostics: getSyntacticDiagnostics, - getOptionsDiagnostics: getOptionsDiagnostics, - getGlobalDiagnostics: getGlobalDiagnostics, - getSemanticDiagnostics: getSemanticDiagnostics, - getDeclarationDiagnostics: getDeclarationDiagnostics, - getTypeChecker: getTypeChecker, - getClassifiableNames: getClassifiableNames, - getDiagnosticsProducingTypeChecker: getDiagnosticsProducingTypeChecker, - getCommonSourceDirectory: getCommonSourceDirectory, - emit: emit, - getCurrentDirectory: function () { return currentDirectory; }, - getNodeCount: function () { return getDiagnosticsProducingTypeChecker().getNodeCount(); }, - getIdentifierCount: function () { return getDiagnosticsProducingTypeChecker().getIdentifierCount(); }, - getSymbolCount: function () { return getDiagnosticsProducingTypeChecker().getSymbolCount(); }, - getTypeCount: function () { return getDiagnosticsProducingTypeChecker().getTypeCount(); }, - getFileProcessingDiagnostics: function () { return fileProcessingDiagnostics; }, - getResolvedTypeReferenceDirectives: function () { return resolvedTypeReferenceDirectives; } - }; - verifyCompilerOptions(); - ts.performance.mark("afterProgram"); - ts.performance.measure("Program", "beforeProgram", "afterProgram"); - return program; - function getCommonSourceDirectory() { - if (typeof commonSourceDirectory === "undefined") { - if (options.rootDir && checkSourceFilesBelongToPath(files, options.rootDir)) { - // If a rootDir is specified and is valid use it as the commonSourceDirectory - commonSourceDirectory = ts.getNormalizedAbsolutePath(options.rootDir, currentDirectory); + function emitDetachedCommentsAndUpdateCommentsInfo(range) { + var currentDetachedCommentInfo = ts.emitDetachedComments(currentText, currentLineMap, writer, writeComment, range, newLine, disabled); + if (currentDetachedCommentInfo) { + if (detachedCommentsInfo) { + detachedCommentsInfo.push(currentDetachedCommentInfo); } else { - commonSourceDirectory = computeCommonSourceDirectory(files); - } - if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== ts.directorySeparator) { - // Make sure directory path ends with directory separator so this string can directly - // used to replace with "" to get the relative path of the source file and the relative path doesn't - // start with / making it rooted path - commonSourceDirectory += ts.directorySeparator; + detachedCommentsInfo = [currentDetachedCommentInfo]; } } - return commonSourceDirectory; } - function getClassifiableNames() { - if (!classifiableNames) { - // Initialize a checker so that all our files are bound. - getTypeChecker(); - classifiableNames = ts.createMap(); - for (var _i = 0, files_2 = files; _i < files_2.length; _i++) { - var sourceFile = files_2[_i]; - ts.copyProperties(sourceFile.classifiableNames, classifiableNames); - } - } - return classifiableNames; + function writeComment(text, lineMap, writer, commentPos, commentEnd, newLine) { + emitPos(commentPos); + ts.writeCommentRange(text, lineMap, writer, commentPos, commentEnd, newLine); + emitPos(commentEnd); } - function tryReuseStructureFromOldProgram() { - if (!oldProgram) { - return false; + /** + * Determine if the given comment is a triple-slash + * + * @return true if the comment is a triple-slash comment else false + **/ + function isTripleSlashComment(commentPos, commentEnd) { + // Verify this is /// comment, but do the regexp match only when we first can find /// in the comment text + // so that we don't end up computing comment string and doing match for all // comments + if (currentText.charCodeAt(commentPos + 1) === 47 /* slash */ && + commentPos + 2 < commentEnd && + currentText.charCodeAt(commentPos + 2) === 47 /* slash */) { + var textSubStr = currentText.substring(commentPos, commentEnd); + return textSubStr.match(ts.fullTripleSlashReferencePathRegEx) || + textSubStr.match(ts.fullTripleSlashAMDReferencePathRegEx) ? + true : false; } - // check properties that can affect structure of the program or module resolution strategy - // if any of these properties has changed - structure cannot be reused - var oldOptions = oldProgram.getCompilerOptions(); - if ((oldOptions.module !== options.module) || - (oldOptions.moduleResolution !== options.moduleResolution) || - (oldOptions.noResolve !== options.noResolve) || - (oldOptions.target !== options.target) || - (oldOptions.noLib !== options.noLib) || - (oldOptions.jsx !== options.jsx) || - (oldOptions.allowJs !== options.allowJs) || - (oldOptions.rootDir !== options.rootDir) || - (oldOptions.configFilePath !== options.configFilePath) || - (oldOptions.baseUrl !== options.baseUrl) || - (oldOptions.maxNodeModuleJsDepth !== options.maxNodeModuleJsDepth) || - !ts.arrayIsEqualTo(oldOptions.typeRoots, oldOptions.typeRoots) || - !ts.arrayIsEqualTo(oldOptions.rootDirs, options.rootDirs) || - !ts.equalOwnProperties(oldOptions.paths, options.paths)) { - return false; + return false; + } + } + ts.createCommentWriter = createCommentWriter; +})(ts || (ts = {})); +/// +/// +/// +/// +/// +/* @internal */ +var ts; +(function (ts) { + // Flags enum to track count of temp variables and a few dedicated names + var TempFlags; + (function (TempFlags) { + TempFlags[TempFlags["Auto"] = 0] = "Auto"; + TempFlags[TempFlags["CountMask"] = 268435455] = "CountMask"; + TempFlags[TempFlags["_i"] = 268435456] = "_i"; + })(TempFlags || (TempFlags = {})); + var id = function (s) { return s; }; + var nullTransformers = [function (ctx) { return id; }]; + // targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature + function emitFiles(resolver, host, targetSourceFile, emitOnlyDtsFiles) { + var delimiters = createDelimiterMap(); + var brackets = createBracketsMap(); + // emit output for the __extends helper function + var extendsHelper = "\nvar __extends = (this && this.__extends) || function (d, b) {\n for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n};"; + // Emit output for the __assign helper function. + // This is typically used for JSX spread attributes, + // and can be used for object literal spread properties. + var assignHelper = "\nvar __assign = (this && this.__assign) || Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n};"; + // emit output for the __decorate helper function + var decorateHelper = "\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};"; + // emit output for the __metadata helper function + var metadataHelper = "\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};"; + // emit output for the __param helper function + var paramHelper = "\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};"; + // emit output for the __awaiter helper function + var awaiterHelper = "\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments)).next());\n });\n};"; + // The __generator helper is used by down-level transformations to emulate the runtime + // semantics of an ES2015 generator function. When called, this helper returns an + // object that implements the Iterator protocol, in that it has `next`, `return`, and + // `throw` methods that step through the generator when invoked. + // + // parameters: + // thisArg The value to use as the `this` binding for the transformed generator body. + // body A function that acts as the transformed generator body. + // + // variables: + // _ Persistent state for the generator that is shared between the helper and the + // generator body. The state object has the following members: + // sent() - A method that returns or throws the current completion value. + // label - The next point at which to resume evaluation of the generator body. + // trys - A stack of protected regions (try/catch/finally blocks). + // ops - A stack of pending instructions when inside of a finally block. + // f A value indicating whether the generator is executing. + // y An iterator to delegate for a yield*. + // t A temporary variable that holds one of the following values (note that these + // cases do not overlap): + // - The completion value when resuming from a `yield` or `yield*`. + // - The error value for a catch block. + // - The current protected region (array of try/catch/finally/end labels). + // - The verb (`next`, `throw`, or `return` method) to delegate to the expression + // of a `yield*`. + // - The result of evaluating the verb delegated to the expression of a `yield*`. + // + // functions: + // verb(n) Creates a bound callback to the `step` function for opcode `n`. + // step(op) Evaluates opcodes in a generator body until execution is suspended or + // completed. + // + // The __generator helper understands a limited set of instructions: + // 0: next(value?) - Start or resume the generator with the specified value. + // 1: throw(error) - Resume the generator with an exception. If the generator is + // suspended inside of one or more protected regions, evaluates + // any intervening finally blocks between the current label and + // the nearest catch block or function boundary. If uncaught, the + // exception is thrown to the caller. + // 2: return(value?) - Resume the generator as if with a return. If the generator is + // suspended inside of one or more protected regions, evaluates any + // intervening finally blocks. + // 3: break(label) - Jump to the specified label. If the label is outside of the + // current protected region, evaluates any intervening finally + // blocks. + // 4: yield(value?) - Yield execution to the caller with an optional value. When + // resumed, the generator will continue at the next label. + // 5: yield*(value) - Delegates evaluation to the supplied iterator. When + // delegation completes, the generator will continue at the next + // label. + // 6: catch(error) - Handles an exception thrown from within the generator body. If + // the current label is inside of one or more protected regions, + // evaluates any intervening finally blocks between the current + // label and the nearest catch block or function boundary. If + // uncaught, the exception is thrown to the caller. + // 7: endfinally - Ends a finally block, resuming the last instruction prior to + // entering a finally block. + // + // For examples of how these are used, see the comments in ./transformers/generators.ts + var generatorHelper = "\nvar __generator = (this && this.__generator) || function (thisArg, body) {\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t;\n return { next: verb(0), \"throw\": verb(1), \"return\": verb(2) };\n function verb(n) { return function (v) { return step([n, v]); }; }\n function step(op) {\n if (f) throw new TypeError(\"Generator is already executing.\");\n while (_) try {\n if (f = 1, y && (t = y[op[0] & 2 ? \"return\" : op[0] ? \"throw\" : \"next\"]) && !(t = t.call(y, op[1])).done) return t;\n if (y = 0, t) op = [0, t.value];\n switch (op[0]) {\n case 0: case 1: t = op; break;\n case 4: _.label++; return { value: op[1], done: false };\n case 5: _.label++; y = op[1]; op = [0]; continue;\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\n default:\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n if (t[2]) _.ops.pop();\n _.trys.pop(); continue;\n }\n op = body.call(thisArg, _);\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n }\n};"; + // emit output for the __export helper function + var exportStarHelper = "\nfunction __export(m) {\n for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];\n}"; + // emit output for the UMD helper function. + var umdHelper = "\n(function (dependencies, factory) {\n if (typeof module === 'object' && typeof module.exports === 'object') {\n var v = factory(require, exports); if (v !== undefined) module.exports = v;\n }\n else if (typeof define === 'function' && define.amd) {\n define(dependencies, factory);\n }\n})"; + var superHelper = "\nconst _super = name => super[name];"; + var advancedSuperHelper = "\nconst _super = (function (geti, seti) {\n const cache = Object.create(null);\n return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });\n})(name => super[name], (name, value) => super[name] = value);"; + var compilerOptions = host.getCompilerOptions(); + var languageVersion = ts.getEmitScriptTarget(compilerOptions); + var moduleKind = ts.getEmitModuleKind(compilerOptions); + var sourceMapDataList = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? [] : undefined; + var emittedFilesList = compilerOptions.listEmittedFiles ? [] : undefined; + var emitterDiagnostics = ts.createDiagnosticCollection(); + var newLine = host.getNewLine(); + var transformers = emitOnlyDtsFiles ? nullTransformers : ts.getTransformers(compilerOptions); + var writer = ts.createTextWriter(newLine); + var write = writer.write, writeLine = writer.writeLine, increaseIndent = writer.increaseIndent, decreaseIndent = writer.decreaseIndent; + var sourceMap = ts.createSourceMapWriter(host, writer); + var emitNodeWithSourceMap = sourceMap.emitNodeWithSourceMap, emitTokenWithSourceMap = sourceMap.emitTokenWithSourceMap; + var comments = ts.createCommentWriter(host, writer, sourceMap); + var emitNodeWithComments = comments.emitNodeWithComments, emitBodyWithDetachedComments = comments.emitBodyWithDetachedComments, emitTrailingCommentsOfPosition = comments.emitTrailingCommentsOfPosition; + var nodeIdToGeneratedName; + var autoGeneratedIdToGeneratedName; + var generatedNameSet; + var tempFlags; + var currentSourceFile; + var currentText; + var currentFileIdentifiers; + var extendsEmitted; + var assignEmitted; + var decorateEmitted; + var paramEmitted; + var awaiterEmitted; + var isOwnFileEmit; + var emitSkipped = false; + var sourceFiles = ts.getSourceFilesToEmit(host, targetSourceFile); + // Transform the source files + ts.performance.mark("beforeTransform"); + var _a = ts.transformFiles(resolver, host, sourceFiles, transformers), transformed = _a.transformed, emitNodeWithSubstitution = _a.emitNodeWithSubstitution, emitNodeWithNotification = _a.emitNodeWithNotification; + ts.performance.measure("transformTime", "beforeTransform"); + // Emit each output file + ts.performance.mark("beforePrint"); + ts.forEachTransformedEmitFile(host, transformed, emitFile, emitOnlyDtsFiles); + ts.performance.measure("printTime", "beforePrint"); + // Clean up emit nodes on parse tree + for (var _b = 0, sourceFiles_4 = sourceFiles; _b < sourceFiles_4.length; _b++) { + var sourceFile = sourceFiles_4[_b]; + ts.disposeEmitNodes(sourceFile); + } + return { + emitSkipped: emitSkipped, + diagnostics: emitterDiagnostics.getDiagnostics(), + emittedFiles: emittedFilesList, + sourceMaps: sourceMapDataList + }; + function emitFile(jsFilePath, sourceMapFilePath, declarationFilePath, sourceFiles, isBundledEmit) { + // Make sure not to write js file and source map file if any of them cannot be written + if (!host.isEmitBlocked(jsFilePath) && !compilerOptions.noEmit) { + if (!emitOnlyDtsFiles) { + printFile(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit); + } } - ts.Debug.assert(!oldProgram.structureIsReused); - // there is an old program, check if we can reuse its structure - var oldRootNames = oldProgram.getRootFileNames(); - if (!ts.arrayIsEqualTo(oldRootNames, rootNames)) { - return false; + else { + emitSkipped = true; } - if (!ts.arrayIsEqualTo(options.types, oldOptions.types)) { - return false; + if (declarationFilePath) { + emitSkipped = ts.writeDeclarationFile(declarationFilePath, ts.getOriginalSourceFiles(sourceFiles), isBundledEmit, host, resolver, emitterDiagnostics, emitOnlyDtsFiles) || emitSkipped; } - // check if program source files has changed in the way that can affect structure of the program - var newSourceFiles = []; - var filePaths = []; - var modifiedSourceFiles = []; - for (var _i = 0, _a = oldProgram.getSourceFiles(); _i < _a.length; _i++) { - var oldSourceFile = _a[_i]; - var newSourceFile = host.getSourceFileByPath - ? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.path, options.target) - : host.getSourceFile(oldSourceFile.fileName, options.target); - if (!newSourceFile) { - return false; - } - newSourceFile.path = oldSourceFile.path; - filePaths.push(newSourceFile.path); - if (oldSourceFile !== newSourceFile) { - if (oldSourceFile.hasNoDefaultLib !== newSourceFile.hasNoDefaultLib) { - // value of no-default-lib has changed - // this will affect if default library is injected into the list of files - return false; - } - // check tripleslash references - if (!ts.arrayIsEqualTo(oldSourceFile.referencedFiles, newSourceFile.referencedFiles, fileReferenceIsEqualTo)) { - // tripleslash references has changed - return false; - } - // check imports and module augmentations - collectExternalModuleReferences(newSourceFile); - if (!ts.arrayIsEqualTo(oldSourceFile.imports, newSourceFile.imports, moduleNameIsEqualTo)) { - // imports has changed - return false; - } - if (!ts.arrayIsEqualTo(oldSourceFile.moduleAugmentations, newSourceFile.moduleAugmentations, moduleNameIsEqualTo)) { - // moduleAugmentations has changed - return false; - } - if (!ts.arrayIsEqualTo(oldSourceFile.typeReferenceDirectives, newSourceFile.typeReferenceDirectives, fileReferenceIsEqualTo)) { - // 'types' references has changed - return false; - } - var newSourceFilePath = ts.getNormalizedAbsolutePath(newSourceFile.fileName, currentDirectory); - if (resolveModuleNamesWorker) { - var moduleNames = ts.map(ts.concatenate(newSourceFile.imports, newSourceFile.moduleAugmentations), getTextOfLiteral); - var resolutions = resolveModuleNamesWorker(moduleNames, newSourceFilePath); - // ensure that module resolution results are still correct - var resolutionsChanged = ts.hasChangesInResolutions(moduleNames, resolutions, oldSourceFile.resolvedModules, ts.moduleResolutionIsEqualTo); - if (resolutionsChanged) { - return false; - } - } - if (resolveTypeReferenceDirectiveNamesWorker) { - var typesReferenceDirectives = ts.map(newSourceFile.typeReferenceDirectives, function (x) { return x.fileName; }); - var resolutions = resolveTypeReferenceDirectiveNamesWorker(typesReferenceDirectives, newSourceFilePath); - // ensure that types resolutions are still correct - var resolutionsChanged = ts.hasChangesInResolutions(typesReferenceDirectives, resolutions, oldSourceFile.resolvedTypeReferenceDirectiveNames, ts.typeDirectiveIsEqualTo); - if (resolutionsChanged) { - return false; - } - } - // pass the cache of module/types resolutions from the old source file - newSourceFile.resolvedModules = oldSourceFile.resolvedModules; - newSourceFile.resolvedTypeReferenceDirectiveNames = oldSourceFile.resolvedTypeReferenceDirectiveNames; - modifiedSourceFiles.push(newSourceFile); + if (!emitSkipped && emittedFilesList) { + if (!emitOnlyDtsFiles) { + emittedFilesList.push(jsFilePath); } - else { - // file has no changes - use it as is - newSourceFile = oldSourceFile; + if (sourceMapFilePath) { + emittedFilesList.push(sourceMapFilePath); } - // if file has passed all checks it should be safe to reuse it - newSourceFiles.push(newSourceFile); - } - // update fileName -> file mapping - for (var i = 0, len = newSourceFiles.length; i < len; i++) { - filesByName.set(filePaths[i], newSourceFiles[i]); - } - files = newSourceFiles; - fileProcessingDiagnostics = oldProgram.getFileProcessingDiagnostics(); - for (var _b = 0, modifiedSourceFiles_1 = modifiedSourceFiles; _b < modifiedSourceFiles_1.length; _b++) { - var modifiedFile = modifiedSourceFiles_1[_b]; - fileProcessingDiagnostics.reattachFileDiagnostics(modifiedFile); - } - resolvedTypeReferenceDirectives = oldProgram.getResolvedTypeReferenceDirectives(); - oldProgram.structureIsReused = true; - return true; - } - function getEmitHost(writeFileCallback) { - return { - getCanonicalFileName: getCanonicalFileName, - getCommonSourceDirectory: program.getCommonSourceDirectory, - getCompilerOptions: program.getCompilerOptions, - getCurrentDirectory: function () { return currentDirectory; }, - getNewLine: function () { return host.getNewLine(); }, - getSourceFile: program.getSourceFile, - getSourceFileByPath: program.getSourceFileByPath, - getSourceFiles: program.getSourceFiles, - isSourceFileFromExternalLibrary: function (file) { return !!sourceFilesFoundSearchingNodeModules[file.path]; }, - writeFile: writeFileCallback || (function (fileName, data, writeByteOrderMark, onError, sourceFiles) { return host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles); }), - isEmitBlocked: isEmitBlocked, - }; + if (declarationFilePath) { + emittedFilesList.push(declarationFilePath); + } + } } - function getDiagnosticsProducingTypeChecker() { - return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = ts.createTypeChecker(program, /*produceDiagnostics:*/ true)); + function printFile(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit) { + sourceMap.initialize(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit); + nodeIdToGeneratedName = []; + autoGeneratedIdToGeneratedName = []; + generatedNameSet = ts.createMap(); + isOwnFileEmit = !isBundledEmit; + // Emit helpers from all the files + if (isBundledEmit && moduleKind) { + for (var _a = 0, sourceFiles_5 = sourceFiles; _a < sourceFiles_5.length; _a++) { + var sourceFile = sourceFiles_5[_a]; + emitEmitHelpers(sourceFile); + } + } + // Print each transformed source file. + ts.forEach(sourceFiles, printSourceFile); + writeLine(); + var sourceMappingURL = sourceMap.getSourceMappingURL(); + if (sourceMappingURL) { + write("//# " + "sourceMappingURL" + "=" + sourceMappingURL); // Sometimes tools can sometimes see this line as a source mapping url comment + } + // Write the source map + if (compilerOptions.sourceMap && !compilerOptions.inlineSourceMap) { + ts.writeFile(host, emitterDiagnostics, sourceMapFilePath, sourceMap.getText(), /*writeByteOrderMark*/ false); + } + // Record source map data for the test harness. + if (sourceMapDataList) { + sourceMapDataList.push(sourceMap.getSourceMapData()); + } + // Write the output file + ts.writeFile(host, emitterDiagnostics, jsFilePath, writer.getText(), compilerOptions.emitBOM); + // Reset state + sourceMap.reset(); + comments.reset(); + writer.reset(); + tempFlags = 0 /* Auto */; + currentSourceFile = undefined; + currentText = undefined; + extendsEmitted = false; + assignEmitted = false; + decorateEmitted = false; + paramEmitted = false; + awaiterEmitted = false; + isOwnFileEmit = false; + } + function printSourceFile(node) { + currentSourceFile = node; + currentText = node.text; + currentFileIdentifiers = node.identifiers; + sourceMap.setSourceFile(node); + comments.setSourceFile(node); + pipelineEmitWithNotification(0 /* SourceFile */, node); } - function getTypeChecker() { - return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = ts.createTypeChecker(program, /*produceDiagnostics:*/ false)); + /** + * Emits a node. + */ + function emit(node) { + pipelineEmitWithNotification(3 /* Unspecified */, node); + } + /** + * Emits an IdentifierName. + */ + function emitIdentifierName(node) { + pipelineEmitWithNotification(2 /* IdentifierName */, node); } - function emit(sourceFile, writeFileCallback, cancellationToken) { - return runWithCancellationToken(function () { return emitWorker(program, sourceFile, writeFileCallback, cancellationToken); }); + /** + * Emits an expression node. + */ + function emitExpression(node) { + pipelineEmitWithNotification(1 /* Expression */, node); } - function isEmitBlocked(emitFileName) { - return hasEmitBlockingDiagnostics.contains(ts.toPath(emitFileName, currentDirectory, getCanonicalFileName)); + /** + * Emits a node with possible notification. + * + * NOTE: Do not call this method directly. It is part of the emit pipeline + * and should only be called from printSourceFile, emit, emitExpression, or + * emitIdentifierName. + */ + function pipelineEmitWithNotification(emitContext, node) { + emitNodeWithNotification(emitContext, node, pipelineEmitWithComments); } - function emitWorker(program, sourceFile, writeFileCallback, cancellationToken) { - var declarationDiagnostics = []; - if (options.noEmit) { - return { diagnostics: declarationDiagnostics, sourceMaps: undefined, emittedFiles: undefined, emitSkipped: true }; + /** + * Emits a node with comments. + * + * NOTE: Do not call this method directly. It is part of the emit pipeline + * and should only be called indirectly from pipelineEmitWithNotification. + */ + function pipelineEmitWithComments(emitContext, node) { + // Do not emit comments for SourceFile + if (emitContext === 0 /* SourceFile */) { + pipelineEmitWithSourceMap(emitContext, node); + return; } - // If the noEmitOnError flag is set, then check if we have any errors so far. If so, - // immediately bail out. Note that we pass 'undefined' for 'sourceFile' so that we - // get any preEmit diagnostics, not just the ones - if (options.noEmitOnError) { - var diagnostics = program.getOptionsDiagnostics(cancellationToken).concat(program.getSyntacticDiagnostics(sourceFile, cancellationToken), program.getGlobalDiagnostics(cancellationToken), program.getSemanticDiagnostics(sourceFile, cancellationToken)); - if (diagnostics.length === 0 && program.getCompilerOptions().declaration) { - declarationDiagnostics = program.getDeclarationDiagnostics(/*sourceFile*/ undefined, cancellationToken); - } - if (diagnostics.length > 0 || declarationDiagnostics.length > 0) { - return { - diagnostics: ts.concatenate(diagnostics, declarationDiagnostics), - sourceMaps: undefined, - emittedFiles: undefined, - emitSkipped: true - }; - } + emitNodeWithComments(emitContext, node, pipelineEmitWithSourceMap); + } + /** + * Emits a node with source maps. + * + * NOTE: Do not call this method directly. It is part of the emit pipeline + * and should only be called indirectly from pipelineEmitWithComments. + */ + function pipelineEmitWithSourceMap(emitContext, node) { + // Do not emit source mappings for SourceFile or IdentifierName + if (emitContext === 0 /* SourceFile */ + || emitContext === 2 /* IdentifierName */) { + pipelineEmitWithSubstitution(emitContext, node); + return; } - // Create the emit resolver outside of the "emitTime" tracking code below. That way - // any cost associated with it (like type checking) are appropriate associated with - // the type-checking counter. - // - // If the -out option is specified, we should not pass the source file to getEmitResolver. - // This is because in the -out scenario all files need to be emitted, and therefore all - // files need to be type checked. And the way to specify that all files need to be type - // checked is to not pass the file to getEmitResolver. - var emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver((options.outFile || options.out) ? undefined : sourceFile); - ts.performance.mark("beforeEmit"); - var emitResult = ts.emitFiles(emitResolver, getEmitHost(writeFileCallback), sourceFile); - ts.performance.mark("afterEmit"); - ts.performance.measure("Emit", "beforeEmit", "afterEmit"); - return emitResult; + emitNodeWithSourceMap(emitContext, node, pipelineEmitWithSubstitution); } - function getSourceFile(fileName) { - return getSourceFileByPath(ts.toPath(fileName, currentDirectory, getCanonicalFileName)); + /** + * Emits a node with possible substitution. + * + * NOTE: Do not call this method directly. It is part of the emit pipeline + * and should only be called indirectly from pipelineEmitWithSourceMap or + * pipelineEmitInUnspecifiedContext (when picking a more specific context). + */ + function pipelineEmitWithSubstitution(emitContext, node) { + emitNodeWithSubstitution(emitContext, node, pipelineEmitForContext); } - function getSourceFileByPath(path) { - return filesByName.get(path); + /** + * Emits a node. + * + * NOTE: Do not call this method directly. It is part of the emit pipeline + * and should only be called indirectly from pipelineEmitWithSubstitution. + */ + function pipelineEmitForContext(emitContext, node) { + switch (emitContext) { + case 0 /* SourceFile */: return pipelineEmitInSourceFileContext(node); + case 2 /* IdentifierName */: return pipelineEmitInIdentifierNameContext(node); + case 3 /* Unspecified */: return pipelineEmitInUnspecifiedContext(node); + case 1 /* Expression */: return pipelineEmitInExpressionContext(node); + } } - function getDiagnosticsHelper(sourceFile, getDiagnostics, cancellationToken) { - if (sourceFile) { - return getDiagnostics(sourceFile, cancellationToken); + /** + * Emits a node in the SourceFile EmitContext. + * + * NOTE: Do not call this method directly. It is part of the emit pipeline + * and should only be called indirectly from pipelineEmitForContext. + */ + function pipelineEmitInSourceFileContext(node) { + var kind = node.kind; + switch (kind) { + // Top-level nodes + case 256 /* SourceFile */: + return emitSourceFile(node); } - var allDiagnostics = []; - ts.forEach(program.getSourceFiles(), function (sourceFile) { - if (cancellationToken) { - cancellationToken.throwIfCancellationRequested(); - } - ts.addRange(allDiagnostics, getDiagnostics(sourceFile, cancellationToken)); - }); - return ts.sortAndDeduplicateDiagnostics(allDiagnostics); } - function getSyntacticDiagnostics(sourceFile, cancellationToken) { - return getDiagnosticsHelper(sourceFile, getSyntacticDiagnosticsForFile, cancellationToken); + /** + * Emits a node in the IdentifierName EmitContext. + * + * NOTE: Do not call this method directly. It is part of the emit pipeline + * and should only be called indirectly from pipelineEmitForContext. + */ + function pipelineEmitInIdentifierNameContext(node) { + var kind = node.kind; + switch (kind) { + // Identifiers + case 69 /* Identifier */: + return emitIdentifier(node); + } } - function getSemanticDiagnostics(sourceFile, cancellationToken) { - return getDiagnosticsHelper(sourceFile, getSemanticDiagnosticsForFile, cancellationToken); + /** + * Emits a node in the Unspecified EmitContext. + * + * NOTE: Do not call this method directly. It is part of the emit pipeline + * and should only be called indirectly from pipelineEmitForContext. + */ + function pipelineEmitInUnspecifiedContext(node) { + var kind = node.kind; + switch (kind) { + // Pseudo-literals + case 12 /* TemplateHead */: + case 13 /* TemplateMiddle */: + case 14 /* TemplateTail */: + return emitLiteral(node); + // Identifiers + case 69 /* Identifier */: + return emitIdentifier(node); + // Reserved words + case 74 /* ConstKeyword */: + case 77 /* DefaultKeyword */: + case 82 /* ExportKeyword */: + case 103 /* VoidKeyword */: + // Strict mode reserved words + case 110 /* PrivateKeyword */: + case 111 /* ProtectedKeyword */: + case 112 /* PublicKeyword */: + case 113 /* StaticKeyword */: + // Contextual keywords + case 115 /* AbstractKeyword */: + case 117 /* AnyKeyword */: + case 118 /* AsyncKeyword */: + case 120 /* BooleanKeyword */: + case 122 /* DeclareKeyword */: + case 130 /* NumberKeyword */: + case 128 /* ReadonlyKeyword */: + case 132 /* StringKeyword */: + case 133 /* SymbolKeyword */: + case 137 /* GlobalKeyword */: + writeTokenText(kind); + return; + // Parse tree nodes + // Names + case 139 /* QualifiedName */: + return emitQualifiedName(node); + case 140 /* ComputedPropertyName */: + return emitComputedPropertyName(node); + // Signature elements + case 141 /* TypeParameter */: + return emitTypeParameter(node); + case 142 /* Parameter */: + return emitParameter(node); + case 143 /* Decorator */: + return emitDecorator(node); + // Type members + case 144 /* PropertySignature */: + return emitPropertySignature(node); + case 145 /* PropertyDeclaration */: + return emitPropertyDeclaration(node); + case 146 /* MethodSignature */: + return emitMethodSignature(node); + case 147 /* MethodDeclaration */: + return emitMethodDeclaration(node); + case 148 /* Constructor */: + return emitConstructor(node); + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + return emitAccessorDeclaration(node); + case 151 /* CallSignature */: + return emitCallSignature(node); + case 152 /* ConstructSignature */: + return emitConstructSignature(node); + case 153 /* IndexSignature */: + return emitIndexSignature(node); + // Types + case 154 /* TypePredicate */: + return emitTypePredicate(node); + case 155 /* TypeReference */: + return emitTypeReference(node); + case 156 /* FunctionType */: + return emitFunctionType(node); + case 157 /* ConstructorType */: + return emitConstructorType(node); + case 158 /* TypeQuery */: + return emitTypeQuery(node); + case 159 /* TypeLiteral */: + return emitTypeLiteral(node); + case 160 /* ArrayType */: + return emitArrayType(node); + case 161 /* TupleType */: + return emitTupleType(node); + case 162 /* UnionType */: + return emitUnionType(node); + case 163 /* IntersectionType */: + return emitIntersectionType(node); + case 164 /* ParenthesizedType */: + return emitParenthesizedType(node); + case 194 /* ExpressionWithTypeArguments */: + return emitExpressionWithTypeArguments(node); + case 165 /* ThisType */: + return emitThisType(node); + case 166 /* LiteralType */: + return emitLiteralType(node); + // Binding patterns + case 167 /* ObjectBindingPattern */: + return emitObjectBindingPattern(node); + case 168 /* ArrayBindingPattern */: + return emitArrayBindingPattern(node); + case 169 /* BindingElement */: + return emitBindingElement(node); + // Misc + case 197 /* TemplateSpan */: + return emitTemplateSpan(node); + case 198 /* SemicolonClassElement */: + return emitSemicolonClassElement(node); + // Statements + case 199 /* Block */: + return emitBlock(node); + case 200 /* VariableStatement */: + return emitVariableStatement(node); + case 201 /* EmptyStatement */: + return emitEmptyStatement(node); + case 202 /* ExpressionStatement */: + return emitExpressionStatement(node); + case 203 /* IfStatement */: + return emitIfStatement(node); + case 204 /* DoStatement */: + return emitDoStatement(node); + case 205 /* WhileStatement */: + return emitWhileStatement(node); + case 206 /* ForStatement */: + return emitForStatement(node); + case 207 /* ForInStatement */: + return emitForInStatement(node); + case 208 /* ForOfStatement */: + return emitForOfStatement(node); + case 209 /* ContinueStatement */: + return emitContinueStatement(node); + case 210 /* BreakStatement */: + return emitBreakStatement(node); + case 211 /* ReturnStatement */: + return emitReturnStatement(node); + case 212 /* WithStatement */: + return emitWithStatement(node); + case 213 /* SwitchStatement */: + return emitSwitchStatement(node); + case 214 /* LabeledStatement */: + return emitLabeledStatement(node); + case 215 /* ThrowStatement */: + return emitThrowStatement(node); + case 216 /* TryStatement */: + return emitTryStatement(node); + case 217 /* DebuggerStatement */: + return emitDebuggerStatement(node); + // Declarations + case 218 /* VariableDeclaration */: + return emitVariableDeclaration(node); + case 219 /* VariableDeclarationList */: + return emitVariableDeclarationList(node); + case 220 /* FunctionDeclaration */: + return emitFunctionDeclaration(node); + case 221 /* ClassDeclaration */: + return emitClassDeclaration(node); + case 222 /* InterfaceDeclaration */: + return emitInterfaceDeclaration(node); + case 223 /* TypeAliasDeclaration */: + return emitTypeAliasDeclaration(node); + case 224 /* EnumDeclaration */: + return emitEnumDeclaration(node); + case 225 /* ModuleDeclaration */: + return emitModuleDeclaration(node); + case 226 /* ModuleBlock */: + return emitModuleBlock(node); + case 227 /* CaseBlock */: + return emitCaseBlock(node); + case 229 /* ImportEqualsDeclaration */: + return emitImportEqualsDeclaration(node); + case 230 /* ImportDeclaration */: + return emitImportDeclaration(node); + case 231 /* ImportClause */: + return emitImportClause(node); + case 232 /* NamespaceImport */: + return emitNamespaceImport(node); + case 233 /* NamedImports */: + return emitNamedImports(node); + case 234 /* ImportSpecifier */: + return emitImportSpecifier(node); + case 235 /* ExportAssignment */: + return emitExportAssignment(node); + case 236 /* ExportDeclaration */: + return emitExportDeclaration(node); + case 237 /* NamedExports */: + return emitNamedExports(node); + case 238 /* ExportSpecifier */: + return emitExportSpecifier(node); + case 239 /* MissingDeclaration */: + return; + // Module references + case 240 /* ExternalModuleReference */: + return emitExternalModuleReference(node); + // JSX (non-expression) + case 244 /* JsxText */: + return emitJsxText(node); + case 243 /* JsxOpeningElement */: + return emitJsxOpeningElement(node); + case 245 /* JsxClosingElement */: + return emitJsxClosingElement(node); + case 246 /* JsxAttribute */: + return emitJsxAttribute(node); + case 247 /* JsxSpreadAttribute */: + return emitJsxSpreadAttribute(node); + case 248 /* JsxExpression */: + return emitJsxExpression(node); + // Clauses + case 249 /* CaseClause */: + return emitCaseClause(node); + case 250 /* DefaultClause */: + return emitDefaultClause(node); + case 251 /* HeritageClause */: + return emitHeritageClause(node); + case 252 /* CatchClause */: + return emitCatchClause(node); + // Property assignments + case 253 /* PropertyAssignment */: + return emitPropertyAssignment(node); + case 254 /* ShorthandPropertyAssignment */: + return emitShorthandPropertyAssignment(node); + // Enum + case 255 /* EnumMember */: + return emitEnumMember(node); + } + // If the node is an expression, try to emit it as an expression with + // substitution. + if (ts.isExpression(node)) { + return pipelineEmitWithSubstitution(1 /* Expression */, node); + } } - function getDeclarationDiagnostics(sourceFile, cancellationToken) { - var options = program.getCompilerOptions(); - // collect diagnostics from the program only once if either no source file was specified or out/outFile is set (bundled emit) - if (!sourceFile || options.out || options.outFile) { - return getDeclarationDiagnosticsWorker(sourceFile, cancellationToken); + /** + * Emits a node in the Expression EmitContext. + * + * NOTE: Do not call this method directly. It is part of the emit pipeline + * and should only be called indirectly from pipelineEmitForContext. + */ + function pipelineEmitInExpressionContext(node) { + var kind = node.kind; + switch (kind) { + // Literals + case 8 /* NumericLiteral */: + return emitNumericLiteral(node); + case 9 /* StringLiteral */: + case 10 /* RegularExpressionLiteral */: + case 11 /* NoSubstitutionTemplateLiteral */: + return emitLiteral(node); + // Identifiers + case 69 /* Identifier */: + return emitIdentifier(node); + // Reserved words + case 84 /* FalseKeyword */: + case 93 /* NullKeyword */: + case 95 /* SuperKeyword */: + case 99 /* TrueKeyword */: + case 97 /* ThisKeyword */: + writeTokenText(kind); + return; + // Expressions + case 170 /* ArrayLiteralExpression */: + return emitArrayLiteralExpression(node); + case 171 /* ObjectLiteralExpression */: + return emitObjectLiteralExpression(node); + case 172 /* PropertyAccessExpression */: + return emitPropertyAccessExpression(node); + case 173 /* ElementAccessExpression */: + return emitElementAccessExpression(node); + case 174 /* CallExpression */: + return emitCallExpression(node); + case 175 /* NewExpression */: + return emitNewExpression(node); + case 176 /* TaggedTemplateExpression */: + return emitTaggedTemplateExpression(node); + case 177 /* TypeAssertionExpression */: + return emitTypeAssertionExpression(node); + case 178 /* ParenthesizedExpression */: + return emitParenthesizedExpression(node); + case 179 /* FunctionExpression */: + return emitFunctionExpression(node); + case 180 /* ArrowFunction */: + return emitArrowFunction(node); + case 181 /* DeleteExpression */: + return emitDeleteExpression(node); + case 182 /* TypeOfExpression */: + return emitTypeOfExpression(node); + case 183 /* VoidExpression */: + return emitVoidExpression(node); + case 184 /* AwaitExpression */: + return emitAwaitExpression(node); + case 185 /* PrefixUnaryExpression */: + return emitPrefixUnaryExpression(node); + case 186 /* PostfixUnaryExpression */: + return emitPostfixUnaryExpression(node); + case 187 /* BinaryExpression */: + return emitBinaryExpression(node); + case 188 /* ConditionalExpression */: + return emitConditionalExpression(node); + case 189 /* TemplateExpression */: + return emitTemplateExpression(node); + case 190 /* YieldExpression */: + return emitYieldExpression(node); + case 191 /* SpreadElementExpression */: + return emitSpreadElementExpression(node); + case 192 /* ClassExpression */: + return emitClassExpression(node); + case 193 /* OmittedExpression */: + return; + case 195 /* AsExpression */: + return emitAsExpression(node); + case 196 /* NonNullExpression */: + return emitNonNullExpression(node); + // JSX + case 241 /* JsxElement */: + return emitJsxElement(node); + case 242 /* JsxSelfClosingElement */: + return emitJsxSelfClosingElement(node); + // Transformation nodes + case 288 /* PartiallyEmittedExpression */: + return emitPartiallyEmittedExpression(node); + } + } + // + // Literals/Pseudo-literals + // + // SyntaxKind.NumericLiteral + function emitNumericLiteral(node) { + emitLiteral(node); + if (node.trailingComment) { + write(" /*" + node.trailingComment + "*/"); + } + } + // SyntaxKind.StringLiteral + // SyntaxKind.RegularExpressionLiteral + // SyntaxKind.NoSubstitutionTemplateLiteral + // SyntaxKind.TemplateHead + // SyntaxKind.TemplateMiddle + // SyntaxKind.TemplateTail + function emitLiteral(node) { + var text = getLiteralTextOfNode(node); + if ((compilerOptions.sourceMap || compilerOptions.inlineSourceMap) + && (node.kind === 9 /* StringLiteral */ || ts.isTemplateLiteralKind(node.kind))) { + writer.writeLiteral(text); } else { - return getDiagnosticsHelper(sourceFile, getDeclarationDiagnosticsForFile, cancellationToken); + write(text); } } - function getSyntacticDiagnosticsForFile(sourceFile, cancellationToken) { - return sourceFile.parseDiagnostics; + // + // Identifiers + // + function emitIdentifier(node) { + if (ts.getEmitFlags(node) & 16 /* UMDDefine */) { + writeLines(umdHelper); + } + else { + write(getTextOfNode(node, /*includeTrivia*/ false)); + } } - function runWithCancellationToken(func) { - try { - return func(); + // + // Names + // + function emitQualifiedName(node) { + emitEntityName(node.left); + write("."); + emit(node.right); + } + function emitEntityName(node) { + if (node.kind === 69 /* Identifier */) { + emitExpression(node); } - catch (e) { - if (e instanceof ts.OperationCanceledException) { - // We were canceled while performing the operation. Because our type checker - // might be a bad state, we need to throw it away. - // - // Note: we are overly aggressive here. We do not actually *have* to throw away - // the "noDiagnosticsTypeChecker". However, for simplicity, i'd like to keep - // the lifetimes of these two TypeCheckers the same. Also, we generally only - // cancel when the user has made a change anyways. And, in that case, we (the - // program instance) will get thrown away anyways. So trying to keep one of - // these type checkers alive doesn't serve much purpose. - noDiagnosticsTypeChecker = undefined; - diagnosticsProducingTypeChecker = undefined; - } - throw e; + else { + emit(node); } } - function getSemanticDiagnosticsForFile(sourceFile, cancellationToken) { - return runWithCancellationToken(function () { - var typeChecker = getDiagnosticsProducingTypeChecker(); - ts.Debug.assert(!!sourceFile.bindDiagnostics); - var bindDiagnostics = sourceFile.bindDiagnostics; - // For JavaScript files, we don't want to report the normal typescript semantic errors. - // Instead, we just report errors for using TypeScript-only constructs from within a - // JavaScript file. - var checkDiagnostics = ts.isSourceFileJavaScript(sourceFile) ? - getJavaScriptSemanticDiagnosticsForFile(sourceFile, cancellationToken) : - typeChecker.getDiagnostics(sourceFile, cancellationToken); - var fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName); - var programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName); - return bindDiagnostics.concat(checkDiagnostics).concat(fileProcessingDiagnosticsInFile).concat(programDiagnosticsInFile); - }); + function emitComputedPropertyName(node) { + write("["); + emitExpression(node.expression); + write("]"); } - function getJavaScriptSemanticDiagnosticsForFile(sourceFile, cancellationToken) { - return runWithCancellationToken(function () { - var diagnostics = []; - walk(sourceFile); - return diagnostics; - function walk(node) { - if (!node) { - return false; - } - switch (node.kind) { - case 229 /* ImportEqualsDeclaration */: - diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.import_can_only_be_used_in_a_ts_file)); - return true; - case 235 /* ExportAssignment */: - if (node.isExportEquals) { - diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.export_can_only_be_used_in_a_ts_file)); - return true; - } - break; - case 221 /* ClassDeclaration */: - var classDeclaration = node; - if (checkModifiers(classDeclaration.modifiers) || - checkTypeParameters(classDeclaration.typeParameters)) { - return true; - } - break; - case 251 /* HeritageClause */: - var heritageClause = node; - if (heritageClause.token === 106 /* ImplementsKeyword */) { - diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.implements_clauses_can_only_be_used_in_a_ts_file)); - return true; - } - break; - case 222 /* InterfaceDeclaration */: - diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.interface_declarations_can_only_be_used_in_a_ts_file)); - return true; - case 225 /* ModuleDeclaration */: - diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.module_declarations_can_only_be_used_in_a_ts_file)); - return true; - case 223 /* TypeAliasDeclaration */: - diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.type_aliases_can_only_be_used_in_a_ts_file)); - return true; - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - case 148 /* Constructor */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 179 /* FunctionExpression */: - case 220 /* FunctionDeclaration */: - case 180 /* ArrowFunction */: - case 220 /* FunctionDeclaration */: - var functionDeclaration = node; - if (checkModifiers(functionDeclaration.modifiers) || - checkTypeParameters(functionDeclaration.typeParameters) || - checkTypeAnnotation(functionDeclaration.type)) { - return true; - } - break; - case 200 /* VariableStatement */: - var variableStatement = node; - if (checkModifiers(variableStatement.modifiers)) { - return true; - } - break; - case 218 /* VariableDeclaration */: - var variableDeclaration = node; - if (checkTypeAnnotation(variableDeclaration.type)) { - return true; - } - break; - case 174 /* CallExpression */: - case 175 /* NewExpression */: - var expression = node; - if (expression.typeArguments && expression.typeArguments.length > 0) { - var start = expression.typeArguments.pos; - diagnostics.push(ts.createFileDiagnostic(sourceFile, start, expression.typeArguments.end - start, ts.Diagnostics.type_arguments_can_only_be_used_in_a_ts_file)); - return true; - } - break; - case 142 /* Parameter */: - var parameter = node; - if (parameter.modifiers) { - var start = parameter.modifiers.pos; - diagnostics.push(ts.createFileDiagnostic(sourceFile, start, parameter.modifiers.end - start, ts.Diagnostics.parameter_modifiers_can_only_be_used_in_a_ts_file)); - return true; - } - if (parameter.questionToken) { - diagnostics.push(ts.createDiagnosticForNode(parameter.questionToken, ts.Diagnostics._0_can_only_be_used_in_a_ts_file, "?")); - return true; - } - if (parameter.type) { - diagnostics.push(ts.createDiagnosticForNode(parameter.type, ts.Diagnostics.types_can_only_be_used_in_a_ts_file)); - return true; - } - break; - case 145 /* PropertyDeclaration */: - var propertyDeclaration = node; - if (propertyDeclaration.modifiers) { - for (var _i = 0, _a = propertyDeclaration.modifiers; _i < _a.length; _i++) { - var modifier = _a[_i]; - if (modifier.kind !== 113 /* StaticKeyword */) { - diagnostics.push(ts.createDiagnosticForNode(modifier, ts.Diagnostics._0_can_only_be_used_in_a_ts_file, ts.tokenToString(modifier.kind))); - return true; - } - } - } - if (checkTypeAnnotation(node.type)) { - return true; - } - break; - case 224 /* EnumDeclaration */: - diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.enum_declarations_can_only_be_used_in_a_ts_file)); - return true; - case 177 /* TypeAssertionExpression */: - var typeAssertionExpression = node; - diagnostics.push(ts.createDiagnosticForNode(typeAssertionExpression.type, ts.Diagnostics.type_assertion_expressions_can_only_be_used_in_a_ts_file)); - return true; - case 143 /* Decorator */: - if (!options.experimentalDecorators) { - diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_to_remove_this_warning)); - } - return true; - } - return ts.forEachChild(node, walk); - } - function checkTypeParameters(typeParameters) { - if (typeParameters) { - var start = typeParameters.pos; - diagnostics.push(ts.createFileDiagnostic(sourceFile, start, typeParameters.end - start, ts.Diagnostics.type_parameter_declarations_can_only_be_used_in_a_ts_file)); - return true; - } - return false; - } - function checkTypeAnnotation(type) { - if (type) { - diagnostics.push(ts.createDiagnosticForNode(type, ts.Diagnostics.types_can_only_be_used_in_a_ts_file)); - return true; - } - return false; - } - function checkModifiers(modifiers) { - if (modifiers) { - for (var _i = 0, modifiers_1 = modifiers; _i < modifiers_1.length; _i++) { - var modifier = modifiers_1[_i]; - switch (modifier.kind) { - case 112 /* PublicKeyword */: - case 110 /* PrivateKeyword */: - case 111 /* ProtectedKeyword */: - case 128 /* ReadonlyKeyword */: - case 122 /* DeclareKeyword */: - diagnostics.push(ts.createDiagnosticForNode(modifier, ts.Diagnostics._0_can_only_be_used_in_a_ts_file, ts.tokenToString(modifier.kind))); - return true; - // These are all legal modifiers. - case 113 /* StaticKeyword */: - case 82 /* ExportKeyword */: - case 74 /* ConstKeyword */: - case 77 /* DefaultKeyword */: - case 115 /* AbstractKeyword */: - } - } - } - return false; - } - }); + // + // Signature elements + // + function emitTypeParameter(node) { + emit(node.name); + emitWithPrefix(" extends ", node.constraint); + } + function emitParameter(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + writeIfPresent(node.dotDotDotToken, "..."); + emit(node.name); + writeIfPresent(node.questionToken, "?"); + emitExpressionWithPrefix(" = ", node.initializer); + emitWithPrefix(": ", node.type); + } + function emitDecorator(decorator) { + write("@"); + emitExpression(decorator.expression); } - function getDeclarationDiagnosticsWorker(sourceFile, cancellationToken) { - return runWithCancellationToken(function () { - var resolver = getDiagnosticsProducingTypeChecker().getEmitResolver(sourceFile, cancellationToken); - // Don't actually write any files since we're just getting diagnostics. - var writeFile = function () { }; - return ts.getDeclarationDiagnostics(getEmitHost(writeFile), resolver, sourceFile); - }); + // + // Type members + // + function emitPropertySignature(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + emit(node.name); + writeIfPresent(node.questionToken, "?"); + emitWithPrefix(": ", node.type); + write(";"); + } + function emitPropertyDeclaration(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + emit(node.name); + emitWithPrefix(": ", node.type); + emitExpressionWithPrefix(" = ", node.initializer); + write(";"); + } + function emitMethodSignature(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + emit(node.name); + writeIfPresent(node.questionToken, "?"); + emitTypeParameters(node, node.typeParameters); + emitParameters(node, node.parameters); + emitWithPrefix(": ", node.type); + write(";"); + } + function emitMethodDeclaration(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + writeIfPresent(node.asteriskToken, "*"); + emit(node.name); + emitSignatureAndBody(node, emitSignatureHead); + } + function emitConstructor(node) { + emitModifiers(node, node.modifiers); + write("constructor"); + emitSignatureAndBody(node, emitSignatureHead); + } + function emitAccessorDeclaration(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + write(node.kind === 149 /* GetAccessor */ ? "get " : "set "); + emit(node.name); + emitSignatureAndBody(node, emitSignatureHead); + } + function emitCallSignature(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + emitTypeParameters(node, node.typeParameters); + emitParameters(node, node.parameters); + emitWithPrefix(": ", node.type); + write(";"); + } + function emitConstructSignature(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + write("new "); + emitTypeParameters(node, node.typeParameters); + emitParameters(node, node.parameters); + emitWithPrefix(": ", node.type); + write(";"); + } + function emitIndexSignature(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + emitParametersForIndexSignature(node, node.parameters); + emitWithPrefix(": ", node.type); + write(";"); } - function getDeclarationDiagnosticsForFile(sourceFile, cancellationToken) { - return ts.isDeclarationFile(sourceFile) ? [] : getDeclarationDiagnosticsWorker(sourceFile, cancellationToken); + function emitSemicolonClassElement(node) { + write(";"); } - function getOptionsDiagnostics() { - var allDiagnostics = []; - ts.addRange(allDiagnostics, fileProcessingDiagnostics.getGlobalDiagnostics()); - ts.addRange(allDiagnostics, programDiagnostics.getGlobalDiagnostics()); - return ts.sortAndDeduplicateDiagnostics(allDiagnostics); + // + // Types + // + function emitTypePredicate(node) { + emit(node.parameterName); + write(" is "); + emit(node.type); + } + function emitTypeReference(node) { + emit(node.typeName); + emitTypeArguments(node, node.typeArguments); + } + function emitFunctionType(node) { + emitTypeParameters(node, node.typeParameters); + emitParametersForArrow(node, node.parameters); + write(" => "); + emit(node.type); + } + function emitConstructorType(node) { + write("new "); + emitTypeParameters(node, node.typeParameters); + emitParametersForArrow(node, node.parameters); + write(" => "); + emit(node.type); + } + function emitTypeQuery(node) { + write("typeof "); + emit(node.exprName); + } + function emitTypeLiteral(node) { + write("{"); + emitList(node, node.members, 65 /* TypeLiteralMembers */); + write("}"); } - function getGlobalDiagnostics() { - var allDiagnostics = []; - ts.addRange(allDiagnostics, getDiagnosticsProducingTypeChecker().getGlobalDiagnostics()); - return ts.sortAndDeduplicateDiagnostics(allDiagnostics); + function emitArrayType(node) { + emit(node.elementType); + write("[]"); } - function hasExtension(fileName) { - return ts.getBaseFileName(fileName).indexOf(".") >= 0; + function emitTupleType(node) { + write("["); + emitList(node, node.elementTypes, 336 /* TupleTypeElements */); + write("]"); } - function processRootFile(fileName, isDefaultLib) { - processSourceFile(ts.normalizePath(fileName), isDefaultLib, /*isReference*/ true); + function emitUnionType(node) { + emitList(node, node.types, 260 /* UnionTypeConstituents */); } - function fileReferenceIsEqualTo(a, b) { - return a.fileName === b.fileName; + function emitIntersectionType(node) { + emitList(node, node.types, 264 /* IntersectionTypeConstituents */); } - function moduleNameIsEqualTo(a, b) { - return a.text === b.text; + function emitParenthesizedType(node) { + write("("); + emit(node.type); + write(")"); } - function getTextOfLiteral(literal) { - return literal.text; + function emitThisType(node) { + write("this"); } - function collectExternalModuleReferences(file) { - if (file.imports) { - return; + function emitLiteralType(node) { + emitExpression(node.literal); + } + // + // Binding patterns + // + function emitObjectBindingPattern(node) { + var elements = node.elements; + if (elements.length === 0) { + write("{}"); } - var isJavaScriptFile = ts.isSourceFileJavaScript(file); - var isExternalModuleFile = ts.isExternalModule(file); - var imports; - var moduleAugmentations; - for (var _i = 0, _a = file.statements; _i < _a.length; _i++) { - var node = _a[_i]; - collectModuleReferences(node, /*inAmbientModule*/ false); - if (isJavaScriptFile) { - collectRequireCalls(node); - } + else { + write("{"); + emitList(node, elements, 432 /* ObjectBindingPatternElements */); + write("}"); } - file.imports = imports || emptyArray; - file.moduleAugmentations = moduleAugmentations || emptyArray; - return; - function collectModuleReferences(node, inAmbientModule) { - switch (node.kind) { - case 230 /* ImportDeclaration */: - case 229 /* ImportEqualsDeclaration */: - case 236 /* ExportDeclaration */: - var moduleNameExpr = ts.getExternalModuleName(node); - if (!moduleNameExpr || moduleNameExpr.kind !== 9 /* StringLiteral */) { - break; - } - if (!moduleNameExpr.text) { - break; - } - // TypeScript 1.0 spec (April 2014): 12.1.6 - // An ExternalImportDeclaration in an AmbientExternalModuleDeclaration may reference other external modules - // only through top - level external module names. Relative external module names are not permitted. - if (!inAmbientModule || !ts.isExternalModuleNameRelative(moduleNameExpr.text)) { - (imports || (imports = [])).push(moduleNameExpr); - } - break; - case 225 /* ModuleDeclaration */: - if (ts.isAmbientModule(node) && (inAmbientModule || node.flags & 2 /* Ambient */ || ts.isDeclarationFile(file))) { - var moduleName = node.name; - // Ambient module declarations can be interpreted as augmentations for some existing external modules. - // This will happen in two cases: - // - if current file is external module then module augmentation is a ambient module declaration defined in the top level scope - // - if current file is not external module then module augmentation is an ambient module declaration with non-relative module name - // immediately nested in top level ambient module declaration . - if (isExternalModuleFile || (inAmbientModule && !ts.isExternalModuleNameRelative(moduleName.text))) { - (moduleAugmentations || (moduleAugmentations = [])).push(moduleName); - } - else if (!inAmbientModule) { - // An AmbientExternalModuleDeclaration declares an external module. - // This type of declaration is permitted only in the global module. - // The StringLiteral must specify a top - level external module name. - // Relative external module names are not permitted - // NOTE: body of ambient module is always a module block, if it exists - var body = node.body; - if (body) { - for (var _i = 0, _a = body.statements; _i < _a.length; _i++) { - var statement = _a[_i]; - collectModuleReferences(statement, /*inAmbientModule*/ true); - } - } - } - } - } + } + function emitArrayBindingPattern(node) { + var elements = node.elements; + if (elements.length === 0) { + write("[]"); } - function collectRequireCalls(node) { - if (ts.isRequireCall(node, /*checkArgumentIsStringLiteral*/ true)) { - (imports || (imports = [])).push(node.arguments[0]); - } - else { - ts.forEachChild(node, collectRequireCalls); - } + else { + write("["); + emitList(node, node.elements, 304 /* ArrayBindingPatternElements */); + write("]"); } } - /** - * 'isReference' indicates whether the file was brought in via a reference directive (rather than an import declaration) - */ - function processSourceFile(fileName, isDefaultLib, isReference, refFile, refPos, refEnd) { - var diagnosticArgument; - var diagnostic; - if (hasExtension(fileName)) { - if (!options.allowNonTsExtensions && !ts.forEach(supportedExtensions, function (extension) { return ts.fileExtensionIs(host.getCanonicalFileName(fileName), extension); })) { - diagnostic = ts.Diagnostics.File_0_has_unsupported_extension_The_only_supported_extensions_are_1; - diagnosticArgument = [fileName, "'" + supportedExtensions.join("', '") + "'"]; - } - else if (!findSourceFile(fileName, ts.toPath(fileName, currentDirectory, getCanonicalFileName), isDefaultLib, isReference, refFile, refPos, refEnd)) { - diagnostic = ts.Diagnostics.File_0_not_found; - diagnosticArgument = [fileName]; - } - else if (refFile && host.getCanonicalFileName(fileName) === host.getCanonicalFileName(refFile.fileName)) { - diagnostic = ts.Diagnostics.A_file_cannot_have_a_reference_to_itself; - diagnosticArgument = [fileName]; - } + function emitBindingElement(node) { + emitWithSuffix(node.propertyName, ": "); + writeIfPresent(node.dotDotDotToken, "..."); + emit(node.name); + emitExpressionWithPrefix(" = ", node.initializer); + } + // + // Expressions + // + function emitArrayLiteralExpression(node) { + var elements = node.elements; + if (elements.length === 0) { + write("[]"); } else { - var nonTsFile = options.allowNonTsExtensions && findSourceFile(fileName, ts.toPath(fileName, currentDirectory, getCanonicalFileName), isDefaultLib, isReference, refFile, refPos, refEnd); - if (!nonTsFile) { - if (options.allowNonTsExtensions) { - diagnostic = ts.Diagnostics.File_0_not_found; - diagnosticArgument = [fileName]; - } - else if (!ts.forEach(supportedExtensions, function (extension) { return findSourceFile(fileName + extension, ts.toPath(fileName + extension, currentDirectory, getCanonicalFileName), isDefaultLib, isReference, refFile, refPos, refEnd); })) { - diagnostic = ts.Diagnostics.File_0_not_found; - fileName += ".ts"; - diagnosticArgument = [fileName]; - } - } + var preferNewLine = node.multiLine ? 32768 /* PreferNewLine */ : 0 /* None */; + emitExpressionList(node, elements, 4466 /* ArrayLiteralExpressionElements */ | preferNewLine); } - if (diagnostic) { - if (refFile !== undefined && refEnd !== undefined && refPos !== undefined) { - fileProcessingDiagnostics.add(ts.createFileDiagnostic.apply(void 0, [refFile, refPos, refEnd - refPos, diagnostic].concat(diagnosticArgument))); + } + function emitObjectLiteralExpression(node) { + var properties = node.properties; + if (properties.length === 0) { + write("{}"); + } + else { + var indentedFlag = ts.getEmitFlags(node) & 524288 /* Indented */; + if (indentedFlag) { + increaseIndent(); } - else { - fileProcessingDiagnostics.add(ts.createCompilerDiagnostic.apply(void 0, [diagnostic].concat(diagnosticArgument))); + var preferNewLine = node.multiLine ? 32768 /* PreferNewLine */ : 0 /* None */; + var allowTrailingComma = languageVersion >= 1 /* ES5 */ ? 32 /* AllowTrailingComma */ : 0 /* None */; + emitList(node, properties, 978 /* ObjectLiteralExpressionProperties */ | allowTrailingComma | preferNewLine); + if (indentedFlag) { + decreaseIndent(); } } } - function reportFileNamesDifferOnlyInCasingError(fileName, existingFileName, refFile, refPos, refEnd) { - if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) { - fileProcessingDiagnostics.add(ts.createFileDiagnostic(refFile, refPos, refEnd - refPos, ts.Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, fileName, existingFileName)); + function emitPropertyAccessExpression(node) { + var indentBeforeDot = false; + var indentAfterDot = false; + if (!(ts.getEmitFlags(node) & 1048576 /* NoIndentation */)) { + var dotRangeStart = node.expression.end; + var dotRangeEnd = ts.skipTrivia(currentText, node.expression.end) + 1; + var dotToken = { kind: 21 /* DotToken */, pos: dotRangeStart, end: dotRangeEnd }; + indentBeforeDot = needsIndentation(node, node.expression, dotToken); + indentAfterDot = needsIndentation(node, dotToken, node.name); + } + emitExpression(node.expression); + increaseIndentIf(indentBeforeDot); + var shouldEmitDotDot = !indentBeforeDot && needsDotDotForPropertyAccess(node.expression); + write(shouldEmitDotDot ? ".." : "."); + increaseIndentIf(indentAfterDot); + emit(node.name); + decreaseIndentIf(indentBeforeDot, indentAfterDot); + } + // 1..toString is a valid property access, emit a dot after the literal + // Also emit a dot if expression is a integer const enum value - it will appear in generated code as numeric literal + function needsDotDotForPropertyAccess(expression) { + if (expression.kind === 8 /* NumericLiteral */) { + // check if numeric literal was originally written with a dot + var text = getLiteralTextOfNode(expression); + return text.indexOf(ts.tokenToString(21 /* DotToken */)) < 0; + } + else if (ts.isPropertyAccessExpression(expression) || ts.isElementAccessExpression(expression)) { + // check if constant enum value is integer + var constantValue = ts.getConstantValue(expression); + // isFinite handles cases when constantValue is undefined + return isFinite(constantValue) + && Math.floor(constantValue) === constantValue + && compilerOptions.removeComments; + } + } + function emitElementAccessExpression(node) { + emitExpression(node.expression); + write("["); + emitExpression(node.argumentExpression); + write("]"); + } + function emitCallExpression(node) { + emitExpression(node.expression); + emitExpressionList(node, node.arguments, 1296 /* CallExpressionArguments */); + } + function emitNewExpression(node) { + write("new "); + emitExpression(node.expression); + emitExpressionList(node, node.arguments, 9488 /* NewExpressionArguments */); + } + function emitTaggedTemplateExpression(node) { + emitExpression(node.tag); + write(" "); + emitExpression(node.template); + } + function emitTypeAssertionExpression(node) { + if (node.type) { + write("<"); + emit(node.type); + write(">"); + } + emitExpression(node.expression); + } + function emitParenthesizedExpression(node) { + write("("); + emitExpression(node.expression); + write(")"); + } + function emitFunctionExpression(node) { + emitFunctionDeclarationOrExpression(node); + } + function emitArrowFunction(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + emitSignatureAndBody(node, emitArrowFunctionHead); + } + function emitArrowFunctionHead(node) { + emitTypeParameters(node, node.typeParameters); + emitParametersForArrow(node, node.parameters); + emitWithPrefix(": ", node.type); + write(" =>"); + } + function emitDeleteExpression(node) { + write("delete "); + emitExpression(node.expression); + } + function emitTypeOfExpression(node) { + write("typeof "); + emitExpression(node.expression); + } + function emitVoidExpression(node) { + write("void "); + emitExpression(node.expression); + } + function emitAwaitExpression(node) { + write("await "); + emitExpression(node.expression); + } + function emitPrefixUnaryExpression(node) { + writeTokenText(node.operator); + if (shouldEmitWhitespaceBeforeOperand(node)) { + write(" "); + } + emitExpression(node.operand); + } + function shouldEmitWhitespaceBeforeOperand(node) { + // In some cases, we need to emit a space between the operator and the operand. One obvious case + // is when the operator is an identifier, like delete or typeof. We also need to do this for plus + // and minus expressions in certain cases. Specifically, consider the following two cases (parens + // are just for clarity of exposition, and not part of the source code): + // + // (+(+1)) + // (+(++1)) + // + // We need to emit a space in both cases. In the first case, the absence of a space will make + // the resulting expression a prefix increment operation. And in the second, it will make the resulting + // expression a prefix increment whose operand is a plus expression - (++(+x)) + // The same is true of minus of course. + var operand = node.operand; + return operand.kind === 185 /* PrefixUnaryExpression */ + && ((node.operator === 35 /* PlusToken */ && (operand.operator === 35 /* PlusToken */ || operand.operator === 41 /* PlusPlusToken */)) + || (node.operator === 36 /* MinusToken */ && (operand.operator === 36 /* MinusToken */ || operand.operator === 42 /* MinusMinusToken */))); + } + function emitPostfixUnaryExpression(node) { + emitExpression(node.operand); + writeTokenText(node.operator); + } + function emitBinaryExpression(node) { + var isCommaOperator = node.operatorToken.kind !== 24 /* CommaToken */; + var indentBeforeOperator = needsIndentation(node, node.left, node.operatorToken); + var indentAfterOperator = needsIndentation(node, node.operatorToken, node.right); + emitExpression(node.left); + increaseIndentIf(indentBeforeOperator, isCommaOperator ? " " : undefined); + writeTokenText(node.operatorToken.kind); + increaseIndentIf(indentAfterOperator, " "); + emitExpression(node.right); + decreaseIndentIf(indentBeforeOperator, indentAfterOperator); + } + function emitConditionalExpression(node) { + var indentBeforeQuestion = needsIndentation(node, node.condition, node.questionToken); + var indentAfterQuestion = needsIndentation(node, node.questionToken, node.whenTrue); + var indentBeforeColon = needsIndentation(node, node.whenTrue, node.colonToken); + var indentAfterColon = needsIndentation(node, node.colonToken, node.whenFalse); + emitExpression(node.condition); + increaseIndentIf(indentBeforeQuestion, " "); + write("?"); + increaseIndentIf(indentAfterQuestion, " "); + emitExpression(node.whenTrue); + decreaseIndentIf(indentBeforeQuestion, indentAfterQuestion); + increaseIndentIf(indentBeforeColon, " "); + write(":"); + increaseIndentIf(indentAfterColon, " "); + emitExpression(node.whenFalse); + decreaseIndentIf(indentBeforeColon, indentAfterColon); + } + function emitTemplateExpression(node) { + emit(node.head); + emitList(node, node.templateSpans, 131072 /* TemplateExpressionSpans */); + } + function emitYieldExpression(node) { + write(node.asteriskToken ? "yield*" : "yield"); + emitExpressionWithPrefix(" ", node.expression); + } + function emitSpreadElementExpression(node) { + write("..."); + emitExpression(node.expression); + } + function emitClassExpression(node) { + emitClassDeclarationOrExpression(node); + } + function emitExpressionWithTypeArguments(node) { + emitExpression(node.expression); + emitTypeArguments(node, node.typeArguments); + } + function emitAsExpression(node) { + emitExpression(node.expression); + if (node.type) { + write(" as "); + emit(node.type); + } + } + function emitNonNullExpression(node) { + emitExpression(node.expression); + write("!"); + } + // + // Misc + // + function emitTemplateSpan(node) { + emitExpression(node.expression); + emit(node.literal); + } + // + // Statements + // + function emitBlock(node, format) { + if (isSingleLineEmptyBlock(node)) { + writeToken(15 /* OpenBraceToken */, node.pos, /*contextNode*/ node); + write(" "); + writeToken(16 /* CloseBraceToken */, node.statements.end, /*contextNode*/ node); } else { - fileProcessingDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, fileName, existingFileName)); + writeToken(15 /* OpenBraceToken */, node.pos, /*contextNode*/ node); + emitBlockStatements(node); + writeToken(16 /* CloseBraceToken */, node.statements.end, /*contextNode*/ node); } } - // Get source file from normalized fileName - function findSourceFile(fileName, path, isDefaultLib, isReference, refFile, refPos, refEnd) { - if (filesByName.contains(path)) { - var file_1 = filesByName.get(path); - // try to check if we've already seen this file but with a different casing in path - // NOTE: this only makes sense for case-insensitive file systems - if (file_1 && options.forceConsistentCasingInFileNames && ts.getNormalizedAbsolutePath(file_1.fileName, currentDirectory) !== ts.getNormalizedAbsolutePath(fileName, currentDirectory)) { - reportFileNamesDifferOnlyInCasingError(fileName, file_1.fileName, refFile, refPos, refEnd); - } - // If the file was previously found via a node_modules search, but is now being processed as a root file, - // then everything it sucks in may also be marked incorrectly, and needs to be checked again. - if (file_1 && sourceFilesFoundSearchingNodeModules[file_1.path] && currentNodeModulesDepth == 0) { - sourceFilesFoundSearchingNodeModules[file_1.path] = false; - if (!options.noResolve) { - processReferencedFiles(file_1, ts.getDirectoryPath(fileName), isDefaultLib); - processTypeReferenceDirectives(file_1); - } - modulesWithElidedImports[file_1.path] = false; - processImportedModules(file_1, ts.getDirectoryPath(fileName)); + function emitBlockStatements(node) { + if (ts.getEmitFlags(node) & 32 /* SingleLine */) { + emitList(node, node.statements, 384 /* SingleLineBlockStatements */); + } + else { + emitList(node, node.statements, 65 /* MultiLineBlockStatements */); + } + } + function emitVariableStatement(node) { + emitModifiers(node, node.modifiers); + emit(node.declarationList); + write(";"); + } + function emitEmptyStatement(node) { + write(";"); + } + function emitExpressionStatement(node) { + emitExpression(node.expression); + write(";"); + } + function emitIfStatement(node) { + var openParenPos = writeToken(88 /* IfKeyword */, node.pos, node); + write(" "); + writeToken(17 /* OpenParenToken */, openParenPos, node); + emitExpression(node.expression); + writeToken(18 /* CloseParenToken */, node.expression.end, node); + emitEmbeddedStatement(node.thenStatement); + if (node.elseStatement) { + writeLine(); + writeToken(80 /* ElseKeyword */, node.thenStatement.end, node); + if (node.elseStatement.kind === 203 /* IfStatement */) { + write(" "); + emit(node.elseStatement); } - else if (file_1 && modulesWithElidedImports[file_1.path]) { - if (currentNodeModulesDepth < maxNodeModulesJsDepth) { - modulesWithElidedImports[file_1.path] = false; - processImportedModules(file_1, ts.getDirectoryPath(fileName)); - } + else { + emitEmbeddedStatement(node.elseStatement); } - return file_1; } - // We haven't looked for this file, do so now and cache result - var file = host.getSourceFile(fileName, options.target, function (hostErrorMessage) { - if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) { - fileProcessingDiagnostics.add(ts.createFileDiagnostic(refFile, refPos, refEnd - refPos, ts.Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage)); + } + function emitDoStatement(node) { + write("do"); + emitEmbeddedStatement(node.statement); + if (ts.isBlock(node.statement)) { + write(" "); + } + else { + writeLine(); + } + write("while ("); + emitExpression(node.expression); + write(");"); + } + function emitWhileStatement(node) { + write("while ("); + emitExpression(node.expression); + write(")"); + emitEmbeddedStatement(node.statement); + } + function emitForStatement(node) { + var openParenPos = writeToken(86 /* ForKeyword */, node.pos); + write(" "); + writeToken(17 /* OpenParenToken */, openParenPos, /*contextNode*/ node); + emitForBinding(node.initializer); + write(";"); + emitExpressionWithPrefix(" ", node.condition); + write(";"); + emitExpressionWithPrefix(" ", node.incrementor); + write(")"); + emitEmbeddedStatement(node.statement); + } + function emitForInStatement(node) { + var openParenPos = writeToken(86 /* ForKeyword */, node.pos); + write(" "); + writeToken(17 /* OpenParenToken */, openParenPos); + emitForBinding(node.initializer); + write(" in "); + emitExpression(node.expression); + writeToken(18 /* CloseParenToken */, node.expression.end); + emitEmbeddedStatement(node.statement); + } + function emitForOfStatement(node) { + var openParenPos = writeToken(86 /* ForKeyword */, node.pos); + write(" "); + writeToken(17 /* OpenParenToken */, openParenPos); + emitForBinding(node.initializer); + write(" of "); + emitExpression(node.expression); + writeToken(18 /* CloseParenToken */, node.expression.end); + emitEmbeddedStatement(node.statement); + } + function emitForBinding(node) { + if (node !== undefined) { + if (node.kind === 219 /* VariableDeclarationList */) { + emit(node); } else { - fileProcessingDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage)); + emitExpression(node); } - }); - filesByName.set(path, file); - if (file) { - sourceFilesFoundSearchingNodeModules[path] = (currentNodeModulesDepth > 0); - file.path = path; - if (host.useCaseSensitiveFileNames()) { - // for case-sensitive file systems check if we've already seen some file with similar filename ignoring case - var existingFile = filesByNameIgnoreCase.get(path); - if (existingFile) { - reportFileNamesDifferOnlyInCasingError(fileName, existingFile.fileName, refFile, refPos, refEnd); + } + } + function emitContinueStatement(node) { + writeToken(75 /* ContinueKeyword */, node.pos); + emitWithPrefix(" ", node.label); + write(";"); + } + function emitBreakStatement(node) { + writeToken(70 /* BreakKeyword */, node.pos); + emitWithPrefix(" ", node.label); + write(";"); + } + function emitReturnStatement(node) { + writeToken(94 /* ReturnKeyword */, node.pos, /*contextNode*/ node); + emitExpressionWithPrefix(" ", node.expression); + write(";"); + } + function emitWithStatement(node) { + write("with ("); + emitExpression(node.expression); + write(")"); + emitEmbeddedStatement(node.statement); + } + function emitSwitchStatement(node) { + var openParenPos = writeToken(96 /* SwitchKeyword */, node.pos); + write(" "); + writeToken(17 /* OpenParenToken */, openParenPos); + emitExpression(node.expression); + writeToken(18 /* CloseParenToken */, node.expression.end); + write(" "); + emit(node.caseBlock); + } + function emitLabeledStatement(node) { + emit(node.label); + write(": "); + emit(node.statement); + } + function emitThrowStatement(node) { + write("throw"); + emitExpressionWithPrefix(" ", node.expression); + write(";"); + } + function emitTryStatement(node) { + write("try "); + emit(node.tryBlock); + emit(node.catchClause); + if (node.finallyBlock) { + writeLine(); + write("finally "); + emit(node.finallyBlock); + } + } + function emitDebuggerStatement(node) { + writeToken(76 /* DebuggerKeyword */, node.pos); + write(";"); + } + // + // Declarations + // + function emitVariableDeclaration(node) { + emit(node.name); + emitExpressionWithPrefix(" = ", node.initializer); + } + function emitVariableDeclarationList(node) { + write(ts.isLet(node) ? "let " : ts.isConst(node) ? "const " : "var "); + emitList(node, node.declarations, 272 /* VariableDeclarationList */); + } + function emitFunctionDeclaration(node) { + emitFunctionDeclarationOrExpression(node); + } + function emitFunctionDeclarationOrExpression(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + write(node.asteriskToken ? "function* " : "function "); + emitIdentifierName(node.name); + emitSignatureAndBody(node, emitSignatureHead); + } + function emitSignatureAndBody(node, emitSignatureHead) { + var body = node.body; + if (body) { + if (ts.isBlock(body)) { + var indentedFlag = ts.getEmitFlags(node) & 524288 /* Indented */; + if (indentedFlag) { + increaseIndent(); + } + if (ts.getEmitFlags(node) & 4194304 /* ReuseTempVariableScope */) { + emitSignatureHead(node); + emitBlockFunctionBody(node, body); } else { - filesByNameIgnoreCase.set(path, file); + var savedTempFlags = tempFlags; + tempFlags = 0; + emitSignatureHead(node); + emitBlockFunctionBody(node, body); + tempFlags = savedTempFlags; + } + if (indentedFlag) { + decreaseIndent(); } - } - skipDefaultLib = skipDefaultLib || file.hasNoDefaultLib; - var basePath = ts.getDirectoryPath(fileName); - if (!options.noResolve) { - processReferencedFiles(file, basePath, isDefaultLib); - processTypeReferenceDirectives(file); - } - // always process imported modules to record module name resolutions - processImportedModules(file, basePath); - if (isDefaultLib) { - files.unshift(file); } else { - files.push(file); + emitSignatureHead(node); + write(" "); + emitExpression(body); } } - return file; + else { + emitSignatureHead(node); + write(";"); + } } - function processReferencedFiles(file, basePath, isDefaultLib) { - ts.forEach(file.referencedFiles, function (ref) { - var referencedFileName = resolveTripleslashReference(ref.fileName, file.fileName); - processSourceFile(referencedFileName, isDefaultLib, /*isReference*/ true, file, ref.pos, ref.end); - }); + function emitSignatureHead(node) { + emitTypeParameters(node, node.typeParameters); + emitParameters(node, node.parameters); + emitWithPrefix(": ", node.type); } - function processTypeReferenceDirectives(file) { - // We lower-case all type references because npm automatically lowercases all packages. See GH#9824. - var typeDirectives = ts.map(file.typeReferenceDirectives, function (ref) { return ref.fileName.toLocaleLowerCase(); }); - var resolutions = resolveTypeReferenceDirectiveNamesWorker(typeDirectives, file.fileName); - for (var i = 0; i < typeDirectives.length; i++) { - var ref = file.typeReferenceDirectives[i]; - var resolvedTypeReferenceDirective = resolutions[i]; - // store resolved type directive on the file - var fileName = ref.fileName.toLocaleLowerCase(); - ts.setResolvedTypeReferenceDirective(file, fileName, resolvedTypeReferenceDirective); - processTypeReferenceDirective(fileName, resolvedTypeReferenceDirective, file, ref.pos, ref.end); + function shouldEmitBlockFunctionBodyOnSingleLine(parentNode, body) { + // We must emit a function body as a single-line body in the following case: + // * The body has NodeEmitFlags.SingleLine specified. + // We must emit a function body as a multi-line body in the following cases: + // * The body is explicitly marked as multi-line. + // * A non-synthesized body's start and end position are on different lines. + // * Any statement in the body starts on a new line. + if (ts.getEmitFlags(body) & 32 /* SingleLine */) { + return true; } - } - function processTypeReferenceDirective(typeReferenceDirective, resolvedTypeReferenceDirective, refFile, refPos, refEnd) { - // If we already found this library as a primary reference - nothing to do - var previousResolution = resolvedTypeReferenceDirectives[typeReferenceDirective]; - if (previousResolution && previousResolution.primary) { - return; + if (body.multiLine) { + return false; } - var saveResolution = true; - if (resolvedTypeReferenceDirective) { - if (resolvedTypeReferenceDirective.primary) { - // resolved from the primary path - processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, /*isDefaultLib*/ false, /*isReference*/ true, refFile, refPos, refEnd); - } - else { - // If we already resolved to this file, it must have been a secondary reference. Check file contents - // for sameness and possibly issue an error - if (previousResolution) { - var otherFileText = host.readFile(resolvedTypeReferenceDirective.resolvedFileName); - if (otherFileText !== getSourceFile(previousResolution.resolvedFileName).text) { - fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd, ts.Diagnostics.Conflicting_definitions_for_0_found_at_1_and_2_Consider_installing_a_specific_version_of_this_library_to_resolve_the_conflict, typeReferenceDirective, resolvedTypeReferenceDirective.resolvedFileName, previousResolution.resolvedFileName)); - } - // don't overwrite previous resolution result - saveResolution = false; - } - else { - // First resolution of this library - processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, /*isDefaultLib*/ false, /*isReference*/ true, refFile, refPos, refEnd); - } + if (!ts.nodeIsSynthesized(body) && !ts.rangeIsOnSingleLine(body, currentSourceFile)) { + return false; + } + if (shouldWriteLeadingLineTerminator(body, body.statements, 2 /* PreserveLines */) + || shouldWriteClosingLineTerminator(body, body.statements, 2 /* PreserveLines */)) { + return false; + } + var previousStatement; + for (var _a = 0, _b = body.statements; _a < _b.length; _a++) { + var statement = _b[_a]; + if (shouldWriteSeparatingLineTerminator(previousStatement, statement, 2 /* PreserveLines */)) { + return false; } + previousStatement = statement; + } + return true; + } + function emitBlockFunctionBody(parentNode, body) { + write(" {"); + increaseIndent(); + emitBodyWithDetachedComments(body, body.statements, shouldEmitBlockFunctionBodyOnSingleLine(parentNode, body) + ? emitBlockFunctionBodyOnSingleLine + : emitBlockFunctionBodyWorker); + decreaseIndent(); + writeToken(16 /* CloseBraceToken */, body.statements.end, body); + } + function emitBlockFunctionBodyOnSingleLine(body) { + emitBlockFunctionBodyWorker(body, /*emitBlockFunctionBodyOnSingleLine*/ true); + } + function emitBlockFunctionBodyWorker(body, emitBlockFunctionBodyOnSingleLine) { + // Emit all the prologue directives (like "use strict"). + var statementOffset = emitPrologueDirectives(body.statements, /*startWithNewLine*/ true); + var helpersEmitted = emitHelpers(body); + if (statementOffset === 0 && !helpersEmitted && emitBlockFunctionBodyOnSingleLine) { + decreaseIndent(); + emitList(body, body.statements, 384 /* SingleLineFunctionBodyStatements */); + increaseIndent(); } else { - fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd, ts.Diagnostics.Cannot_find_type_definition_file_for_0, typeReferenceDirective)); + emitList(body, body.statements, 1 /* MultiLineFunctionBodyStatements */, statementOffset); } - if (saveResolution) { - resolvedTypeReferenceDirectives[typeReferenceDirective] = resolvedTypeReferenceDirective; + } + function emitClassDeclaration(node) { + emitClassDeclarationOrExpression(node); + } + function emitClassDeclarationOrExpression(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + write("class"); + emitNodeWithPrefix(" ", node.name, emitIdentifierName); + var indentedFlag = ts.getEmitFlags(node) & 524288 /* Indented */; + if (indentedFlag) { + increaseIndent(); + } + emitTypeParameters(node, node.typeParameters); + emitList(node, node.heritageClauses, 256 /* ClassHeritageClauses */); + var savedTempFlags = tempFlags; + tempFlags = 0; + write(" {"); + emitList(node, node.members, 65 /* ClassMembers */); + write("}"); + if (indentedFlag) { + decreaseIndent(); } + tempFlags = savedTempFlags; } - function createDiagnostic(refFile, refPos, refEnd, message) { - var args = []; - for (var _i = 4; _i < arguments.length; _i++) { - args[_i - 4] = arguments[_i]; + function emitInterfaceDeclaration(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + write("interface "); + emit(node.name); + emitTypeParameters(node, node.typeParameters); + emitList(node, node.heritageClauses, 256 /* HeritageClauses */); + write(" {"); + emitList(node, node.members, 65 /* InterfaceMembers */); + write("}"); + } + function emitTypeAliasDeclaration(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + write("type "); + emit(node.name); + emitTypeParameters(node, node.typeParameters); + write(" = "); + emit(node.type); + write(";"); + } + function emitEnumDeclaration(node) { + emitModifiers(node, node.modifiers); + write("enum "); + emit(node.name); + var savedTempFlags = tempFlags; + tempFlags = 0; + write(" {"); + emitList(node, node.members, 81 /* EnumMembers */); + write("}"); + tempFlags = savedTempFlags; + } + function emitModuleDeclaration(node) { + emitModifiers(node, node.modifiers); + write(node.flags & 16 /* Namespace */ ? "namespace " : "module "); + emit(node.name); + var body = node.body; + while (body.kind === 225 /* ModuleDeclaration */) { + write("."); + emit(body.name); + body = body.body; } - if (refFile === undefined || refPos === undefined || refEnd === undefined) { - return ts.createCompilerDiagnostic.apply(void 0, [message].concat(args)); + write(" "); + emit(body); + } + function emitModuleBlock(node) { + if (isSingleLineEmptyBlock(node)) { + write("{ }"); } else { - return ts.createFileDiagnostic.apply(void 0, [refFile, refPos, refEnd - refPos, message].concat(args)); + var savedTempFlags = tempFlags; + tempFlags = 0; + write("{"); + increaseIndent(); + emitBlockStatements(node); + write("}"); + tempFlags = savedTempFlags; } } - function getCanonicalFileName(fileName) { - return host.getCanonicalFileName(fileName); + function emitCaseBlock(node) { + writeToken(15 /* OpenBraceToken */, node.pos); + emitList(node, node.clauses, 65 /* CaseBlockClauses */); + writeToken(16 /* CloseBraceToken */, node.clauses.end); } - function processImportedModules(file, basePath) { - collectExternalModuleReferences(file); - if (file.imports.length || file.moduleAugmentations.length) { - file.resolvedModules = ts.createMap(); - var moduleNames = ts.map(ts.concatenate(file.imports, file.moduleAugmentations), getTextOfLiteral); - var resolutions = resolveModuleNamesWorker(moduleNames, ts.getNormalizedAbsolutePath(file.fileName, currentDirectory)); - for (var i = 0; i < moduleNames.length; i++) { - var resolution = resolutions[i]; - ts.setResolvedModule(file, moduleNames[i], resolution); - var resolvedPath = resolution ? ts.toPath(resolution.resolvedFileName, currentDirectory, getCanonicalFileName) : undefined; - // add file to program only if: - // - resolution was successful - // - noResolve is falsy - // - module name comes from the list of imports - // - it's not a top level JavaScript module that exceeded the search max - var isFromNodeModulesSearch = resolution && resolution.isExternalLibraryImport; - var isJsFileFromNodeModules = isFromNodeModulesSearch && ts.hasJavaScriptFileExtension(resolution.resolvedFileName); - if (isFromNodeModulesSearch) { - currentNodeModulesDepth++; - } - var elideImport = isJsFileFromNodeModules && currentNodeModulesDepth > maxNodeModulesJsDepth; - var shouldAddFile = resolution && !options.noResolve && i < file.imports.length && !elideImport; - if (elideImport) { - modulesWithElidedImports[file.path] = true; - } - else if (shouldAddFile) { - findSourceFile(resolution.resolvedFileName, resolvedPath, - /*isDefaultLib*/ false, /*isReference*/ false, file, ts.skipTrivia(file.text, file.imports[i].pos), file.imports[i].end); - } - if (isFromNodeModulesSearch) { - currentNodeModulesDepth--; - } - } + function emitImportEqualsDeclaration(node) { + emitModifiers(node, node.modifiers); + write("import "); + emit(node.name); + write(" = "); + emitModuleReference(node.moduleReference); + write(";"); + } + function emitModuleReference(node) { + if (node.kind === 69 /* Identifier */) { + emitExpression(node); } else { - // no imports - drop cached module resolutions - file.resolvedModules = undefined; + emit(node); } - return; } - function computeCommonSourceDirectory(sourceFiles) { - var fileNames = []; - for (var _i = 0, sourceFiles_2 = sourceFiles; _i < sourceFiles_2.length; _i++) { - var file = sourceFiles_2[_i]; - if (!file.isDeclarationFile) { - fileNames.push(file.fileName); - } + function emitImportDeclaration(node) { + emitModifiers(node, node.modifiers); + write("import "); + if (node.importClause) { + emit(node.importClause); + write(" from "); } - return computeCommonSourceDirectoryOfFilenames(fileNames, currentDirectory, getCanonicalFileName); + emitExpression(node.moduleSpecifier); + write(";"); } - function checkSourceFilesBelongToPath(sourceFiles, rootDirectory) { - var allFilesBelongToPath = true; - if (sourceFiles) { - var absoluteRootDirectoryPath = host.getCanonicalFileName(ts.getNormalizedAbsolutePath(rootDirectory, currentDirectory)); - for (var _i = 0, sourceFiles_3 = sourceFiles; _i < sourceFiles_3.length; _i++) { - var sourceFile = sourceFiles_3[_i]; - if (!ts.isDeclarationFile(sourceFile)) { - var absoluteSourceFilePath = host.getCanonicalFileName(ts.getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory)); - if (absoluteSourceFilePath.indexOf(absoluteRootDirectoryPath) !== 0) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, sourceFile.fileName, options.rootDir)); - allFilesBelongToPath = false; - } - } - } + function emitImportClause(node) { + emit(node.name); + if (node.name && node.namedBindings) { + write(", "); + } + emit(node.namedBindings); + } + function emitNamespaceImport(node) { + write("* as "); + emit(node.name); + } + function emitNamedImports(node) { + emitNamedImportsOrExports(node); + } + function emitImportSpecifier(node) { + emitImportOrExportSpecifier(node); + } + function emitExportAssignment(node) { + write(node.isExportEquals ? "export = " : "export default "); + emitExpression(node.expression); + write(";"); + } + function emitExportDeclaration(node) { + write("export "); + if (node.exportClause) { + emit(node.exportClause); + } + else { + write("*"); + } + if (node.moduleSpecifier) { + write(" from "); + emitExpression(node.moduleSpecifier); + } + write(";"); + } + function emitNamedExports(node) { + emitNamedImportsOrExports(node); + } + function emitExportSpecifier(node) { + emitImportOrExportSpecifier(node); + } + function emitNamedImportsOrExports(node) { + write("{"); + emitList(node, node.elements, 432 /* NamedImportsOrExportsElements */); + write("}"); + } + function emitImportOrExportSpecifier(node) { + if (node.propertyName) { + emit(node.propertyName); + write(" as "); + } + emit(node.name); + } + // + // Module references + // + function emitExternalModuleReference(node) { + write("require("); + emitExpression(node.expression); + write(")"); + } + // + // JSX + // + function emitJsxElement(node) { + emit(node.openingElement); + emitList(node, node.children, 131072 /* JsxElementChildren */); + emit(node.closingElement); + } + function emitJsxSelfClosingElement(node) { + write("<"); + emitJsxTagName(node.tagName); + write(" "); + emitList(node, node.attributes, 131328 /* JsxElementAttributes */); + write("/>"); + } + function emitJsxOpeningElement(node) { + write("<"); + emitJsxTagName(node.tagName); + writeIfAny(node.attributes, " "); + emitList(node, node.attributes, 131328 /* JsxElementAttributes */); + write(">"); + } + function emitJsxText(node) { + writer.writeLiteral(getTextOfNode(node, /*includeTrivia*/ true)); + } + function emitJsxClosingElement(node) { + write(""); + } + function emitJsxAttribute(node) { + emit(node.name); + emitWithPrefix("=", node.initializer); + } + function emitJsxSpreadAttribute(node) { + write("{..."); + emitExpression(node.expression); + write("}"); + } + function emitJsxExpression(node) { + if (node.expression) { + write("{"); + emitExpression(node.expression); + write("}"); + } + } + function emitJsxTagName(node) { + if (node.kind === 69 /* Identifier */) { + emitExpression(node); + } + else { + emit(node); } - return allFilesBelongToPath; } - function verifyCompilerOptions() { - if (options.isolatedModules) { - if (options.declaration) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "declaration", "isolatedModules")); - } - if (options.noEmitOnError) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "noEmitOnError", "isolatedModules")); - } - if (options.out) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "out", "isolatedModules")); - } - if (options.outFile) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "outFile", "isolatedModules")); - } + // + // Clauses + // + function emitCaseClause(node) { + write("case "); + emitExpression(node.expression); + write(":"); + emitCaseOrDefaultClauseStatements(node, node.statements); + } + function emitDefaultClause(node) { + write("default:"); + emitCaseOrDefaultClauseStatements(node, node.statements); + } + function emitCaseOrDefaultClauseStatements(parentNode, statements) { + var emitAsSingleStatement = statements.length === 1 && + ( + // treat synthesized nodes as located on the same line for emit purposes + ts.nodeIsSynthesized(parentNode) || + ts.nodeIsSynthesized(statements[0]) || + ts.rangeStartPositionsAreOnSameLine(parentNode, statements[0], currentSourceFile)); + if (emitAsSingleStatement) { + write(" "); + emit(statements[0]); } - if (options.inlineSourceMap) { - if (options.sourceMap) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "sourceMap", "inlineSourceMap")); - } - if (options.mapRoot) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "mapRoot", "inlineSourceMap")); - } + else { + emitList(parentNode, statements, 81985 /* CaseOrDefaultClauseStatements */); } - if (options.paths && options.baseUrl === undefined) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_paths_cannot_be_used_without_specifying_baseUrl_option)); + } + function emitHeritageClause(node) { + write(" "); + writeTokenText(node.token); + write(" "); + emitList(node, node.types, 272 /* HeritageClauseTypes */); + } + function emitCatchClause(node) { + writeLine(); + var openParenPos = writeToken(72 /* CatchKeyword */, node.pos); + write(" "); + writeToken(17 /* OpenParenToken */, openParenPos); + emit(node.variableDeclaration); + writeToken(18 /* CloseParenToken */, node.variableDeclaration ? node.variableDeclaration.end : openParenPos); + write(" "); + emit(node.block); + } + // + // Property assignments + // + function emitPropertyAssignment(node) { + emit(node.name); + write(": "); + // This is to ensure that we emit comment in the following case: + // For example: + // obj = { + // id: /*comment1*/ ()=>void + // } + // "comment1" is not considered to be leading comment for node.initializer + // but rather a trailing comment on the previous node. + var initializer = node.initializer; + if ((ts.getEmitFlags(initializer) & 16384 /* NoLeadingComments */) === 0) { + var commentRange = ts.getCommentRange(initializer); + emitTrailingCommentsOfPosition(commentRange.pos); } - if (options.paths) { - for (var key in options.paths) { - if (!ts.hasProperty(options.paths, key)) { - continue; - } - if (!hasZeroOrOneAsteriskCharacter(key)) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, key)); - } - if (ts.isArray(options.paths[key])) { - if (options.paths[key].length === 0) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Substitutions_for_pattern_0_shouldn_t_be_an_empty_array, key)); - } - for (var _i = 0, _a = options.paths[key]; _i < _a.length; _i++) { - var subst = _a[_i]; - var typeOfSubst = typeof subst; - if (typeOfSubst === "string") { - if (!hasZeroOrOneAsteriskCharacter(subst)) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Substitution_0_in_pattern_1_in_can_have_at_most_one_Asterisk_character, subst, key)); - } - } - else { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Substitution_0_for_pattern_1_has_incorrect_type_expected_string_got_2, subst, key, typeOfSubst)); - } - } - } - else { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Substitutions_for_pattern_0_should_be_an_array, key)); - } - } + emitExpression(initializer); + } + function emitShorthandPropertyAssignment(node) { + emit(node.name); + if (node.objectAssignmentInitializer) { + write(" = "); + emitExpression(node.objectAssignmentInitializer); } - if (!options.sourceMap && !options.inlineSourceMap) { - if (options.inlineSources) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided, "inlineSources")); + } + // + // Enum + // + function emitEnumMember(node) { + emit(node.name); + emitExpressionWithPrefix(" = ", node.initializer); + } + // + // Top-level nodes + // + function emitSourceFile(node) { + writeLine(); + emitShebang(); + emitBodyWithDetachedComments(node, node.statements, emitSourceFileWorker); + } + function emitSourceFileWorker(node) { + var statements = node.statements; + var statementOffset = emitPrologueDirectives(statements); + var savedTempFlags = tempFlags; + tempFlags = 0; + emitHelpers(node); + emitList(node, statements, 1 /* MultiLine */, statementOffset); + tempFlags = savedTempFlags; + } + // Transformation nodes + function emitPartiallyEmittedExpression(node) { + emitExpression(node.expression); + } + /** + * Emits any prologue directives at the start of a Statement list, returning the + * number of prologue directives written to the output. + */ + function emitPrologueDirectives(statements, startWithNewLine) { + for (var i = 0; i < statements.length; i++) { + if (ts.isPrologueDirective(statements[i])) { + if (startWithNewLine || i > 0) { + writeLine(); + } + emit(statements[i]); } - if (options.sourceRoot) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided, "sourceRoot")); + else { + // return index of the first non prologue directive + return i; } } - if (options.out && options.outFile) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "out", "outFile")); + return statements.length; + } + function emitHelpers(node) { + var emitFlags = ts.getEmitFlags(node); + var helpersEmitted = false; + if (emitFlags & 1 /* EmitEmitHelpers */) { + helpersEmitted = emitEmitHelpers(currentSourceFile); } - if (options.mapRoot && !options.sourceMap) { - // Error to specify --mapRoot without --sourcemap - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "mapRoot", "sourceMap")); + if (emitFlags & 2 /* EmitExportStar */) { + writeLines(exportStarHelper); + helpersEmitted = true; } - if (options.declarationDir) { - if (!options.declaration) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "declarationDir", "declaration")); - } - if (options.out || options.outFile) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "declarationDir", options.out ? "out" : "outFile")); - } + if (emitFlags & 4 /* EmitSuperHelper */) { + writeLines(superHelper); + helpersEmitted = true; } - if (options.lib && options.noLib) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "lib", "noLib")); + if (emitFlags & 8 /* EmitAdvancedSuperHelper */) { + writeLines(advancedSuperHelper); + helpersEmitted = true; } - var languageVersion = options.target || 0 /* ES3 */; - var outFile = options.outFile || options.out; - var firstNonAmbientExternalModuleSourceFile = ts.forEach(files, function (f) { return ts.isExternalModule(f) && !ts.isDeclarationFile(f) ? f : undefined; }); - if (options.isolatedModules) { - if (options.module === ts.ModuleKind.None && languageVersion < 2 /* ES6 */) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_isolatedModules_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES2015_or_higher)); - } - var firstNonExternalModuleSourceFile = ts.forEach(files, function (f) { return !ts.isExternalModule(f) && !ts.isDeclarationFile(f) ? f : undefined; }); - if (firstNonExternalModuleSourceFile) { - var span = ts.getErrorSpanForNode(firstNonExternalModuleSourceFile, firstNonExternalModuleSourceFile); - programDiagnostics.add(ts.createFileDiagnostic(firstNonExternalModuleSourceFile, span.start, span.length, ts.Diagnostics.Cannot_compile_namespaces_when_the_isolatedModules_flag_is_provided)); - } + return helpersEmitted; + } + function emitEmitHelpers(node) { + // Only emit helpers if the user did not say otherwise. + if (compilerOptions.noEmitHelpers) { + return false; } - else if (firstNonAmbientExternalModuleSourceFile && languageVersion < 2 /* ES6 */ && options.module === ts.ModuleKind.None) { - // We cannot use createDiagnosticFromNode because nodes do not have parents yet - var span = ts.getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, firstNonAmbientExternalModuleSourceFile.externalModuleIndicator); - programDiagnostics.add(ts.createFileDiagnostic(firstNonAmbientExternalModuleSourceFile, span.start, span.length, ts.Diagnostics.Cannot_use_imports_exports_or_module_augmentations_when_module_is_none)); + // Don't emit helpers if we can import them. + if (compilerOptions.importHelpers + && (ts.isExternalModule(node) || compilerOptions.isolatedModules)) { + return false; } - // Cannot specify module gen that isn't amd or system with --out - if (outFile) { - if (options.module && !(options.module === ts.ModuleKind.AMD || options.module === ts.ModuleKind.System)) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Only_amd_and_system_modules_are_supported_alongside_0, options.out ? "out" : "outFile")); - } - else if (options.module === undefined && firstNonAmbientExternalModuleSourceFile) { - var span = ts.getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, firstNonAmbientExternalModuleSourceFile.externalModuleIndicator); - programDiagnostics.add(ts.createFileDiagnostic(firstNonAmbientExternalModuleSourceFile, span.start, span.length, ts.Diagnostics.Cannot_compile_modules_using_option_0_unless_the_module_flag_is_amd_or_system, options.out ? "out" : "outFile")); - } + var helpersEmitted = false; + // Only Emit __extends function when target ES5. + // For target ES6 and above, we can emit classDeclaration as is. + if ((languageVersion < 2 /* ES6 */) && (!extendsEmitted && node.flags & 1024 /* HasClassExtends */)) { + writeLines(extendsHelper); + extendsEmitted = true; + helpersEmitted = true; } - // there has to be common source directory if user specified --outdir || --sourceRoot - // if user specified --mapRoot, there needs to be common source directory if there would be multiple files being emitted - if (options.outDir || - options.sourceRoot || - options.mapRoot) { - // Precalculate and cache the common source directory - var dir = getCommonSourceDirectory(); - // If we failed to find a good common directory, but outDir is specified and at least one of our files is on a windows drive/URL/other resource, add a failure - if (options.outDir && dir === "" && ts.forEach(files, function (file) { return ts.getRootLength(file.fileName) > 1; })) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files)); - } + if (compilerOptions.jsx !== 1 /* Preserve */ && !assignEmitted && (node.flags & 16384 /* HasJsxSpreadAttributes */)) { + writeLines(assignHelper); + assignEmitted = true; } - if (!options.noEmit && options.allowJs && options.declaration) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration")); + if (!decorateEmitted && node.flags & 2048 /* HasDecorators */) { + writeLines(decorateHelper); + if (compilerOptions.emitDecoratorMetadata) { + writeLines(metadataHelper); + } + decorateEmitted = true; + helpersEmitted = true; } - if (options.emitDecoratorMetadata && - !options.experimentalDecorators) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDecoratorMetadata", "experimentalDecorators")); + if (!paramEmitted && node.flags & 4096 /* HasParamDecorators */) { + writeLines(paramHelper); + paramEmitted = true; + helpersEmitted = true; } - if (options.reactNamespace && !ts.isIdentifier(options.reactNamespace, languageVersion)) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Invalid_value_for_reactNamespace_0_is_not_a_valid_identifier, options.reactNamespace)); + if (!awaiterEmitted && node.flags & 8192 /* HasAsyncFunctions */) { + writeLines(awaiterHelper); + if (languageVersion < 2 /* ES6 */) { + writeLines(generatorHelper); + } + awaiterEmitted = true; + helpersEmitted = true; } - // If the emit is enabled make sure that every output file is unique and not overwriting any of the input files - if (!options.noEmit && !options.suppressOutputPathCheck) { - var emitHost = getEmitHost(); - var emitFilesSeen_1 = ts.createFileMap(!host.useCaseSensitiveFileNames() ? function (key) { return key.toLocaleLowerCase(); } : undefined); - ts.forEachExpectedEmitFile(emitHost, function (emitFileNames, sourceFiles, isBundledEmit) { - verifyEmitFilePath(emitFileNames.jsFilePath, emitFilesSeen_1); - verifyEmitFilePath(emitFileNames.declarationFilePath, emitFilesSeen_1); - }); + if (helpersEmitted) { + writeLine(); } - // Verify that all the emit files are unique and don't overwrite input files - function verifyEmitFilePath(emitFileName, emitFilesSeen) { - if (emitFileName) { - var emitFilePath = ts.toPath(emitFileName, currentDirectory, getCanonicalFileName); - // Report error if the output overwrites input file - if (filesByName.contains(emitFilePath)) { - createEmitBlockingDiagnostics(emitFileName, emitFilePath, ts.Diagnostics.Cannot_write_file_0_because_it_would_overwrite_input_file); - } - // Report error if multiple files write into same file - if (emitFilesSeen.contains(emitFilePath)) { - // Already seen the same emit file - report error - createEmitBlockingDiagnostics(emitFileName, emitFilePath, ts.Diagnostics.Cannot_write_file_0_because_it_would_be_overwritten_by_multiple_input_files); - } - else { - emitFilesSeen.set(emitFilePath, true); + return helpersEmitted; + } + function writeLines(text) { + var lines = text.split(/\r\n|\r|\n/g); + for (var i = 0; i < lines.length; i++) { + var line = lines[i]; + if (line.length) { + if (i > 0) { + writeLine(); } + write(line); } } } - function createEmitBlockingDiagnostics(emitFileName, emitFilePath, message) { - hasEmitBlockingDiagnostics.set(ts.toPath(emitFileName, currentDirectory, getCanonicalFileName), true); - programDiagnostics.add(ts.createCompilerDiagnostic(message, emitFileName)); - } - } - ts.createProgram = createProgram; -})(ts || (ts = {})); -/// -/// -var ts; -(function (ts) { - var defaultFormatDiagnosticsHost = { - getCurrentDirectory: function () { return ts.sys.getCurrentDirectory(); }, - getNewLine: function () { return ts.sys.newLine; }, - getCanonicalFileName: ts.createGetCanonicalFileName(ts.sys.useCaseSensitiveFileNames) - }; - var reportDiagnosticWorker = reportDiagnosticSimply; - function reportDiagnostic(diagnostic, host) { - reportDiagnosticWorker(diagnostic, host || defaultFormatDiagnosticsHost); - } - function reportDiagnostics(diagnostics, host) { - for (var _i = 0, diagnostics_3 = diagnostics; _i < diagnostics_3.length; _i++) { - var diagnostic = diagnostics_3[_i]; - reportDiagnostic(diagnostic, host); - } - } - function reportEmittedFiles(files, host) { - if (!files || files.length == 0) { - return; + // + // Helpers + // + function emitShebang() { + var shebang = ts.getShebang(currentText); + if (shebang) { + write(shebang); + writeLine(); + } } - var currentDir = ts.sys.getCurrentDirectory(); - for (var _i = 0, files_3 = files; _i < files_3.length; _i++) { - var file = files_3[_i]; - var filepath = ts.getNormalizedAbsolutePath(file, currentDir); - ts.sys.write("TSFILE: " + filepath + ts.sys.newLine); + function emitModifiers(node, modifiers) { + if (modifiers && modifiers.length) { + emitList(node, modifiers, 256 /* Modifiers */); + write(" "); + } } - } - /** - * Checks to see if the locale is in the appropriate format, - * and if it is, attempts to set the appropriate language. - */ - function validateLocaleAndSetLanguage(locale, errors) { - var matchResult = /^([a-z]+)([_\-]([a-z]+))?$/.exec(locale.toLowerCase()); - if (!matchResult) { - errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Locale_must_be_of_the_form_language_or_language_territory_For_example_0_or_1, "en", "ja-jp")); - return false; + function emitWithPrefix(prefix, node) { + emitNodeWithPrefix(prefix, node, emit); } - var language = matchResult[1]; - var territory = matchResult[3]; - // First try the entire locale, then fall back to just language if that's all we have. - // Either ways do not fail, and fallback to the English diagnostic strings. - if (!trySetLanguageAndTerritory(language, territory, errors)) { - trySetLanguageAndTerritory(language, undefined, errors); + function emitExpressionWithPrefix(prefix, node) { + emitNodeWithPrefix(prefix, node, emitExpression); } - return true; - } - function trySetLanguageAndTerritory(language, territory, errors) { - var compilerFilePath = ts.normalizePath(ts.sys.getExecutingFilePath()); - var containingDirectoryPath = ts.getDirectoryPath(compilerFilePath); - var filePath = ts.combinePaths(containingDirectoryPath, language); - if (territory) { - filePath = filePath + "-" + territory; + function emitNodeWithPrefix(prefix, node, emit) { + if (node) { + write(prefix); + emit(node); + } } - filePath = ts.sys.resolvePath(ts.combinePaths(filePath, "diagnosticMessages.generated.json")); - if (!ts.sys.fileExists(filePath)) { - return false; + function emitWithSuffix(node, suffix) { + if (node) { + emit(node); + write(suffix); + } } - // TODO: Add codePage support for readFile? - var fileContents = ""; - try { - fileContents = ts.sys.readFile(filePath); + function emitEmbeddedStatement(node) { + if (ts.isBlock(node)) { + write(" "); + emit(node); + } + else { + writeLine(); + increaseIndent(); + emit(node); + decreaseIndent(); + } } - catch (e) { - errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unable_to_open_file_0, filePath)); - return false; + function emitDecorators(parentNode, decorators) { + emitList(parentNode, decorators, 24577 /* Decorators */); } - try { - ts.localizedDiagnosticMessages = JSON.parse(fileContents); + function emitTypeArguments(parentNode, typeArguments) { + emitList(parentNode, typeArguments, 26960 /* TypeArguments */); } - catch (e) { - errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Corrupted_locale_file_0, filePath)); - return false; + function emitTypeParameters(parentNode, typeParameters) { + emitList(parentNode, typeParameters, 26960 /* TypeParameters */); } - return true; - } - function countLines(program) { - var count = 0; - ts.forEach(program.getSourceFiles(), function (file) { - count += ts.getLineStarts(file).length; - }); - return count; - } - function getDiagnosticText(message) { - var args = []; - for (var _i = 1; _i < arguments.length; _i++) { - args[_i - 1] = arguments[_i]; + function emitParameters(parentNode, parameters) { + emitList(parentNode, parameters, 1360 /* Parameters */); } - var diagnostic = ts.createCompilerDiagnostic.apply(undefined, arguments); - return diagnostic.messageText; - } - function reportDiagnosticSimply(diagnostic, host) { - ts.sys.write(ts.formatDiagnostics([diagnostic], host)); - } - var redForegroundEscapeSequence = "\u001b[91m"; - var yellowForegroundEscapeSequence = "\u001b[93m"; - var blueForegroundEscapeSequence = "\u001b[93m"; - var gutterStyleSequence = "\u001b[100;30m"; - var gutterSeparator = " "; - var resetEscapeSequence = "\u001b[0m"; - var ellipsis = "..."; - var categoryFormatMap = ts.createMap((_a = {}, - _a[ts.DiagnosticCategory.Warning] = yellowForegroundEscapeSequence, - _a[ts.DiagnosticCategory.Error] = redForegroundEscapeSequence, - _a[ts.DiagnosticCategory.Message] = blueForegroundEscapeSequence, - _a - )); - function formatAndReset(text, formatStyle) { - return formatStyle + text + resetEscapeSequence; - } - function reportDiagnosticWithColorAndContext(diagnostic, host) { - var output = ""; - if (diagnostic.file) { - var start = diagnostic.start, length_4 = diagnostic.length, file = diagnostic.file; - var _a = ts.getLineAndCharacterOfPosition(file, start), firstLine = _a.line, firstLineChar = _a.character; - var _b = ts.getLineAndCharacterOfPosition(file, start + length_4), lastLine = _b.line, lastLineChar = _b.character; - var lastLineInFile = ts.getLineAndCharacterOfPosition(file, file.text.length).line; - var relativeFileName = host ? ts.convertToRelativePath(file.fileName, host.getCurrentDirectory(), function (fileName) { return host.getCanonicalFileName(fileName); }) : file.fileName; - var hasMoreThanFiveLines = (lastLine - firstLine) >= 4; - var gutterWidth = (lastLine + 1 + "").length; - if (hasMoreThanFiveLines) { - gutterWidth = Math.max(ellipsis.length, gutterWidth); + function emitParametersForArrow(parentNode, parameters) { + if (parameters && + parameters.length === 1 && + parameters[0].type === undefined && + parameters[0].pos === parentNode.pos) { + emit(parameters[0]); } - output += ts.sys.newLine; - for (var i = firstLine; i <= lastLine; i++) { - // If the error spans over 5 lines, we'll only show the first 2 and last 2 lines, - // so we'll skip ahead to the second-to-last line. - if (hasMoreThanFiveLines && firstLine + 1 < i && i < lastLine - 1) { - output += formatAndReset(padLeft(ellipsis, gutterWidth), gutterStyleSequence) + gutterSeparator + ts.sys.newLine; - i = lastLine - 1; - } - var lineStart = ts.getPositionOfLineAndCharacter(file, i, 0); - var lineEnd = i < lastLineInFile ? ts.getPositionOfLineAndCharacter(file, i + 1, 0) : file.text.length; - var lineContent = file.text.slice(lineStart, lineEnd); - lineContent = lineContent.replace(/\s+$/g, ""); // trim from end - lineContent = lineContent.replace("\t", " "); // convert tabs to single spaces - // Output the gutter and the actual contents of the line. - output += formatAndReset(padLeft(i + 1 + "", gutterWidth), gutterStyleSequence) + gutterSeparator; - output += lineContent + ts.sys.newLine; - // Output the gutter and the error span for the line using tildes. - output += formatAndReset(padLeft("", gutterWidth), gutterStyleSequence) + gutterSeparator; - output += redForegroundEscapeSequence; - if (i === firstLine) { - // If we're on the last line, then limit it to the last character of the last line. - // Otherwise, we'll just squiggle the rest of the line, giving 'slice' no end position. - var lastCharForLine = i === lastLine ? lastLineChar : undefined; - output += lineContent.slice(0, firstLineChar).replace(/\S/g, " "); - output += lineContent.slice(firstLineChar, lastCharForLine).replace(/./g, "~"); - } - else if (i === lastLine) { - output += lineContent.slice(0, lastLineChar).replace(/./g, "~"); - } - else { - // Squiggle the entire line. - output += lineContent.replace(/./g, "~"); - } - output += resetEscapeSequence; - output += ts.sys.newLine; + else { + emitParameters(parentNode, parameters); } - output += ts.sys.newLine; - output += relativeFileName + "(" + (firstLine + 1) + "," + (firstLineChar + 1) + "): "; } - var categoryColor = categoryFormatMap[diagnostic.category]; - var category = ts.DiagnosticCategory[diagnostic.category].toLowerCase(); - output += formatAndReset(category, categoryColor) + " TS" + diagnostic.code + ": " + ts.flattenDiagnosticMessageText(diagnostic.messageText, ts.sys.newLine); - output += ts.sys.newLine + ts.sys.newLine; - ts.sys.write(output); - } - function reportWatchDiagnostic(diagnostic) { - var output = new Date().toLocaleTimeString() + " - "; - if (diagnostic.file) { - var loc = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start); - output += diagnostic.file.fileName + "(" + (loc.line + 1) + "," + (loc.character + 1) + "): "; + function emitParametersForIndexSignature(parentNode, parameters) { + emitList(parentNode, parameters, 4432 /* IndexSignatureParameters */); } - output += "" + ts.flattenDiagnosticMessageText(diagnostic.messageText, ts.sys.newLine) + ts.sys.newLine; - ts.sys.write(output); - } - function padLeft(s, length) { - while (s.length < length) { - s = " " + s; + function emitList(parentNode, children, format, start, count) { + emitNodeList(emit, parentNode, children, format, start, count); } - return s; - } - function padRight(s, length) { - while (s.length < length) { - s = s + " "; + function emitExpressionList(parentNode, children, format, start, count) { + emitNodeList(emitExpression, parentNode, children, format, start, count); } - return s; - } - function reportStatisticalValue(name, value) { - ts.sys.write(padRight(name + ":", 12) + padLeft(value.toString(), 10) + ts.sys.newLine); - } - function reportCountStatistic(name, count) { - reportStatisticalValue(name, "" + count); - } - function reportTimeStatistic(name, time) { - reportStatisticalValue(name, (time / 1000).toFixed(2) + "s"); - } - function isJSONSupported() { - return typeof JSON === "object" && typeof JSON.parse === "function"; - } - function executeCommandLine(args) { - var commandLine = ts.parseCommandLine(args); - var configFileName; // Configuration file name (if any) - var cachedConfigFileText; // Cached configuration file text, used for reparsing (if any) - var configFileWatcher; // Configuration file watcher - var directoryWatcher; // Directory watcher to monitor source file addition/removal - var cachedProgram; // Program cached from last compilation - var rootFileNames; // Root fileNames for compilation - var compilerOptions; // Compiler options for compilation - var compilerHost; // Compiler host - var hostGetSourceFile; // getSourceFile method from default host - var timerHandleForRecompilation; // Handle for 0.25s wait timer to trigger recompilation - var timerHandleForDirectoryChanges; // Handle for 0.25s wait timer to trigger directory change handler - // This map stores and reuses results of fileExists check that happen inside 'createProgram' - // This allows to save time in module resolution heavy scenarios when existence of the same file might be checked multiple times. - var cachedExistingFiles; - var hostFileExists; - if (commandLine.options.locale) { - if (!isJSONSupported()) { - reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.The_current_host_does_not_support_the_0_option, "--locale"), /* host */ undefined); - return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + function emitNodeList(emit, parentNode, children, format, start, count) { + if (start === void 0) { start = 0; } + if (count === void 0) { count = children ? children.length - start : 0; } + var isUndefined = children === undefined; + if (isUndefined && format & 8192 /* OptionalIfUndefined */) { + return; } - validateLocaleAndSetLanguage(commandLine.options.locale, commandLine.errors); - } - // If there are any errors due to command line parsing and/or - // setting up localization, report them and quit. - if (commandLine.errors.length > 0) { - reportDiagnostics(commandLine.errors, compilerHost); - return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); - } - if (commandLine.options.init) { - writeConfigFile(commandLine.options, commandLine.fileNames); - return ts.sys.exit(ts.ExitStatus.Success); - } - if (commandLine.options.version) { - printVersion(); - return ts.sys.exit(ts.ExitStatus.Success); - } - if (commandLine.options.help) { - printVersion(); - printHelp(); - return ts.sys.exit(ts.ExitStatus.Success); - } - if (commandLine.options.project) { - if (!isJSONSupported()) { - reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.The_current_host_does_not_support_the_0_option, "--project"), /* host */ undefined); - return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + var isEmpty = isUndefined || children.length === 0 || start >= children.length || count === 0; + if (isEmpty && format & 16384 /* OptionalIfEmpty */) { + return; } - if (commandLine.fileNames.length !== 0) { - reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line), /* host */ undefined); - return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + if (format & 7680 /* BracketsMask */) { + write(getOpeningBracket(format)); } - var fileOrDirectory = ts.normalizePath(commandLine.options.project); - if (!fileOrDirectory /* current directory "." */ || ts.sys.directoryExists(fileOrDirectory)) { - configFileName = ts.combinePaths(fileOrDirectory, "tsconfig.json"); - if (!ts.sys.fileExists(configFileName)) { - reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_find_a_tsconfig_json_file_at_the_specified_directory_Colon_0, commandLine.options.project), /* host */ undefined); - return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + if (isEmpty) { + // Write a line terminator if the parent node was multi-line + if (format & 1 /* MultiLine */) { + writeLine(); + } + else if (format & 128 /* SpaceBetweenBraces */) { + write(" "); } } else { - configFileName = fileOrDirectory; - if (!ts.sys.fileExists(configFileName)) { - reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.The_specified_path_does_not_exist_Colon_0, commandLine.options.project), /* host */ undefined); - return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + // Write the opening line terminator or leading whitespace. + var mayEmitInterveningComments = (format & 131072 /* NoInterveningComments */) === 0; + var shouldEmitInterveningComments = mayEmitInterveningComments; + if (shouldWriteLeadingLineTerminator(parentNode, children, format)) { + writeLine(); + shouldEmitInterveningComments = false; + } + else if (format & 128 /* SpaceBetweenBraces */) { + write(" "); + } + // Increase the indent, if requested. + if (format & 64 /* Indented */) { + increaseIndent(); + } + // Emit each child. + var previousSibling = void 0; + var shouldDecreaseIndentAfterEmit = void 0; + var delimiter = getDelimiter(format); + for (var i = 0; i < count; i++) { + var child = children[start + i]; + // Write the delimiter if this is not the first node. + if (previousSibling) { + write(delimiter); + // Write either a line terminator or whitespace to separate the elements. + if (shouldWriteSeparatingLineTerminator(previousSibling, child, format)) { + // If a synthesized node in a single-line list starts on a new + // line, we should increase the indent. + if ((format & (3 /* LinesMask */ | 64 /* Indented */)) === 0 /* SingleLine */) { + increaseIndent(); + shouldDecreaseIndentAfterEmit = true; + } + writeLine(); + shouldEmitInterveningComments = false; + } + else if (previousSibling && format & 256 /* SpaceBetweenSiblings */) { + write(" "); + } + } + if (shouldEmitInterveningComments) { + var commentRange = ts.getCommentRange(child); + emitTrailingCommentsOfPosition(commentRange.pos); + } + else { + shouldEmitInterveningComments = mayEmitInterveningComments; + } + // Emit this child. + emit(child); + if (shouldDecreaseIndentAfterEmit) { + decreaseIndent(); + shouldDecreaseIndentAfterEmit = false; + } + previousSibling = child; + } + // Write a trailing comma, if requested. + var hasTrailingComma = (format & 32 /* AllowTrailingComma */) && children.hasTrailingComma; + if (format & 16 /* CommaDelimited */ && hasTrailingComma) { + write(","); + } + // Decrease the indent, if requested. + if (format & 64 /* Indented */) { + decreaseIndent(); + } + // Write the closing line terminator or closing whitespace. + if (shouldWriteClosingLineTerminator(parentNode, children, format)) { + writeLine(); + } + else if (format & 128 /* SpaceBetweenBraces */) { + write(" "); } } + if (format & 7680 /* BracketsMask */) { + write(getClosingBracket(format)); + } } - else if (commandLine.fileNames.length === 0 && isJSONSupported()) { - var searchPath = ts.normalizePath(ts.sys.getCurrentDirectory()); - configFileName = ts.findConfigFile(searchPath, ts.sys.fileExists); + function writeIfAny(nodes, text) { + if (nodes && nodes.length > 0) { + write(text); + } } - if (commandLine.fileNames.length === 0 && !configFileName) { - printVersion(); - printHelp(); - return ts.sys.exit(ts.ExitStatus.Success); + function writeIfPresent(node, text) { + if (node !== undefined) { + write(text); + } } - if (ts.isWatchSet(commandLine.options)) { - if (!ts.sys.watchFile) { - reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), /* host */ undefined); - return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + function writeToken(token, pos, contextNode) { + return emitTokenWithSourceMap(contextNode, token, pos, writeTokenText); + } + function writeTokenText(token, pos) { + var tokenString = ts.tokenToString(token); + write(tokenString); + return pos < 0 ? pos : pos + tokenString.length; + } + function increaseIndentIf(value, valueToWriteWhenNotIndenting) { + if (value) { + increaseIndent(); + writeLine(); } - if (configFileName) { - configFileWatcher = ts.sys.watchFile(configFileName, configFileChanged); + else if (valueToWriteWhenNotIndenting) { + write(valueToWriteWhenNotIndenting); } - if (ts.sys.watchDirectory && configFileName) { - var directory = ts.getDirectoryPath(configFileName); - directoryWatcher = ts.sys.watchDirectory( - // When the configFileName is just "tsconfig.json", the watched directory should be - // the current directory; if there is a given "project" parameter, then the configFileName - // is an absolute file name. - directory == "" ? "." : directory, watchedDirectoryChanged, /*recursive*/ true); + } + // Helper function to decrease the indent if we previously indented. Allows multiple + // previous indent values to be considered at a time. This also allows caller to just + // call this once, passing in all their appropriate indent values, instead of needing + // to call this helper function multiple times. + function decreaseIndentIf(value1, value2) { + if (value1) { + decreaseIndent(); + } + if (value2) { + decreaseIndent(); } } - performCompilation(); - function parseConfigFile() { - if (!cachedConfigFileText) { - try { - cachedConfigFileText = ts.sys.readFile(configFileName); + function shouldWriteLeadingLineTerminator(parentNode, children, format) { + if (format & 1 /* MultiLine */) { + return true; + } + if (format & 2 /* PreserveLines */) { + if (format & 32768 /* PreferNewLine */) { + return true; + } + var firstChild = children[0]; + if (firstChild === undefined) { + return !ts.rangeIsOnSingleLine(parentNode, currentSourceFile); } - catch (e) { - var error = ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_read_file_0_Colon_1, configFileName, e.message); - reportWatchDiagnostic(error); - ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); - return; + else if (ts.positionIsSynthesized(parentNode.pos) || ts.nodeIsSynthesized(firstChild)) { + return synthesizedNodeStartsOnNewLine(firstChild, format); + } + else { + return !ts.rangeStartPositionsAreOnSameLine(parentNode, firstChild, currentSourceFile); } } - if (!cachedConfigFileText) { - var error = ts.createCompilerDiagnostic(ts.Diagnostics.File_0_not_found, configFileName); - reportDiagnostics([error], /* compilerHost */ undefined); - ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); - return; - } - var result = ts.parseConfigFileTextToJson(configFileName, cachedConfigFileText); - var configObject = result.config; - if (!configObject) { - reportDiagnostics([result.error], /* compilerHost */ undefined); - ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); - return; + else { + return false; } - var cwd = ts.sys.getCurrentDirectory(); - var configParseResult = ts.parseJsonConfigFileContent(configObject, ts.sys, ts.getNormalizedAbsolutePath(ts.getDirectoryPath(configFileName), cwd), commandLine.options, ts.getNormalizedAbsolutePath(configFileName, cwd)); - if (configParseResult.errors.length > 0) { - reportDiagnostics(configParseResult.errors, /* compilerHost */ undefined); - ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); - return; + } + function shouldWriteSeparatingLineTerminator(previousNode, nextNode, format) { + if (format & 1 /* MultiLine */) { + return true; } - if (ts.isWatchSet(configParseResult.options)) { - if (!ts.sys.watchFile) { - reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), /* host */ undefined); - ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + else if (format & 2 /* PreserveLines */) { + if (previousNode === undefined || nextNode === undefined) { + return false; } - if (!directoryWatcher && ts.sys.watchDirectory && configFileName) { - var directory = ts.getDirectoryPath(configFileName); - directoryWatcher = ts.sys.watchDirectory( - // When the configFileName is just "tsconfig.json", the watched directory should be - // the current directory; if there is a given "project" parameter, then the configFileName - // is an absolute file name. - directory == "" ? "." : directory, watchedDirectoryChanged, /*recursive*/ true); + else if (ts.nodeIsSynthesized(previousNode) || ts.nodeIsSynthesized(nextNode)) { + return synthesizedNodeStartsOnNewLine(previousNode, format) || synthesizedNodeStartsOnNewLine(nextNode, format); + } + else { + return !ts.rangeEndIsOnSameLineAsRangeStart(previousNode, nextNode, currentSourceFile); } - ; } - return configParseResult; + else { + return nextNode.startsOnNewLine; + } } - // Invoked to perform initial compilation or re-compilation in watch mode - function performCompilation() { - if (!cachedProgram) { - if (configFileName) { - var configParseResult = parseConfigFile(); - rootFileNames = configParseResult.fileNames; - compilerOptions = configParseResult.options; + function shouldWriteClosingLineTerminator(parentNode, children, format) { + if (format & 1 /* MultiLine */) { + return (format & 65536 /* NoTrailingNewLine */) === 0; + } + else if (format & 2 /* PreserveLines */) { + if (format & 32768 /* PreferNewLine */) { + return true; + } + var lastChild = ts.lastOrUndefined(children); + if (lastChild === undefined) { + return !ts.rangeIsOnSingleLine(parentNode, currentSourceFile); + } + else if (ts.positionIsSynthesized(parentNode.pos) || ts.nodeIsSynthesized(lastChild)) { + return synthesizedNodeStartsOnNewLine(lastChild, format); } else { - rootFileNames = commandLine.fileNames; - compilerOptions = commandLine.options; + return !ts.rangeEndPositionsAreOnSameLine(parentNode, lastChild, currentSourceFile); } - compilerHost = ts.createCompilerHost(compilerOptions); - hostGetSourceFile = compilerHost.getSourceFile; - compilerHost.getSourceFile = getSourceFile; - hostFileExists = compilerHost.fileExists; - compilerHost.fileExists = cachedFileExists; } - if (compilerOptions.pretty) { - reportDiagnosticWorker = reportDiagnosticWithColorAndContext; + else { + return false; } - // reset the cache of existing files - cachedExistingFiles = ts.createMap(); - var compileResult = compile(rootFileNames, compilerOptions, compilerHost); - if (!ts.isWatchSet(compilerOptions)) { - return ts.sys.exit(compileResult.exitStatus); + } + function synthesizedNodeStartsOnNewLine(node, format) { + if (ts.nodeIsSynthesized(node)) { + var startsOnNewLine = node.startsOnNewLine; + if (startsOnNewLine === undefined) { + return (format & 32768 /* PreferNewLine */) !== 0; + } + return startsOnNewLine; } - setCachedProgram(compileResult.program); - reportWatchDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.Compilation_complete_Watching_for_file_changes)); + return (format & 32768 /* PreferNewLine */) !== 0; } - function cachedFileExists(fileName) { - return fileName in cachedExistingFiles - ? cachedExistingFiles[fileName] - : cachedExistingFiles[fileName] = hostFileExists(fileName); + function needsIndentation(parent, node1, node2) { + parent = skipSynthesizedParentheses(parent); + node1 = skipSynthesizedParentheses(node1); + node2 = skipSynthesizedParentheses(node2); + // Always use a newline for synthesized code if the synthesizer desires it. + if (node2.startsOnNewLine) { + return true; + } + return !ts.nodeIsSynthesized(parent) + && !ts.nodeIsSynthesized(node1) + && !ts.nodeIsSynthesized(node2) + && !ts.rangeEndIsOnSameLineAsRangeStart(node1, node2, currentSourceFile); } - function getSourceFile(fileName, languageVersion, onError) { - // Return existing SourceFile object if one is available - if (cachedProgram) { - var sourceFile_1 = cachedProgram.getSourceFile(fileName); - // A modified source file has no watcher and should not be reused - if (sourceFile_1 && sourceFile_1.fileWatcher) { - return sourceFile_1; + function skipSynthesizedParentheses(node) { + while (node.kind === 178 /* ParenthesizedExpression */ && ts.nodeIsSynthesized(node)) { + node = node.expression; + } + return node; + } + function getTextOfNode(node, includeTrivia) { + if (ts.isGeneratedIdentifier(node)) { + return getGeneratedIdentifier(node); + } + else if (ts.isIdentifier(node) && (ts.nodeIsSynthesized(node) || !node.parent)) { + return ts.unescapeIdentifier(node.text); + } + else if (node.kind === 9 /* StringLiteral */ && node.textSourceNode) { + return getTextOfNode(node.textSourceNode, includeTrivia); + } + else if (ts.isLiteralExpression(node) && (ts.nodeIsSynthesized(node) || !node.parent)) { + return node.text; + } + return ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node, includeTrivia); + } + function getLiteralTextOfNode(node) { + if (node.kind === 9 /* StringLiteral */ && node.textSourceNode) { + var textSourceNode = node.textSourceNode; + if (ts.isIdentifier(textSourceNode)) { + return "\"" + ts.escapeNonAsciiCharacters(ts.escapeString(getTextOfNode(textSourceNode))) + "\""; + } + else { + return getLiteralTextOfNode(textSourceNode); } } - // Use default host function - var sourceFile = hostGetSourceFile(fileName, languageVersion, onError); - if (sourceFile && ts.isWatchSet(compilerOptions) && ts.sys.watchFile) { - // Attach a file watcher - sourceFile.fileWatcher = ts.sys.watchFile(sourceFile.fileName, function (fileName, removed) { return sourceFileChanged(sourceFile, removed); }); + return ts.getLiteralText(node, currentSourceFile, languageVersion); + } + function isSingleLineEmptyBlock(block) { + return !block.multiLine + && block.statements.length === 0 + && ts.rangeEndIsOnSameLineAsRangeStart(block, block, currentSourceFile); + } + function isUniqueName(name) { + return !resolver.hasGlobalName(name) && + !ts.hasProperty(currentFileIdentifiers, name) && + !ts.hasProperty(generatedNameSet, name); + } + function isUniqueLocalName(name, container) { + for (var node = container; ts.isNodeDescendantOf(node, container); node = node.nextContainer) { + if (node.locals && ts.hasProperty(node.locals, name)) { + // We conservatively include alias symbols to cover cases where they're emitted as locals + if (node.locals[name].flags & (107455 /* Value */ | 1048576 /* ExportValue */ | 8388608 /* Alias */)) { + return false; + } + } } - return sourceFile; + return true; } - // Change cached program to the given program - function setCachedProgram(program) { - if (cachedProgram) { - var newSourceFiles_1 = program ? program.getSourceFiles() : undefined; - ts.forEach(cachedProgram.getSourceFiles(), function (sourceFile) { - if (!(newSourceFiles_1 && ts.contains(newSourceFiles_1, sourceFile))) { - if (sourceFile.fileWatcher) { - sourceFile.fileWatcher.close(); - sourceFile.fileWatcher = undefined; - } + /** + * Return the next available name in the pattern _a ... _z, _0, _1, ... + * TempFlags._i or TempFlags._n may be used to express a preference for that dedicated name. + * Note that names generated by makeTempVariableName and makeUniqueName will never conflict. + */ + function makeTempVariableName(flags) { + if (flags && !(tempFlags & flags)) { + var name_44 = flags === 268435456 /* _i */ ? "_i" : "_n"; + if (isUniqueName(name_44)) { + tempFlags |= flags; + return name_44; + } + } + while (true) { + var count = tempFlags & 268435455 /* CountMask */; + tempFlags++; + // Skip over 'i' and 'n' + if (count !== 8 && count !== 13) { + var name_45 = count < 26 + ? "_" + String.fromCharCode(97 /* a */ + count) + : "_" + (count - 26); + if (isUniqueName(name_45)) { + return name_45; } - }); + } } - cachedProgram = program; } - // If a source file changes, mark it as unwatched and start the recompilation timer - function sourceFileChanged(sourceFile, removed) { - sourceFile.fileWatcher.close(); - sourceFile.fileWatcher = undefined; - if (removed) { - ts.unorderedRemoveItem(rootFileNames, sourceFile.fileName); + // Generate a name that is unique within the current file and doesn't conflict with any names + // in global scope. The name is formed by adding an '_n' suffix to the specified base name, + // where n is a positive integer. Note that names generated by makeTempVariableName and + // makeUniqueName are guaranteed to never conflict. + function makeUniqueName(baseName) { + // Find the first unique 'name_n', where n is a positive number + if (baseName.charCodeAt(baseName.length - 1) !== 95 /* _ */) { + baseName += "_"; + } + var i = 1; + while (true) { + var generatedName = baseName + i; + if (isUniqueName(generatedName)) { + return generatedNameSet[generatedName] = generatedName; + } + i++; } - startTimerForRecompilation(); } - // If the configuration file changes, forget cached program and start the recompilation timer - function configFileChanged() { - setCachedProgram(undefined); - cachedConfigFileText = undefined; - startTimerForRecompilation(); + function generateNameForModuleOrEnum(node) { + var name = getTextOfNode(node.name); + // Use module/enum name itself if it is unique, otherwise make a unique variation + return isUniqueLocalName(name, node) ? name : makeUniqueName(name); } - function watchedDirectoryChanged(fileName) { - if (fileName && !ts.isSupportedSourceFileName(fileName, compilerOptions)) { - return; + function generateNameForImportOrExportDeclaration(node) { + var expr = ts.getExternalModuleName(node); + var baseName = expr.kind === 9 /* StringLiteral */ ? + ts.escapeIdentifier(ts.makeIdentifierFromModuleName(expr.text)) : "module"; + return makeUniqueName(baseName); + } + function generateNameForExportDefault() { + return makeUniqueName("default"); + } + function generateNameForClassExpression() { + return makeUniqueName("class"); + } + /** + * Generates a unique name from a node. + * + * @param node A node. + */ + function generateNameForNode(node) { + switch (node.kind) { + case 69 /* Identifier */: + return makeUniqueName(getTextOfNode(node)); + case 225 /* ModuleDeclaration */: + case 224 /* EnumDeclaration */: + return generateNameForModuleOrEnum(node); + case 230 /* ImportDeclaration */: + case 236 /* ExportDeclaration */: + return generateNameForImportOrExportDeclaration(node); + case 220 /* FunctionDeclaration */: + case 221 /* ClassDeclaration */: + case 235 /* ExportAssignment */: + return generateNameForExportDefault(); + case 192 /* ClassExpression */: + return generateNameForClassExpression(); + default: + return makeTempVariableName(0 /* Auto */); } - startTimerForHandlingDirectoryChanges(); } - function startTimerForHandlingDirectoryChanges() { - if (timerHandleForDirectoryChanges) { - clearTimeout(timerHandleForDirectoryChanges); + /** + * Generates a unique identifier for a node. + * + * @param name A generated name. + */ + function generateName(name) { + switch (name.autoGenerateKind) { + case 1 /* Auto */: + return makeTempVariableName(0 /* Auto */); + case 2 /* Loop */: + return makeTempVariableName(268435456 /* _i */); + case 3 /* Unique */: + return makeUniqueName(name.text); } - timerHandleForDirectoryChanges = setTimeout(directoryChangeHandler, 250); + ts.Debug.fail("Unsupported GeneratedIdentifierKind."); } - function directoryChangeHandler() { - var parsedCommandLine = parseConfigFile(); - var newFileNames = ts.map(parsedCommandLine.fileNames, compilerHost.getCanonicalFileName); - var canonicalRootFileNames = ts.map(rootFileNames, compilerHost.getCanonicalFileName); - // We check if the project file list has changed. If so, we just throw away the old program and start fresh. - if (!ts.arrayIsEqualTo(newFileNames && newFileNames.sort(), canonicalRootFileNames && canonicalRootFileNames.sort())) { - setCachedProgram(undefined); - startTimerForRecompilation(); + /** + * Gets the node from which a name should be generated. + * + * @param name A generated name wrapper. + */ + function getNodeForGeneratedName(name) { + var autoGenerateId = name.autoGenerateId; + var node = name; + var original = node.original; + while (original) { + node = original; + // if "node" is a different generated name (having a different + // "autoGenerateId"), use it and stop traversing. + if (ts.isIdentifier(node) + && node.autoGenerateKind === 4 /* Node */ + && node.autoGenerateId !== autoGenerateId) { + break; + } + original = node.original; } + // otherwise, return the original node for the source; + return node; } - // Upon detecting a file change, wait for 250ms and then perform a recompilation. This gives batch - // operations (such as saving all modified files in an editor) a chance to complete before we kick - // off a new compilation. - function startTimerForRecompilation() { - if (timerHandleForRecompilation) { - clearTimeout(timerHandleForRecompilation); + /** + * Gets the generated identifier text from a generated identifier. + * + * @param name The generated identifier. + */ + function getGeneratedIdentifier(name) { + if (name.autoGenerateKind === 4 /* Node */) { + // Generated names generate unique names based on their original node + // and are cached based on that node's id + var node = getNodeForGeneratedName(name); + var nodeId = ts.getNodeId(node); + return nodeIdToGeneratedName[nodeId] || (nodeIdToGeneratedName[nodeId] = ts.unescapeIdentifier(generateNameForNode(node))); + } + else { + // Auto, Loop, and Unique names are cached based on their unique + // autoGenerateId. + var autoGenerateId = name.autoGenerateId; + return autoGeneratedIdToGeneratedName[autoGenerateId] || (autoGeneratedIdToGeneratedName[autoGenerateId] = ts.unescapeIdentifier(generateName(name))); } - timerHandleForRecompilation = setTimeout(recompile, 250); } - function recompile() { - timerHandleForRecompilation = undefined; - reportWatchDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.File_change_detected_Starting_incremental_compilation)); - performCompilation(); + function createDelimiterMap() { + var delimiters = []; + delimiters[0 /* None */] = ""; + delimiters[16 /* CommaDelimited */] = ","; + delimiters[4 /* BarDelimited */] = " |"; + delimiters[8 /* AmpersandDelimited */] = " &"; + return delimiters; + } + function getDelimiter(format) { + return delimiters[format & 28 /* DelimitersMask */]; + } + function createBracketsMap() { + var brackets = []; + brackets[512 /* Braces */] = ["{", "}"]; + brackets[1024 /* Parenthesis */] = ["(", ")"]; + brackets[2048 /* AngleBrackets */] = ["<", ">"]; + brackets[4096 /* SquareBrackets */] = ["[", "]"]; + return brackets; + } + function getOpeningBracket(format) { + return brackets[format & 7680 /* BracketsMask */][0]; + } + function getClosingBracket(format) { + return brackets[format & 7680 /* BracketsMask */][1]; } } - ts.executeCommandLine = executeCommandLine; - function compile(fileNames, compilerOptions, compilerHost) { - var hasDiagnostics = compilerOptions.diagnostics || compilerOptions.extendedDiagnostics; - if (hasDiagnostics) - ts.performance.enable(); - var program = ts.createProgram(fileNames, compilerOptions, compilerHost); - var exitStatus = compileProgram(); - if (compilerOptions.listFiles) { - ts.forEach(program.getSourceFiles(), function (file) { - ts.sys.write(file.fileName + ts.sys.newLine); - }); + ts.emitFiles = emitFiles; + var ListFormat; + (function (ListFormat) { + ListFormat[ListFormat["None"] = 0] = "None"; + // Line separators + ListFormat[ListFormat["SingleLine"] = 0] = "SingleLine"; + ListFormat[ListFormat["MultiLine"] = 1] = "MultiLine"; + ListFormat[ListFormat["PreserveLines"] = 2] = "PreserveLines"; + ListFormat[ListFormat["LinesMask"] = 3] = "LinesMask"; + // Delimiters + ListFormat[ListFormat["NotDelimited"] = 0] = "NotDelimited"; + ListFormat[ListFormat["BarDelimited"] = 4] = "BarDelimited"; + ListFormat[ListFormat["AmpersandDelimited"] = 8] = "AmpersandDelimited"; + ListFormat[ListFormat["CommaDelimited"] = 16] = "CommaDelimited"; + ListFormat[ListFormat["DelimitersMask"] = 28] = "DelimitersMask"; + ListFormat[ListFormat["AllowTrailingComma"] = 32] = "AllowTrailingComma"; + // Whitespace + ListFormat[ListFormat["Indented"] = 64] = "Indented"; + ListFormat[ListFormat["SpaceBetweenBraces"] = 128] = "SpaceBetweenBraces"; + ListFormat[ListFormat["SpaceBetweenSiblings"] = 256] = "SpaceBetweenSiblings"; + // Brackets/Braces + ListFormat[ListFormat["Braces"] = 512] = "Braces"; + ListFormat[ListFormat["Parenthesis"] = 1024] = "Parenthesis"; + ListFormat[ListFormat["AngleBrackets"] = 2048] = "AngleBrackets"; + ListFormat[ListFormat["SquareBrackets"] = 4096] = "SquareBrackets"; + ListFormat[ListFormat["BracketsMask"] = 7680] = "BracketsMask"; + ListFormat[ListFormat["OptionalIfUndefined"] = 8192] = "OptionalIfUndefined"; + ListFormat[ListFormat["OptionalIfEmpty"] = 16384] = "OptionalIfEmpty"; + ListFormat[ListFormat["Optional"] = 24576] = "Optional"; + // Other + ListFormat[ListFormat["PreferNewLine"] = 32768] = "PreferNewLine"; + ListFormat[ListFormat["NoTrailingNewLine"] = 65536] = "NoTrailingNewLine"; + ListFormat[ListFormat["NoInterveningComments"] = 131072] = "NoInterveningComments"; + // Precomputed Formats + ListFormat[ListFormat["Modifiers"] = 256] = "Modifiers"; + ListFormat[ListFormat["HeritageClauses"] = 256] = "HeritageClauses"; + ListFormat[ListFormat["TypeLiteralMembers"] = 65] = "TypeLiteralMembers"; + ListFormat[ListFormat["TupleTypeElements"] = 336] = "TupleTypeElements"; + ListFormat[ListFormat["UnionTypeConstituents"] = 260] = "UnionTypeConstituents"; + ListFormat[ListFormat["IntersectionTypeConstituents"] = 264] = "IntersectionTypeConstituents"; + ListFormat[ListFormat["ObjectBindingPatternElements"] = 432] = "ObjectBindingPatternElements"; + ListFormat[ListFormat["ArrayBindingPatternElements"] = 304] = "ArrayBindingPatternElements"; + ListFormat[ListFormat["ObjectLiteralExpressionProperties"] = 978] = "ObjectLiteralExpressionProperties"; + ListFormat[ListFormat["ArrayLiteralExpressionElements"] = 4466] = "ArrayLiteralExpressionElements"; + ListFormat[ListFormat["CallExpressionArguments"] = 1296] = "CallExpressionArguments"; + ListFormat[ListFormat["NewExpressionArguments"] = 9488] = "NewExpressionArguments"; + ListFormat[ListFormat["TemplateExpressionSpans"] = 131072] = "TemplateExpressionSpans"; + ListFormat[ListFormat["SingleLineBlockStatements"] = 384] = "SingleLineBlockStatements"; + ListFormat[ListFormat["MultiLineBlockStatements"] = 65] = "MultiLineBlockStatements"; + ListFormat[ListFormat["VariableDeclarationList"] = 272] = "VariableDeclarationList"; + ListFormat[ListFormat["SingleLineFunctionBodyStatements"] = 384] = "SingleLineFunctionBodyStatements"; + ListFormat[ListFormat["MultiLineFunctionBodyStatements"] = 1] = "MultiLineFunctionBodyStatements"; + ListFormat[ListFormat["ClassHeritageClauses"] = 256] = "ClassHeritageClauses"; + ListFormat[ListFormat["ClassMembers"] = 65] = "ClassMembers"; + ListFormat[ListFormat["InterfaceMembers"] = 65] = "InterfaceMembers"; + ListFormat[ListFormat["EnumMembers"] = 81] = "EnumMembers"; + ListFormat[ListFormat["CaseBlockClauses"] = 65] = "CaseBlockClauses"; + ListFormat[ListFormat["NamedImportsOrExportsElements"] = 432] = "NamedImportsOrExportsElements"; + ListFormat[ListFormat["JsxElementChildren"] = 131072] = "JsxElementChildren"; + ListFormat[ListFormat["JsxElementAttributes"] = 131328] = "JsxElementAttributes"; + ListFormat[ListFormat["CaseOrDefaultClauseStatements"] = 81985] = "CaseOrDefaultClauseStatements"; + ListFormat[ListFormat["HeritageClauseTypes"] = 272] = "HeritageClauseTypes"; + ListFormat[ListFormat["SourceFileStatements"] = 65537] = "SourceFileStatements"; + ListFormat[ListFormat["Decorators"] = 24577] = "Decorators"; + ListFormat[ListFormat["TypeArguments"] = 26960] = "TypeArguments"; + ListFormat[ListFormat["TypeParameters"] = 26960] = "TypeParameters"; + ListFormat[ListFormat["Parameters"] = 1360] = "Parameters"; + ListFormat[ListFormat["IndexSignatureParameters"] = 4432] = "IndexSignatureParameters"; + })(ListFormat || (ListFormat = {})); +})(ts || (ts = {})); +/// +/// +/// +var ts; +(function (ts) { + /** The version of the TypeScript compiler release */ + ts.version = "2.1.0"; + var emptyArray = []; + function findConfigFile(searchPath, fileExists, configName) { + if (configName === void 0) { configName = "tsconfig.json"; } + while (true) { + var fileName = ts.combinePaths(searchPath, configName); + if (fileExists(fileName)) { + return fileName; + } + var parentPath = ts.getDirectoryPath(searchPath); + if (parentPath === searchPath) { + break; + } + searchPath = parentPath; } - if (hasDiagnostics) { - var memoryUsed = ts.sys.getMemoryUsage ? ts.sys.getMemoryUsage() : -1; - reportCountStatistic("Files", program.getSourceFiles().length); - reportCountStatistic("Lines", countLines(program)); - reportCountStatistic("Nodes", program.getNodeCount()); - reportCountStatistic("Identifiers", program.getIdentifierCount()); - reportCountStatistic("Symbols", program.getSymbolCount()); - reportCountStatistic("Types", program.getTypeCount()); - if (memoryUsed >= 0) { - reportStatisticalValue("Memory used", Math.round(memoryUsed / 1000) + "K"); + return undefined; + } + ts.findConfigFile = findConfigFile; + function resolveTripleslashReference(moduleName, containingFile) { + var basePath = ts.getDirectoryPath(containingFile); + var referencedFileName = ts.isRootedDiskPath(moduleName) ? moduleName : ts.combinePaths(basePath, moduleName); + return ts.normalizePath(referencedFileName); + } + ts.resolveTripleslashReference = resolveTripleslashReference; + /* @internal */ + function computeCommonSourceDirectoryOfFilenames(fileNames, currentDirectory, getCanonicalFileName) { + var commonPathComponents; + var failed = ts.forEach(fileNames, function (sourceFile) { + // Each file contributes into common source file path + var sourcePathComponents = ts.getNormalizedPathComponents(sourceFile, currentDirectory); + sourcePathComponents.pop(); // The base file name is not part of the common directory path + if (!commonPathComponents) { + // first file + commonPathComponents = sourcePathComponents; + return; } - var programTime = ts.performance.getDuration("Program"); - var bindTime = ts.performance.getDuration("Bind"); - var checkTime = ts.performance.getDuration("Check"); - var emitTime = ts.performance.getDuration("Emit"); - if (compilerOptions.extendedDiagnostics) { - ts.performance.forEachMeasure(function (name, duration) { return reportTimeStatistic(name + " time", duration); }); + for (var i = 0, n = Math.min(commonPathComponents.length, sourcePathComponents.length); i < n; i++) { + if (getCanonicalFileName(commonPathComponents[i]) !== getCanonicalFileName(sourcePathComponents[i])) { + if (i === 0) { + // Failed to find any common path component + return true; + } + // New common path found that is 0 -> i-1 + commonPathComponents.length = i; + break; + } } - else { - // Individual component times. - // Note: To match the behavior of previous versions of the compiler, the reported parse time includes - // I/O read time and processing time for triple-slash references and module imports, and the reported - // emit time includes I/O write time. We preserve this behavior so we can accurately compare times. - reportTimeStatistic("I/O read", ts.performance.getDuration("I/O Read")); - reportTimeStatistic("I/O write", ts.performance.getDuration("I/O Write")); - reportTimeStatistic("Parse time", programTime); - reportTimeStatistic("Bind time", bindTime); - reportTimeStatistic("Check time", checkTime); - reportTimeStatistic("Emit time", emitTime); + // If the sourcePathComponents was shorter than the commonPathComponents, truncate to the sourcePathComponents + if (sourcePathComponents.length < commonPathComponents.length) { + commonPathComponents.length = sourcePathComponents.length; } - reportTimeStatistic("Total time", programTime + bindTime + checkTime + emitTime); - ts.performance.disable(); + }); + // A common path can not be found when paths span multiple drives on windows, for example + if (failed) { + return ""; } - return { program: program, exitStatus: exitStatus }; - function compileProgram() { - var diagnostics; - // First get and report any syntactic errors. - diagnostics = program.getSyntacticDiagnostics(); - // If we didn't have any syntactic errors, then also try getting the global and - // semantic errors. - if (diagnostics.length === 0) { - diagnostics = program.getOptionsDiagnostics().concat(program.getGlobalDiagnostics()); - if (diagnostics.length === 0) { - diagnostics = program.getSemanticDiagnostics(); + if (!commonPathComponents) { + return currentDirectory; + } + return ts.getNormalizedPathFromPathComponents(commonPathComponents); + } + ts.computeCommonSourceDirectoryOfFilenames = computeCommonSourceDirectoryOfFilenames; + function createCompilerHost(options, setParentNodes) { + var existingDirectories = ts.createMap(); + function getCanonicalFileName(fileName) { + // if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form. + // otherwise use toLowerCase as a canonical form. + return ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); + } + // returned by CScript sys environment + var unsupportedFileEncodingErrorCode = -2147024809; + function getSourceFile(fileName, languageVersion, onError) { + var text; + try { + ts.performance.mark("beforeIORead"); + text = ts.sys.readFile(fileName, options.charset); + ts.performance.mark("afterIORead"); + ts.performance.measure("I/O Read", "beforeIORead", "afterIORead"); + } + catch (e) { + if (onError) { + onError(e.number === unsupportedFileEncodingErrorCode + ? ts.createCompilerDiagnostic(ts.Diagnostics.Unsupported_file_encoding).messageText + : e.message); } + text = ""; } - // Otherwise, emit and report any errors we ran into. - var emitOutput = program.emit(); - diagnostics = diagnostics.concat(emitOutput.diagnostics); - reportDiagnostics(ts.sortAndDeduplicateDiagnostics(diagnostics), compilerHost); - reportEmittedFiles(emitOutput.emittedFiles, compilerHost); - if (emitOutput.emitSkipped && diagnostics.length > 0) { - // If the emitter didn't emit anything, then pass that value along. - return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped; + return text !== undefined ? ts.createSourceFile(fileName, text, languageVersion, setParentNodes) : undefined; + } + function directoryExists(directoryPath) { + if (directoryPath in existingDirectories) { + return true; } - else if (diagnostics.length > 0) { - // The emitter emitted something, inform the caller if that happened in the presence - // of diagnostics or not. - return ts.ExitStatus.DiagnosticsPresent_OutputsGenerated; + if (ts.sys.directoryExists(directoryPath)) { + existingDirectories[directoryPath] = true; + return true; } - return ts.ExitStatus.Success; + return false; } - } - function printVersion() { - ts.sys.write(getDiagnosticText(ts.Diagnostics.Version_0, ts.version) + ts.sys.newLine); - } - function printHelp() { - var output = ""; - // We want to align our "syntax" and "examples" commands to a certain margin. - var syntaxLength = getDiagnosticText(ts.Diagnostics.Syntax_Colon_0, "").length; - var examplesLength = getDiagnosticText(ts.Diagnostics.Examples_Colon_0, "").length; - var marginLength = Math.max(syntaxLength, examplesLength); - // Build up the syntactic skeleton. - var syntax = makePadding(marginLength - syntaxLength); - syntax += "tsc [" + getDiagnosticText(ts.Diagnostics.options) + "] [" + getDiagnosticText(ts.Diagnostics.file) + " ...]"; - output += getDiagnosticText(ts.Diagnostics.Syntax_Colon_0, syntax); - output += ts.sys.newLine + ts.sys.newLine; - // Build up the list of examples. - var padding = makePadding(marginLength); - output += getDiagnosticText(ts.Diagnostics.Examples_Colon_0, makePadding(marginLength - examplesLength) + "tsc hello.ts") + ts.sys.newLine; - output += padding + "tsc --outFile file.js file.ts" + ts.sys.newLine; - output += padding + "tsc @args.txt" + ts.sys.newLine; - output += ts.sys.newLine; - output += getDiagnosticText(ts.Diagnostics.Options_Colon) + ts.sys.newLine; - // Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch") - var optsList = ts.filter(ts.optionDeclarations.slice(), function (v) { return !v.experimental; }); - optsList.sort(function (a, b) { return ts.compareValues(a.name.toLowerCase(), b.name.toLowerCase()); }); - // We want our descriptions to align at the same column in our output, - // so we keep track of the longest option usage string. - marginLength = 0; - var usageColumn = []; // Things like "-d, --declaration" go in here. - var descriptionColumn = []; - var optionsDescriptionMap = ts.createMap(); // Map between option.description and list of option.type if it is a kind - for (var i = 0; i < optsList.length; i++) { - var option = optsList[i]; - // If an option lacks a description, - // it is not officially supported. - if (!option.description) { - continue; + function ensureDirectoriesExist(directoryPath) { + if (directoryPath.length > ts.getRootLength(directoryPath) && !directoryExists(directoryPath)) { + var parentDirectory = ts.getDirectoryPath(directoryPath); + ensureDirectoriesExist(parentDirectory); + ts.sys.createDirectory(directoryPath); } - var usageText_1 = " "; - if (option.shortName) { - usageText_1 += "-" + option.shortName; - usageText_1 += getParamType(option); - usageText_1 += ", "; + } + var outputFingerprints; + function writeFileIfUpdated(fileName, data, writeByteOrderMark) { + if (!outputFingerprints) { + outputFingerprints = ts.createMap(); } - usageText_1 += "--" + option.name; - usageText_1 += getParamType(option); - usageColumn.push(usageText_1); - var description = void 0; - if (option.name === "lib") { - description = getDiagnosticText(option.description); - var options = []; - var element = option.element; - var typeMap = element.type; - for (var key in typeMap) { - options.push("'" + key + "'"); + var hash = ts.sys.createHash(data); + var mtimeBefore = ts.sys.getModifiedTime(fileName); + if (mtimeBefore && fileName in outputFingerprints) { + var fingerprint = outputFingerprints[fileName]; + // If output has not been changed, and the file has no external modification + if (fingerprint.byteOrderMark === writeByteOrderMark && + fingerprint.hash === hash && + fingerprint.mtime.getTime() === mtimeBefore.getTime()) { + return; } - optionsDescriptionMap[description] = options; } - else { - description = getDiagnosticText(option.description); + ts.sys.writeFile(fileName, data, writeByteOrderMark); + var mtimeAfter = ts.sys.getModifiedTime(fileName); + outputFingerprints[fileName] = { + hash: hash, + byteOrderMark: writeByteOrderMark, + mtime: mtimeAfter + }; + } + function writeFile(fileName, data, writeByteOrderMark, onError) { + try { + ts.performance.mark("beforeIOWrite"); + ensureDirectoriesExist(ts.getDirectoryPath(ts.normalizePath(fileName))); + if (ts.isWatchSet(options) && ts.sys.createHash && ts.sys.getModifiedTime) { + writeFileIfUpdated(fileName, data, writeByteOrderMark); + } + else { + ts.sys.writeFile(fileName, data, writeByteOrderMark); + } + ts.performance.mark("afterIOWrite"); + ts.performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite"); } - descriptionColumn.push(description); - // Set the new margin for the description column if necessary. - marginLength = Math.max(usageText_1.length, marginLength); + catch (e) { + if (onError) { + onError(e.message); + } + } + } + function getDefaultLibLocation() { + return ts.getDirectoryPath(ts.normalizePath(ts.sys.getExecutingFilePath())); + } + var newLine = ts.getNewLineCharacter(options); + var realpath = ts.sys.realpath && (function (path) { return ts.sys.realpath(path); }); + return { + getSourceFile: getSourceFile, + getDefaultLibLocation: getDefaultLibLocation, + getDefaultLibFileName: function (options) { return ts.combinePaths(getDefaultLibLocation(), ts.getDefaultLibFileName(options)); }, + writeFile: writeFile, + getCurrentDirectory: ts.memoize(function () { return ts.sys.getCurrentDirectory(); }), + useCaseSensitiveFileNames: function () { return ts.sys.useCaseSensitiveFileNames; }, + getCanonicalFileName: getCanonicalFileName, + getNewLine: function () { return newLine; }, + fileExists: function (fileName) { return ts.sys.fileExists(fileName); }, + readFile: function (fileName) { return ts.sys.readFile(fileName); }, + trace: function (s) { return ts.sys.write(s + newLine); }, + directoryExists: function (directoryName) { return ts.sys.directoryExists(directoryName); }, + getEnvironmentVariable: function (name) { return ts.getEnvironmentVariable(name, /*host*/ undefined); }, + getDirectories: function (path) { return ts.sys.getDirectories(path); }, + realpath: realpath + }; + } + ts.createCompilerHost = createCompilerHost; + function getPreEmitDiagnostics(program, sourceFile, cancellationToken) { + var diagnostics = program.getOptionsDiagnostics(cancellationToken).concat(program.getSyntacticDiagnostics(sourceFile, cancellationToken), program.getGlobalDiagnostics(cancellationToken), program.getSemanticDiagnostics(sourceFile, cancellationToken)); + if (program.getCompilerOptions().declaration) { + diagnostics = diagnostics.concat(program.getDeclarationDiagnostics(sourceFile, cancellationToken)); + } + return ts.sortAndDeduplicateDiagnostics(diagnostics); + } + ts.getPreEmitDiagnostics = getPreEmitDiagnostics; + function formatDiagnostics(diagnostics, host) { + var output = ""; + for (var _i = 0, diagnostics_1 = diagnostics; _i < diagnostics_1.length; _i++) { + var diagnostic = diagnostics_1[_i]; + if (diagnostic.file) { + var _a = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start), line = _a.line, character = _a.character; + var fileName = diagnostic.file.fileName; + var relativeFileName = ts.convertToRelativePath(fileName, host.getCurrentDirectory(), function (fileName) { return host.getCanonicalFileName(fileName); }); + output += relativeFileName + "(" + (line + 1) + "," + (character + 1) + "): "; + } + var category = ts.DiagnosticCategory[diagnostic.category].toLowerCase(); + output += category + " TS" + diagnostic.code + ": " + flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine()) + host.getNewLine(); + } + return output; + } + ts.formatDiagnostics = formatDiagnostics; + function flattenDiagnosticMessageText(messageText, newLine) { + if (typeof messageText === "string") { + return messageText; } - // Special case that can't fit in the loop. - var usageText = " @<" + getDiagnosticText(ts.Diagnostics.file) + ">"; - usageColumn.push(usageText); - descriptionColumn.push(getDiagnosticText(ts.Diagnostics.Insert_command_line_options_and_files_from_a_file)); - marginLength = Math.max(usageText.length, marginLength); - // Print out each row, aligning all the descriptions on the same column. - for (var i = 0; i < usageColumn.length; i++) { - var usage = usageColumn[i]; - var description = descriptionColumn[i]; - var kindsList = optionsDescriptionMap[description]; - output += usage + makePadding(marginLength - usage.length + 2) + description + ts.sys.newLine; - if (kindsList) { - output += makePadding(marginLength + 4); - for (var _i = 0, kindsList_1 = kindsList; _i < kindsList_1.length; _i++) { - var kind = kindsList_1[_i]; - output += kind + " "; + else { + var diagnosticChain = messageText; + var result = ""; + var indent = 0; + while (diagnosticChain) { + if (indent) { + result += newLine; + for (var i = 0; i < indent; i++) { + result += " "; + } } - output += ts.sys.newLine; + result += diagnosticChain.messageText; + indent++; + diagnosticChain = diagnosticChain.next; } + return result; } - ts.sys.write(output); - return; - function getParamType(option) { - if (option.paramType !== undefined) { - return " " + getDiagnosticText(option.paramType); - } - return ""; + } + ts.flattenDiagnosticMessageText = flattenDiagnosticMessageText; + function loadWithLocalCache(names, containingFile, loader) { + if (names.length === 0) { + return []; } - function makePadding(paddingLength) { - return Array(paddingLength + 1).join(" "); + var resolutions = []; + var cache = ts.createMap(); + for (var _i = 0, names_2 = names; _i < names_2.length; _i++) { + var name_46 = names_2[_i]; + var result = name_46 in cache + ? cache[name_46] + : cache[name_46] = loader(name_46, containingFile); + resolutions.push(result); } + return resolutions; } - function writeConfigFile(options, fileNames) { - var currentDirectory = ts.sys.getCurrentDirectory(); - var file = ts.normalizePath(ts.combinePaths(currentDirectory, "tsconfig.json")); - if (ts.sys.fileExists(file)) { - reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file), /* host */ undefined); + function createProgram(rootNames, options, host, oldProgram) { + var program; + var files = []; + var commonSourceDirectory; + var diagnosticsProducingTypeChecker; + var noDiagnosticsTypeChecker; + var classifiableNames; + var resolvedTypeReferenceDirectives = ts.createMap(); + var fileProcessingDiagnostics = ts.createDiagnosticCollection(); + // The below settings are to track if a .js file should be add to the program if loaded via searching under node_modules. + // This works as imported modules are discovered recursively in a depth first manner, specifically: + // - For each root file, findSourceFile is called. + // - This calls processImportedModules for each module imported in the source file. + // - This calls resolveModuleNames, and then calls findSourceFile for each resolved module. + // As all these operations happen - and are nested - within the createProgram call, they close over the below variables. + // The current resolution depth is tracked by incrementing/decrementing as the depth first search progresses. + var maxNodeModulesJsDepth = typeof options.maxNodeModuleJsDepth === "number" ? options.maxNodeModuleJsDepth : 0; + var currentNodeModulesDepth = 0; + // If a module has some of its imports skipped due to being at the depth limit under node_modules, then track + // this, as it may be imported at a shallower depth later, and then it will need its skipped imports processed. + var modulesWithElidedImports = ts.createMap(); + // Track source files that are source files found by searching under node_modules, as these shouldn't be compiled. + var sourceFilesFoundSearchingNodeModules = ts.createMap(); + ts.performance.mark("beforeProgram"); + host = host || createCompilerHost(options); + var skipDefaultLib = options.noLib; + var programDiagnostics = ts.createDiagnosticCollection(); + var currentDirectory = host.getCurrentDirectory(); + var supportedExtensions = ts.getSupportedExtensions(options); + // Map storing if there is emit blocking diagnostics for given input + var hasEmitBlockingDiagnostics = ts.createFileMap(getCanonicalFileName); + var resolveModuleNamesWorker; + if (host.resolveModuleNames) { + resolveModuleNamesWorker = function (moduleNames, containingFile) { return host.resolveModuleNames(moduleNames, containingFile); }; } else { - ts.sys.writeFile(file, JSON.stringify(ts.generateTSConfig(options, fileNames), undefined, 4)); - reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.Successfully_created_a_tsconfig_json_file), /* host */ undefined); + var loader_1 = function (moduleName, containingFile) { return ts.resolveModuleName(moduleName, containingFile, options, host).resolvedModule; }; + resolveModuleNamesWorker = function (moduleNames, containingFile) { return loadWithLocalCache(moduleNames, containingFile, loader_1); }; } - return; - } - var _a; -})(ts || (ts = {})); - -/* @internal */ -var ts; -(function (ts) { - var OutliningElementsCollector; - (function (OutliningElementsCollector) { - function collectElements(sourceFile) { - var elements = []; - var collapseText = "..."; - function addOutliningSpan(hintSpanNode, startElement, endElement, autoCollapse) { - if (hintSpanNode && startElement && endElement) { - var span = { - textSpan: ts.createTextSpanFromBounds(startElement.pos, endElement.end), - hintSpan: ts.createTextSpanFromBounds(hintSpanNode.getStart(), hintSpanNode.end), - bannerText: collapseText, - autoCollapse: autoCollapse - }; - elements.push(span); + var resolveTypeReferenceDirectiveNamesWorker; + if (host.resolveTypeReferenceDirectives) { + resolveTypeReferenceDirectiveNamesWorker = function (typeDirectiveNames, containingFile) { return host.resolveTypeReferenceDirectives(typeDirectiveNames, containingFile); }; + } + else { + var loader_2 = function (typesRef, containingFile) { return ts.resolveTypeReferenceDirective(typesRef, containingFile, options, host).resolvedTypeReferenceDirective; }; + resolveTypeReferenceDirectiveNamesWorker = function (typeReferenceDirectiveNames, containingFile) { return loadWithLocalCache(typeReferenceDirectiveNames, containingFile, loader_2); }; + } + var filesByName = ts.createFileMap(); + // stores 'filename -> file association' ignoring case + // used to track cases when two file names differ only in casing + var filesByNameIgnoreCase = host.useCaseSensitiveFileNames() ? ts.createFileMap(function (fileName) { return fileName.toLowerCase(); }) : undefined; + if (!tryReuseStructureFromOldProgram()) { + ts.forEach(rootNames, function (name) { return processRootFile(name, /*isDefaultLib*/ false); }); + // load type declarations specified via 'types' argument or implicitly from types/ and node_modules/@types folders + var typeReferences = ts.getAutomaticTypeDirectiveNames(options, host); + if (typeReferences) { + // This containingFilename needs to match with the one used in managed-side + var containingFilename = ts.combinePaths(host.getCurrentDirectory(), "__inferred type names__.ts"); + var resolutions = resolveTypeReferenceDirectiveNamesWorker(typeReferences, containingFilename); + for (var i = 0; i < typeReferences.length; i++) { + processTypeReferenceDirective(typeReferences[i], resolutions[i]); } } - function addOutliningSpanComments(commentSpan, autoCollapse) { - if (commentSpan) { - var span = { - textSpan: ts.createTextSpanFromBounds(commentSpan.pos, commentSpan.end), - hintSpan: ts.createTextSpanFromBounds(commentSpan.pos, commentSpan.end), - bannerText: collapseText, - autoCollapse: autoCollapse - }; - elements.push(span); + // Do not process the default library if: + // - The '--noLib' flag is used. + // - A 'no-default-lib' reference comment is encountered in + // processing the root files. + if (!skipDefaultLib) { + // If '--lib' is not specified, include default library file according to '--target' + // otherwise, using options specified in '--lib' instead of '--target' default library file + if (!options.lib) { + processRootFile(host.getDefaultLibFileName(options), /*isDefaultLib*/ true); + } + else { + var libDirectory_1 = host.getDefaultLibLocation ? host.getDefaultLibLocation() : ts.getDirectoryPath(host.getDefaultLibFileName(options)); + ts.forEach(options.lib, function (libFileName) { + processRootFile(ts.combinePaths(libDirectory_1, libFileName), /*isDefaultLib*/ true); + }); } } - function addOutliningForLeadingCommentsForNode(n) { - var comments = ts.getLeadingCommentRangesOfNode(n, sourceFile); - if (comments) { - var firstSingleLineCommentStart = -1; - var lastSingleLineCommentEnd = -1; - var isFirstSingleLineComment = true; - var singleLineCommentCount = 0; - for (var _i = 0, comments_2 = comments; _i < comments_2.length; _i++) { - var currentComment = comments_2[_i]; - // For single line comments, combine consecutive ones (2 or more) into - // a single span from the start of the first till the end of the last - if (currentComment.kind === 2 /* SingleLineCommentTrivia */) { - if (isFirstSingleLineComment) { - firstSingleLineCommentStart = currentComment.pos; - } - isFirstSingleLineComment = false; - lastSingleLineCommentEnd = currentComment.end; - singleLineCommentCount++; - } - else if (currentComment.kind === 3 /* MultiLineCommentTrivia */) { - combineAndAddMultipleSingleLineComments(singleLineCommentCount, firstSingleLineCommentStart, lastSingleLineCommentEnd); - addOutliningSpanComments(currentComment, /*autoCollapse*/ false); - singleLineCommentCount = 0; - lastSingleLineCommentEnd = -1; - isFirstSingleLineComment = true; - } - } - combineAndAddMultipleSingleLineComments(singleLineCommentCount, firstSingleLineCommentStart, lastSingleLineCommentEnd); + } + // unconditionally set oldProgram to undefined to prevent it from being captured in closure + oldProgram = undefined; + program = { + getRootFileNames: function () { return rootNames; }, + getSourceFile: getSourceFile, + getSourceFileByPath: getSourceFileByPath, + getSourceFiles: function () { return files; }, + getCompilerOptions: function () { return options; }, + getSyntacticDiagnostics: getSyntacticDiagnostics, + getOptionsDiagnostics: getOptionsDiagnostics, + getGlobalDiagnostics: getGlobalDiagnostics, + getSemanticDiagnostics: getSemanticDiagnostics, + getDeclarationDiagnostics: getDeclarationDiagnostics, + getTypeChecker: getTypeChecker, + getClassifiableNames: getClassifiableNames, + getDiagnosticsProducingTypeChecker: getDiagnosticsProducingTypeChecker, + getCommonSourceDirectory: getCommonSourceDirectory, + emit: emit, + getCurrentDirectory: function () { return currentDirectory; }, + getNodeCount: function () { return getDiagnosticsProducingTypeChecker().getNodeCount(); }, + getIdentifierCount: function () { return getDiagnosticsProducingTypeChecker().getIdentifierCount(); }, + getSymbolCount: function () { return getDiagnosticsProducingTypeChecker().getSymbolCount(); }, + getTypeCount: function () { return getDiagnosticsProducingTypeChecker().getTypeCount(); }, + getFileProcessingDiagnostics: function () { return fileProcessingDiagnostics; }, + getResolvedTypeReferenceDirectives: function () { return resolvedTypeReferenceDirectives; }, + dropDiagnosticsProducingTypeChecker: dropDiagnosticsProducingTypeChecker + }; + verifyCompilerOptions(); + ts.performance.mark("afterProgram"); + ts.performance.measure("Program", "beforeProgram", "afterProgram"); + return program; + function getCommonSourceDirectory() { + if (typeof commonSourceDirectory === "undefined") { + if (options.rootDir && checkSourceFilesBelongToPath(files, options.rootDir)) { + // If a rootDir is specified and is valid use it as the commonSourceDirectory + commonSourceDirectory = ts.getNormalizedAbsolutePath(options.rootDir, currentDirectory); + } + else { + commonSourceDirectory = computeCommonSourceDirectory(files); + } + if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== ts.directorySeparator) { + // Make sure directory path ends with directory separator so this string can directly + // used to replace with "" to get the relative path of the source file and the relative path doesn't + // start with / making it rooted path + commonSourceDirectory += ts.directorySeparator; } } - function combineAndAddMultipleSingleLineComments(count, start, end) { - // Only outline spans of two or more consecutive single line comments - if (count > 1) { - var multipleSingleLineComments = { - pos: start, - end: end, - kind: 2 /* SingleLineCommentTrivia */ - }; - addOutliningSpanComments(multipleSingleLineComments, /*autoCollapse*/ false); + return commonSourceDirectory; + } + function getClassifiableNames() { + if (!classifiableNames) { + // Initialize a checker so that all our files are bound. + getTypeChecker(); + classifiableNames = ts.createMap(); + for (var _i = 0, files_2 = files; _i < files_2.length; _i++) { + var sourceFile = files_2[_i]; + ts.copyProperties(sourceFile.classifiableNames, classifiableNames); } } - function autoCollapse(node) { - return ts.isFunctionBlock(node) && node.parent.kind !== 180 /* ArrowFunction */; + return classifiableNames; + } + function tryReuseStructureFromOldProgram() { + if (!oldProgram) { + return false; } - var depth = 0; - var maxDepth = 20; - function walk(n) { - if (depth > maxDepth) { - return; - } - if (ts.isDeclaration(n)) { - addOutliningForLeadingCommentsForNode(n); + // check properties that can affect structure of the program or module resolution strategy + // if any of these properties has changed - structure cannot be reused + var oldOptions = oldProgram.getCompilerOptions(); + if ((oldOptions.module !== options.module) || + (oldOptions.moduleResolution !== options.moduleResolution) || + (oldOptions.noResolve !== options.noResolve) || + (oldOptions.target !== options.target) || + (oldOptions.noLib !== options.noLib) || + (oldOptions.jsx !== options.jsx) || + (oldOptions.allowJs !== options.allowJs) || + (oldOptions.rootDir !== options.rootDir) || + (oldOptions.configFilePath !== options.configFilePath) || + (oldOptions.baseUrl !== options.baseUrl) || + (oldOptions.maxNodeModuleJsDepth !== options.maxNodeModuleJsDepth) || + !ts.arrayIsEqualTo(oldOptions.typeRoots, oldOptions.typeRoots) || + !ts.arrayIsEqualTo(oldOptions.rootDirs, options.rootDirs) || + !ts.equalOwnProperties(oldOptions.paths, options.paths)) { + return false; + } + ts.Debug.assert(!oldProgram.structureIsReused); + // there is an old program, check if we can reuse its structure + var oldRootNames = oldProgram.getRootFileNames(); + if (!ts.arrayIsEqualTo(oldRootNames, rootNames)) { + return false; + } + if (!ts.arrayIsEqualTo(options.types, oldOptions.types)) { + return false; + } + // check if program source files has changed in the way that can affect structure of the program + var newSourceFiles = []; + var filePaths = []; + var modifiedSourceFiles = []; + for (var _i = 0, _a = oldProgram.getSourceFiles(); _i < _a.length; _i++) { + var oldSourceFile = _a[_i]; + var newSourceFile = host.getSourceFileByPath + ? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.path, options.target) + : host.getSourceFile(oldSourceFile.fileName, options.target); + if (!newSourceFile) { + return false; } - switch (n.kind) { - case 199 /* Block */: - if (!ts.isFunctionBlock(n)) { - var parent_16 = n.parent; - var openBrace = ts.findChildOfKind(n, 15 /* OpenBraceToken */, sourceFile); - var closeBrace = ts.findChildOfKind(n, 16 /* CloseBraceToken */, sourceFile); - // Check if the block is standalone, or 'attached' to some parent statement. - // If the latter, we want to collapse the block, but consider its hint span - // to be the entire span of the parent. - if (parent_16.kind === 204 /* DoStatement */ || - parent_16.kind === 207 /* ForInStatement */ || - parent_16.kind === 208 /* ForOfStatement */ || - parent_16.kind === 206 /* ForStatement */ || - parent_16.kind === 203 /* IfStatement */ || - parent_16.kind === 205 /* WhileStatement */ || - parent_16.kind === 212 /* WithStatement */ || - parent_16.kind === 252 /* CatchClause */) { - addOutliningSpan(parent_16, openBrace, closeBrace, autoCollapse(n)); - break; - } - if (parent_16.kind === 216 /* TryStatement */) { - // Could be the try-block, or the finally-block. - var tryStatement = parent_16; - if (tryStatement.tryBlock === n) { - addOutliningSpan(parent_16, openBrace, closeBrace, autoCollapse(n)); - break; - } - else if (tryStatement.finallyBlock === n) { - var finallyKeyword = ts.findChildOfKind(tryStatement, 85 /* FinallyKeyword */, sourceFile); - if (finallyKeyword) { - addOutliningSpan(finallyKeyword, openBrace, closeBrace, autoCollapse(n)); - break; - } - } - } - // Block was a standalone block. In this case we want to only collapse - // the span of the block, independent of any parent span. - var span = ts.createTextSpanFromBounds(n.getStart(), n.end); - elements.push({ - textSpan: span, - hintSpan: span, - bannerText: collapseText, - autoCollapse: autoCollapse(n) - }); - break; + newSourceFile.path = oldSourceFile.path; + filePaths.push(newSourceFile.path); + if (oldSourceFile !== newSourceFile) { + if (oldSourceFile.hasNoDefaultLib !== newSourceFile.hasNoDefaultLib) { + // value of no-default-lib has changed + // this will affect if default library is injected into the list of files + return false; + } + // check tripleslash references + if (!ts.arrayIsEqualTo(oldSourceFile.referencedFiles, newSourceFile.referencedFiles, fileReferenceIsEqualTo)) { + // tripleslash references has changed + return false; + } + // check imports and module augmentations + collectExternalModuleReferences(newSourceFile); + if (!ts.arrayIsEqualTo(oldSourceFile.imports, newSourceFile.imports, moduleNameIsEqualTo)) { + // imports has changed + return false; + } + if (!ts.arrayIsEqualTo(oldSourceFile.moduleAugmentations, newSourceFile.moduleAugmentations, moduleNameIsEqualTo)) { + // moduleAugmentations has changed + return false; + } + if (!ts.arrayIsEqualTo(oldSourceFile.typeReferenceDirectives, newSourceFile.typeReferenceDirectives, fileReferenceIsEqualTo)) { + // 'types' references has changed + return false; + } + var newSourceFilePath = ts.getNormalizedAbsolutePath(newSourceFile.fileName, currentDirectory); + if (resolveModuleNamesWorker) { + var moduleNames = ts.map(ts.concatenate(newSourceFile.imports, newSourceFile.moduleAugmentations), getTextOfLiteral); + var resolutions = resolveModuleNamesWorker(moduleNames, newSourceFilePath); + // ensure that module resolution results are still correct + var resolutionsChanged = ts.hasChangesInResolutions(moduleNames, resolutions, oldSourceFile.resolvedModules, ts.moduleResolutionIsEqualTo); + if (resolutionsChanged) { + return false; } - // Fallthrough. - case 226 /* ModuleBlock */: { - var openBrace = ts.findChildOfKind(n, 15 /* OpenBraceToken */, sourceFile); - var closeBrace = ts.findChildOfKind(n, 16 /* CloseBraceToken */, sourceFile); - addOutliningSpan(n.parent, openBrace, closeBrace, autoCollapse(n)); - break; } - case 221 /* ClassDeclaration */: - case 222 /* InterfaceDeclaration */: - case 224 /* EnumDeclaration */: - case 171 /* ObjectLiteralExpression */: - case 227 /* CaseBlock */: { - var openBrace = ts.findChildOfKind(n, 15 /* OpenBraceToken */, sourceFile); - var closeBrace = ts.findChildOfKind(n, 16 /* CloseBraceToken */, sourceFile); - addOutliningSpan(n, openBrace, closeBrace, autoCollapse(n)); - break; + if (resolveTypeReferenceDirectiveNamesWorker) { + var typesReferenceDirectives = ts.map(newSourceFile.typeReferenceDirectives, function (x) { return x.fileName; }); + var resolutions = resolveTypeReferenceDirectiveNamesWorker(typesReferenceDirectives, newSourceFilePath); + // ensure that types resolutions are still correct + var resolutionsChanged = ts.hasChangesInResolutions(typesReferenceDirectives, resolutions, oldSourceFile.resolvedTypeReferenceDirectiveNames, ts.typeDirectiveIsEqualTo); + if (resolutionsChanged) { + return false; + } } - case 170 /* ArrayLiteralExpression */: - var openBracket = ts.findChildOfKind(n, 19 /* OpenBracketToken */, sourceFile); - var closeBracket = ts.findChildOfKind(n, 20 /* CloseBracketToken */, sourceFile); - addOutliningSpan(n, openBracket, closeBracket, autoCollapse(n)); - break; + // pass the cache of module/types resolutions from the old source file + newSourceFile.resolvedModules = oldSourceFile.resolvedModules; + newSourceFile.resolvedTypeReferenceDirectiveNames = oldSourceFile.resolvedTypeReferenceDirectiveNames; + modifiedSourceFiles.push(newSourceFile); } - depth++; - ts.forEachChild(n, walk); - depth--; + else { + // file has no changes - use it as is + newSourceFile = oldSourceFile; + } + // if file has passed all checks it should be safe to reuse it + newSourceFiles.push(newSourceFile); } - walk(sourceFile); - return elements; + // update fileName -> file mapping + for (var i = 0, len = newSourceFiles.length; i < len; i++) { + filesByName.set(filePaths[i], newSourceFiles[i]); + } + files = newSourceFiles; + fileProcessingDiagnostics = oldProgram.getFileProcessingDiagnostics(); + for (var _b = 0, modifiedSourceFiles_1 = modifiedSourceFiles; _b < modifiedSourceFiles_1.length; _b++) { + var modifiedFile = modifiedSourceFiles_1[_b]; + fileProcessingDiagnostics.reattachFileDiagnostics(modifiedFile); + } + resolvedTypeReferenceDirectives = oldProgram.getResolvedTypeReferenceDirectives(); + oldProgram.structureIsReused = true; + return true; } - OutliningElementsCollector.collectElements = collectElements; - })(OutliningElementsCollector = ts.OutliningElementsCollector || (ts.OutliningElementsCollector = {})); -})(ts || (ts = {})); -/* @internal */ -var ts; -(function (ts) { - var NavigateTo; - (function (NavigateTo) { - function getNavigateToItems(program, checker, cancellationToken, searchValue, maxResultCount) { - var patternMatcher = ts.createPatternMatcher(searchValue); - var rawItems = []; - // This means "compare in a case insensitive manner." - var baseSensitivity = { sensitivity: "base" }; - // Search the declarations in all files and output matched NavigateToItem into array of NavigateToItem[] - ts.forEach(program.getSourceFiles(), function (sourceFile) { - cancellationToken.throwIfCancellationRequested(); - var nameToDeclarations = sourceFile.getNamedDeclarations(); - for (var name_37 in nameToDeclarations) { - var declarations = nameToDeclarations[name_37]; - if (declarations) { - // First do a quick check to see if the name of the declaration matches the - // last portion of the (possibly) dotted name they're searching for. - var matches = patternMatcher.getMatchesForLastSegmentOfPattern(name_37); - if (!matches) { - continue; - } - for (var _i = 0, declarations_7 = declarations; _i < declarations_7.length; _i++) { - var declaration = declarations_7[_i]; - // It was a match! If the pattern has dots in it, then also see if the - // declaration container matches as well. - if (patternMatcher.patternContainsDots) { - var containers = getContainers(declaration); - if (!containers) { - return undefined; - } - matches = patternMatcher.getMatches(containers, name_37); - if (!matches) { - continue; - } - } - var fileName = sourceFile.fileName; - var matchKind = bestMatchKind(matches); - rawItems.push({ name: name_37, fileName: fileName, matchKind: matchKind, isCaseSensitive: allMatchesAreCaseSensitive(matches), declaration: declaration }); - } - } + function getEmitHost(writeFileCallback) { + return { + getCanonicalFileName: getCanonicalFileName, + getCommonSourceDirectory: program.getCommonSourceDirectory, + getCompilerOptions: program.getCompilerOptions, + getCurrentDirectory: function () { return currentDirectory; }, + getNewLine: function () { return host.getNewLine(); }, + getSourceFile: program.getSourceFile, + getSourceFileByPath: program.getSourceFileByPath, + getSourceFiles: program.getSourceFiles, + isSourceFileFromExternalLibrary: function (file) { return !!sourceFilesFoundSearchingNodeModules[file.path]; }, + writeFile: writeFileCallback || (function (fileName, data, writeByteOrderMark, onError, sourceFiles) { return host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles); }), + isEmitBlocked: isEmitBlocked, + }; + } + function getDiagnosticsProducingTypeChecker() { + return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = ts.createTypeChecker(program, /*produceDiagnostics:*/ true)); + } + function dropDiagnosticsProducingTypeChecker() { + diagnosticsProducingTypeChecker = undefined; + } + function getTypeChecker() { + return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = ts.createTypeChecker(program, /*produceDiagnostics:*/ false)); + } + function emit(sourceFile, writeFileCallback, cancellationToken, emitOnlyDtsFiles) { + return runWithCancellationToken(function () { return emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnlyDtsFiles); }); + } + function isEmitBlocked(emitFileName) { + return hasEmitBlockingDiagnostics.contains(ts.toPath(emitFileName, currentDirectory, getCanonicalFileName)); + } + function emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnlyDtsFiles) { + var declarationDiagnostics = []; + if (options.noEmit) { + return { diagnostics: declarationDiagnostics, sourceMaps: undefined, emittedFiles: undefined, emitSkipped: true }; + } + // If the noEmitOnError flag is set, then check if we have any errors so far. If so, + // immediately bail out. Note that we pass 'undefined' for 'sourceFile' so that we + // get any preEmit diagnostics, not just the ones + if (options.noEmitOnError) { + var diagnostics = program.getOptionsDiagnostics(cancellationToken).concat(program.getSyntacticDiagnostics(sourceFile, cancellationToken), program.getGlobalDiagnostics(cancellationToken), program.getSemanticDiagnostics(sourceFile, cancellationToken)); + if (diagnostics.length === 0 && program.getCompilerOptions().declaration) { + declarationDiagnostics = program.getDeclarationDiagnostics(/*sourceFile*/ undefined, cancellationToken); } - }); - // Remove imports when the imported declaration is already in the list and has the same name. - rawItems = ts.filter(rawItems, function (item) { - var decl = item.declaration; - if (decl.kind === 231 /* ImportClause */ || decl.kind === 234 /* ImportSpecifier */ || decl.kind === 229 /* ImportEqualsDeclaration */) { - var importer = checker.getSymbolAtLocation(decl.name); - var imported = checker.getAliasedSymbol(importer); - return importer.name !== imported.name; + if (diagnostics.length > 0 || declarationDiagnostics.length > 0) { + return { + diagnostics: ts.concatenate(diagnostics, declarationDiagnostics), + sourceMaps: undefined, + emittedFiles: undefined, + emitSkipped: true + }; } - else { - return true; + } + // Create the emit resolver outside of the "emitTime" tracking code below. That way + // any cost associated with it (like type checking) are appropriate associated with + // the type-checking counter. + // + // If the -out option is specified, we should not pass the source file to getEmitResolver. + // This is because in the -out scenario all files need to be emitted, and therefore all + // files need to be type checked. And the way to specify that all files need to be type + // checked is to not pass the file to getEmitResolver. + var emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver((options.outFile || options.out) ? undefined : sourceFile); + ts.performance.mark("beforeEmit"); + var emitResult = ts.emitFiles(emitResolver, getEmitHost(writeFileCallback), sourceFile, emitOnlyDtsFiles); + ts.performance.mark("afterEmit"); + ts.performance.measure("Emit", "beforeEmit", "afterEmit"); + return emitResult; + } + function getSourceFile(fileName) { + return getSourceFileByPath(ts.toPath(fileName, currentDirectory, getCanonicalFileName)); + } + function getSourceFileByPath(path) { + return filesByName.get(path); + } + function getDiagnosticsHelper(sourceFile, getDiagnostics, cancellationToken) { + if (sourceFile) { + return getDiagnostics(sourceFile, cancellationToken); + } + var allDiagnostics = []; + ts.forEach(program.getSourceFiles(), function (sourceFile) { + if (cancellationToken) { + cancellationToken.throwIfCancellationRequested(); } + ts.addRange(allDiagnostics, getDiagnostics(sourceFile, cancellationToken)); }); - rawItems.sort(compareNavigateToItems); - if (maxResultCount !== undefined) { - rawItems = rawItems.slice(0, maxResultCount); + return ts.sortAndDeduplicateDiagnostics(allDiagnostics); + } + function getSyntacticDiagnostics(sourceFile, cancellationToken) { + return getDiagnosticsHelper(sourceFile, getSyntacticDiagnosticsForFile, cancellationToken); + } + function getSemanticDiagnostics(sourceFile, cancellationToken) { + return getDiagnosticsHelper(sourceFile, getSemanticDiagnosticsForFile, cancellationToken); + } + function getDeclarationDiagnostics(sourceFile, cancellationToken) { + var options = program.getCompilerOptions(); + // collect diagnostics from the program only once if either no source file was specified or out/outFile is set (bundled emit) + if (!sourceFile || options.out || options.outFile) { + return getDeclarationDiagnosticsWorker(sourceFile, cancellationToken); } - var items = ts.map(rawItems, createNavigateToItem); - return items; - function allMatchesAreCaseSensitive(matches) { - ts.Debug.assert(matches.length > 0); - // This is a case sensitive match, only if all the submatches were case sensitive. - for (var _i = 0, matches_1 = matches; _i < matches_1.length; _i++) { - var match = matches_1[_i]; - if (!match.isCaseSensitive) { - return false; - } - } - return true; + else { + return getDiagnosticsHelper(sourceFile, getDeclarationDiagnosticsForFile, cancellationToken); } - function getTextOfIdentifierOrLiteral(node) { - if (node) { - if (node.kind === 69 /* Identifier */ || - node.kind === 9 /* StringLiteral */ || - node.kind === 8 /* NumericLiteral */) { - return node.text; - } - } - return undefined; + } + function getSyntacticDiagnosticsForFile(sourceFile, cancellationToken) { + return sourceFile.parseDiagnostics; + } + function runWithCancellationToken(func) { + try { + return func(); } - function tryAddSingleDeclarationName(declaration, containers) { - if (declaration && declaration.name) { - var text = getTextOfIdentifierOrLiteral(declaration.name); - if (text !== undefined) { - containers.unshift(text); - } - else if (declaration.name.kind === 140 /* ComputedPropertyName */) { - return tryAddComputedPropertyName(declaration.name.expression, containers, /*includeLastPortion*/ true); - } - else { - // Don't know how to add this. - return false; - } + catch (e) { + if (e instanceof ts.OperationCanceledException) { + // We were canceled while performing the operation. Because our type checker + // might be a bad state, we need to throw it away. + // + // Note: we are overly aggressive here. We do not actually *have* to throw away + // the "noDiagnosticsTypeChecker". However, for simplicity, i'd like to keep + // the lifetimes of these two TypeCheckers the same. Also, we generally only + // cancel when the user has made a change anyways. And, in that case, we (the + // program instance) will get thrown away anyways. So trying to keep one of + // these type checkers alive doesn't serve much purpose. + noDiagnosticsTypeChecker = undefined; + diagnosticsProducingTypeChecker = undefined; } - return true; + throw e; } - // Only added the names of computed properties if they're simple dotted expressions, like: - // - // [X.Y.Z]() { } - function tryAddComputedPropertyName(expression, containers, includeLastPortion) { - var text = getTextOfIdentifierOrLiteral(expression); - if (text !== undefined) { - if (includeLastPortion) { - containers.unshift(text); + } + function getSemanticDiagnosticsForFile(sourceFile, cancellationToken) { + return runWithCancellationToken(function () { + var typeChecker = getDiagnosticsProducingTypeChecker(); + ts.Debug.assert(!!sourceFile.bindDiagnostics); + var bindDiagnostics = sourceFile.bindDiagnostics; + // For JavaScript files, we don't want to report the normal typescript semantic errors. + // Instead, we just report errors for using TypeScript-only constructs from within a + // JavaScript file. + var checkDiagnostics = ts.isSourceFileJavaScript(sourceFile) ? + getJavaScriptSemanticDiagnosticsForFile(sourceFile, cancellationToken) : + typeChecker.getDiagnostics(sourceFile, cancellationToken); + var fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName); + var programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName); + return bindDiagnostics.concat(checkDiagnostics).concat(fileProcessingDiagnosticsInFile).concat(programDiagnosticsInFile); + }); + } + function getJavaScriptSemanticDiagnosticsForFile(sourceFile, cancellationToken) { + return runWithCancellationToken(function () { + var diagnostics = []; + walk(sourceFile); + return diagnostics; + function walk(node) { + if (!node) { + return false; } - return true; - } - if (expression.kind === 172 /* PropertyAccessExpression */) { - var propertyAccess = expression; - if (includeLastPortion) { - containers.unshift(propertyAccess.name.text); + switch (node.kind) { + case 229 /* ImportEqualsDeclaration */: + diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.import_can_only_be_used_in_a_ts_file)); + return true; + case 235 /* ExportAssignment */: + if (node.isExportEquals) { + diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.export_can_only_be_used_in_a_ts_file)); + return true; + } + break; + case 221 /* ClassDeclaration */: + var classDeclaration = node; + if (checkModifiers(classDeclaration.modifiers) || + checkTypeParameters(classDeclaration.typeParameters)) { + return true; + } + break; + case 251 /* HeritageClause */: + var heritageClause = node; + if (heritageClause.token === 106 /* ImplementsKeyword */) { + diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.implements_clauses_can_only_be_used_in_a_ts_file)); + return true; + } + break; + case 222 /* InterfaceDeclaration */: + diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.interface_declarations_can_only_be_used_in_a_ts_file)); + return true; + case 225 /* ModuleDeclaration */: + diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.module_declarations_can_only_be_used_in_a_ts_file)); + return true; + case 223 /* TypeAliasDeclaration */: + diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.type_aliases_can_only_be_used_in_a_ts_file)); + return true; + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + case 148 /* Constructor */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 179 /* FunctionExpression */: + case 220 /* FunctionDeclaration */: + case 180 /* ArrowFunction */: + case 220 /* FunctionDeclaration */: + var functionDeclaration = node; + if (checkModifiers(functionDeclaration.modifiers) || + checkTypeParameters(functionDeclaration.typeParameters) || + checkTypeAnnotation(functionDeclaration.type)) { + return true; + } + break; + case 200 /* VariableStatement */: + var variableStatement = node; + if (checkModifiers(variableStatement.modifiers)) { + return true; + } + break; + case 218 /* VariableDeclaration */: + var variableDeclaration = node; + if (checkTypeAnnotation(variableDeclaration.type)) { + return true; + } + break; + case 174 /* CallExpression */: + case 175 /* NewExpression */: + var expression = node; + if (expression.typeArguments && expression.typeArguments.length > 0) { + var start = expression.typeArguments.pos; + diagnostics.push(ts.createFileDiagnostic(sourceFile, start, expression.typeArguments.end - start, ts.Diagnostics.type_arguments_can_only_be_used_in_a_ts_file)); + return true; + } + break; + case 142 /* Parameter */: + var parameter = node; + if (parameter.modifiers) { + var start = parameter.modifiers.pos; + diagnostics.push(ts.createFileDiagnostic(sourceFile, start, parameter.modifiers.end - start, ts.Diagnostics.parameter_modifiers_can_only_be_used_in_a_ts_file)); + return true; + } + if (parameter.questionToken) { + diagnostics.push(ts.createDiagnosticForNode(parameter.questionToken, ts.Diagnostics._0_can_only_be_used_in_a_ts_file, "?")); + return true; + } + if (parameter.type) { + diagnostics.push(ts.createDiagnosticForNode(parameter.type, ts.Diagnostics.types_can_only_be_used_in_a_ts_file)); + return true; + } + break; + case 145 /* PropertyDeclaration */: + var propertyDeclaration = node; + if (propertyDeclaration.modifiers) { + for (var _i = 0, _a = propertyDeclaration.modifiers; _i < _a.length; _i++) { + var modifier = _a[_i]; + if (modifier.kind !== 113 /* StaticKeyword */) { + diagnostics.push(ts.createDiagnosticForNode(modifier, ts.Diagnostics._0_can_only_be_used_in_a_ts_file, ts.tokenToString(modifier.kind))); + return true; + } + } + } + if (checkTypeAnnotation(node.type)) { + return true; + } + break; + case 224 /* EnumDeclaration */: + diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.enum_declarations_can_only_be_used_in_a_ts_file)); + return true; + case 177 /* TypeAssertionExpression */: + var typeAssertionExpression = node; + diagnostics.push(ts.createDiagnosticForNode(typeAssertionExpression.type, ts.Diagnostics.type_assertion_expressions_can_only_be_used_in_a_ts_file)); + return true; + case 143 /* Decorator */: + if (!options.experimentalDecorators) { + diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_to_remove_this_warning)); + } + return true; } - return tryAddComputedPropertyName(propertyAccess.expression, containers, /*includeLastPortion*/ true); + return ts.forEachChild(node, walk); } - return false; - } - function getContainers(declaration) { - var containers = []; - // First, if we started with a computed property name, then add all but the last - // portion into the container array. - if (declaration.name.kind === 140 /* ComputedPropertyName */) { - if (!tryAddComputedPropertyName(declaration.name.expression, containers, /*includeLastPortion*/ false)) { - return undefined; + function checkTypeParameters(typeParameters) { + if (typeParameters) { + var start = typeParameters.pos; + diagnostics.push(ts.createFileDiagnostic(sourceFile, start, typeParameters.end - start, ts.Diagnostics.type_parameter_declarations_can_only_be_used_in_a_ts_file)); + return true; } + return false; } - // Now, walk up our containers, adding all their names to the container array. - declaration = ts.getContainerNode(declaration); - while (declaration) { - if (!tryAddSingleDeclarationName(declaration, containers)) { - return undefined; + function checkTypeAnnotation(type) { + if (type) { + diagnostics.push(ts.createDiagnosticForNode(type, ts.Diagnostics.types_can_only_be_used_in_a_ts_file)); + return true; } - declaration = ts.getContainerNode(declaration); + return false; } - return containers; - } - function bestMatchKind(matches) { - ts.Debug.assert(matches.length > 0); - var bestMatchKind = ts.PatternMatchKind.camelCase; - for (var _i = 0, matches_2 = matches; _i < matches_2.length; _i++) { - var match = matches_2[_i]; - var kind = match.kind; - if (kind < bestMatchKind) { - bestMatchKind = kind; + function checkModifiers(modifiers) { + if (modifiers) { + for (var _i = 0, modifiers_1 = modifiers; _i < modifiers_1.length; _i++) { + var modifier = modifiers_1[_i]; + switch (modifier.kind) { + case 112 /* PublicKeyword */: + case 110 /* PrivateKeyword */: + case 111 /* ProtectedKeyword */: + case 128 /* ReadonlyKeyword */: + case 122 /* DeclareKeyword */: + diagnostics.push(ts.createDiagnosticForNode(modifier, ts.Diagnostics._0_can_only_be_used_in_a_ts_file, ts.tokenToString(modifier.kind))); + return true; + // These are all legal modifiers. + case 113 /* StaticKeyword */: + case 82 /* ExportKeyword */: + case 74 /* ConstKeyword */: + case 77 /* DefaultKeyword */: + case 115 /* AbstractKeyword */: + } + } } + return false; } - return bestMatchKind; - } - function compareNavigateToItems(i1, i2) { - // TODO(cyrusn): get the gamut of comparisons that VS already uses here. - // Right now we just sort by kind first, and then by name of the item. - // We first sort case insensitively. So "Aaa" will come before "bar". - // Then we sort case sensitively, so "aaa" will come before "Aaa". - return i1.matchKind - i2.matchKind || - i1.name.localeCompare(i2.name, undefined, baseSensitivity) || - i1.name.localeCompare(i2.name); - } - function createNavigateToItem(rawItem) { - var declaration = rawItem.declaration; - var container = ts.getContainerNode(declaration); - return { - name: rawItem.name, - kind: ts.getNodeKind(declaration), - kindModifiers: ts.getNodeModifiers(declaration), - matchKind: ts.PatternMatchKind[rawItem.matchKind], - isCaseSensitive: rawItem.isCaseSensitive, - fileName: rawItem.fileName, - textSpan: ts.createTextSpanFromBounds(declaration.getStart(), declaration.getEnd()), - // TODO(jfreeman): What should be the containerName when the container has a computed name? - containerName: container && container.name ? container.name.text : "", - containerKind: container && container.name ? ts.getNodeKind(container) : "" - }; - } - } - NavigateTo.getNavigateToItems = getNavigateToItems; - })(NavigateTo = ts.NavigateTo || (ts.NavigateTo = {})); -})(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - var NavigationBar; - (function (NavigationBar) { - function getNavigationBarItems(sourceFile) { - curSourceFile = sourceFile; - var result = ts.map(topLevelItems(rootNavigationBarNode(sourceFile)), convertToTopLevelItem); - curSourceFile = undefined; - return result; + }); } - NavigationBar.getNavigationBarItems = getNavigationBarItems; - // Keep sourceFile handy so we don't have to search for it every time we need to call `getText`. - var curSourceFile; - function nodeText(node) { - return node.getText(curSourceFile); + function getDeclarationDiagnosticsWorker(sourceFile, cancellationToken) { + return runWithCancellationToken(function () { + var resolver = getDiagnosticsProducingTypeChecker().getEmitResolver(sourceFile, cancellationToken); + // Don't actually write any files since we're just getting diagnostics. + var writeFile = function () { }; + return ts.getDeclarationDiagnostics(getEmitHost(writeFile), resolver, sourceFile); + }); } - function navigationBarNodeKind(n) { - return n.node.kind; + function getDeclarationDiagnosticsForFile(sourceFile, cancellationToken) { + return ts.isDeclarationFile(sourceFile) ? [] : getDeclarationDiagnosticsWorker(sourceFile, cancellationToken); } - function pushChild(parent, child) { - if (parent.children) { - parent.children.push(child); - } - else { - parent.children = [child]; - } + function getOptionsDiagnostics() { + var allDiagnostics = []; + ts.addRange(allDiagnostics, fileProcessingDiagnostics.getGlobalDiagnostics()); + ts.addRange(allDiagnostics, programDiagnostics.getGlobalDiagnostics()); + return ts.sortAndDeduplicateDiagnostics(allDiagnostics); } - /* - For performance, we keep navigation bar parents on a stack rather than passing them through each recursion. - `parent` is the current parent and is *not* stored in parentsStack. - `startNode` sets a new parent and `endNode` returns to the previous parent. - */ - var parentsStack = []; - var parent; - function rootNavigationBarNode(sourceFile) { - ts.Debug.assert(!parentsStack.length); - var root = { node: sourceFile, additionalNodes: undefined, parent: undefined, children: undefined, indent: 0 }; - parent = root; - for (var _i = 0, _a = sourceFile.statements; _i < _a.length; _i++) { - var statement = _a[_i]; - addChildrenRecursively(statement); - } - endNode(); - ts.Debug.assert(!parent && !parentsStack.length); - return root; + function getGlobalDiagnostics() { + var allDiagnostics = []; + ts.addRange(allDiagnostics, getDiagnosticsProducingTypeChecker().getGlobalDiagnostics()); + return ts.sortAndDeduplicateDiagnostics(allDiagnostics); } - function addLeafNode(node) { - pushChild(parent, emptyNavigationBarNode(node)); + function hasExtension(fileName) { + return ts.getBaseFileName(fileName).indexOf(".") >= 0; } - function emptyNavigationBarNode(node) { - return { - node: node, - additionalNodes: undefined, - parent: parent, - children: undefined, - indent: parent.indent + 1 - }; + function processRootFile(fileName, isDefaultLib) { + processSourceFile(ts.normalizePath(fileName), isDefaultLib, /*isReference*/ true); } - /** - * Add a new level of NavigationBarNodes. - * This pushes to the stack, so you must call `endNode` when you are done adding to this node. - */ - function startNode(node) { - var navNode = emptyNavigationBarNode(node); - pushChild(parent, navNode); - // Save the old parent - parentsStack.push(parent); - parent = navNode; + function fileReferenceIsEqualTo(a, b) { + return a.fileName === b.fileName; } - /** Call after calling `startNode` and adding children to it. */ - function endNode() { - if (parent.children) { - mergeChildren(parent.children); - sortChildren(parent.children); - } - parent = parentsStack.pop(); + function moduleNameIsEqualTo(a, b) { + return a.text === b.text; } - function addNodeWithRecursiveChild(node, child) { - startNode(node); - addChildrenRecursively(child); - endNode(); + function getTextOfLiteral(literal) { + return literal.text; } - /** Look for navigation bar items in node's subtree, adding them to the current `parent`. */ - function addChildrenRecursively(node) { - if (!node || ts.isToken(node)) { + function collectExternalModuleReferences(file) { + if (file.imports) { return; } - switch (node.kind) { - case 148 /* Constructor */: - // Get parameter properties, and treat them as being on the *same* level as the constructor, not under it. - var ctr = node; - addNodeWithRecursiveChild(ctr, ctr.body); - // Parameter properties are children of the class, not the constructor. - for (var _i = 0, _a = ctr.parameters; _i < _a.length; _i++) { - var param = _a[_i]; - if (ts.isParameterPropertyDeclaration(param)) { - addLeafNode(param); - } - } - break; - case 147 /* MethodDeclaration */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 146 /* MethodSignature */: - if (!ts.hasDynamicName(node)) { - addNodeWithRecursiveChild(node, node.body); - } - break; - case 145 /* PropertyDeclaration */: - case 144 /* PropertySignature */: - if (!ts.hasDynamicName(node)) { - addLeafNode(node); - } - break; - case 231 /* ImportClause */: - var importClause = node; - // Handle default import case e.g.: - // import d from "mod"; - if (importClause.name) { - addLeafNode(importClause); - } - // Handle named bindings in imports e.g.: - // import * as NS from "mod"; - // import {a, b as B} from "mod"; - var namedBindings = importClause.namedBindings; - if (namedBindings) { - if (namedBindings.kind === 232 /* NamespaceImport */) { - addLeafNode(namedBindings); + var isJavaScriptFile = ts.isSourceFileJavaScript(file); + var isExternalModuleFile = ts.isExternalModule(file); + var imports; + var moduleAugmentations; + // If we are importing helpers, we need to add a synthetic reference to resolve the + // helpers library. + if (options.importHelpers + && (options.isolatedModules || isExternalModuleFile) + && !file.isDeclarationFile) { + var externalHelpersModuleReference = ts.createNode(9 /* StringLiteral */); + externalHelpersModuleReference.text = ts.externalHelpersModuleNameText; + externalHelpersModuleReference.parent = file; + imports = [externalHelpersModuleReference]; + } + for (var _i = 0, _a = file.statements; _i < _a.length; _i++) { + var node = _a[_i]; + collectModuleReferences(node, /*inAmbientModule*/ false); + if (isJavaScriptFile) { + collectRequireCalls(node); + } + } + file.imports = imports || emptyArray; + file.moduleAugmentations = moduleAugmentations || emptyArray; + return; + function collectModuleReferences(node, inAmbientModule) { + switch (node.kind) { + case 230 /* ImportDeclaration */: + case 229 /* ImportEqualsDeclaration */: + case 236 /* ExportDeclaration */: + var moduleNameExpr = ts.getExternalModuleName(node); + if (!moduleNameExpr || moduleNameExpr.kind !== 9 /* StringLiteral */) { + break; } - else { - for (var _b = 0, _c = namedBindings.elements; _b < _c.length; _b++) { - var element = _c[_b]; - addLeafNode(element); - } + if (!moduleNameExpr.text) { + break; } - } - break; - case 169 /* BindingElement */: - case 218 /* VariableDeclaration */: - var decl = node; - var name_38 = decl.name; - if (ts.isBindingPattern(name_38)) { - addChildrenRecursively(name_38); - } - else if (decl.initializer && isFunctionOrClassExpression(decl.initializer)) { - // For `const x = function() {}`, just use the function node, not the const. - addChildrenRecursively(decl.initializer); - } - else { - addNodeWithRecursiveChild(decl, decl.initializer); - } - break; - case 180 /* ArrowFunction */: - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - addNodeWithRecursiveChild(node, node.body); - break; - case 224 /* EnumDeclaration */: - startNode(node); - for (var _d = 0, _e = node.members; _d < _e.length; _d++) { - var member = _e[_d]; - if (!isComputedProperty(member)) { - addLeafNode(member); + // TypeScript 1.0 spec (April 2014): 12.1.6 + // An ExternalImportDeclaration in an AmbientExternalModuleDeclaration may reference other external modules + // only through top - level external module names. Relative external module names are not permitted. + if (!inAmbientModule || !ts.isExternalModuleNameRelative(moduleNameExpr.text)) { + (imports || (imports = [])).push(moduleNameExpr); } - } - endNode(); - break; - case 221 /* ClassDeclaration */: - case 192 /* ClassExpression */: - case 222 /* InterfaceDeclaration */: - startNode(node); - for (var _f = 0, _g = node.members; _f < _g.length; _f++) { - var member = _g[_f]; - addChildrenRecursively(member); - } - endNode(); - break; - case 225 /* ModuleDeclaration */: - addNodeWithRecursiveChild(node, getInteriorModule(node).body); - break; - case 238 /* ExportSpecifier */: - case 229 /* ImportEqualsDeclaration */: - case 153 /* IndexSignature */: - case 151 /* CallSignature */: - case 152 /* ConstructSignature */: - case 223 /* TypeAliasDeclaration */: - addLeafNode(node); - break; - default: - if (node.jsDocComments) { - for (var _h = 0, _j = node.jsDocComments; _h < _j.length; _h++) { - var jsDocComment = _j[_h]; - for (var _k = 0, _l = jsDocComment.tags; _k < _l.length; _k++) { - var tag = _l[_k]; - if (tag.kind === 279 /* JSDocTypedefTag */) { - addLeafNode(tag); + break; + case 225 /* ModuleDeclaration */: + if (ts.isAmbientModule(node) && (inAmbientModule || ts.hasModifier(node, 2 /* Ambient */) || ts.isDeclarationFile(file))) { + var moduleName = node.name; + // Ambient module declarations can be interpreted as augmentations for some existing external modules. + // This will happen in two cases: + // - if current file is external module then module augmentation is a ambient module declaration defined in the top level scope + // - if current file is not external module then module augmentation is an ambient module declaration with non-relative module name + // immediately nested in top level ambient module declaration . + if (isExternalModuleFile || (inAmbientModule && !ts.isExternalModuleNameRelative(moduleName.text))) { + (moduleAugmentations || (moduleAugmentations = [])).push(moduleName); + } + else if (!inAmbientModule) { + // An AmbientExternalModuleDeclaration declares an external module. + // This type of declaration is permitted only in the global module. + // The StringLiteral must specify a top - level external module name. + // Relative external module names are not permitted + // NOTE: body of ambient module is always a module block, if it exists + var body = node.body; + if (body) { + for (var _i = 0, _a = body.statements; _i < _a.length; _i++) { + var statement = _a[_i]; + collectModuleReferences(statement, /*inAmbientModule*/ true); + } } } } - } - ts.forEachChild(node, addChildrenRecursively); + } } - } - /** Merge declarations of the same kind. */ - function mergeChildren(children) { - var nameToItems = ts.createMap(); - ts.filterMutate(children, function (child) { - var decl = child.node; - var name = decl.name && nodeText(decl.name); - if (!name) { - // Anonymous items are never merged. - return true; + function collectRequireCalls(node) { + if (ts.isRequireCall(node, /*checkArgumentIsStringLiteral*/ true)) { + (imports || (imports = [])).push(node.arguments[0]); } - var itemsWithSameName = nameToItems[name]; - if (!itemsWithSameName) { - nameToItems[name] = child; - return true; + else { + ts.forEachChild(node, collectRequireCalls); } - if (itemsWithSameName instanceof Array) { - for (var _i = 0, itemsWithSameName_1 = itemsWithSameName; _i < itemsWithSameName_1.length; _i++) { - var itemWithSameName = itemsWithSameName_1[_i]; - if (tryMerge(itemWithSameName, child)) { - return false; - } - } - itemsWithSameName.push(child); - return true; + } + } + /** + * 'isReference' indicates whether the file was brought in via a reference directive (rather than an import declaration) + */ + function processSourceFile(fileName, isDefaultLib, isReference, refFile, refPos, refEnd) { + var diagnosticArgument; + var diagnostic; + if (hasExtension(fileName)) { + if (!options.allowNonTsExtensions && !ts.forEach(supportedExtensions, function (extension) { return ts.fileExtensionIs(host.getCanonicalFileName(fileName), extension); })) { + diagnostic = ts.Diagnostics.File_0_has_unsupported_extension_The_only_supported_extensions_are_1; + diagnosticArgument = [fileName, "'" + supportedExtensions.join("', '") + "'"]; } - else { - var itemWithSameName = itemsWithSameName; - if (tryMerge(itemWithSameName, child)) { - return false; - } - nameToItems[name] = [itemWithSameName, child]; - return true; + else if (!findSourceFile(fileName, ts.toPath(fileName, currentDirectory, getCanonicalFileName), isDefaultLib, isReference, refFile, refPos, refEnd)) { + diagnostic = ts.Diagnostics.File_0_not_found; + diagnosticArgument = [fileName]; } - function tryMerge(a, b) { - if (shouldReallyMerge(a.node, b.node)) { - merge(a, b); - return true; - } - return false; + else if (refFile && host.getCanonicalFileName(fileName) === host.getCanonicalFileName(refFile.fileName)) { + diagnostic = ts.Diagnostics.A_file_cannot_have_a_reference_to_itself; + diagnosticArgument = [fileName]; } - }); - /** a and b have the same name, but they may not be mergeable. */ - function shouldReallyMerge(a, b) { - return a.kind === b.kind && (a.kind !== 225 /* ModuleDeclaration */ || areSameModule(a, b)); - // We use 1 NavNode to represent 'A.B.C', but there are multiple source nodes. - // Only merge module nodes that have the same chain. Don't merge 'A.B.C' with 'A'! - function areSameModule(a, b) { - if (a.body.kind !== b.body.kind) { - return false; + } + else { + var nonTsFile = options.allowNonTsExtensions && findSourceFile(fileName, ts.toPath(fileName, currentDirectory, getCanonicalFileName), isDefaultLib, isReference, refFile, refPos, refEnd); + if (!nonTsFile) { + if (options.allowNonTsExtensions) { + diagnostic = ts.Diagnostics.File_0_not_found; + diagnosticArgument = [fileName]; } - if (a.body.kind !== 225 /* ModuleDeclaration */) { - return true; + else if (!ts.forEach(supportedExtensions, function (extension) { return findSourceFile(fileName + extension, ts.toPath(fileName + extension, currentDirectory, getCanonicalFileName), isDefaultLib, isReference, refFile, refPos, refEnd); })) { + diagnostic = ts.Diagnostics.File_0_not_found; + fileName += ".ts"; + diagnosticArgument = [fileName]; } - return areSameModule(a.body, b.body); } } - /** Merge source into target. Source should be thrown away after this is called. */ - function merge(target, source) { - target.additionalNodes = target.additionalNodes || []; - target.additionalNodes.push(source.node); - if (source.additionalNodes) { - (_a = target.additionalNodes).push.apply(_a, source.additionalNodes); + if (diagnostic) { + if (refFile !== undefined && refEnd !== undefined && refPos !== undefined) { + fileProcessingDiagnostics.add(ts.createFileDiagnostic.apply(void 0, [refFile, refPos, refEnd - refPos, diagnostic].concat(diagnosticArgument))); } - target.children = ts.concatenate(target.children, source.children); - if (target.children) { - mergeChildren(target.children); - sortChildren(target.children); + else { + fileProcessingDiagnostics.add(ts.createCompilerDiagnostic.apply(void 0, [diagnostic].concat(diagnosticArgument))); } - var _a; } } - /** Recursively ensure that each NavNode's children are in sorted order. */ - function sortChildren(children) { - children.sort(compareChildren); - } - function compareChildren(child1, child2) { - var name1 = tryGetName(child1.node), name2 = tryGetName(child2.node); - if (name1 && name2) { - var cmp = localeCompareFix(name1, name2); - return cmp !== 0 ? cmp : navigationBarNodeKind(child1) - navigationBarNodeKind(child2); + function reportFileNamesDifferOnlyInCasingError(fileName, existingFileName, refFile, refPos, refEnd) { + if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) { + fileProcessingDiagnostics.add(ts.createFileDiagnostic(refFile, refPos, refEnd - refPos, ts.Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, fileName, existingFileName)); } else { - return name1 ? 1 : name2 ? -1 : navigationBarNodeKind(child1) - navigationBarNodeKind(child2); - } - } - // More efficient to create a collator once and use its `compare` than to call `a.localeCompare(b)` many times. - var collator = typeof Intl === "undefined" ? undefined : new Intl.Collator(); - // Intl is missing in Safari, and node 0.10 treats "a" as greater than "B". - var localeCompareIsCorrect = collator && collator.compare("a", "B") < 0; - var localeCompareFix = localeCompareIsCorrect ? collator.compare : function (a, b) { - // This isn't perfect, but it passes all of our tests. - for (var i = 0; i < Math.min(a.length, b.length); i++) { - var chA = a.charAt(i), chB = b.charAt(i); - if (chA === "\"" && chB === "'") { - return 1; - } - if (chA === "'" && chB === "\"") { - return -1; - } - var cmp = chA.toLocaleLowerCase().localeCompare(chB.toLocaleLowerCase()); - if (cmp !== 0) { - return cmp; - } - } - return a.length - b.length; - }; - /** - * This differs from getItemName because this is just used for sorting. - * We only sort nodes by name that have a more-or-less "direct" name, as opposed to `new()` and the like. - * So `new()` can still come before an `aardvark` method. - */ - function tryGetName(node) { - if (node.kind === 225 /* ModuleDeclaration */) { - return getModuleName(node); - } - var decl = node; - if (decl.name) { - return ts.getPropertyNameForPropertyNameNode(decl.name); - } - switch (node.kind) { - case 179 /* FunctionExpression */: - case 180 /* ArrowFunction */: - case 192 /* ClassExpression */: - return getFunctionOrClassName(node); - case 279 /* JSDocTypedefTag */: - return getJSDocTypedefTagName(node); - default: - return undefined; + fileProcessingDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, fileName, existingFileName)); } } - function getItemName(node) { - if (node.kind === 225 /* ModuleDeclaration */) { - return getModuleName(node); - } - var name = node.name; - if (name) { - var text = nodeText(name); - if (text.length > 0) { - return text; + // Get source file from normalized fileName + function findSourceFile(fileName, path, isDefaultLib, isReference, refFile, refPos, refEnd) { + if (filesByName.contains(path)) { + var file_1 = filesByName.get(path); + // try to check if we've already seen this file but with a different casing in path + // NOTE: this only makes sense for case-insensitive file systems + if (file_1 && options.forceConsistentCasingInFileNames && ts.getNormalizedAbsolutePath(file_1.fileName, currentDirectory) !== ts.getNormalizedAbsolutePath(fileName, currentDirectory)) { + reportFileNamesDifferOnlyInCasingError(fileName, file_1.fileName, refFile, refPos, refEnd); } - } - switch (node.kind) { - case 256 /* SourceFile */: - var sourceFile = node; - return ts.isExternalModule(sourceFile) - ? "\"" + ts.escapeString(ts.getBaseFileName(ts.removeFileExtension(ts.normalizePath(sourceFile.fileName)))) + "\"" - : ""; - case 180 /* ArrowFunction */: - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - case 221 /* ClassDeclaration */: - case 192 /* ClassExpression */: - if (node.flags & 512 /* Default */) { - return "default"; - } - return getFunctionOrClassName(node); - case 148 /* Constructor */: - return "constructor"; - case 152 /* ConstructSignature */: - return "new()"; - case 151 /* CallSignature */: - return "()"; - case 153 /* IndexSignature */: - return "[]"; - case 279 /* JSDocTypedefTag */: - return getJSDocTypedefTagName(node); - default: - return ""; - } - } - function getJSDocTypedefTagName(node) { - if (node.name) { - return node.name.text; - } - else { - var parentNode = node.parent && node.parent.parent; - if (parentNode && parentNode.kind === 200 /* VariableStatement */) { - if (parentNode.declarationList.declarations.length > 0) { - var nameIdentifier = parentNode.declarationList.declarations[0].name; - if (nameIdentifier.kind === 69 /* Identifier */) { - return nameIdentifier.text; - } + // If the file was previously found via a node_modules search, but is now being processed as a root file, + // then everything it sucks in may also be marked incorrectly, and needs to be checked again. + if (file_1 && sourceFilesFoundSearchingNodeModules[file_1.path] && currentNodeModulesDepth == 0) { + sourceFilesFoundSearchingNodeModules[file_1.path] = false; + if (!options.noResolve) { + processReferencedFiles(file_1, ts.getDirectoryPath(fileName), isDefaultLib); + processTypeReferenceDirectives(file_1); } + modulesWithElidedImports[file_1.path] = false; + processImportedModules(file_1, ts.getDirectoryPath(fileName)); } - return ""; - } - } - /** Flattens the NavNode tree to a list, keeping only the top-level items. */ - function topLevelItems(root) { - var topLevel = []; - function recur(item) { - if (isTopLevel(item)) { - topLevel.push(item); - if (item.children) { - for (var _i = 0, _a = item.children; _i < _a.length; _i++) { - var child = _a[_i]; - recur(child); - } + else if (file_1 && modulesWithElidedImports[file_1.path]) { + if (currentNodeModulesDepth < maxNodeModulesJsDepth) { + modulesWithElidedImports[file_1.path] = false; + processImportedModules(file_1, ts.getDirectoryPath(fileName)); } } + return file_1; } - recur(root); - return topLevel; - function isTopLevel(item) { - switch (navigationBarNodeKind(item)) { - case 221 /* ClassDeclaration */: - case 192 /* ClassExpression */: - case 224 /* EnumDeclaration */: - case 222 /* InterfaceDeclaration */: - case 225 /* ModuleDeclaration */: - case 256 /* SourceFile */: - case 223 /* TypeAliasDeclaration */: - case 279 /* JSDocTypedefTag */: - return true; - case 148 /* Constructor */: - case 147 /* MethodDeclaration */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 218 /* VariableDeclaration */: - return hasSomeImportantChild(item); - case 180 /* ArrowFunction */: - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - return isTopLevelFunctionDeclaration(item); - default: - return false; + // We haven't looked for this file, do so now and cache result + var file = host.getSourceFile(fileName, options.target, function (hostErrorMessage) { + if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) { + fileProcessingDiagnostics.add(ts.createFileDiagnostic(refFile, refPos, refEnd - refPos, ts.Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage)); } - function isTopLevelFunctionDeclaration(item) { - if (!item.node.body) { - return false; + else { + fileProcessingDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage)); + } + }); + filesByName.set(path, file); + if (file) { + sourceFilesFoundSearchingNodeModules[path] = (currentNodeModulesDepth > 0); + file.path = path; + if (host.useCaseSensitiveFileNames()) { + // for case-sensitive file systems check if we've already seen some file with similar filename ignoring case + var existingFile = filesByNameIgnoreCase.get(path); + if (existingFile) { + reportFileNamesDifferOnlyInCasingError(fileName, existingFile.fileName, refFile, refPos, refEnd); } - switch (navigationBarNodeKind(item.parent)) { - case 226 /* ModuleBlock */: - case 256 /* SourceFile */: - case 147 /* MethodDeclaration */: - case 148 /* Constructor */: - return true; - default: - return hasSomeImportantChild(item); + else { + filesByNameIgnoreCase.set(path, file); } } - function hasSomeImportantChild(item) { - return ts.forEach(item.children, function (child) { - var childKind = navigationBarNodeKind(child); - return childKind !== 218 /* VariableDeclaration */ && childKind !== 169 /* BindingElement */; - }); + skipDefaultLib = skipDefaultLib || file.hasNoDefaultLib; + var basePath = ts.getDirectoryPath(fileName); + if (!options.noResolve) { + processReferencedFiles(file, basePath, isDefaultLib); + processTypeReferenceDirectives(file); } - } - } - // NavigationBarItem requires an array, but will not mutate it, so just give it this for performance. - var emptyChildItemArray = []; - function convertToTopLevelItem(n) { - return { - text: getItemName(n.node), - kind: ts.getNodeKind(n.node), - kindModifiers: ts.getNodeModifiers(n.node), - spans: getSpans(n), - childItems: ts.map(n.children, convertToChildItem) || emptyChildItemArray, - indent: n.indent, - bolded: false, - grayed: false - }; - function convertToChildItem(n) { - return { - text: getItemName(n.node), - kind: ts.getNodeKind(n.node), - kindModifiers: ts.getNodeModifiers(n.node), - spans: getSpans(n), - childItems: emptyChildItemArray, - indent: 0, - bolded: false, - grayed: false - }; - } - function getSpans(n) { - var spans = [getNodeSpan(n.node)]; - if (n.additionalNodes) { - for (var _i = 0, _a = n.additionalNodes; _i < _a.length; _i++) { - var node = _a[_i]; - spans.push(getNodeSpan(node)); - } + // always process imported modules to record module name resolutions + processImportedModules(file, basePath); + if (isDefaultLib) { + files.unshift(file); + } + else { + files.push(file); } - return spans; - } - } - function getModuleName(moduleDeclaration) { - // We want to maintain quotation marks. - if (ts.isAmbientModule(moduleDeclaration)) { - return ts.getTextOfNode(moduleDeclaration.name); - } - // Otherwise, we need to aggregate each identifier to build up the qualified name. - var result = []; - result.push(moduleDeclaration.name.text); - while (moduleDeclaration.body && moduleDeclaration.body.kind === 225 /* ModuleDeclaration */) { - moduleDeclaration = moduleDeclaration.body; - result.push(moduleDeclaration.name.text); } - return result.join("."); - } - /** - * For 'module A.B.C', we want to get the node for 'C'. - * We store 'A' as associated with a NavNode, and use getModuleName to traverse down again. - */ - function getInteriorModule(decl) { - return decl.body.kind === 225 /* ModuleDeclaration */ ? getInteriorModule(decl.body) : decl; + return file; } - function isComputedProperty(member) { - return !member.name || member.name.kind === 140 /* ComputedPropertyName */; + function processReferencedFiles(file, basePath, isDefaultLib) { + ts.forEach(file.referencedFiles, function (ref) { + var referencedFileName = resolveTripleslashReference(ref.fileName, file.fileName); + processSourceFile(referencedFileName, isDefaultLib, /*isReference*/ true, file, ref.pos, ref.end); + }); } - function getNodeSpan(node) { - return node.kind === 256 /* SourceFile */ - ? ts.createTextSpanFromBounds(node.getFullStart(), node.getEnd()) - : ts.createTextSpanFromBounds(node.getStart(curSourceFile), node.getEnd()); + function processTypeReferenceDirectives(file) { + // We lower-case all type references because npm automatically lowercases all packages. See GH#9824. + var typeDirectives = ts.map(file.typeReferenceDirectives, function (ref) { return ref.fileName.toLocaleLowerCase(); }); + var resolutions = resolveTypeReferenceDirectiveNamesWorker(typeDirectives, file.fileName); + for (var i = 0; i < typeDirectives.length; i++) { + var ref = file.typeReferenceDirectives[i]; + var resolvedTypeReferenceDirective = resolutions[i]; + // store resolved type directive on the file + var fileName = ref.fileName.toLocaleLowerCase(); + ts.setResolvedTypeReferenceDirective(file, fileName, resolvedTypeReferenceDirective); + processTypeReferenceDirective(fileName, resolvedTypeReferenceDirective, file, ref.pos, ref.end); + } } - function getFunctionOrClassName(node) { - if (node.name && ts.getFullWidth(node.name) > 0) { - return ts.declarationNameToString(node.name); + function processTypeReferenceDirective(typeReferenceDirective, resolvedTypeReferenceDirective, refFile, refPos, refEnd) { + // If we already found this library as a primary reference - nothing to do + var previousResolution = resolvedTypeReferenceDirectives[typeReferenceDirective]; + if (previousResolution && previousResolution.primary) { + return; + } + var saveResolution = true; + if (resolvedTypeReferenceDirective) { + if (resolvedTypeReferenceDirective.primary) { + // resolved from the primary path + processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, /*isDefaultLib*/ false, /*isReference*/ true, refFile, refPos, refEnd); + } + else { + // If we already resolved to this file, it must have been a secondary reference. Check file contents + // for sameness and possibly issue an error + if (previousResolution) { + var otherFileText = host.readFile(resolvedTypeReferenceDirective.resolvedFileName); + if (otherFileText !== getSourceFile(previousResolution.resolvedFileName).text) { + fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd, ts.Diagnostics.Conflicting_definitions_for_0_found_at_1_and_2_Consider_installing_a_specific_version_of_this_library_to_resolve_the_conflict, typeReferenceDirective, resolvedTypeReferenceDirective.resolvedFileName, previousResolution.resolvedFileName)); + } + // don't overwrite previous resolution result + saveResolution = false; + } + else { + // First resolution of this library + processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, /*isDefaultLib*/ false, /*isReference*/ true, refFile, refPos, refEnd); + } + } } - else if (node.parent.kind === 218 /* VariableDeclaration */) { - return ts.declarationNameToString(node.parent.name); + else { + fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd, ts.Diagnostics.Cannot_find_type_definition_file_for_0, typeReferenceDirective)); } - else if (node.parent.kind === 187 /* BinaryExpression */ && - node.parent.operatorToken.kind === 56 /* EqualsToken */) { - return nodeText(node.parent.left); + if (saveResolution) { + resolvedTypeReferenceDirectives[typeReferenceDirective] = resolvedTypeReferenceDirective; } - else if (node.parent.kind === 253 /* PropertyAssignment */ && node.parent.name) { - return nodeText(node.parent.name); + } + function createDiagnostic(refFile, refPos, refEnd, message) { + var args = []; + for (var _i = 4; _i < arguments.length; _i++) { + args[_i - 4] = arguments[_i]; } - else if (node.flags & 512 /* Default */) { - return "default"; + if (refFile === undefined || refPos === undefined || refEnd === undefined) { + return ts.createCompilerDiagnostic.apply(void 0, [message].concat(args)); } else { - return ts.isClassLike(node) ? "" : ""; + return ts.createFileDiagnostic.apply(void 0, [refFile, refPos, refEnd - refPos, message].concat(args)); } } - function isFunctionOrClassExpression(node) { - return node.kind === 179 /* FunctionExpression */ || node.kind === 180 /* ArrowFunction */ || node.kind === 192 /* ClassExpression */; - } - })(NavigationBar = ts.NavigationBar || (ts.NavigationBar = {})); -})(ts || (ts = {})); -/* @internal */ -var ts; -(function (ts) { - // Note(cyrusn): this enum is ordered from strongest match type to weakest match type. - (function (PatternMatchKind) { - PatternMatchKind[PatternMatchKind["exact"] = 0] = "exact"; - PatternMatchKind[PatternMatchKind["prefix"] = 1] = "prefix"; - PatternMatchKind[PatternMatchKind["substring"] = 2] = "substring"; - PatternMatchKind[PatternMatchKind["camelCase"] = 3] = "camelCase"; - })(ts.PatternMatchKind || (ts.PatternMatchKind = {})); - var PatternMatchKind = ts.PatternMatchKind; - function createPatternMatch(kind, punctuationStripped, isCaseSensitive, camelCaseWeight) { - return { - kind: kind, - punctuationStripped: punctuationStripped, - isCaseSensitive: isCaseSensitive, - camelCaseWeight: camelCaseWeight - }; - } - function createPatternMatcher(pattern) { - // We'll often see the same candidate string many times when searching (For example, when - // we see the name of a module that is used everywhere, or the name of an overload). As - // such, we cache the information we compute about the candidate for the life of this - // pattern matcher so we don't have to compute it multiple times. - var stringToWordSpans = ts.createMap(); - pattern = pattern.trim(); - var dotSeparatedSegments = pattern.split(".").map(function (p) { return createSegment(p.trim()); }); - var invalidPattern = dotSeparatedSegments.length === 0 || ts.forEach(dotSeparatedSegments, segmentIsInvalid); - return { - getMatches: getMatches, - getMatchesForLastSegmentOfPattern: getMatchesForLastSegmentOfPattern, - patternContainsDots: dotSeparatedSegments.length > 1 - }; - // Quick checks so we can bail out when asked to match a candidate. - function skipMatch(candidate) { - return invalidPattern || !candidate; - } - function getMatchesForLastSegmentOfPattern(candidate) { - if (skipMatch(candidate)) { - return undefined; - } - return matchSegment(candidate, ts.lastOrUndefined(dotSeparatedSegments)); + function getCanonicalFileName(fileName) { + return host.getCanonicalFileName(fileName); } - function getMatches(candidateContainers, candidate) { - if (skipMatch(candidate)) { - return undefined; - } - // First, check that the last part of the dot separated pattern matches the name of the - // candidate. If not, then there's no point in proceeding and doing the more - // expensive work. - var candidateMatch = matchSegment(candidate, ts.lastOrUndefined(dotSeparatedSegments)); - if (!candidateMatch) { - return undefined; + function processImportedModules(file, basePath) { + collectExternalModuleReferences(file); + if (file.imports.length || file.moduleAugmentations.length) { + file.resolvedModules = ts.createMap(); + var moduleNames = ts.map(ts.concatenate(file.imports, file.moduleAugmentations), getTextOfLiteral); + var resolutions = resolveModuleNamesWorker(moduleNames, ts.getNormalizedAbsolutePath(file.fileName, currentDirectory)); + for (var i = 0; i < moduleNames.length; i++) { + var resolution = resolutions[i]; + ts.setResolvedModule(file, moduleNames[i], resolution); + var resolvedPath = resolution ? ts.toPath(resolution.resolvedFileName, currentDirectory, getCanonicalFileName) : undefined; + // add file to program only if: + // - resolution was successful + // - noResolve is falsy + // - module name comes from the list of imports + // - it's not a top level JavaScript module that exceeded the search max + var isFromNodeModulesSearch = resolution && resolution.isExternalLibraryImport; + var isJsFileFromNodeModules = isFromNodeModulesSearch && ts.hasJavaScriptFileExtension(resolution.resolvedFileName); + if (isFromNodeModulesSearch) { + currentNodeModulesDepth++; + } + var elideImport = isJsFileFromNodeModules && currentNodeModulesDepth > maxNodeModulesJsDepth; + var shouldAddFile = resolution && !options.noResolve && i < file.imports.length && !elideImport; + if (elideImport) { + modulesWithElidedImports[file.path] = true; + } + else if (shouldAddFile) { + findSourceFile(resolution.resolvedFileName, resolvedPath, + /*isDefaultLib*/ false, /*isReference*/ false, file, ts.skipTrivia(file.text, file.imports[i].pos), file.imports[i].end); + } + if (isFromNodeModulesSearch) { + currentNodeModulesDepth--; + } + } } - candidateContainers = candidateContainers || []; - // -1 because the last part was checked against the name, and only the rest - // of the parts are checked against the container. - if (dotSeparatedSegments.length - 1 > candidateContainers.length) { - // There weren't enough container parts to match against the pattern parts. - // So this definitely doesn't match. - return undefined; + else { + // no imports - drop cached module resolutions + file.resolvedModules = undefined; } - // So far so good. Now break up the container for the candidate and check if all - // the dotted parts match up correctly. - var totalMatch = candidateMatch; - for (var i = dotSeparatedSegments.length - 2, j = candidateContainers.length - 1; i >= 0; i -= 1, j -= 1) { - var segment = dotSeparatedSegments[i]; - var containerName = candidateContainers[j]; - var containerMatch = matchSegment(containerName, segment); - if (!containerMatch) { - // This container didn't match the pattern piece. So there's no match at all. - return undefined; + return; + } + function computeCommonSourceDirectory(sourceFiles) { + var fileNames = []; + for (var _i = 0, sourceFiles_6 = sourceFiles; _i < sourceFiles_6.length; _i++) { + var file = sourceFiles_6[_i]; + if (!file.isDeclarationFile) { + fileNames.push(file.fileName); } - ts.addRange(totalMatch, containerMatch); } - // Success, this symbol's full name matched against the dotted name the user was asking - // about. - return totalMatch; + return computeCommonSourceDirectoryOfFilenames(fileNames, currentDirectory, getCanonicalFileName); } - function getWordSpans(word) { - if (!(word in stringToWordSpans)) { - stringToWordSpans[word] = breakIntoWordSpans(word); + function checkSourceFilesBelongToPath(sourceFiles, rootDirectory) { + var allFilesBelongToPath = true; + if (sourceFiles) { + var absoluteRootDirectoryPath = host.getCanonicalFileName(ts.getNormalizedAbsolutePath(rootDirectory, currentDirectory)); + for (var _i = 0, sourceFiles_7 = sourceFiles; _i < sourceFiles_7.length; _i++) { + var sourceFile = sourceFiles_7[_i]; + if (!ts.isDeclarationFile(sourceFile)) { + var absoluteSourceFilePath = host.getCanonicalFileName(ts.getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory)); + if (absoluteSourceFilePath.indexOf(absoluteRootDirectoryPath) !== 0) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, sourceFile.fileName, options.rootDir)); + allFilesBelongToPath = false; + } + } + } } - return stringToWordSpans[word]; + return allFilesBelongToPath; } - function matchTextChunk(candidate, chunk, punctuationStripped) { - var index = indexOfIgnoringCase(candidate, chunk.textLowerCase); - if (index === 0) { - if (chunk.text.length === candidate.length) { - // a) Check if the part matches the candidate entirely, in an case insensitive or - // sensitive manner. If it does, return that there was an exact match. - return createPatternMatch(PatternMatchKind.exact, punctuationStripped, /*isCaseSensitive:*/ candidate === chunk.text); + function verifyCompilerOptions() { + if (options.isolatedModules) { + if (options.declaration) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "declaration", "isolatedModules")); } - else { - // b) Check if the part is a prefix of the candidate, in a case insensitive or sensitive - // manner. If it does, return that there was a prefix match. - return createPatternMatch(PatternMatchKind.prefix, punctuationStripped, /*isCaseSensitive:*/ ts.startsWith(candidate, chunk.text)); + if (options.noEmitOnError) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "noEmitOnError", "isolatedModules")); } - } - var isLowercase = chunk.isLowerCase; - if (isLowercase) { - if (index > 0) { - // c) If the part is entirely lowercase, then check if it is contained anywhere in the - // candidate in a case insensitive manner. If so, return that there was a substring - // match. - // - // Note: We only have a substring match if the lowercase part is prefix match of some - // word part. That way we don't match something like 'Class' when the user types 'a'. - // But we would match 'FooAttribute' (since 'Attribute' starts with 'a'). - var wordSpans = getWordSpans(candidate); - for (var _i = 0, wordSpans_1 = wordSpans; _i < wordSpans_1.length; _i++) { - var span = wordSpans_1[_i]; - if (partStartsWith(candidate, span, chunk.text, /*ignoreCase:*/ true)) { - return createPatternMatch(PatternMatchKind.substring, punctuationStripped, - /*isCaseSensitive:*/ partStartsWith(candidate, span, chunk.text, /*ignoreCase:*/ false)); - } - } + if (options.out) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "out", "isolatedModules")); + } + if (options.outFile) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "outFile", "isolatedModules")); } } - else { - // d) If the part was not entirely lowercase, then check if it is contained in the - // candidate in a case *sensitive* manner. If so, return that there was a substring - // match. - if (candidate.indexOf(chunk.text) > 0) { - return createPatternMatch(PatternMatchKind.substring, punctuationStripped, /*isCaseSensitive:*/ true); + if (options.inlineSourceMap) { + if (options.sourceMap) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "sourceMap", "inlineSourceMap")); + } + if (options.mapRoot) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "mapRoot", "inlineSourceMap")); } } - if (!isLowercase) { - // e) If the part was not entirely lowercase, then attempt a camel cased match as well. - if (chunk.characterSpans.length > 0) { - var candidateParts = getWordSpans(candidate); - var camelCaseWeight = tryCamelCaseMatch(candidate, candidateParts, chunk, /*ignoreCase:*/ false); - if (camelCaseWeight !== undefined) { - return createPatternMatch(PatternMatchKind.camelCase, punctuationStripped, /*isCaseSensitive:*/ true, /*camelCaseWeight:*/ camelCaseWeight); + if (options.paths && options.baseUrl === undefined) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_paths_cannot_be_used_without_specifying_baseUrl_option)); + } + if (options.paths) { + for (var key in options.paths) { + if (!ts.hasProperty(options.paths, key)) { + continue; } - camelCaseWeight = tryCamelCaseMatch(candidate, candidateParts, chunk, /*ignoreCase:*/ true); - if (camelCaseWeight !== undefined) { - return createPatternMatch(PatternMatchKind.camelCase, punctuationStripped, /*isCaseSensitive:*/ false, /*camelCaseWeight:*/ camelCaseWeight); + if (!ts.hasZeroOrOneAsteriskCharacter(key)) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, key)); } - } - } - if (isLowercase) { - // f) Is the pattern a substring of the candidate starting on one of the candidate's word boundaries? - // We could check every character boundary start of the candidate for the pattern. However, that's - // an m * n operation in the wost case. Instead, find the first instance of the pattern - // substring, and see if it starts on a capital letter. It seems unlikely that the user will try to - // filter the list based on a substring that starts on a capital letter and also with a lowercase one. - // (Pattern: fogbar, Candidate: quuxfogbarFogBar). - if (chunk.text.length < candidate.length) { - if (index > 0 && isUpperCaseLetter(candidate.charCodeAt(index))) { - return createPatternMatch(PatternMatchKind.substring, punctuationStripped, /*isCaseSensitive:*/ false); + if (ts.isArray(options.paths[key])) { + if (options.paths[key].length === 0) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Substitutions_for_pattern_0_shouldn_t_be_an_empty_array, key)); + } + for (var _i = 0, _a = options.paths[key]; _i < _a.length; _i++) { + var subst = _a[_i]; + var typeOfSubst = typeof subst; + if (typeOfSubst === "string") { + if (!ts.hasZeroOrOneAsteriskCharacter(subst)) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Substitution_0_in_pattern_1_in_can_have_at_most_one_Asterisk_character, subst, key)); + } + } + else { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Substitution_0_for_pattern_1_has_incorrect_type_expected_string_got_2, subst, key, typeOfSubst)); + } + } + } + else { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Substitutions_for_pattern_0_should_be_an_array, key)); } } } - return undefined; - } - function containsSpaceOrAsterisk(text) { - for (var i = 0; i < text.length; i++) { - var ch = text.charCodeAt(i); - if (ch === 32 /* space */ || ch === 42 /* asterisk */) { - return true; + if (!options.sourceMap && !options.inlineSourceMap) { + if (options.inlineSources) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided, "inlineSources")); + } + if (options.sourceRoot) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided, "sourceRoot")); } } - return false; - } - function matchSegment(candidate, segment) { - // First check if the segment matches as is. This is also useful if the segment contains - // characters we would normally strip when splitting into parts that we also may want to - // match in the candidate. For example if the segment is "@int" and the candidate is - // "@int", then that will show up as an exact match here. - // - // Note: if the segment contains a space or an asterisk then we must assume that it's a - // multi-word segment. - if (!containsSpaceOrAsterisk(segment.totalTextChunk.text)) { - var match = matchTextChunk(candidate, segment.totalTextChunk, /*punctuationStripped:*/ false); - if (match) { - return [match]; + if (options.out && options.outFile) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "out", "outFile")); + } + if (options.mapRoot && !options.sourceMap) { + // Error to specify --mapRoot without --sourcemap + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "mapRoot", "sourceMap")); + } + if (options.declarationDir) { + if (!options.declaration) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "declarationDir", "declaration")); + } + if (options.out || options.outFile) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "declarationDir", options.out ? "out" : "outFile")); } } - // The logic for pattern matching is now as follows: - // - // 1) Break the segment passed in into words. Breaking is rather simple and a - // good way to think about it that if gives you all the individual alphanumeric words - // of the pattern. - // - // 2) For each word try to match the word against the candidate value. - // - // 3) Matching is as follows: - // - // a) Check if the word matches the candidate entirely, in an case insensitive or - // sensitive manner. If it does, return that there was an exact match. - // - // b) Check if the word is a prefix of the candidate, in a case insensitive or - // sensitive manner. If it does, return that there was a prefix match. - // - // c) If the word is entirely lowercase, then check if it is contained anywhere in the - // candidate in a case insensitive manner. If so, return that there was a substring - // match. - // - // Note: We only have a substring match if the lowercase part is prefix match of - // some word part. That way we don't match something like 'Class' when the user - // types 'a'. But we would match 'FooAttribute' (since 'Attribute' starts with - // 'a'). - // - // d) If the word was not entirely lowercase, then check if it is contained in the - // candidate in a case *sensitive* manner. If so, return that there was a substring - // match. - // - // e) If the word was not entirely lowercase, then attempt a camel cased match as - // well. - // - // f) The word is all lower case. Is it a case insensitive substring of the candidate starting - // on a part boundary of the candidate? - // - // Only if all words have some sort of match is the pattern considered matched. - var subWordTextChunks = segment.subWordTextChunks; - var matches = undefined; - for (var _i = 0, subWordTextChunks_1 = subWordTextChunks; _i < subWordTextChunks_1.length; _i++) { - var subWordTextChunk = subWordTextChunks_1[_i]; - // Try to match the candidate with this word - var result = matchTextChunk(candidate, subWordTextChunk, /*punctuationStripped:*/ true); - if (!result) { - return undefined; + if (options.lib && options.noLib) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "lib", "noLib")); + } + var languageVersion = options.target || 0 /* ES3 */; + var outFile = options.outFile || options.out; + var firstNonAmbientExternalModuleSourceFile = ts.forEach(files, function (f) { return ts.isExternalModule(f) && !ts.isDeclarationFile(f) ? f : undefined; }); + if (options.isolatedModules) { + if (options.module === ts.ModuleKind.None && languageVersion < 2 /* ES6 */) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_isolatedModules_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES2015_or_higher)); + } + var firstNonExternalModuleSourceFile = ts.forEach(files, function (f) { return !ts.isExternalModule(f) && !ts.isDeclarationFile(f) ? f : undefined; }); + if (firstNonExternalModuleSourceFile) { + var span_7 = ts.getErrorSpanForNode(firstNonExternalModuleSourceFile, firstNonExternalModuleSourceFile); + programDiagnostics.add(ts.createFileDiagnostic(firstNonExternalModuleSourceFile, span_7.start, span_7.length, ts.Diagnostics.Cannot_compile_namespaces_when_the_isolatedModules_flag_is_provided)); } - matches = matches || []; - matches.push(result); } - return matches; - } - function partStartsWith(candidate, candidateSpan, pattern, ignoreCase, patternSpan) { - var patternPartStart = patternSpan ? patternSpan.start : 0; - var patternPartLength = patternSpan ? patternSpan.length : pattern.length; - if (patternPartLength > candidateSpan.length) { - // Pattern part is longer than the candidate part. There can never be a match. - return false; + else if (firstNonAmbientExternalModuleSourceFile && languageVersion < 2 /* ES6 */ && options.module === ts.ModuleKind.None) { + // We cannot use createDiagnosticFromNode because nodes do not have parents yet + var span_8 = ts.getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, firstNonAmbientExternalModuleSourceFile.externalModuleIndicator); + programDiagnostics.add(ts.createFileDiagnostic(firstNonAmbientExternalModuleSourceFile, span_8.start, span_8.length, ts.Diagnostics.Cannot_use_imports_exports_or_module_augmentations_when_module_is_none)); } - if (ignoreCase) { - for (var i = 0; i < patternPartLength; i++) { - var ch1 = pattern.charCodeAt(patternPartStart + i); - var ch2 = candidate.charCodeAt(candidateSpan.start + i); - if (toLowerCase(ch1) !== toLowerCase(ch2)) { - return false; - } + // Cannot specify module gen that isn't amd or system with --out + if (outFile) { + if (options.module && !(options.module === ts.ModuleKind.AMD || options.module === ts.ModuleKind.System)) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Only_amd_and_system_modules_are_supported_alongside_0, options.out ? "out" : "outFile")); + } + else if (options.module === undefined && firstNonAmbientExternalModuleSourceFile) { + var span_9 = ts.getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, firstNonAmbientExternalModuleSourceFile.externalModuleIndicator); + programDiagnostics.add(ts.createFileDiagnostic(firstNonAmbientExternalModuleSourceFile, span_9.start, span_9.length, ts.Diagnostics.Cannot_compile_modules_using_option_0_unless_the_module_flag_is_amd_or_system, options.out ? "out" : "outFile")); } } - else { - for (var i = 0; i < patternPartLength; i++) { - var ch1 = pattern.charCodeAt(patternPartStart + i); - var ch2 = candidate.charCodeAt(candidateSpan.start + i); - if (ch1 !== ch2) { - return false; - } + // there has to be common source directory if user specified --outdir || --sourceRoot + // if user specified --mapRoot, there needs to be common source directory if there would be multiple files being emitted + if (options.outDir || + options.sourceRoot || + options.mapRoot) { + // Precalculate and cache the common source directory + var dir = getCommonSourceDirectory(); + // If we failed to find a good common directory, but outDir is specified and at least one of our files is on a windows drive/URL/other resource, add a failure + if (options.outDir && dir === "" && ts.forEach(files, function (file) { return ts.getRootLength(file.fileName) > 1; })) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files)); } } - return true; - } - function tryCamelCaseMatch(candidate, candidateParts, chunk, ignoreCase) { - var chunkCharacterSpans = chunk.characterSpans; - // Note: we may have more pattern parts than candidate parts. This is because multiple - // pattern parts may match a candidate part. For example "SiUI" against "SimpleUI". - // We'll have 3 pattern parts Si/U/I against two candidate parts Simple/UI. However, U - // and I will both match in UI. - var currentCandidate = 0; - var currentChunkSpan = 0; - var firstMatch = undefined; - var contiguous = undefined; - while (true) { - // Let's consider our termination cases - if (currentChunkSpan === chunkCharacterSpans.length) { - // We did match! We shall assign a weight to this - var weight = 0; - // Was this contiguous? - if (contiguous) { - weight += 1; - } - // Did we start at the beginning of the candidate? - if (firstMatch === 0) { - weight += 2; + if (!options.noEmit && options.allowJs && options.declaration) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration")); + } + if (options.emitDecoratorMetadata && + !options.experimentalDecorators) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDecoratorMetadata", "experimentalDecorators")); + } + if (options.reactNamespace && !ts.isIdentifierText(options.reactNamespace, languageVersion)) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Invalid_value_for_reactNamespace_0_is_not_a_valid_identifier, options.reactNamespace)); + } + // If the emit is enabled make sure that every output file is unique and not overwriting any of the input files + if (!options.noEmit && !options.suppressOutputPathCheck) { + var emitHost = getEmitHost(); + var emitFilesSeen_1 = ts.createFileMap(!host.useCaseSensitiveFileNames() ? function (key) { return key.toLocaleLowerCase(); } : undefined); + ts.forEachExpectedEmitFile(emitHost, function (emitFileNames, sourceFiles, isBundledEmit) { + verifyEmitFilePath(emitFileNames.jsFilePath, emitFilesSeen_1); + verifyEmitFilePath(emitFileNames.declarationFilePath, emitFilesSeen_1); + }); + } + // Verify that all the emit files are unique and don't overwrite input files + function verifyEmitFilePath(emitFileName, emitFilesSeen) { + if (emitFileName) { + var emitFilePath = ts.toPath(emitFileName, currentDirectory, getCanonicalFileName); + // Report error if the output overwrites input file + if (filesByName.contains(emitFilePath)) { + createEmitBlockingDiagnostics(emitFileName, emitFilePath, ts.Diagnostics.Cannot_write_file_0_because_it_would_overwrite_input_file); } - return weight; - } - else if (currentCandidate === candidateParts.length) { - // No match, since we still have more of the pattern to hit - return undefined; - } - var candidatePart = candidateParts[currentCandidate]; - var gotOneMatchThisCandidate = false; - // Consider the case of matching SiUI against SimpleUIElement. The candidate parts - // will be Simple/UI/Element, and the pattern parts will be Si/U/I. We'll match 'Si' - // against 'Simple' first. Then we'll match 'U' against 'UI'. However, we want to - // still keep matching pattern parts against that candidate part. - for (; currentChunkSpan < chunkCharacterSpans.length; currentChunkSpan++) { - var chunkCharacterSpan = chunkCharacterSpans[currentChunkSpan]; - if (gotOneMatchThisCandidate) { - // We've already gotten one pattern part match in this candidate. We will - // only continue trying to consumer pattern parts if the last part and this - // part are both upper case. - if (!isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan - 1].start)) || - !isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan].start))) { - break; - } + // Report error if multiple files write into same file + if (emitFilesSeen.contains(emitFilePath)) { + // Already seen the same emit file - report error + createEmitBlockingDiagnostics(emitFileName, emitFilePath, ts.Diagnostics.Cannot_write_file_0_because_it_would_be_overwritten_by_multiple_input_files); } - if (!partStartsWith(candidate, candidatePart, chunk.text, ignoreCase, chunkCharacterSpan)) { - break; + else { + emitFilesSeen.set(emitFilePath, true); } - gotOneMatchThisCandidate = true; - firstMatch = firstMatch === undefined ? currentCandidate : firstMatch; - // If we were contiguous, then keep that value. If we weren't, then keep that - // value. If we don't know, then set the value to 'true' as an initial match is - // obviously contiguous. - contiguous = contiguous === undefined ? true : contiguous; - candidatePart = ts.createTextSpan(candidatePart.start + chunkCharacterSpan.length, candidatePart.length - chunkCharacterSpan.length); - } - // Check if we matched anything at all. If we didn't, then we need to unset the - // contiguous bit if we currently had it set. - // If we haven't set the bit yet, then that means we haven't matched anything so - // far, and we don't want to change that. - if (!gotOneMatchThisCandidate && contiguous !== undefined) { - contiguous = false; } - // Move onto the next candidate. - currentCandidate++; } } + function createEmitBlockingDiagnostics(emitFileName, emitFilePath, message) { + hasEmitBlockingDiagnostics.set(ts.toPath(emitFileName, currentDirectory, getCanonicalFileName), true); + programDiagnostics.add(ts.createCompilerDiagnostic(message, emitFileName)); + } + } + ts.createProgram = createProgram; +})(ts || (ts = {})); +/// +/// +var ts; +(function (ts) { + var defaultFormatDiagnosticsHost = { + getCurrentDirectory: function () { return ts.sys.getCurrentDirectory(); }, + getNewLine: function () { return ts.sys.newLine; }, + getCanonicalFileName: ts.createGetCanonicalFileName(ts.sys.useCaseSensitiveFileNames) + }; + var reportDiagnosticWorker = reportDiagnosticSimply; + function reportDiagnostic(diagnostic, host) { + reportDiagnosticWorker(diagnostic, host || defaultFormatDiagnosticsHost); + } + function reportDiagnostics(diagnostics, host) { + for (var _i = 0, diagnostics_2 = diagnostics; _i < diagnostics_2.length; _i++) { + var diagnostic = diagnostics_2[_i]; + reportDiagnostic(diagnostic, host); + } } - ts.createPatternMatcher = createPatternMatcher; - function createSegment(text) { - return { - totalTextChunk: createTextChunk(text), - subWordTextChunks: breakPatternIntoTextChunks(text) - }; + function reportEmittedFiles(files, host) { + if (!files || files.length == 0) { + return; + } + var currentDir = ts.sys.getCurrentDirectory(); + for (var _i = 0, files_3 = files; _i < files_3.length; _i++) { + var file = files_3[_i]; + var filepath = ts.getNormalizedAbsolutePath(file, currentDir); + ts.sys.write("TSFILE: " + filepath + ts.sys.newLine); + } } - // A segment is considered invalid if we couldn't find any words in it. - function segmentIsInvalid(segment) { - return segment.subWordTextChunks.length === 0; + /** + * Checks to see if the locale is in the appropriate format, + * and if it is, attempts to set the appropriate language. + */ + function validateLocaleAndSetLanguage(locale, errors) { + var matchResult = /^([a-z]+)([_\-]([a-z]+))?$/.exec(locale.toLowerCase()); + if (!matchResult) { + errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Locale_must_be_of_the_form_language_or_language_territory_For_example_0_or_1, "en", "ja-jp")); + return false; + } + var language = matchResult[1]; + var territory = matchResult[3]; + // First try the entire locale, then fall back to just language if that's all we have. + // Either ways do not fail, and fallback to the English diagnostic strings. + if (!trySetLanguageAndTerritory(language, territory, errors)) { + trySetLanguageAndTerritory(language, undefined, errors); + } + return true; } - function isUpperCaseLetter(ch) { - // Fast check for the ascii range. - if (ch >= 65 /* A */ && ch <= 90 /* Z */) { - return true; + function trySetLanguageAndTerritory(language, territory, errors) { + var compilerFilePath = ts.normalizePath(ts.sys.getExecutingFilePath()); + var containingDirectoryPath = ts.getDirectoryPath(compilerFilePath); + var filePath = ts.combinePaths(containingDirectoryPath, language); + if (territory) { + filePath = filePath + "-" + territory; } - if (ch < 127 /* maxAsciiCharacter */ || !ts.isUnicodeIdentifierStart(ch, 2 /* Latest */)) { + filePath = ts.sys.resolvePath(ts.combinePaths(filePath, "diagnosticMessages.generated.json")); + if (!ts.sys.fileExists(filePath)) { return false; } - // TODO: find a way to determine this for any unicode characters in a - // non-allocating manner. - var str = String.fromCharCode(ch); - return str === str.toUpperCase(); - } - function isLowerCaseLetter(ch) { - // Fast check for the ascii range. - if (ch >= 97 /* a */ && ch <= 122 /* z */) { - return true; + // TODO: Add codePage support for readFile? + var fileContents = ""; + try { + fileContents = ts.sys.readFile(filePath); } - if (ch < 127 /* maxAsciiCharacter */ || !ts.isUnicodeIdentifierStart(ch, 2 /* Latest */)) { + catch (e) { + errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unable_to_open_file_0, filePath)); return false; } - // TODO: find a way to determine this for any unicode characters in a - // non-allocating manner. - var str = String.fromCharCode(ch); - return str === str.toLowerCase(); - } - // Assumes 'value' is already lowercase. - function indexOfIgnoringCase(string, value) { - for (var i = 0, n = string.length - value.length; i <= n; i++) { - if (startsWithIgnoringCase(string, value, i)) { - return i; - } + try { + ts.localizedDiagnosticMessages = JSON.parse(fileContents); } - return -1; - } - // Assumes 'value' is already lowercase. - function startsWithIgnoringCase(string, value, start) { - for (var i = 0, n = value.length; i < n; i++) { - var ch1 = toLowerCase(string.charCodeAt(i + start)); - var ch2 = value.charCodeAt(i); - if (ch1 !== ch2) { - return false; - } + catch (e) { + errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Corrupted_locale_file_0, filePath)); + return false; } return true; } - function toLowerCase(ch) { - // Fast convert for the ascii range. - if (ch >= 65 /* A */ && ch <= 90 /* Z */) { - return 97 /* a */ + (ch - 65 /* A */); - } - if (ch < 127 /* maxAsciiCharacter */) { - return ch; + function countLines(program) { + var count = 0; + ts.forEach(program.getSourceFiles(), function (file) { + count += ts.getLineStarts(file).length; + }); + return count; + } + function getDiagnosticText(message) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; } - // TODO: find a way to compute this for any unicode characters in a - // non-allocating manner. - return String.fromCharCode(ch).toLowerCase().charCodeAt(0); + var diagnostic = ts.createCompilerDiagnostic.apply(undefined, arguments); + return diagnostic.messageText; } - function isDigit(ch) { - // TODO(cyrusn): Find a way to support this for unicode digits. - return ch >= 48 /* _0 */ && ch <= 57 /* _9 */; + function reportDiagnosticSimply(diagnostic, host) { + ts.sys.write(ts.formatDiagnostics([diagnostic], host)); } - function isWordChar(ch) { - return isUpperCaseLetter(ch) || isLowerCaseLetter(ch) || isDigit(ch) || ch === 95 /* _ */ || ch === 36 /* $ */; + var redForegroundEscapeSequence = "\u001b[91m"; + var yellowForegroundEscapeSequence = "\u001b[93m"; + var blueForegroundEscapeSequence = "\u001b[93m"; + var gutterStyleSequence = "\u001b[100;30m"; + var gutterSeparator = " "; + var resetEscapeSequence = "\u001b[0m"; + var ellipsis = "..."; + var categoryFormatMap = ts.createMap((_a = {}, + _a[ts.DiagnosticCategory.Warning] = yellowForegroundEscapeSequence, + _a[ts.DiagnosticCategory.Error] = redForegroundEscapeSequence, + _a[ts.DiagnosticCategory.Message] = blueForegroundEscapeSequence, + _a)); + function formatAndReset(text, formatStyle) { + return formatStyle + text + resetEscapeSequence; } - function breakPatternIntoTextChunks(pattern) { - var result = []; - var wordStart = 0; - var wordLength = 0; - for (var i = 0; i < pattern.length; i++) { - var ch = pattern.charCodeAt(i); - if (isWordChar(ch)) { - if (wordLength === 0) { - wordStart = i; - } - wordLength++; + function reportDiagnosticWithColorAndContext(diagnostic, host) { + var output = ""; + if (diagnostic.file) { + var start = diagnostic.start, length_4 = diagnostic.length, file = diagnostic.file; + var _a = ts.getLineAndCharacterOfPosition(file, start), firstLine = _a.line, firstLineChar = _a.character; + var _b = ts.getLineAndCharacterOfPosition(file, start + length_4), lastLine = _b.line, lastLineChar = _b.character; + var lastLineInFile = ts.getLineAndCharacterOfPosition(file, file.text.length).line; + var relativeFileName = host ? ts.convertToRelativePath(file.fileName, host.getCurrentDirectory(), function (fileName) { return host.getCanonicalFileName(fileName); }) : file.fileName; + var hasMoreThanFiveLines = (lastLine - firstLine) >= 4; + var gutterWidth = (lastLine + 1 + "").length; + if (hasMoreThanFiveLines) { + gutterWidth = Math.max(ellipsis.length, gutterWidth); } - else { - if (wordLength > 0) { - result.push(createTextChunk(pattern.substr(wordStart, wordLength))); - wordLength = 0; + output += ts.sys.newLine; + for (var i = firstLine; i <= lastLine; i++) { + // If the error spans over 5 lines, we'll only show the first 2 and last 2 lines, + // so we'll skip ahead to the second-to-last line. + if (hasMoreThanFiveLines && firstLine + 1 < i && i < lastLine - 1) { + output += formatAndReset(padLeft(ellipsis, gutterWidth), gutterStyleSequence) + gutterSeparator + ts.sys.newLine; + i = lastLine - 1; } - } - } - if (wordLength > 0) { - result.push(createTextChunk(pattern.substr(wordStart, wordLength))); - } - return result; - } - function createTextChunk(text) { - var textLowerCase = text.toLowerCase(); - return { - text: text, - textLowerCase: textLowerCase, - isLowerCase: text === textLowerCase, - characterSpans: breakIntoCharacterSpans(text) - }; - } - /* @internal */ function breakIntoCharacterSpans(identifier) { - return breakIntoSpans(identifier, /*word:*/ false); - } - ts.breakIntoCharacterSpans = breakIntoCharacterSpans; - /* @internal */ function breakIntoWordSpans(identifier) { - return breakIntoSpans(identifier, /*word:*/ true); - } - ts.breakIntoWordSpans = breakIntoWordSpans; - function breakIntoSpans(identifier, word) { - var result = []; - var wordStart = 0; - for (var i = 1, n = identifier.length; i < n; i++) { - var lastIsDigit = isDigit(identifier.charCodeAt(i - 1)); - var currentIsDigit = isDigit(identifier.charCodeAt(i)); - var hasTransitionFromLowerToUpper = transitionFromLowerToUpper(identifier, word, i); - var hasTransitionFromUpperToLower = transitionFromUpperToLower(identifier, word, i, wordStart); - if (charIsPunctuation(identifier.charCodeAt(i - 1)) || - charIsPunctuation(identifier.charCodeAt(i)) || - lastIsDigit !== currentIsDigit || - hasTransitionFromLowerToUpper || - hasTransitionFromUpperToLower) { - if (!isAllPunctuation(identifier, wordStart, i)) { - result.push(ts.createTextSpan(wordStart, i - wordStart)); + var lineStart = ts.getPositionOfLineAndCharacter(file, i, 0); + var lineEnd = i < lastLineInFile ? ts.getPositionOfLineAndCharacter(file, i + 1, 0) : file.text.length; + var lineContent = file.text.slice(lineStart, lineEnd); + lineContent = lineContent.replace(/\s+$/g, ""); // trim from end + lineContent = lineContent.replace("\t", " "); // convert tabs to single spaces + // Output the gutter and the actual contents of the line. + output += formatAndReset(padLeft(i + 1 + "", gutterWidth), gutterStyleSequence) + gutterSeparator; + output += lineContent + ts.sys.newLine; + // Output the gutter and the error span for the line using tildes. + output += formatAndReset(padLeft("", gutterWidth), gutterStyleSequence) + gutterSeparator; + output += redForegroundEscapeSequence; + if (i === firstLine) { + // If we're on the last line, then limit it to the last character of the last line. + // Otherwise, we'll just squiggle the rest of the line, giving 'slice' no end position. + var lastCharForLine = i === lastLine ? lastLineChar : undefined; + output += lineContent.slice(0, firstLineChar).replace(/\S/g, " "); + output += lineContent.slice(firstLineChar, lastCharForLine).replace(/./g, "~"); } - wordStart = i; + else if (i === lastLine) { + output += lineContent.slice(0, lastLineChar).replace(/./g, "~"); + } + else { + // Squiggle the entire line. + output += lineContent.replace(/./g, "~"); + } + output += resetEscapeSequence; + output += ts.sys.newLine; } + output += ts.sys.newLine; + output += relativeFileName + "(" + (firstLine + 1) + "," + (firstLineChar + 1) + "): "; } - if (!isAllPunctuation(identifier, wordStart, identifier.length)) { - result.push(ts.createTextSpan(wordStart, identifier.length - wordStart)); - } - return result; + var categoryColor = categoryFormatMap[diagnostic.category]; + var category = ts.DiagnosticCategory[diagnostic.category].toLowerCase(); + output += formatAndReset(category, categoryColor) + " TS" + diagnostic.code + ": " + ts.flattenDiagnosticMessageText(diagnostic.messageText, ts.sys.newLine); + output += ts.sys.newLine + ts.sys.newLine; + ts.sys.write(output); } - function charIsPunctuation(ch) { - switch (ch) { - case 33 /* exclamation */: - case 34 /* doubleQuote */: - case 35 /* hash */: - case 37 /* percent */: - case 38 /* ampersand */: - case 39 /* singleQuote */: - case 40 /* openParen */: - case 41 /* closeParen */: - case 42 /* asterisk */: - case 44 /* comma */: - case 45 /* minus */: - case 46 /* dot */: - case 47 /* slash */: - case 58 /* colon */: - case 59 /* semicolon */: - case 63 /* question */: - case 64 /* at */: - case 91 /* openBracket */: - case 92 /* backslash */: - case 93 /* closeBracket */: - case 95 /* _ */: - case 123 /* openBrace */: - case 125 /* closeBrace */: - return true; + function reportWatchDiagnostic(diagnostic) { + var output = new Date().toLocaleTimeString() + " - "; + if (diagnostic.file) { + var loc = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start); + output += diagnostic.file.fileName + "(" + (loc.line + 1) + "," + (loc.character + 1) + "): "; } - return false; + output += "" + ts.flattenDiagnosticMessageText(diagnostic.messageText, ts.sys.newLine) + ts.sys.newLine; + ts.sys.write(output); } - function isAllPunctuation(identifier, start, end) { - for (var i = start; i < end; i++) { - var ch = identifier.charCodeAt(i); - // We don't consider _ or $ as punctuation as there may be things with that name. - if (!charIsPunctuation(ch) || ch === 95 /* _ */ || ch === 36 /* $ */) { - return false; - } + function padLeft(s, length) { + while (s.length < length) { + s = " " + s; } - return true; + return s; } - function transitionFromUpperToLower(identifier, word, index, wordStart) { - if (word) { - // Cases this supports: - // 1) IDisposable -> I, Disposable - // 2) UIElement -> UI, Element - // 3) HTMLDocument -> HTML, Document - // - // etc. - if (index !== wordStart && - index + 1 < identifier.length) { - var currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index)); - var nextIsLower = isLowerCaseLetter(identifier.charCodeAt(index + 1)); - if (currentIsUpper && nextIsLower) { - // We have a transition from an upper to a lower letter here. But we only - // want to break if all the letters that preceded are uppercase. i.e. if we - // have "Foo" we don't want to break that into "F, oo". But if we have - // "IFoo" or "UIFoo", then we want to break that into "I, Foo" and "UI, - // Foo". i.e. the last uppercase letter belongs to the lowercase letters - // that follows. Note: this will make the following not split properly: - // "HELLOthere". However, these sorts of names do not show up in .Net - // programs. - for (var i = wordStart; i < index; i++) { - if (!isUpperCaseLetter(identifier.charCodeAt(i))) { - return false; - } - } - return true; - } - } + function padRight(s, length) { + while (s.length < length) { + s = s + " "; } - return false; + return s; } - function transitionFromLowerToUpper(identifier, word, index) { - var lastIsUpper = isUpperCaseLetter(identifier.charCodeAt(index - 1)); - var currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index)); - // See if the casing indicates we're starting a new word. Note: if we're breaking on - // words, then just seeing an upper case character isn't enough. Instead, it has to - // be uppercase and the previous character can't be uppercase. - // - // For example, breaking "AddMetadata" on words would make: Add Metadata - // - // on characters would be: A dd M etadata - // - // Break "AM" on words would be: AM - // - // on characters would be: A M - // - // We break the search string on characters. But we break the symbol name on words. - var transition = word - ? (currentIsUpper && !lastIsUpper) - : currentIsUpper; - return transition; + function isJSONSupported() { + return typeof JSON === "object" && typeof JSON.parse === "function"; } -})(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - var SignatureHelp; - (function (SignatureHelp) { - // A partially written generic type expression is not guaranteed to have the correct syntax tree. the expression could be parsed as less than/greater than expression or a comma expression - // or some other combination depending on what the user has typed so far. For the purposes of signature help we need to consider any location after "<" as a possible generic type reference. - // To do this, the method will back parse the expression starting at the position required. it will try to parse the current expression as a generic type expression, if it did succeed it - // will return the generic identifier that started the expression (e.g. "foo" in "foo 0) { + reportDiagnostics(commandLine.errors, compilerHost); + return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + } + if (commandLine.options.init) { + writeConfigFile(commandLine.options, commandLine.fileNames); + return ts.sys.exit(ts.ExitStatus.Success); + } + if (commandLine.options.version) { + printVersion(); + return ts.sys.exit(ts.ExitStatus.Success); + } + if (commandLine.options.help) { + printVersion(); + printHelp(); + return ts.sys.exit(ts.ExitStatus.Success); + } + if (commandLine.options.project) { + if (!isJSONSupported()) { + reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.The_current_host_does_not_support_the_0_option, "--project"), /* host */ undefined); + return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); } - var call = argumentInfo.invocation; - var candidates = []; - var resolvedSignature = typeChecker.getResolvedSignature(call, candidates); - cancellationToken.throwIfCancellationRequested(); - if (!candidates.length) { - // We didn't have any sig help items produced by the TS compiler. If this is a JS - // file, then see if we can figure out anything better. - if (ts.isSourceFileJavaScript(sourceFile)) { - return createJavaScriptSignatureHelpItems(argumentInfo, program); + if (commandLine.fileNames.length !== 0) { + reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line), /* host */ undefined); + return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + } + var fileOrDirectory = ts.normalizePath(commandLine.options.project); + if (!fileOrDirectory /* current directory "." */ || ts.sys.directoryExists(fileOrDirectory)) { + configFileName = ts.combinePaths(fileOrDirectory, "tsconfig.json"); + if (!ts.sys.fileExists(configFileName)) { + reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_find_a_tsconfig_json_file_at_the_specified_directory_Colon_0, commandLine.options.project), /* host */ undefined); + return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + } + } + else { + configFileName = fileOrDirectory; + if (!ts.sys.fileExists(configFileName)) { + reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.The_specified_path_does_not_exist_Colon_0, commandLine.options.project), /* host */ undefined); + return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); } - return undefined; } - return createSignatureHelpItems(candidates, resolvedSignature, argumentInfo, typeChecker); } - SignatureHelp.getSignatureHelpItems = getSignatureHelpItems; - function createJavaScriptSignatureHelpItems(argumentInfo, program) { - if (argumentInfo.invocation.kind !== 174 /* CallExpression */) { - return undefined; + else if (commandLine.fileNames.length === 0 && isJSONSupported()) { + var searchPath = ts.normalizePath(ts.sys.getCurrentDirectory()); + configFileName = ts.findConfigFile(searchPath, ts.sys.fileExists); + } + if (commandLine.fileNames.length === 0 && !configFileName) { + printVersion(); + printHelp(); + return ts.sys.exit(ts.ExitStatus.Success); + } + if (ts.isWatchSet(commandLine.options)) { + if (!ts.sys.watchFile) { + reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), /* host */ undefined); + return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); } - // See if we can find some symbol with the call expression name that has call signatures. - var callExpression = argumentInfo.invocation; - var expression = callExpression.expression; - var name = expression.kind === 69 /* Identifier */ - ? expression - : expression.kind === 172 /* PropertyAccessExpression */ - ? expression.name - : undefined; - if (!name || !name.text) { - return undefined; + if (configFileName) { + configFileWatcher = ts.sys.watchFile(configFileName, configFileChanged); } - var typeChecker = program.getTypeChecker(); - for (var _i = 0, _a = program.getSourceFiles(); _i < _a.length; _i++) { - var sourceFile = _a[_i]; - var nameToDeclarations = sourceFile.getNamedDeclarations(); - var declarations = nameToDeclarations[name.text]; - if (declarations) { - for (var _b = 0, declarations_8 = declarations; _b < declarations_8.length; _b++) { - var declaration = declarations_8[_b]; - var symbol = declaration.symbol; - if (symbol) { - var type = typeChecker.getTypeOfSymbolAtLocation(symbol, declaration); - if (type) { - var callSignatures = type.getCallSignatures(); - if (callSignatures && callSignatures.length) { - return createSignatureHelpItems(callSignatures, callSignatures[0], argumentInfo, typeChecker); - } - } - } - } - } + if (ts.sys.watchDirectory && configFileName) { + var directory = ts.getDirectoryPath(configFileName); + directoryWatcher = ts.sys.watchDirectory( + // When the configFileName is just "tsconfig.json", the watched directory should be + // the current directory; if there is a given "project" parameter, then the configFileName + // is an absolute file name. + directory == "" ? "." : directory, watchedDirectoryChanged, /*recursive*/ true); } } - /** - * Returns relevant information for the argument list and the current argument if we are - * in the argument of an invocation; returns undefined otherwise. - */ - function getImmediatelyContainingArgumentInfo(node, position, sourceFile) { - if (node.parent.kind === 174 /* CallExpression */ || node.parent.kind === 175 /* NewExpression */) { - var callExpression = node.parent; - // There are 3 cases to handle: - // 1. The token introduces a list, and should begin a sig help session - // 2. The token is either not associated with a list, or ends a list, so the session should end - // 3. The token is buried inside a list, and should give sig help - // - // The following are examples of each: - // - // Case 1: - // foo<#T, U>(#a, b) -> The token introduces a list, and should begin a sig help session - // Case 2: - // fo#o#(a, b)# -> The token is either not associated with a list, or ends a list, so the session should end - // Case 3: - // foo(a#, #b#) -> The token is buried inside a list, and should give sig help - // Find out if 'node' is an argument, a type argument, or neither - if (node.kind === 25 /* LessThanToken */ || - node.kind === 17 /* OpenParenToken */) { - // Find the list that starts right *after* the < or ( token. - // If the user has just opened a list, consider this item 0. - var list = getChildListThatStartsWithOpenerToken(callExpression, node, sourceFile); - var isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos; - ts.Debug.assert(list !== undefined); - return { - kind: isTypeArgList ? 0 /* TypeArguments */ : 1 /* CallArguments */, - invocation: callExpression, - argumentsSpan: getApplicableSpanForArguments(list, sourceFile), - argumentIndex: 0, - argumentCount: getArgumentCount(list) - }; + performCompilation(); + function parseConfigFile() { + if (!cachedConfigFileText) { + try { + cachedConfigFileText = ts.sys.readFile(configFileName); } - // findListItemInfo can return undefined if we are not in parent's argument list - // or type argument list. This includes cases where the cursor is: - // - To the right of the closing paren, non-substitution template, or template tail. - // - Between the type arguments and the arguments (greater than token) - // - On the target of the call (parent.func) - // - On the 'new' keyword in a 'new' expression - var listItemInfo = ts.findListItemInfo(node); - if (listItemInfo) { - var list = listItemInfo.list; - var isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos; - var argumentIndex = getArgumentIndex(list, node); - var argumentCount = getArgumentCount(list); - ts.Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, "argumentCount < argumentIndex, " + argumentCount + " < " + argumentIndex); - return { - kind: isTypeArgList ? 0 /* TypeArguments */ : 1 /* CallArguments */, - invocation: callExpression, - argumentsSpan: getApplicableSpanForArguments(list, sourceFile), - argumentIndex: argumentIndex, - argumentCount: argumentCount - }; + catch (e) { + var error = ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_read_file_0_Colon_1, configFileName, e.message); + reportWatchDiagnostic(error); + ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + return; } - return undefined; } - else if (node.kind === 11 /* NoSubstitutionTemplateLiteral */ && node.parent.kind === 176 /* TaggedTemplateExpression */) { - // Check if we're actually inside the template; - // otherwise we'll fall out and return undefined. - if (ts.isInsideTemplateLiteral(node, position)) { - return getArgumentListInfoForTemplate(node.parent, /*argumentIndex*/ 0, sourceFile); - } + if (!cachedConfigFileText) { + var error = ts.createCompilerDiagnostic(ts.Diagnostics.File_0_not_found, configFileName); + reportDiagnostics([error], /* compilerHost */ undefined); + ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + return; } - else if (node.kind === 12 /* TemplateHead */ && node.parent.parent.kind === 176 /* TaggedTemplateExpression */) { - var templateExpression = node.parent; - var tagExpression = templateExpression.parent; - ts.Debug.assert(templateExpression.kind === 189 /* TemplateExpression */); - var argumentIndex = ts.isInsideTemplateLiteral(node, position) ? 0 : 1; - return getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile); + var result = ts.parseConfigFileTextToJson(configFileName, cachedConfigFileText); + var configObject = result.config; + if (!configObject) { + reportDiagnostics([result.error], /* compilerHost */ undefined); + ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + return; } - else if (node.parent.kind === 197 /* TemplateSpan */ && node.parent.parent.parent.kind === 176 /* TaggedTemplateExpression */) { - var templateSpan = node.parent; - var templateExpression = templateSpan.parent; - var tagExpression = templateExpression.parent; - ts.Debug.assert(templateExpression.kind === 189 /* TemplateExpression */); - // If we're just after a template tail, don't show signature help. - if (node.kind === 14 /* TemplateTail */ && !ts.isInsideTemplateLiteral(node, position)) { - return undefined; + var cwd = ts.sys.getCurrentDirectory(); + var configParseResult = ts.parseJsonConfigFileContent(configObject, ts.sys, ts.getNormalizedAbsolutePath(ts.getDirectoryPath(configFileName), cwd), commandLine.options, ts.getNormalizedAbsolutePath(configFileName, cwd)); + if (configParseResult.errors.length > 0) { + reportDiagnostics(configParseResult.errors, /* compilerHost */ undefined); + ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + return; + } + if (ts.isWatchSet(configParseResult.options)) { + if (!ts.sys.watchFile) { + reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), /* host */ undefined); + ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); } - var spanIndex = templateExpression.templateSpans.indexOf(templateSpan); - var argumentIndex = getArgumentIndexForTemplatePiece(spanIndex, node, position); - return getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile); + if (!directoryWatcher && ts.sys.watchDirectory && configFileName) { + var directory = ts.getDirectoryPath(configFileName); + directoryWatcher = ts.sys.watchDirectory( + // When the configFileName is just "tsconfig.json", the watched directory should be + // the current directory; if there is a given "project" parameter, then the configFileName + // is an absolute file name. + directory == "" ? "." : directory, watchedDirectoryChanged, /*recursive*/ true); + } + ; } - return undefined; + return configParseResult; } - function getArgumentIndex(argumentsList, node) { - // The list we got back can include commas. In the presence of errors it may - // also just have nodes without commas. For example "Foo(a b c)" will have 3 - // args without commas. We want to find what index we're at. So we count - // forward until we hit ourselves, only incrementing the index if it isn't a - // comma. - // - // Note: the subtlety around trailing commas (in getArgumentCount) does not apply - // here. That's because we're only walking forward until we hit the node we're - // on. In that case, even if we're after the trailing comma, we'll still see - // that trailing comma in the list, and we'll have generated the appropriate - // arg index. - var argumentIndex = 0; - var listChildren = argumentsList.getChildren(); - for (var _i = 0, listChildren_1 = listChildren; _i < listChildren_1.length; _i++) { - var child = listChildren_1[_i]; - if (child === node) { - break; + // Invoked to perform initial compilation or re-compilation in watch mode + function performCompilation() { + if (!cachedProgram) { + if (configFileName) { + var configParseResult = parseConfigFile(); + rootFileNames = configParseResult.fileNames; + compilerOptions = configParseResult.options; } - if (child.kind !== 24 /* CommaToken */) { - argumentIndex++; + else { + rootFileNames = commandLine.fileNames; + compilerOptions = commandLine.options; } + compilerHost = ts.createCompilerHost(compilerOptions); + hostGetSourceFile = compilerHost.getSourceFile; + compilerHost.getSourceFile = getSourceFile; + hostFileExists = compilerHost.fileExists; + compilerHost.fileExists = cachedFileExists; } - return argumentIndex; - } - function getArgumentCount(argumentsList) { - // The argument count for a list is normally the number of non-comma children it has. - // For example, if you have "Foo(a,b)" then there will be three children of the arg - // list 'a' '' 'b'. So, in this case the arg count will be 2. However, there - // is a small subtlety. If you have "Foo(a,)", then the child list will just have - // 'a' ''. So, in the case where the last child is a comma, we increase the - // arg count by one to compensate. - // - // Note: this subtlety only applies to the last comma. If you had "Foo(a,," then - // we'll have: 'a' '' '' - // That will give us 2 non-commas. We then add one for the last comma, givin us an - // arg count of 3. - var listChildren = argumentsList.getChildren(); - var argumentCount = ts.countWhere(listChildren, function (arg) { return arg.kind !== 24 /* CommaToken */; }); - if (listChildren.length > 0 && ts.lastOrUndefined(listChildren).kind === 24 /* CommaToken */) { - argumentCount++; + if (compilerOptions.pretty) { + reportDiagnosticWorker = reportDiagnosticWithColorAndContext; } - return argumentCount; + // reset the cache of existing files + cachedExistingFiles = ts.createMap(); + var compileResult = compile(rootFileNames, compilerOptions, compilerHost); + if (!ts.isWatchSet(compilerOptions)) { + return ts.sys.exit(compileResult.exitStatus); + } + setCachedProgram(compileResult.program); + reportWatchDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.Compilation_complete_Watching_for_file_changes)); } - // spanIndex is either the index for a given template span. - // This does not give appropriate results for a NoSubstitutionTemplateLiteral - function getArgumentIndexForTemplatePiece(spanIndex, node, position) { - // Because the TemplateStringsArray is the first argument, we have to offset each substitution expression by 1. - // There are three cases we can encounter: - // 1. We are precisely in the template literal (argIndex = 0). - // 2. We are in or to the right of the substitution expression (argIndex = spanIndex + 1). - // 3. We are directly to the right of the template literal, but because we look for the token on the left, - // not enough to put us in the substitution expression; we should consider ourselves part of - // the *next* span's expression by offsetting the index (argIndex = (spanIndex + 1) + 1). - // - // Example: f `# abcd $#{# 1 + 1# }# efghi ${ #"#hello"# } # ` - // ^ ^ ^ ^ ^ ^ ^ ^ ^ - // Case: 1 1 3 2 1 3 2 2 1 - ts.Debug.assert(position >= node.getStart(), "Assumed 'position' could not occur before node."); - if (ts.isTemplateLiteralKind(node.kind)) { - if (ts.isInsideTemplateLiteral(node, position)) { - return 0; + function cachedFileExists(fileName) { + return fileName in cachedExistingFiles + ? cachedExistingFiles[fileName] + : cachedExistingFiles[fileName] = hostFileExists(fileName); + } + function getSourceFile(fileName, languageVersion, onError) { + // Return existing SourceFile object if one is available + if (cachedProgram) { + var sourceFile_1 = cachedProgram.getSourceFile(fileName); + // A modified source file has no watcher and should not be reused + if (sourceFile_1 && sourceFile_1.fileWatcher) { + return sourceFile_1; } - return spanIndex + 2; } - return spanIndex + 1; + // Use default host function + var sourceFile = hostGetSourceFile(fileName, languageVersion, onError); + if (sourceFile && ts.isWatchSet(compilerOptions) && ts.sys.watchFile) { + // Attach a file watcher + sourceFile.fileWatcher = ts.sys.watchFile(sourceFile.fileName, function (fileName, removed) { return sourceFileChanged(sourceFile, removed); }); + } + return sourceFile; } - function getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile) { - // argumentCount is either 1 or (numSpans + 1) to account for the template strings array argument. - var argumentCount = tagExpression.template.kind === 11 /* NoSubstitutionTemplateLiteral */ - ? 1 - : tagExpression.template.templateSpans.length + 1; - ts.Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, "argumentCount < argumentIndex, " + argumentCount + " < " + argumentIndex); - return { - kind: 2 /* TaggedTemplateArguments */, - invocation: tagExpression, - argumentsSpan: getApplicableSpanForTaggedTemplate(tagExpression, sourceFile), - argumentIndex: argumentIndex, - argumentCount: argumentCount - }; + // Change cached program to the given program + function setCachedProgram(program) { + if (cachedProgram) { + var newSourceFiles_1 = program ? program.getSourceFiles() : undefined; + ts.forEach(cachedProgram.getSourceFiles(), function (sourceFile) { + if (!(newSourceFiles_1 && ts.contains(newSourceFiles_1, sourceFile))) { + if (sourceFile.fileWatcher) { + sourceFile.fileWatcher.close(); + sourceFile.fileWatcher = undefined; + } + } + }); + } + cachedProgram = program; } - function getApplicableSpanForArguments(argumentsList, sourceFile) { - // We use full start and skip trivia on the end because we want to include trivia on - // both sides. For example, - // - // foo( /*comment */ a, b, c /*comment*/ ) - // | | - // - // The applicable span is from the first bar to the second bar (inclusive, - // but not including parentheses) - var applicableSpanStart = argumentsList.getFullStart(); - var applicableSpanEnd = ts.skipTrivia(sourceFile.text, argumentsList.getEnd(), /*stopAfterLineBreak*/ false); - return ts.createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart); + // If a source file changes, mark it as unwatched and start the recompilation timer + function sourceFileChanged(sourceFile, removed) { + sourceFile.fileWatcher.close(); + sourceFile.fileWatcher = undefined; + if (removed) { + ts.unorderedRemoveItem(rootFileNames, sourceFile.fileName); + } + startTimerForRecompilation(); } - function getApplicableSpanForTaggedTemplate(taggedTemplate, sourceFile) { - var template = taggedTemplate.template; - var applicableSpanStart = template.getStart(); - var applicableSpanEnd = template.getEnd(); - // We need to adjust the end position for the case where the template does not have a tail. - // Otherwise, we will not show signature help past the expression. - // For example, - // - // ` ${ 1 + 1 foo(10) - // | | - // - // This is because a Missing node has no width. However, what we actually want is to include trivia - // leading up to the next token in case the user is about to type in a TemplateMiddle or TemplateTail. - if (template.kind === 189 /* TemplateExpression */) { - var lastSpan = ts.lastOrUndefined(template.templateSpans); - if (lastSpan.literal.getFullWidth() === 0) { - applicableSpanEnd = ts.skipTrivia(sourceFile.text, applicableSpanEnd, /*stopAfterLineBreak*/ false); + // If the configuration file changes, forget cached program and start the recompilation timer + function configFileChanged() { + setCachedProgram(undefined); + cachedConfigFileText = undefined; + startTimerForRecompilation(); + } + function watchedDirectoryChanged(fileName) { + if (fileName && !ts.isSupportedSourceFileName(fileName, compilerOptions)) { + return; + } + startTimerForHandlingDirectoryChanges(); + } + function startTimerForHandlingDirectoryChanges() { + if (timerHandleForDirectoryChanges) { + clearTimeout(timerHandleForDirectoryChanges); + } + timerHandleForDirectoryChanges = setTimeout(directoryChangeHandler, 250); + } + function directoryChangeHandler() { + var parsedCommandLine = parseConfigFile(); + var newFileNames = ts.map(parsedCommandLine.fileNames, compilerHost.getCanonicalFileName); + var canonicalRootFileNames = ts.map(rootFileNames, compilerHost.getCanonicalFileName); + // We check if the project file list has changed. If so, we just throw away the old program and start fresh. + if (!ts.arrayIsEqualTo(newFileNames && newFileNames.sort(), canonicalRootFileNames && canonicalRootFileNames.sort())) { + setCachedProgram(undefined); + startTimerForRecompilation(); + } + } + // Upon detecting a file change, wait for 250ms and then perform a recompilation. This gives batch + // operations (such as saving all modified files in an editor) a chance to complete before we kick + // off a new compilation. + function startTimerForRecompilation() { + if (timerHandleForRecompilation) { + clearTimeout(timerHandleForRecompilation); + } + timerHandleForRecompilation = setTimeout(recompile, 250); + } + function recompile() { + timerHandleForRecompilation = undefined; + reportWatchDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.File_change_detected_Starting_incremental_compilation)); + performCompilation(); + } + } + ts.executeCommandLine = executeCommandLine; + function compile(fileNames, compilerOptions, compilerHost) { + var hasDiagnostics = compilerOptions.diagnostics || compilerOptions.extendedDiagnostics; + var statistics; + if (hasDiagnostics) { + ts.performance.enable(); + statistics = []; + } + var program = ts.createProgram(fileNames, compilerOptions, compilerHost); + var exitStatus = compileProgram(); + if (compilerOptions.listFiles) { + ts.forEach(program.getSourceFiles(), function (file) { + ts.sys.write(file.fileName + ts.sys.newLine); + }); + } + if (hasDiagnostics) { + var memoryUsed = ts.sys.getMemoryUsage ? ts.sys.getMemoryUsage() : -1; + reportCountStatistic("Files", program.getSourceFiles().length); + reportCountStatistic("Lines", countLines(program)); + reportCountStatistic("Nodes", program.getNodeCount()); + reportCountStatistic("Identifiers", program.getIdentifierCount()); + reportCountStatistic("Symbols", program.getSymbolCount()); + reportCountStatistic("Types", program.getTypeCount()); + if (memoryUsed >= 0) { + reportStatisticalValue("Memory used", Math.round(memoryUsed / 1000) + "K"); + } + var programTime = ts.performance.getDuration("Program"); + var bindTime = ts.performance.getDuration("Bind"); + var checkTime = ts.performance.getDuration("Check"); + var emitTime = ts.performance.getDuration("Emit"); + if (compilerOptions.extendedDiagnostics) { + ts.performance.forEachMeasure(function (name, duration) { return reportTimeStatistic(name + " time", duration); }); + } + else { + // Individual component times. + // Note: To match the behavior of previous versions of the compiler, the reported parse time includes + // I/O read time and processing time for triple-slash references and module imports, and the reported + // emit time includes I/O write time. We preserve this behavior so we can accurately compare times. + reportTimeStatistic("I/O read", ts.performance.getDuration("I/O Read")); + reportTimeStatistic("I/O write", ts.performance.getDuration("I/O Write")); + reportTimeStatistic("Parse time", programTime); + reportTimeStatistic("Bind time", bindTime); + reportTimeStatistic("Check time", checkTime); + reportTimeStatistic("Emit time", emitTime); + } + reportTimeStatistic("Total time", programTime + bindTime + checkTime + emitTime); + reportStatistics(); + ts.performance.disable(); + } + return { program: program, exitStatus: exitStatus }; + function compileProgram() { + var diagnostics; + // First get and report any syntactic errors. + diagnostics = program.getSyntacticDiagnostics(); + // If we didn't have any syntactic errors, then also try getting the global and + // semantic errors. + if (diagnostics.length === 0) { + diagnostics = program.getOptionsDiagnostics().concat(program.getGlobalDiagnostics()); + if (diagnostics.length === 0) { + diagnostics = program.getSemanticDiagnostics(); } } - return ts.createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart); + // Otherwise, emit and report any errors we ran into. + var emitOutput = program.emit(); + diagnostics = diagnostics.concat(emitOutput.diagnostics); + reportDiagnostics(ts.sortAndDeduplicateDiagnostics(diagnostics), compilerHost); + reportEmittedFiles(emitOutput.emittedFiles, compilerHost); + if (emitOutput.emitSkipped && diagnostics.length > 0) { + // If the emitter didn't emit anything, then pass that value along. + return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped; + } + else if (diagnostics.length > 0) { + // The emitter emitted something, inform the caller if that happened in the presence + // of diagnostics or not. + return ts.ExitStatus.DiagnosticsPresent_OutputsGenerated; + } + return ts.ExitStatus.Success; } - function getContainingArgumentInfo(node, position, sourceFile) { - for (var n = node; n.kind !== 256 /* SourceFile */; n = n.parent) { - if (ts.isFunctionBlock(n)) { - return undefined; - } - // If the node is not a subspan of its parent, this is a big problem. - // There have been crashes that might be caused by this violation. - if (n.pos < n.parent.pos || n.end > n.parent.end) { - ts.Debug.fail("Node of kind " + n.kind + " is not a subspan of its parent of kind " + n.parent.kind); + function reportStatistics() { + var nameSize = 0; + var valueSize = 0; + for (var _i = 0, statistics_1 = statistics; _i < statistics_1.length; _i++) { + var _a = statistics_1[_i], name_47 = _a.name, value = _a.value; + if (name_47.length > nameSize) { + nameSize = name_47.length; } - var argumentInfo = getImmediatelyContainingArgumentInfo(n, position, sourceFile); - if (argumentInfo) { - return argumentInfo; + if (value.length > valueSize) { + valueSize = value.length; } } - return undefined; + for (var _b = 0, statistics_2 = statistics; _b < statistics_2.length; _b++) { + var _c = statistics_2[_b], name_48 = _c.name, value = _c.value; + ts.sys.write(padRight(name_48 + ":", nameSize + 2) + padLeft(value.toString(), valueSize) + ts.sys.newLine); + } } - SignatureHelp.getContainingArgumentInfo = getContainingArgumentInfo; - function getChildListThatStartsWithOpenerToken(parent, openerToken, sourceFile) { - var children = parent.getChildren(sourceFile); - var indexOfOpenerToken = children.indexOf(openerToken); - ts.Debug.assert(indexOfOpenerToken >= 0 && children.length > indexOfOpenerToken + 1); - return children[indexOfOpenerToken + 1]; + function reportStatisticalValue(name, value) { + statistics.push({ name: name, value: value }); } - /** - * The selectedItemIndex could be negative for several reasons. - * 1. There are too many arguments for all of the overloads - * 2. None of the overloads were type compatible - * The solution here is to try to pick the best overload by picking - * either the first one that has an appropriate number of parameters, - * or the one with the most parameters. - */ - function selectBestInvalidOverloadIndex(candidates, argumentCount) { - var maxParamsSignatureIndex = -1; - var maxParams = -1; - for (var i = 0; i < candidates.length; i++) { - var candidate = candidates[i]; - if (candidate.hasRestParameter || candidate.parameters.length >= argumentCount) { - return i; - } - if (candidate.parameters.length > maxParams) { - maxParams = candidate.parameters.length; - maxParamsSignatureIndex = i; + function reportCountStatistic(name, count) { + reportStatisticalValue(name, "" + count); + } + function reportTimeStatistic(name, time) { + reportStatisticalValue(name, (time / 1000).toFixed(2) + "s"); + } + } + function printVersion() { + ts.sys.write(getDiagnosticText(ts.Diagnostics.Version_0, ts.version) + ts.sys.newLine); + } + function printHelp() { + var output = []; + // We want to align our "syntax" and "examples" commands to a certain margin. + var syntaxLength = getDiagnosticText(ts.Diagnostics.Syntax_Colon_0, "").length; + var examplesLength = getDiagnosticText(ts.Diagnostics.Examples_Colon_0, "").length; + var marginLength = Math.max(syntaxLength, examplesLength); + // Build up the syntactic skeleton. + var syntax = makePadding(marginLength - syntaxLength); + syntax += "tsc [" + getDiagnosticText(ts.Diagnostics.options) + "] [" + getDiagnosticText(ts.Diagnostics.file) + " ...]"; + output.push(getDiagnosticText(ts.Diagnostics.Syntax_Colon_0, syntax)); + output.push(ts.sys.newLine + ts.sys.newLine); + // Build up the list of examples. + var padding = makePadding(marginLength); + output.push(getDiagnosticText(ts.Diagnostics.Examples_Colon_0, makePadding(marginLength - examplesLength) + "tsc hello.ts") + ts.sys.newLine); + output.push(padding + "tsc --outFile file.js file.ts" + ts.sys.newLine); + output.push(padding + "tsc @args.txt" + ts.sys.newLine); + output.push(ts.sys.newLine); + output.push(getDiagnosticText(ts.Diagnostics.Options_Colon) + ts.sys.newLine); + // Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch") + var optsList = ts.filter(ts.optionDeclarations.slice(), function (v) { return !v.experimental; }); + optsList.sort(function (a, b) { return ts.compareValues(a.name.toLowerCase(), b.name.toLowerCase()); }); + // We want our descriptions to align at the same column in our output, + // so we keep track of the longest option usage string. + marginLength = 0; + var usageColumn = []; // Things like "-d, --declaration" go in here. + var descriptionColumn = []; + var optionsDescriptionMap = ts.createMap(); // Map between option.description and list of option.type if it is a kind + for (var i = 0; i < optsList.length; i++) { + var option = optsList[i]; + // If an option lacks a description, + // it is not officially supported. + if (!option.description) { + continue; + } + var usageText_1 = " "; + if (option.shortName) { + usageText_1 += "-" + option.shortName; + usageText_1 += getParamType(option); + usageText_1 += ", "; + } + usageText_1 += "--" + option.name; + usageText_1 += getParamType(option); + usageColumn.push(usageText_1); + var description = void 0; + if (option.name === "lib") { + description = getDiagnosticText(option.description); + var options = []; + var element = option.element; + var typeMap = element.type; + for (var key in typeMap) { + options.push("'" + key + "'"); } + optionsDescriptionMap[description] = options; } - return maxParamsSignatureIndex; + else { + description = getDiagnosticText(option.description); + } + descriptionColumn.push(description); + // Set the new margin for the description column if necessary. + marginLength = Math.max(usageText_1.length, marginLength); } - function createSignatureHelpItems(candidates, bestSignature, argumentListInfo, typeChecker) { - var applicableSpan = argumentListInfo.argumentsSpan; - var isTypeParameterList = argumentListInfo.kind === 0 /* TypeArguments */; - var invocation = argumentListInfo.invocation; - var callTarget = ts.getInvokedExpression(invocation); - var callTargetSymbol = typeChecker.getSymbolAtLocation(callTarget); - var callTargetDisplayParts = callTargetSymbol && ts.symbolToDisplayParts(typeChecker, callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined); - var items = ts.map(candidates, function (candidateSignature) { - var signatureHelpParameters; - var prefixDisplayParts = []; - var suffixDisplayParts = []; - if (callTargetDisplayParts) { - ts.addRange(prefixDisplayParts, callTargetDisplayParts); - } - if (isTypeParameterList) { - prefixDisplayParts.push(ts.punctuationPart(25 /* LessThanToken */)); - var typeParameters = candidateSignature.typeParameters; - signatureHelpParameters = typeParameters && typeParameters.length > 0 ? ts.map(typeParameters, createSignatureHelpParameterForTypeParameter) : emptyArray; - suffixDisplayParts.push(ts.punctuationPart(27 /* GreaterThanToken */)); - var parameterParts = ts.mapToDisplayParts(function (writer) { - return typeChecker.getSymbolDisplayBuilder().buildDisplayForParametersAndDelimiters(candidateSignature.thisParameter, candidateSignature.parameters, writer, invocation); - }); - ts.addRange(suffixDisplayParts, parameterParts); - } - else { - var typeParameterParts = ts.mapToDisplayParts(function (writer) { - return typeChecker.getSymbolDisplayBuilder().buildDisplayForTypeParametersAndDelimiters(candidateSignature.typeParameters, writer, invocation); - }); - ts.addRange(prefixDisplayParts, typeParameterParts); - prefixDisplayParts.push(ts.punctuationPart(17 /* OpenParenToken */)); - var parameters = candidateSignature.parameters; - signatureHelpParameters = parameters.length > 0 ? ts.map(parameters, createSignatureHelpParameterForParameter) : emptyArray; - suffixDisplayParts.push(ts.punctuationPart(18 /* CloseParenToken */)); + // Special case that can't fit in the loop. + var usageText = " @<" + getDiagnosticText(ts.Diagnostics.file) + ">"; + usageColumn.push(usageText); + descriptionColumn.push(getDiagnosticText(ts.Diagnostics.Insert_command_line_options_and_files_from_a_file)); + marginLength = Math.max(usageText.length, marginLength); + // Print out each row, aligning all the descriptions on the same column. + for (var i = 0; i < usageColumn.length; i++) { + var usage = usageColumn[i]; + var description = descriptionColumn[i]; + var kindsList = optionsDescriptionMap[description]; + output.push(usage + makePadding(marginLength - usage.length + 2) + description + ts.sys.newLine); + if (kindsList) { + output.push(makePadding(marginLength + 4)); + for (var _i = 0, kindsList_1 = kindsList; _i < kindsList_1.length; _i++) { + var kind = kindsList_1[_i]; + output.push(kind + " "); } - var returnTypeParts = ts.mapToDisplayParts(function (writer) { - return typeChecker.getSymbolDisplayBuilder().buildReturnTypeDisplay(candidateSignature, writer, invocation); - }); - ts.addRange(suffixDisplayParts, returnTypeParts); - return { - isVariadic: candidateSignature.hasRestParameter, - prefixDisplayParts: prefixDisplayParts, - suffixDisplayParts: suffixDisplayParts, - separatorDisplayParts: [ts.punctuationPart(24 /* CommaToken */), ts.spacePart()], - parameters: signatureHelpParameters, - documentation: candidateSignature.getDocumentationComment() - }; - }); - var argumentIndex = argumentListInfo.argumentIndex; - // argumentCount is the *apparent* number of arguments. - var argumentCount = argumentListInfo.argumentCount; - var selectedItemIndex = candidates.indexOf(bestSignature); - if (selectedItemIndex < 0) { - selectedItemIndex = selectBestInvalidOverloadIndex(candidates, argumentCount); - } - ts.Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, "argumentCount < argumentIndex, " + argumentCount + " < " + argumentIndex); - return { - items: items, - applicableSpan: applicableSpan, - selectedItemIndex: selectedItemIndex, - argumentIndex: argumentIndex, - argumentCount: argumentCount - }; - function createSignatureHelpParameterForParameter(parameter) { - var displayParts = ts.mapToDisplayParts(function (writer) { - return typeChecker.getSymbolDisplayBuilder().buildParameterDisplay(parameter, writer, invocation); - }); - return { - name: parameter.name, - documentation: parameter.getDocumentationComment(), - displayParts: displayParts, - isOptional: typeChecker.isOptionalParameter(parameter.valueDeclaration) - }; + output.push(ts.sys.newLine); } - function createSignatureHelpParameterForTypeParameter(typeParameter) { - var displayParts = ts.mapToDisplayParts(function (writer) { - return typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(typeParameter, writer, invocation); - }); - return { - name: typeParameter.symbol.name, - documentation: emptyArray, - displayParts: displayParts, - isOptional: false - }; + } + for (var _a = 0, output_1 = output; _a < output_1.length; _a++) { + var line = output_1[_a]; + ts.sys.write(line); + } + return; + function getParamType(option) { + if (option.paramType !== undefined) { + return " " + getDiagnosticText(option.paramType); } + return ""; } - })(SignatureHelp = ts.SignatureHelp || (ts.SignatureHelp = {})); + function makePadding(paddingLength) { + return Array(paddingLength + 1).join(" "); + } + } + function writeConfigFile(options, fileNames) { + var currentDirectory = ts.sys.getCurrentDirectory(); + var file = ts.normalizePath(ts.combinePaths(currentDirectory, "tsconfig.json")); + if (ts.sys.fileExists(file)) { + reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file), /* host */ undefined); + } + else { + ts.sys.writeFile(file, JSON.stringify(ts.generateTSConfig(options, fileNames), undefined, 4)); + reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.Successfully_created_a_tsconfig_json_file), /* host */ undefined); + } + return; + } + var _a; })(ts || (ts = {})); +if (ts.sys.tryEnableSourceMapsForHost && /^development$/i.test(ts.sys.getEnvironmentVariable("NODE_ENV"))) { + ts.sys.tryEnableSourceMapsForHost(); +} + var ts; (function (ts) { var ScriptSnapshot; @@ -50069,6 +61160,8 @@ var ts; ScriptElementKind.alias = "alias"; ScriptElementKind.constElement = "const"; ScriptElementKind.letElement = "let"; + ScriptElementKind.directory = "directory"; + ScriptElementKind.externalModuleName = "external module name"; })(ScriptElementKind = ts.ScriptElementKind || (ts.ScriptElementKind = {})); var ScriptElementKindModifier; (function (ScriptElementKindModifier) { @@ -50084,64 +61177,421 @@ var ts; var ClassificationTypeNames = (function () { function ClassificationTypeNames() { } - ClassificationTypeNames.comment = "comment"; - ClassificationTypeNames.identifier = "identifier"; - ClassificationTypeNames.keyword = "keyword"; - ClassificationTypeNames.numericLiteral = "number"; - ClassificationTypeNames.operator = "operator"; - ClassificationTypeNames.stringLiteral = "string"; - ClassificationTypeNames.whiteSpace = "whitespace"; - ClassificationTypeNames.text = "text"; - ClassificationTypeNames.punctuation = "punctuation"; - ClassificationTypeNames.className = "class name"; - ClassificationTypeNames.enumName = "enum name"; - ClassificationTypeNames.interfaceName = "interface name"; - ClassificationTypeNames.moduleName = "module name"; - ClassificationTypeNames.typeParameterName = "type parameter name"; - ClassificationTypeNames.typeAliasName = "type alias name"; - ClassificationTypeNames.parameterName = "parameter name"; - ClassificationTypeNames.docCommentTagName = "doc comment tag name"; - ClassificationTypeNames.jsxOpenTagName = "jsx open tag name"; - ClassificationTypeNames.jsxCloseTagName = "jsx close tag name"; - ClassificationTypeNames.jsxSelfClosingTagName = "jsx self closing tag name"; - ClassificationTypeNames.jsxAttribute = "jsx attribute"; - ClassificationTypeNames.jsxText = "jsx text"; - ClassificationTypeNames.jsxAttributeStringLiteralValue = "jsx attribute string literal value"; - return ClassificationTypeNames; - }()); - ts.ClassificationTypeNames = ClassificationTypeNames; - (function (ClassificationType) { - ClassificationType[ClassificationType["comment"] = 1] = "comment"; - ClassificationType[ClassificationType["identifier"] = 2] = "identifier"; - ClassificationType[ClassificationType["keyword"] = 3] = "keyword"; - ClassificationType[ClassificationType["numericLiteral"] = 4] = "numericLiteral"; - ClassificationType[ClassificationType["operator"] = 5] = "operator"; - ClassificationType[ClassificationType["stringLiteral"] = 6] = "stringLiteral"; - ClassificationType[ClassificationType["regularExpressionLiteral"] = 7] = "regularExpressionLiteral"; - ClassificationType[ClassificationType["whiteSpace"] = 8] = "whiteSpace"; - ClassificationType[ClassificationType["text"] = 9] = "text"; - ClassificationType[ClassificationType["punctuation"] = 10] = "punctuation"; - ClassificationType[ClassificationType["className"] = 11] = "className"; - ClassificationType[ClassificationType["enumName"] = 12] = "enumName"; - ClassificationType[ClassificationType["interfaceName"] = 13] = "interfaceName"; - ClassificationType[ClassificationType["moduleName"] = 14] = "moduleName"; - ClassificationType[ClassificationType["typeParameterName"] = 15] = "typeParameterName"; - ClassificationType[ClassificationType["typeAliasName"] = 16] = "typeAliasName"; - ClassificationType[ClassificationType["parameterName"] = 17] = "parameterName"; - ClassificationType[ClassificationType["docCommentTagName"] = 18] = "docCommentTagName"; - ClassificationType[ClassificationType["jsxOpenTagName"] = 19] = "jsxOpenTagName"; - ClassificationType[ClassificationType["jsxCloseTagName"] = 20] = "jsxCloseTagName"; - ClassificationType[ClassificationType["jsxSelfClosingTagName"] = 21] = "jsxSelfClosingTagName"; - ClassificationType[ClassificationType["jsxAttribute"] = 22] = "jsxAttribute"; - ClassificationType[ClassificationType["jsxText"] = 23] = "jsxText"; - ClassificationType[ClassificationType["jsxAttributeStringLiteralValue"] = 24] = "jsxAttributeStringLiteralValue"; - })(ts.ClassificationType || (ts.ClassificationType = {})); - var ClassificationType = ts.ClassificationType; -})(ts || (ts = {})); -// These utilities are common to multiple language service features. -/* @internal */ -var ts; -(function (ts) { + return ClassificationTypeNames; + }()); + ClassificationTypeNames.comment = "comment"; + ClassificationTypeNames.identifier = "identifier"; + ClassificationTypeNames.keyword = "keyword"; + ClassificationTypeNames.numericLiteral = "number"; + ClassificationTypeNames.operator = "operator"; + ClassificationTypeNames.stringLiteral = "string"; + ClassificationTypeNames.whiteSpace = "whitespace"; + ClassificationTypeNames.text = "text"; + ClassificationTypeNames.punctuation = "punctuation"; + ClassificationTypeNames.className = "class name"; + ClassificationTypeNames.enumName = "enum name"; + ClassificationTypeNames.interfaceName = "interface name"; + ClassificationTypeNames.moduleName = "module name"; + ClassificationTypeNames.typeParameterName = "type parameter name"; + ClassificationTypeNames.typeAliasName = "type alias name"; + ClassificationTypeNames.parameterName = "parameter name"; + ClassificationTypeNames.docCommentTagName = "doc comment tag name"; + ClassificationTypeNames.jsxOpenTagName = "jsx open tag name"; + ClassificationTypeNames.jsxCloseTagName = "jsx close tag name"; + ClassificationTypeNames.jsxSelfClosingTagName = "jsx self closing tag name"; + ClassificationTypeNames.jsxAttribute = "jsx attribute"; + ClassificationTypeNames.jsxText = "jsx text"; + ClassificationTypeNames.jsxAttributeStringLiteralValue = "jsx attribute string literal value"; + ts.ClassificationTypeNames = ClassificationTypeNames; + (function (ClassificationType) { + ClassificationType[ClassificationType["comment"] = 1] = "comment"; + ClassificationType[ClassificationType["identifier"] = 2] = "identifier"; + ClassificationType[ClassificationType["keyword"] = 3] = "keyword"; + ClassificationType[ClassificationType["numericLiteral"] = 4] = "numericLiteral"; + ClassificationType[ClassificationType["operator"] = 5] = "operator"; + ClassificationType[ClassificationType["stringLiteral"] = 6] = "stringLiteral"; + ClassificationType[ClassificationType["regularExpressionLiteral"] = 7] = "regularExpressionLiteral"; + ClassificationType[ClassificationType["whiteSpace"] = 8] = "whiteSpace"; + ClassificationType[ClassificationType["text"] = 9] = "text"; + ClassificationType[ClassificationType["punctuation"] = 10] = "punctuation"; + ClassificationType[ClassificationType["className"] = 11] = "className"; + ClassificationType[ClassificationType["enumName"] = 12] = "enumName"; + ClassificationType[ClassificationType["interfaceName"] = 13] = "interfaceName"; + ClassificationType[ClassificationType["moduleName"] = 14] = "moduleName"; + ClassificationType[ClassificationType["typeParameterName"] = 15] = "typeParameterName"; + ClassificationType[ClassificationType["typeAliasName"] = 16] = "typeAliasName"; + ClassificationType[ClassificationType["parameterName"] = 17] = "parameterName"; + ClassificationType[ClassificationType["docCommentTagName"] = 18] = "docCommentTagName"; + ClassificationType[ClassificationType["jsxOpenTagName"] = 19] = "jsxOpenTagName"; + ClassificationType[ClassificationType["jsxCloseTagName"] = 20] = "jsxCloseTagName"; + ClassificationType[ClassificationType["jsxSelfClosingTagName"] = 21] = "jsxSelfClosingTagName"; + ClassificationType[ClassificationType["jsxAttribute"] = 22] = "jsxAttribute"; + ClassificationType[ClassificationType["jsxText"] = 23] = "jsxText"; + ClassificationType[ClassificationType["jsxAttributeStringLiteralValue"] = 24] = "jsxAttributeStringLiteralValue"; + })(ts.ClassificationType || (ts.ClassificationType = {})); + var ClassificationType = ts.ClassificationType; +})(ts || (ts = {})); +// These utilities are common to multiple language service features. +/* @internal */ +var ts; +(function (ts) { + ts.scanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ true); + ts.emptyArray = []; + (function (SemanticMeaning) { + SemanticMeaning[SemanticMeaning["None"] = 0] = "None"; + SemanticMeaning[SemanticMeaning["Value"] = 1] = "Value"; + SemanticMeaning[SemanticMeaning["Type"] = 2] = "Type"; + SemanticMeaning[SemanticMeaning["Namespace"] = 4] = "Namespace"; + SemanticMeaning[SemanticMeaning["All"] = 7] = "All"; + })(ts.SemanticMeaning || (ts.SemanticMeaning = {})); + var SemanticMeaning = ts.SemanticMeaning; + function getMeaningFromDeclaration(node) { + switch (node.kind) { + case 142 /* Parameter */: + case 218 /* VariableDeclaration */: + case 169 /* BindingElement */: + case 145 /* PropertyDeclaration */: + case 144 /* PropertySignature */: + case 253 /* PropertyAssignment */: + case 254 /* ShorthandPropertyAssignment */: + case 255 /* EnumMember */: + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + case 148 /* Constructor */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + case 180 /* ArrowFunction */: + case 252 /* CatchClause */: + return 1 /* Value */; + case 141 /* TypeParameter */: + case 222 /* InterfaceDeclaration */: + case 223 /* TypeAliasDeclaration */: + case 159 /* TypeLiteral */: + return 2 /* Type */; + case 221 /* ClassDeclaration */: + case 224 /* EnumDeclaration */: + return 1 /* Value */ | 2 /* Type */; + case 225 /* ModuleDeclaration */: + if (ts.isAmbientModule(node)) { + return 4 /* Namespace */ | 1 /* Value */; + } + else if (ts.getModuleInstanceState(node) === 1 /* Instantiated */) { + return 4 /* Namespace */ | 1 /* Value */; + } + else { + return 4 /* Namespace */; + } + case 233 /* NamedImports */: + case 234 /* ImportSpecifier */: + case 229 /* ImportEqualsDeclaration */: + case 230 /* ImportDeclaration */: + case 235 /* ExportAssignment */: + case 236 /* ExportDeclaration */: + return 1 /* Value */ | 2 /* Type */ | 4 /* Namespace */; + // An external module can be a Value + case 256 /* SourceFile */: + return 4 /* Namespace */ | 1 /* Value */; + } + return 1 /* Value */ | 2 /* Type */ | 4 /* Namespace */; + } + ts.getMeaningFromDeclaration = getMeaningFromDeclaration; + function getMeaningFromLocation(node) { + if (node.parent.kind === 235 /* ExportAssignment */) { + return 1 /* Value */ | 2 /* Type */ | 4 /* Namespace */; + } + else if (isInRightSideOfImport(node)) { + return getMeaningFromRightHandSideOfImportEquals(node); + } + else if (ts.isDeclarationName(node)) { + return getMeaningFromDeclaration(node.parent); + } + else if (isTypeReference(node)) { + return 2 /* Type */; + } + else if (isNamespaceReference(node)) { + return 4 /* Namespace */; + } + else { + return 1 /* Value */; + } + } + ts.getMeaningFromLocation = getMeaningFromLocation; + function getMeaningFromRightHandSideOfImportEquals(node) { + ts.Debug.assert(node.kind === 69 /* Identifier */); + // import a = |b|; // Namespace + // import a = |b.c|; // Value, type, namespace + // import a = |b.c|.d; // Namespace + if (node.parent.kind === 139 /* QualifiedName */ && + node.parent.right === node && + node.parent.parent.kind === 229 /* ImportEqualsDeclaration */) { + return 1 /* Value */ | 2 /* Type */ | 4 /* Namespace */; + } + return 4 /* Namespace */; + } + function isInRightSideOfImport(node) { + while (node.parent.kind === 139 /* QualifiedName */) { + node = node.parent; + } + return ts.isInternalModuleImportEqualsDeclaration(node.parent) && node.parent.moduleReference === node; + } + function isNamespaceReference(node) { + return isQualifiedNameNamespaceReference(node) || isPropertyAccessNamespaceReference(node); + } + function isQualifiedNameNamespaceReference(node) { + var root = node; + var isLastClause = true; + if (root.parent.kind === 139 /* QualifiedName */) { + while (root.parent && root.parent.kind === 139 /* QualifiedName */) { + root = root.parent; + } + isLastClause = root.right === node; + } + return root.parent.kind === 155 /* TypeReference */ && !isLastClause; + } + function isPropertyAccessNamespaceReference(node) { + var root = node; + var isLastClause = true; + if (root.parent.kind === 172 /* PropertyAccessExpression */) { + while (root.parent && root.parent.kind === 172 /* PropertyAccessExpression */) { + root = root.parent; + } + isLastClause = root.name === node; + } + if (!isLastClause && root.parent.kind === 194 /* ExpressionWithTypeArguments */ && root.parent.parent.kind === 251 /* HeritageClause */) { + var decl = root.parent.parent.parent; + return (decl.kind === 221 /* ClassDeclaration */ && root.parent.parent.token === 106 /* ImplementsKeyword */) || + (decl.kind === 222 /* InterfaceDeclaration */ && root.parent.parent.token === 83 /* ExtendsKeyword */); + } + return false; + } + function isTypeReference(node) { + if (ts.isRightSideOfQualifiedNameOrPropertyAccess(node)) { + node = node.parent; + } + return node.parent.kind === 155 /* TypeReference */ || + (node.parent.kind === 194 /* ExpressionWithTypeArguments */ && !ts.isExpressionWithTypeArgumentsInClassExtendsClause(node.parent)) || + (node.kind === 97 /* ThisKeyword */ && !ts.isPartOfExpression(node)) || + node.kind === 165 /* ThisType */; + } + function isCallExpressionTarget(node) { + return isCallOrNewExpressionTarget(node, 174 /* CallExpression */); + } + ts.isCallExpressionTarget = isCallExpressionTarget; + function isNewExpressionTarget(node) { + return isCallOrNewExpressionTarget(node, 175 /* NewExpression */); + } + ts.isNewExpressionTarget = isNewExpressionTarget; + function isCallOrNewExpressionTarget(node, kind) { + var target = climbPastPropertyAccess(node); + return target && target.parent && target.parent.kind === kind && target.parent.expression === target; + } + function climbPastPropertyAccess(node) { + return isRightSideOfPropertyAccess(node) ? node.parent : node; + } + ts.climbPastPropertyAccess = climbPastPropertyAccess; + function getTargetLabel(referenceNode, labelName) { + while (referenceNode) { + if (referenceNode.kind === 214 /* LabeledStatement */ && referenceNode.label.text === labelName) { + return referenceNode.label; + } + referenceNode = referenceNode.parent; + } + return undefined; + } + ts.getTargetLabel = getTargetLabel; + function isJumpStatementTarget(node) { + return node.kind === 69 /* Identifier */ && + (node.parent.kind === 210 /* BreakStatement */ || node.parent.kind === 209 /* ContinueStatement */) && + node.parent.label === node; + } + ts.isJumpStatementTarget = isJumpStatementTarget; + function isLabelOfLabeledStatement(node) { + return node.kind === 69 /* Identifier */ && + node.parent.kind === 214 /* LabeledStatement */ && + node.parent.label === node; + } + function isLabelName(node) { + return isLabelOfLabeledStatement(node) || isJumpStatementTarget(node); + } + ts.isLabelName = isLabelName; + function isRightSideOfQualifiedName(node) { + return node.parent.kind === 139 /* QualifiedName */ && node.parent.right === node; + } + ts.isRightSideOfQualifiedName = isRightSideOfQualifiedName; + function isRightSideOfPropertyAccess(node) { + return node && node.parent && node.parent.kind === 172 /* PropertyAccessExpression */ && node.parent.name === node; + } + ts.isRightSideOfPropertyAccess = isRightSideOfPropertyAccess; + function isNameOfModuleDeclaration(node) { + return node.parent.kind === 225 /* ModuleDeclaration */ && node.parent.name === node; + } + ts.isNameOfModuleDeclaration = isNameOfModuleDeclaration; + function isNameOfFunctionDeclaration(node) { + return node.kind === 69 /* Identifier */ && + ts.isFunctionLike(node.parent) && node.parent.name === node; + } + ts.isNameOfFunctionDeclaration = isNameOfFunctionDeclaration; + function isLiteralNameOfPropertyDeclarationOrIndexAccess(node) { + if (node.kind === 9 /* StringLiteral */ || node.kind === 8 /* NumericLiteral */) { + switch (node.parent.kind) { + case 145 /* PropertyDeclaration */: + case 144 /* PropertySignature */: + case 253 /* PropertyAssignment */: + case 255 /* EnumMember */: + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 225 /* ModuleDeclaration */: + return node.parent.name === node; + case 173 /* ElementAccessExpression */: + return node.parent.argumentExpression === node; + case 140 /* ComputedPropertyName */: + return true; + } + } + return false; + } + ts.isLiteralNameOfPropertyDeclarationOrIndexAccess = isLiteralNameOfPropertyDeclarationOrIndexAccess; + function isExpressionOfExternalModuleImportEqualsDeclaration(node) { + return ts.isExternalModuleImportEqualsDeclaration(node.parent.parent) && + ts.getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node; + } + ts.isExpressionOfExternalModuleImportEqualsDeclaration = isExpressionOfExternalModuleImportEqualsDeclaration; + /** Returns true if the position is within a comment */ + function isInsideComment(sourceFile, token, position) { + // The position has to be: 1. in the leading trivia (before token.getStart()), and 2. within a comment + return position <= token.getStart(sourceFile) && + (isInsideCommentRange(ts.getTrailingCommentRanges(sourceFile.text, token.getFullStart())) || + isInsideCommentRange(ts.getLeadingCommentRanges(sourceFile.text, token.getFullStart()))); + function isInsideCommentRange(comments) { + return ts.forEach(comments, function (comment) { + // either we are 1. completely inside the comment, or 2. at the end of the comment + if (comment.pos < position && position < comment.end) { + return true; + } + else if (position === comment.end) { + var text = sourceFile.text; + var width = comment.end - comment.pos; + // is single line comment or just /* + if (width <= 2 || text.charCodeAt(comment.pos + 1) === 47 /* slash */) { + return true; + } + else { + // is unterminated multi-line comment + return !(text.charCodeAt(comment.end - 1) === 47 /* slash */ && + text.charCodeAt(comment.end - 2) === 42 /* asterisk */); + } + } + return false; + }); + } + } + ts.isInsideComment = isInsideComment; + function getContainerNode(node) { + while (true) { + node = node.parent; + if (!node) { + return undefined; + } + switch (node.kind) { + case 256 /* SourceFile */: + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 221 /* ClassDeclaration */: + case 222 /* InterfaceDeclaration */: + case 224 /* EnumDeclaration */: + case 225 /* ModuleDeclaration */: + return node; + } + } + } + ts.getContainerNode = getContainerNode; + function getNodeKind(node) { + switch (node.kind) { + case 256 /* SourceFile */: + return ts.isExternalModule(node) ? ts.ScriptElementKind.moduleElement : ts.ScriptElementKind.scriptElement; + case 225 /* ModuleDeclaration */: + return ts.ScriptElementKind.moduleElement; + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + return ts.ScriptElementKind.classElement; + case 222 /* InterfaceDeclaration */: return ts.ScriptElementKind.interfaceElement; + case 223 /* TypeAliasDeclaration */: return ts.ScriptElementKind.typeElement; + case 224 /* EnumDeclaration */: return ts.ScriptElementKind.enumElement; + case 218 /* VariableDeclaration */: + return getKindOfVariableDeclaration(node); + case 169 /* BindingElement */: + return getKindOfVariableDeclaration(ts.getRootDeclaration(node)); + case 180 /* ArrowFunction */: + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + return ts.ScriptElementKind.functionElement; + case 149 /* GetAccessor */: return ts.ScriptElementKind.memberGetAccessorElement; + case 150 /* SetAccessor */: return ts.ScriptElementKind.memberSetAccessorElement; + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + return ts.ScriptElementKind.memberFunctionElement; + case 145 /* PropertyDeclaration */: + case 144 /* PropertySignature */: + return ts.ScriptElementKind.memberVariableElement; + case 153 /* IndexSignature */: return ts.ScriptElementKind.indexSignatureElement; + case 152 /* ConstructSignature */: return ts.ScriptElementKind.constructSignatureElement; + case 151 /* CallSignature */: return ts.ScriptElementKind.callSignatureElement; + case 148 /* Constructor */: return ts.ScriptElementKind.constructorImplementationElement; + case 141 /* TypeParameter */: return ts.ScriptElementKind.typeParameterElement; + case 255 /* EnumMember */: return ts.ScriptElementKind.enumMemberElement; + case 142 /* Parameter */: return ts.hasModifier(node, 92 /* ParameterPropertyModifier */) ? ts.ScriptElementKind.memberVariableElement : ts.ScriptElementKind.parameterElement; + case 229 /* ImportEqualsDeclaration */: + case 234 /* ImportSpecifier */: + case 231 /* ImportClause */: + case 238 /* ExportSpecifier */: + case 232 /* NamespaceImport */: + return ts.ScriptElementKind.alias; + case 279 /* JSDocTypedefTag */: + return ts.ScriptElementKind.typeElement; + default: + return ts.ScriptElementKind.unknown; + } + function getKindOfVariableDeclaration(v) { + return ts.isConst(v) + ? ts.ScriptElementKind.constElement + : ts.isLet(v) + ? ts.ScriptElementKind.letElement + : ts.ScriptElementKind.variableElement; + } + } + ts.getNodeKind = getNodeKind; + function getStringLiteralTypeForNode(node, typeChecker) { + var searchNode = node.parent.kind === 166 /* LiteralType */ ? node.parent : node; + var type = typeChecker.getTypeAtLocation(searchNode); + if (type && type.flags & 32 /* StringLiteral */) { + return type; + } + return undefined; + } + ts.getStringLiteralTypeForNode = getStringLiteralTypeForNode; + function isThis(node) { + switch (node.kind) { + case 97 /* ThisKeyword */: + // case SyntaxKind.ThisType: TODO: GH#9267 + return true; + case 69 /* Identifier */: + // 'this' as a parameter + return node.originalKeywordKind === 97 /* ThisKeyword */ && node.parent.kind === 142 /* Parameter */; + default: + return false; + } + } + ts.isThis = isThis; + // Matches the beginning of a triple slash directive + var tripleSlashDirectivePrefixRegex = /^\/\/\/\s*= node.end) { + return c; + } + }); + // Either we didn't find an appropriate list, or the list must contain us. + ts.Debug.assert(!syntaxList || ts.contains(syntaxList.getChildren(), node)); + return syntaxList; + } + ts.findContainingList = findContainingList; + /* Gets the token whose text has range [start, end) and + * position >= start and (position < end or (position === end && token is keyword or identifier)) + */ + function getTouchingWord(sourceFile, position, includeJsDocComment) { + if (includeJsDocComment === void 0) { includeJsDocComment = false; } + return getTouchingToken(sourceFile, position, function (n) { return isWord(n.kind); }, includeJsDocComment); + } + ts.getTouchingWord = getTouchingWord; + /* Gets the token whose text has range [start, end) and position >= start + * and (position < end or (position === end && token is keyword or identifier or numeric/string literal)) + */ + function getTouchingPropertyName(sourceFile, position, includeJsDocComment) { + if (includeJsDocComment === void 0) { includeJsDocComment = false; } + return getTouchingToken(sourceFile, position, function (n) { return isPropertyName(n.kind); }, includeJsDocComment); + } + ts.getTouchingPropertyName = getTouchingPropertyName; + /** Returns the token if position is in [start, end) or if position === end and includeItemAtEndPosition(token) === true */ + function getTouchingToken(sourceFile, position, includeItemAtEndPosition, includeJsDocComment) { + if (includeJsDocComment === void 0) { includeJsDocComment = false; } + return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ false, includeItemAtEndPosition, includeJsDocComment); + } + ts.getTouchingToken = getTouchingToken; + /** Returns a token if position is in [start-of-leading-trivia, end) */ + function getTokenAtPosition(sourceFile, position, includeJsDocComment) { + if (includeJsDocComment === void 0) { includeJsDocComment = false; } + return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ true, /*includeItemAtEndPosition*/ undefined, includeJsDocComment); + } + ts.getTokenAtPosition = getTokenAtPosition; + /** Get the token whose text contains the position */ + function getTokenAtPositionWorker(sourceFile, position, allowPositionInLeadingTrivia, includeItemAtEndPosition, includeJsDocComment) { + if (includeJsDocComment === void 0) { includeJsDocComment = false; } + var current = sourceFile; + outer: while (true) { + if (isToken(current)) { + // exit early + return current; + } + if (includeJsDocComment) { + var jsDocChildren = ts.filter(current.getChildren(), ts.isJSDocNode); + for (var _i = 0, jsDocChildren_1 = jsDocChildren; _i < jsDocChildren_1.length; _i++) { + var jsDocChild = jsDocChildren_1[_i]; + var start = allowPositionInLeadingTrivia ? jsDocChild.getFullStart() : jsDocChild.getStart(sourceFile, includeJsDocComment); + if (start <= position) { + var end = jsDocChild.getEnd(); + if (position < end || (position === end && jsDocChild.kind === 1 /* EndOfFileToken */)) { + current = jsDocChild; + continue outer; + } + else if (includeItemAtEndPosition && end === position) { + var previousToken = findPrecedingToken(position, sourceFile, jsDocChild); + if (previousToken && includeItemAtEndPosition(previousToken)) { + return previousToken; + } + } + } + } + } + // find the child that contains 'position' + for (var i = 0, n = current.getChildCount(sourceFile); i < n; i++) { + var child = current.getChildAt(i); + // all jsDocComment nodes were already visited + if (ts.isJSDocNode(child)) { + continue; + } + var start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile, includeJsDocComment); + if (start <= position) { + var end = child.getEnd(); + if (position < end || (position === end && child.kind === 1 /* EndOfFileToken */)) { + current = child; + continue outer; + } + else if (includeItemAtEndPosition && end === position) { + var previousToken = findPrecedingToken(position, sourceFile, child); + if (previousToken && includeItemAtEndPosition(previousToken)) { + return previousToken; + } + } + } + } + return current; + } + } + /** + * The token on the left of the position is the token that strictly includes the position + * or sits to the left of the cursor if it is on a boundary. For example + * + * fo|o -> will return foo + * foo |bar -> will return foo + * + */ + function findTokenOnLeftOfPosition(file, position) { + // Ideally, getTokenAtPosition should return a token. However, it is currently + // broken, so we do a check to make sure the result was indeed a token. + var tokenAtPosition = getTokenAtPosition(file, position); + if (isToken(tokenAtPosition) && position > tokenAtPosition.getStart(file) && position < tokenAtPosition.getEnd()) { + return tokenAtPosition; + } + return findPrecedingToken(position, file); + } + ts.findTokenOnLeftOfPosition = findTokenOnLeftOfPosition; + function findNextToken(previousToken, parent) { + return find(parent); + function find(n) { + if (isToken(n) && n.pos === previousToken.end) { + // this is token that starts at the end of previous token - return it + return n; + } + var children = n.getChildren(); + for (var _i = 0, children_2 = children; _i < children_2.length; _i++) { + var child = children_2[_i]; + var shouldDiveInChildNode = + // previous token is enclosed somewhere in the child + (child.pos <= previousToken.pos && child.end > previousToken.end) || + // previous token ends exactly at the beginning of child + (child.pos === previousToken.end); + if (shouldDiveInChildNode && nodeHasTokens(child)) { + return find(child); + } + } + return undefined; + } + } + ts.findNextToken = findNextToken; + function findPrecedingToken(position, sourceFile, startNode) { + return find(startNode || sourceFile); + function findRightmostToken(n) { + if (isToken(n) || n.kind === 244 /* JsxText */) { + return n; + } + var children = n.getChildren(); + var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length); + return candidate && findRightmostToken(candidate); + } + function find(n) { + if (isToken(n) || n.kind === 244 /* JsxText */) { + return n; + } + var children = n.getChildren(); + for (var i = 0, len = children.length; i < len; i++) { + var child = children[i]; + // condition 'position < child.end' checks if child node end after the position + // in the example below this condition will be false for 'aaaa' and 'bbbb' and true for 'ccc' + // aaaa___bbbb___$__ccc + // after we found child node with end after the position we check if start of the node is after the position. + // if yes - then position is in the trivia and we need to look into the previous child to find the token in question. + // if no - position is in the node itself so we should recurse in it. + // NOTE: JsxText is a weird kind of node that can contain only whitespaces (since they are not counted as trivia). + // if this is the case - then we should assume that token in question is located in previous child. + if (position < child.end && (nodeHasTokens(child) || child.kind === 244 /* JsxText */)) { + var start = child.getStart(sourceFile); + var lookInPreviousChild = (start >= position) || + (child.kind === 244 /* JsxText */ && start === child.end); // whitespace only JsxText + if (lookInPreviousChild) { + // actual start of the node is past the position - previous token should be at the end of previous child + var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ i); + return candidate && findRightmostToken(candidate); + } + else { + // candidate should be in this node + return find(child); + } + } + } + ts.Debug.assert(startNode !== undefined || n.kind === 256 /* SourceFile */); + // Here we know that none of child token nodes embrace the position, + // the only known case is when position is at the end of the file. + // Try to find the rightmost token in the file without filtering. + // Namely we are skipping the check: 'position < node.end' + if (children.length) { + var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length); + return candidate && findRightmostToken(candidate); + } + } + /// finds last node that is considered as candidate for search (isCandidate(node) === true) starting from 'exclusiveStartPosition' + function findRightmostChildNodeWithTokens(children, exclusiveStartPosition) { + for (var i = exclusiveStartPosition - 1; i >= 0; i--) { + if (nodeHasTokens(children[i])) { + return children[i]; + } + } + } + } + ts.findPrecedingToken = findPrecedingToken; + function isInString(sourceFile, position) { + var previousToken = findPrecedingToken(position, sourceFile); + if (previousToken && previousToken.kind === 9 /* StringLiteral */) { + var start = previousToken.getStart(); + var end = previousToken.getEnd(); + // To be "in" one of these literals, the position has to be: + // 1. entirely within the token text. + // 2. at the end position of an unterminated token. + // 3. at the end of a regular expression (due to trailing flags like '/foo/g'). + if (start < position && position < end) { + return true; + } + if (position === end) { + return !!previousToken.isUnterminated; + } + } + return false; + } + ts.isInString = isInString; + function isInComment(sourceFile, position) { + return isInCommentHelper(sourceFile, position, /*predicate*/ undefined); + } + ts.isInComment = isInComment; + /** + * returns true if the position is in between the open and close elements of an JSX expression. + */ + function isInsideJsxElementOrAttribute(sourceFile, position) { + var token = getTokenAtPosition(sourceFile, position); + if (!token) { + return false; + } + if (token.kind === 244 /* JsxText */) { + return true; + } + //
Hello |
+ if (token.kind === 25 /* LessThanToken */ && token.parent.kind === 244 /* JsxText */) { + return true; + } + //
{ |
or
+ if (token.kind === 25 /* LessThanToken */ && token.parent.kind === 248 /* JsxExpression */) { + return true; + } + //
{ + // | + // } < /div> + if (token && token.kind === 16 /* CloseBraceToken */ && token.parent.kind === 248 /* JsxExpression */) { + return true; + } + //
|
+ if (token.kind === 25 /* LessThanToken */ && token.parent.kind === 245 /* JsxClosingElement */) { + return true; + } + return false; + } + ts.isInsideJsxElementOrAttribute = isInsideJsxElementOrAttribute; + function isInTemplateString(sourceFile, position) { + var token = getTokenAtPosition(sourceFile, position); + return ts.isTemplateLiteralKind(token.kind) && position > token.getStart(sourceFile); + } + ts.isInTemplateString = isInTemplateString; + /** + * Returns true if the cursor at position in sourceFile is within a comment that additionally + * satisfies predicate, and false otherwise. + */ + function isInCommentHelper(sourceFile, position, predicate) { + var token = getTokenAtPosition(sourceFile, position); + if (token && position <= token.getStart(sourceFile)) { + var commentRanges = ts.getLeadingCommentRanges(sourceFile.text, token.pos); + // The end marker of a single-line comment does not include the newline character. + // In the following case, we are inside a comment (^ denotes the cursor position): + // + // // asdf ^\n + // + // But for multi-line comments, we don't want to be inside the comment in the following case: + // + // /* asdf */^ + // + // Internally, we represent the end of the comment at the newline and closing '/', respectively. + return predicate ? + ts.forEach(commentRanges, function (c) { return c.pos < position && + (c.kind == 2 /* SingleLineCommentTrivia */ ? position <= c.end : position < c.end) && + predicate(c); }) : + ts.forEach(commentRanges, function (c) { return c.pos < position && + (c.kind == 2 /* SingleLineCommentTrivia */ ? position <= c.end : position < c.end); }); + } + return false; + } + ts.isInCommentHelper = isInCommentHelper; + function hasDocComment(sourceFile, position) { + var token = getTokenAtPosition(sourceFile, position); + // First, we have to see if this position actually landed in a comment. + var commentRanges = ts.getLeadingCommentRanges(sourceFile.text, token.pos); + return ts.forEach(commentRanges, jsDocPrefix); + function jsDocPrefix(c) { + var text = sourceFile.text; + return text.length >= c.pos + 3 && text[c.pos] === "/" && text[c.pos + 1] === "*" && text[c.pos + 2] === "*"; + } + } + ts.hasDocComment = hasDocComment; + /** + * Get the corresponding JSDocTag node if the position is in a jsDoc comment + */ + function getJsDocTagAtPosition(sourceFile, position) { + var node = ts.getTokenAtPosition(sourceFile, position); + if (isToken(node)) { + switch (node.kind) { + case 102 /* VarKeyword */: + case 108 /* LetKeyword */: + case 74 /* ConstKeyword */: + // if the current token is var, let or const, skip the VariableDeclarationList + node = node.parent === undefined ? undefined : node.parent.parent; + break; + default: + node = node.parent; + break; + } + } + if (node) { + if (node.jsDocComments) { + for (var _i = 0, _a = node.jsDocComments; _i < _a.length; _i++) { + var jsDocComment = _a[_i]; + if (jsDocComment.tags) { + for (var _b = 0, _c = jsDocComment.tags; _b < _c.length; _b++) { + var tag = _c[_b]; + if (tag.pos <= position && position <= tag.end) { + return tag; + } + } + } + } + } + } + return undefined; + } + ts.getJsDocTagAtPosition = getJsDocTagAtPosition; + function nodeHasTokens(n) { + // If we have a token or node that has a non-zero width, it must have tokens. + // Note, that getWidth() does not take trivia into account. + return n.getWidth() !== 0; + } + function getNodeModifiers(node) { + var flags = ts.getCombinedModifierFlags(node); + var result = []; + if (flags & 8 /* Private */) + result.push(ts.ScriptElementKindModifier.privateMemberModifier); + if (flags & 16 /* Protected */) + result.push(ts.ScriptElementKindModifier.protectedMemberModifier); + if (flags & 4 /* Public */) + result.push(ts.ScriptElementKindModifier.publicMemberModifier); + if (flags & 32 /* Static */) + result.push(ts.ScriptElementKindModifier.staticModifier); + if (flags & 128 /* Abstract */) + result.push(ts.ScriptElementKindModifier.abstractModifier); + if (flags & 1 /* Export */) + result.push(ts.ScriptElementKindModifier.exportedModifier); + if (ts.isInAmbientContext(node)) + result.push(ts.ScriptElementKindModifier.ambientModifier); + return result.length > 0 ? result.join(",") : ts.ScriptElementKindModifier.none; + } + ts.getNodeModifiers = getNodeModifiers; + function getTypeArgumentOrTypeParameterList(node) { + if (node.kind === 155 /* TypeReference */ || node.kind === 174 /* CallExpression */) { + return node.typeArguments; + } + if (ts.isFunctionLike(node) || node.kind === 221 /* ClassDeclaration */ || node.kind === 222 /* InterfaceDeclaration */) { + return node.typeParameters; + } + return undefined; + } + ts.getTypeArgumentOrTypeParameterList = getTypeArgumentOrTypeParameterList; + function isToken(n) { + return n.kind >= 0 /* FirstToken */ && n.kind <= 138 /* LastToken */; + } + ts.isToken = isToken; + function isWord(kind) { + return kind === 69 /* Identifier */ || ts.isKeyword(kind); + } + ts.isWord = isWord; + function isPropertyName(kind) { + return kind === 9 /* StringLiteral */ || kind === 8 /* NumericLiteral */ || isWord(kind); + } + function isComment(kind) { + return kind === 2 /* SingleLineCommentTrivia */ || kind === 3 /* MultiLineCommentTrivia */; + } + ts.isComment = isComment; + function isStringOrRegularExpressionOrTemplateLiteral(kind) { + if (kind === 9 /* StringLiteral */ + || kind === 10 /* RegularExpressionLiteral */ + || ts.isTemplateLiteralKind(kind)) { + return true; + } + return false; + } + ts.isStringOrRegularExpressionOrTemplateLiteral = isStringOrRegularExpressionOrTemplateLiteral; + function isPunctuation(kind) { + return 15 /* FirstPunctuation */ <= kind && kind <= 68 /* LastPunctuation */; + } + ts.isPunctuation = isPunctuation; + function isInsideTemplateLiteral(node, position) { + return ts.isTemplateLiteralKind(node.kind) + && (node.getStart() < position && position < node.getEnd()) || (!!node.isUnterminated && position === node.getEnd()); + } + ts.isInsideTemplateLiteral = isInsideTemplateLiteral; + function isAccessibilityModifier(kind) { + switch (kind) { + case 112 /* PublicKeyword */: + case 110 /* PrivateKeyword */: + case 111 /* ProtectedKeyword */: + return true; + } + return false; + } + ts.isAccessibilityModifier = isAccessibilityModifier; + function compareDataObjects(dst, src) { + for (var e in dst) { + if (typeof dst[e] === "object") { + if (!compareDataObjects(dst[e], src[e])) { + return false; + } + } + else if (typeof dst[e] !== "function") { + if (dst[e] !== src[e]) { + return false; } - return isCompletedNode(n.statement, sourceFile); - case 158 /* TypeQuery */: - return isCompletedNode(n.exprName, sourceFile); - case 182 /* TypeOfExpression */: - case 181 /* DeleteExpression */: - case 183 /* VoidExpression */: - case 190 /* YieldExpression */: - case 191 /* SpreadElementExpression */: - var unaryWordExpression = n; - return isCompletedNode(unaryWordExpression.expression, sourceFile); - case 176 /* TaggedTemplateExpression */: - return isCompletedNode(n.template, sourceFile); - case 189 /* TemplateExpression */: - var lastSpan = ts.lastOrUndefined(n.templateSpans); - return isCompletedNode(lastSpan, sourceFile); - case 197 /* TemplateSpan */: - return ts.nodeIsPresent(n.literal); - case 236 /* ExportDeclaration */: - case 230 /* ImportDeclaration */: - return ts.nodeIsPresent(n.moduleSpecifier); - case 185 /* PrefixUnaryExpression */: - return isCompletedNode(n.operand, sourceFile); - case 187 /* BinaryExpression */: - return isCompletedNode(n.right, sourceFile); - case 188 /* ConditionalExpression */: - return isCompletedNode(n.whenFalse, sourceFile); - default: - return true; + } } + return true; } - ts.isCompletedNode = isCompletedNode; - /* - * Checks if node ends with 'expectedLastToken'. - * If child at position 'length - 1' is 'SemicolonToken' it is skipped and 'expectedLastToken' is compared with child at position 'length - 2'. - */ - function nodeEndsWith(n, expectedLastToken, sourceFile) { - var children = n.getChildren(sourceFile); - if (children.length) { - var last = ts.lastOrUndefined(children); - if (last.kind === expectedLastToken) { + ts.compareDataObjects = compareDataObjects; + function isArrayLiteralOrObjectLiteralDestructuringPattern(node) { + if (node.kind === 170 /* ArrayLiteralExpression */ || + node.kind === 171 /* ObjectLiteralExpression */) { + // [a,b,c] from: + // [a, b, c] = someExpression; + if (node.parent.kind === 187 /* BinaryExpression */ && + node.parent.left === node && + node.parent.operatorToken.kind === 56 /* EqualsToken */) { return true; } - else if (last.kind === 23 /* SemicolonToken */ && children.length !== 1) { - return children[children.length - 2].kind === expectedLastToken; + // [a, b, c] from: + // for([a, b, c] of expression) + if (node.parent.kind === 208 /* ForOfStatement */ && + node.parent.initializer === node) { + return true; + } + // [a, b, c] of + // [x, [a, b, c] ] = someExpression + // or + // {x, a: {a, b, c} } = someExpression + if (isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent.kind === 253 /* PropertyAssignment */ ? node.parent.parent : node.parent)) { + return true; } } return false; } - function findListItemInfo(node) { - var list = findContainingList(node); - // It is possible at this point for syntaxList to be undefined, either if - // node.parent had no list child, or if none of its list children contained - // the span of node. If this happens, return undefined. The caller should - // handle this case. - if (!list) { - return undefined; + ts.isArrayLiteralOrObjectLiteralDestructuringPattern = isArrayLiteralOrObjectLiteralDestructuringPattern; + function hasTrailingDirectorySeparator(path) { + var lastCharacter = path.charAt(path.length - 1); + return lastCharacter === "/" || lastCharacter === "\\"; + } + ts.hasTrailingDirectorySeparator = hasTrailingDirectorySeparator; + function isInReferenceComment(sourceFile, position) { + return isInCommentHelper(sourceFile, position, isReferenceComment); + function isReferenceComment(c) { + var commentText = sourceFile.text.substring(c.pos, c.end); + return tripleSlashDirectivePrefixRegex.test(commentText); } - var children = list.getChildren(); - var listItemIndex = ts.indexOf(children, node); + } + ts.isInReferenceComment = isInReferenceComment; + function isInNonReferenceComment(sourceFile, position) { + return isInCommentHelper(sourceFile, position, isNonReferenceComment); + function isNonReferenceComment(c) { + var commentText = sourceFile.text.substring(c.pos, c.end); + return !tripleSlashDirectivePrefixRegex.test(commentText); + } + } + ts.isInNonReferenceComment = isInNonReferenceComment; +})(ts || (ts = {})); +// Display-part writer helpers +/* @internal */ +var ts; +(function (ts) { + function isFirstDeclarationOfSymbolParameter(symbol) { + return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === 142 /* Parameter */; + } + ts.isFirstDeclarationOfSymbolParameter = isFirstDeclarationOfSymbolParameter; + var displayPartWriter = getDisplayPartWriter(); + function getDisplayPartWriter() { + var displayParts; + var lineStart; + var indent; + resetWriter(); return { - listItemIndex: listItemIndex, - list: list + displayParts: function () { return displayParts; }, + writeKeyword: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.keyword); }, + writeOperator: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.operator); }, + writePunctuation: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.punctuation); }, + writeSpace: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.space); }, + writeStringLiteral: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.stringLiteral); }, + writeParameter: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.parameterName); }, + writeSymbol: writeSymbol, + writeLine: writeLine, + increaseIndent: function () { indent++; }, + decreaseIndent: function () { indent--; }, + clear: resetWriter, + trackSymbol: function () { }, + reportInaccessibleThisError: function () { } }; + function writeIndent() { + if (lineStart) { + var indentString = ts.getIndentString(indent); + if (indentString) { + displayParts.push(displayPart(indentString, ts.SymbolDisplayPartKind.space)); + } + lineStart = false; + } + } + function writeKind(text, kind) { + writeIndent(); + displayParts.push(displayPart(text, kind)); + } + function writeSymbol(text, symbol) { + writeIndent(); + displayParts.push(symbolPart(text, symbol)); + } + function writeLine() { + displayParts.push(lineBreakPart()); + lineStart = true; + } + function resetWriter() { + displayParts = []; + lineStart = true; + indent = 0; + } } - ts.findListItemInfo = findListItemInfo; - function hasChildOfKind(n, kind, sourceFile) { - return !!findChildOfKind(n, kind, sourceFile); + function symbolPart(text, symbol) { + return displayPart(text, displayPartKind(symbol), symbol); + function displayPartKind(symbol) { + var flags = symbol.flags; + if (flags & 3 /* Variable */) { + return isFirstDeclarationOfSymbolParameter(symbol) ? ts.SymbolDisplayPartKind.parameterName : ts.SymbolDisplayPartKind.localName; + } + else if (flags & 4 /* Property */) { + return ts.SymbolDisplayPartKind.propertyName; + } + else if (flags & 32768 /* GetAccessor */) { + return ts.SymbolDisplayPartKind.propertyName; + } + else if (flags & 65536 /* SetAccessor */) { + return ts.SymbolDisplayPartKind.propertyName; + } + else if (flags & 8 /* EnumMember */) { + return ts.SymbolDisplayPartKind.enumMemberName; + } + else if (flags & 16 /* Function */) { + return ts.SymbolDisplayPartKind.functionName; + } + else if (flags & 32 /* Class */) { + return ts.SymbolDisplayPartKind.className; + } + else if (flags & 64 /* Interface */) { + return ts.SymbolDisplayPartKind.interfaceName; + } + else if (flags & 384 /* Enum */) { + return ts.SymbolDisplayPartKind.enumName; + } + else if (flags & 1536 /* Module */) { + return ts.SymbolDisplayPartKind.moduleName; + } + else if (flags & 8192 /* Method */) { + return ts.SymbolDisplayPartKind.methodName; + } + else if (flags & 262144 /* TypeParameter */) { + return ts.SymbolDisplayPartKind.typeParameterName; + } + else if (flags & 524288 /* TypeAlias */) { + return ts.SymbolDisplayPartKind.aliasName; + } + else if (flags & 8388608 /* Alias */) { + return ts.SymbolDisplayPartKind.aliasName; + } + return ts.SymbolDisplayPartKind.text; + } } - ts.hasChildOfKind = hasChildOfKind; - function findChildOfKind(n, kind, sourceFile) { - return ts.forEach(n.getChildren(sourceFile), function (c) { return c.kind === kind && c; }); + ts.symbolPart = symbolPart; + function displayPart(text, kind, symbol) { + return { + text: text, + kind: ts.SymbolDisplayPartKind[kind] + }; } - ts.findChildOfKind = findChildOfKind; - function findContainingList(node) { - // The node might be a list element (nonsynthetic) or a comma (synthetic). Either way, it will - // be parented by the container of the SyntaxList, not the SyntaxList itself. - // In order to find the list item index, we first need to locate SyntaxList itself and then search - // for the position of the relevant node (or comma). - var syntaxList = ts.forEach(node.parent.getChildren(), function (c) { - // find syntax list that covers the span of the node - if (c.kind === 286 /* SyntaxList */ && c.pos <= node.pos && c.end >= node.end) { - return c; - } - }); - // Either we didn't find an appropriate list, or the list must contain us. - ts.Debug.assert(!syntaxList || ts.contains(syntaxList.getChildren(), node)); - return syntaxList; + ts.displayPart = displayPart; + function spacePart() { + return displayPart(" ", ts.SymbolDisplayPartKind.space); } - ts.findContainingList = findContainingList; - /* Gets the token whose text has range [start, end) and - * position >= start and (position < end or (position === end && token is keyword or identifier)) + ts.spacePart = spacePart; + function keywordPart(kind) { + return displayPart(ts.tokenToString(kind), ts.SymbolDisplayPartKind.keyword); + } + ts.keywordPart = keywordPart; + function punctuationPart(kind) { + return displayPart(ts.tokenToString(kind), ts.SymbolDisplayPartKind.punctuation); + } + ts.punctuationPart = punctuationPart; + function operatorPart(kind) { + return displayPart(ts.tokenToString(kind), ts.SymbolDisplayPartKind.operator); + } + ts.operatorPart = operatorPart; + function textOrKeywordPart(text) { + var kind = ts.stringToToken(text); + return kind === undefined + ? textPart(text) + : keywordPart(kind); + } + ts.textOrKeywordPart = textOrKeywordPart; + function textPart(text) { + return displayPart(text, ts.SymbolDisplayPartKind.text); + } + ts.textPart = textPart; + var carriageReturnLineFeed = "\r\n"; + /** + * The default is CRLF. */ - function getTouchingWord(sourceFile, position, includeJsDocComment) { - if (includeJsDocComment === void 0) { includeJsDocComment = false; } - return getTouchingToken(sourceFile, position, function (n) { return isWord(n.kind); }, includeJsDocComment); + function getNewLineOrDefaultFromHost(host) { + return host.getNewLine ? host.getNewLine() : carriageReturnLineFeed; } - ts.getTouchingWord = getTouchingWord; - /* Gets the token whose text has range [start, end) and position >= start - * and (position < end or (position === end && token is keyword or identifier or numeric/string literal)) + ts.getNewLineOrDefaultFromHost = getNewLineOrDefaultFromHost; + function lineBreakPart() { + return displayPart("\n", ts.SymbolDisplayPartKind.lineBreak); + } + ts.lineBreakPart = lineBreakPart; + function mapToDisplayParts(writeDisplayParts) { + writeDisplayParts(displayPartWriter); + var result = displayPartWriter.displayParts(); + displayPartWriter.clear(); + return result; + } + ts.mapToDisplayParts = mapToDisplayParts; + function typeToDisplayParts(typechecker, type, enclosingDeclaration, flags) { + return mapToDisplayParts(function (writer) { + typechecker.getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags); + }); + } + ts.typeToDisplayParts = typeToDisplayParts; + function symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration, meaning, flags) { + return mapToDisplayParts(function (writer) { + typeChecker.getSymbolDisplayBuilder().buildSymbolDisplay(symbol, writer, enclosingDeclaration, meaning, flags); + }); + } + ts.symbolToDisplayParts = symbolToDisplayParts; + function signatureToDisplayParts(typechecker, signature, enclosingDeclaration, flags) { + return mapToDisplayParts(function (writer) { + typechecker.getSymbolDisplayBuilder().buildSignatureDisplay(signature, writer, enclosingDeclaration, flags); + }); + } + ts.signatureToDisplayParts = signatureToDisplayParts; + function getDeclaredName(typeChecker, symbol, location) { + // If this is an export or import specifier it could have been renamed using the 'as' syntax. + // If so we want to search for whatever is under the cursor. + if (isImportOrExportSpecifierName(location)) { + return location.getText(); + } + else if (ts.isStringOrNumericLiteral(location.kind) && + location.parent.kind === 140 /* ComputedPropertyName */) { + return location.text; + } + // Try to get the local symbol if we're dealing with an 'export default' + // since that symbol has the "true" name. + var localExportDefaultSymbol = ts.getLocalSymbolForExportDefault(symbol); + var name = typeChecker.symbolToString(localExportDefaultSymbol || symbol); + return name; + } + ts.getDeclaredName = getDeclaredName; + function isImportOrExportSpecifierName(location) { + return location.parent && + (location.parent.kind === 234 /* ImportSpecifier */ || location.parent.kind === 238 /* ExportSpecifier */) && + location.parent.propertyName === location; + } + ts.isImportOrExportSpecifierName = isImportOrExportSpecifierName; + /** + * Strip off existed single quotes or double quotes from a given string + * + * @return non-quoted string */ - function getTouchingPropertyName(sourceFile, position, includeJsDocComment) { - if (includeJsDocComment === void 0) { includeJsDocComment = false; } - return getTouchingToken(sourceFile, position, function (n) { return isPropertyName(n.kind); }, includeJsDocComment); + function stripQuotes(name) { + var length = name.length; + if (length >= 2 && + name.charCodeAt(0) === name.charCodeAt(length - 1) && + (name.charCodeAt(0) === 34 /* doubleQuote */ || name.charCodeAt(0) === 39 /* singleQuote */)) { + return name.substring(1, length - 1); + } + ; + return name; } - ts.getTouchingPropertyName = getTouchingPropertyName; - /** Returns the token if position is in [start, end) or if position === end and includeItemAtEndPosition(token) === true */ - function getTouchingToken(sourceFile, position, includeItemAtEndPosition, includeJsDocComment) { - if (includeJsDocComment === void 0) { includeJsDocComment = false; } - return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ false, includeItemAtEndPosition, includeJsDocComment); + ts.stripQuotes = stripQuotes; + function scriptKindIs(fileName, host) { + var scriptKinds = []; + for (var _i = 2; _i < arguments.length; _i++) { + scriptKinds[_i - 2] = arguments[_i]; + } + var scriptKind = getScriptKind(fileName, host); + return ts.forEach(scriptKinds, function (k) { return k === scriptKind; }); } - ts.getTouchingToken = getTouchingToken; - /** Returns a token if position is in [start-of-leading-trivia, end) */ - function getTokenAtPosition(sourceFile, position, includeJsDocComment) { - if (includeJsDocComment === void 0) { includeJsDocComment = false; } - return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ true, /*includeItemAtEndPosition*/ undefined, includeJsDocComment); + ts.scriptKindIs = scriptKindIs; + function getScriptKind(fileName, host) { + // First check to see if the script kind was specified by the host. Chances are the host + // may override the default script kind for the file extension. + var scriptKind; + if (host && host.getScriptKind) { + scriptKind = host.getScriptKind(fileName); + } + if (!scriptKind) { + scriptKind = ts.getScriptKindFromFileName(fileName); + } + return ts.ensureScriptKind(fileName, scriptKind); } - ts.getTokenAtPosition = getTokenAtPosition; - /** Get the token whose text contains the position */ - function getTokenAtPositionWorker(sourceFile, position, allowPositionInLeadingTrivia, includeItemAtEndPosition, includeJsDocComment) { - if (includeJsDocComment === void 0) { includeJsDocComment = false; } - var current = sourceFile; - outer: while (true) { - if (isToken(current)) { - // exit early - return current; - } - if (includeJsDocComment) { - var jsDocChildren = ts.filter(current.getChildren(), ts.isJSDocNode); - for (var _i = 0, jsDocChildren_1 = jsDocChildren; _i < jsDocChildren_1.length; _i++) { - var jsDocChild = jsDocChildren_1[_i]; - var start = allowPositionInLeadingTrivia ? jsDocChild.getFullStart() : jsDocChild.getStart(sourceFile, includeJsDocComment); - if (start <= position) { - var end = jsDocChild.getEnd(); - if (position < end || (position === end && jsDocChild.kind === 1 /* EndOfFileToken */)) { - current = jsDocChild; - continue outer; - } - else if (includeItemAtEndPosition && end === position) { - var previousToken = findPrecedingToken(position, sourceFile, jsDocChild); - if (previousToken && includeItemAtEndPosition(previousToken)) { - return previousToken; - } - } - } + ts.getScriptKind = getScriptKind; + function sanitizeConfigFile(configFileName, content) { + var options = { + fileName: "config.js", + compilerOptions: { + target: 2 /* ES6 */, + removeComments: true + }, + reportDiagnostics: true + }; + var _a = ts.transpileModule("(" + content + ")", options), outputText = _a.outputText, diagnostics = _a.diagnostics; + // Becasue the content was wrapped in "()", the start position of diagnostics needs to be subtract by 1 + // also, the emitted result will have "(" in the beginning and ");" in the end. We need to strip these + // as well + var trimmedOutput = outputText.trim(); + for (var _i = 0, diagnostics_3 = diagnostics; _i < diagnostics_3.length; _i++) { + var diagnostic = diagnostics_3[_i]; + diagnostic.start = diagnostic.start - 1; + } + var _b = ts.parseConfigFileTextToJson(configFileName, trimmedOutput.substring(1, trimmedOutput.length - 2), /*stripComments*/ false), config = _b.config, error = _b.error; + return { + configJsonObject: config || {}, + diagnostics: error ? ts.concatenate(diagnostics, [error]) : diagnostics + }; + } + ts.sanitizeConfigFile = sanitizeConfigFile; +})(ts || (ts = {})); +var ts; +(function (ts) { + /// Classifier + function createClassifier() { + var scanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ false); + /// We do not have a full parser support to know when we should parse a regex or not + /// If we consider every slash token to be a regex, we could be missing cases like "1/2/3", where + /// we have a series of divide operator. this list allows us to be more accurate by ruling out + /// locations where a regexp cannot exist. + var noRegexTable = []; + noRegexTable[69 /* Identifier */] = true; + noRegexTable[9 /* StringLiteral */] = true; + noRegexTable[8 /* NumericLiteral */] = true; + noRegexTable[10 /* RegularExpressionLiteral */] = true; + noRegexTable[97 /* ThisKeyword */] = true; + noRegexTable[41 /* PlusPlusToken */] = true; + noRegexTable[42 /* MinusMinusToken */] = true; + noRegexTable[18 /* CloseParenToken */] = true; + noRegexTable[20 /* CloseBracketToken */] = true; + noRegexTable[16 /* CloseBraceToken */] = true; + noRegexTable[99 /* TrueKeyword */] = true; + noRegexTable[84 /* FalseKeyword */] = true; + // Just a stack of TemplateHeads and OpenCurlyBraces, used to perform rudimentary (inexact) + // classification on template strings. Because of the context free nature of templates, + // the only precise way to classify a template portion would be by propagating the stack across + // lines, just as we do with the end-of-line state. However, this is a burden for implementers, + // and the behavior is entirely subsumed by the syntactic classifier anyway, so we instead + // flatten any nesting when the template stack is non-empty and encode it in the end-of-line state. + // Situations in which this fails are + // 1) When template strings are nested across different lines: + // `hello ${ `world + // ` }` + // + // Where on the second line, you will get the closing of a template, + // a closing curly, and a new template. + // + // 2) When substitution expressions have curly braces and the curly brace falls on the next line: + // `hello ${ () => { + // return "world" } } ` + // + // Where on the second line, you will get the 'return' keyword, + // a string literal, and a template end consisting of '} } `'. + var templateStack = []; + /** Returns true if 'keyword2' can legally follow 'keyword1' in any language construct. */ + function canFollow(keyword1, keyword2) { + if (ts.isAccessibilityModifier(keyword1)) { + if (keyword2 === 123 /* GetKeyword */ || + keyword2 === 131 /* SetKeyword */ || + keyword2 === 121 /* ConstructorKeyword */ || + keyword2 === 113 /* StaticKeyword */) { + // Allow things like "public get", "public constructor" and "public static". + // These are all legal. + return true; } + // Any other keyword following "public" is actually an identifier an not a real + // keyword. + return false; } - // find the child that contains 'position' - for (var i = 0, n = current.getChildCount(sourceFile); i < n; i++) { - var child = current.getChildAt(i); - // all jsDocComment nodes were already visited - if (ts.isJSDocNode(child)) { - continue; - } - var start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile, includeJsDocComment); - if (start <= position) { - var end = child.getEnd(); - if (position < end || (position === end && child.kind === 1 /* EndOfFileToken */)) { - current = child; - continue outer; - } - else if (includeItemAtEndPosition && end === position) { - var previousToken = findPrecedingToken(position, sourceFile, child); - if (previousToken && includeItemAtEndPosition(previousToken)) { - return previousToken; - } + // Assume any other keyword combination is legal. This can be refined in the future + // if there are more cases we want the classifier to be better at. + return true; + } + function convertClassifications(classifications, text) { + var entries = []; + var dense = classifications.spans; + var lastEnd = 0; + for (var i = 0, n = dense.length; i < n; i += 3) { + var start = dense[i]; + var length_5 = dense[i + 1]; + var type = dense[i + 2]; + // Make a whitespace entry between the last item and this one. + if (lastEnd >= 0) { + var whitespaceLength_1 = start - lastEnd; + if (whitespaceLength_1 > 0) { + entries.push({ length: whitespaceLength_1, classification: ts.TokenClass.Whitespace }); } } + entries.push({ length: length_5, classification: convertClassification(type) }); + lastEnd = start + length_5; } - return current; - } - } - /** - * The token on the left of the position is the token that strictly includes the position - * or sits to the left of the cursor if it is on a boundary. For example - * - * fo|o -> will return foo - * foo |bar -> will return foo - * - */ - function findTokenOnLeftOfPosition(file, position) { - // Ideally, getTokenAtPosition should return a token. However, it is currently - // broken, so we do a check to make sure the result was indeed a token. - var tokenAtPosition = getTokenAtPosition(file, position); - if (isToken(tokenAtPosition) && position > tokenAtPosition.getStart(file) && position < tokenAtPosition.getEnd()) { - return tokenAtPosition; - } - return findPrecedingToken(position, file); - } - ts.findTokenOnLeftOfPosition = findTokenOnLeftOfPosition; - function findNextToken(previousToken, parent) { - return find(parent); - function find(n) { - if (isToken(n) && n.pos === previousToken.end) { - // this is token that starts at the end of previous token - return it - return n; - } - var children = n.getChildren(); - for (var _i = 0, children_1 = children; _i < children_1.length; _i++) { - var child = children_1[_i]; - var shouldDiveInChildNode = - // previous token is enclosed somewhere in the child - (child.pos <= previousToken.pos && child.end > previousToken.end) || - // previous token ends exactly at the beginning of child - (child.pos === previousToken.end); - if (shouldDiveInChildNode && nodeHasTokens(child)) { - return find(child); - } + var whitespaceLength = text.length - lastEnd; + if (whitespaceLength > 0) { + entries.push({ length: whitespaceLength, classification: ts.TokenClass.Whitespace }); } - return undefined; + return { entries: entries, finalLexState: classifications.endOfLineState }; } - } - ts.findNextToken = findNextToken; - function findPrecedingToken(position, sourceFile, startNode) { - return find(startNode || sourceFile); - function findRightmostToken(n) { - if (isToken(n) || n.kind === 244 /* JsxText */) { - return n; + function convertClassification(type) { + switch (type) { + case 1 /* comment */: return ts.TokenClass.Comment; + case 3 /* keyword */: return ts.TokenClass.Keyword; + case 4 /* numericLiteral */: return ts.TokenClass.NumberLiteral; + case 5 /* operator */: return ts.TokenClass.Operator; + case 6 /* stringLiteral */: return ts.TokenClass.StringLiteral; + case 8 /* whiteSpace */: return ts.TokenClass.Whitespace; + case 10 /* punctuation */: return ts.TokenClass.Punctuation; + case 2 /* identifier */: + case 11 /* className */: + case 12 /* enumName */: + case 13 /* interfaceName */: + case 14 /* moduleName */: + case 15 /* typeParameterName */: + case 16 /* typeAliasName */: + case 9 /* text */: + case 17 /* parameterName */: + default: + return ts.TokenClass.Identifier; } - var children = n.getChildren(); - var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length); - return candidate && findRightmostToken(candidate); } - function find(n) { - if (isToken(n) || n.kind === 244 /* JsxText */) { - return n; + function getClassificationsForLine(text, lexState, syntacticClassifierAbsent) { + return convertClassifications(getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent), text); + } + // If there is a syntactic classifier ('syntacticClassifierAbsent' is false), + // we will be more conservative in order to avoid conflicting with the syntactic classifier. + function getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent) { + var offset = 0; + var token = 0 /* Unknown */; + var lastNonTriviaToken = 0 /* Unknown */; + // Empty out the template stack for reuse. + while (templateStack.length > 0) { + templateStack.pop(); } - var children = n.getChildren(); - for (var i = 0, len = children.length; i < len; i++) { - var child = children[i]; - // condition 'position < child.end' checks if child node end after the position - // in the example below this condition will be false for 'aaaa' and 'bbbb' and true for 'ccc' - // aaaa___bbbb___$__ccc - // after we found child node with end after the position we check if start of the node is after the position. - // if yes - then position is in the trivia and we need to look into the previous child to find the token in question. - // if no - position is in the node itself so we should recurse in it. - // NOTE: JsxText is a weird kind of node that can contain only whitespaces (since they are not counted as trivia). - // if this is the case - then we should assume that token in question is located in previous child. - if (position < child.end && (nodeHasTokens(child) || child.kind === 244 /* JsxText */)) { - var start = child.getStart(sourceFile); - var lookInPreviousChild = (start >= position) || - (child.kind === 244 /* JsxText */ && start === child.end); // whitespace only JsxText - if (lookInPreviousChild) { - // actual start of the node is past the position - previous token should be at the end of previous child - var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ i); - return candidate && findRightmostToken(candidate); + // If we're in a string literal, then prepend: "\ + // (and a newline). That way when we lex we'll think we're still in a string literal. + // + // If we're in a multiline comment, then prepend: /* + // (and a newline). That way when we lex we'll think we're still in a multiline comment. + switch (lexState) { + case 3 /* InDoubleQuoteStringLiteral */: + text = "\"\\\n" + text; + offset = 3; + break; + case 2 /* InSingleQuoteStringLiteral */: + text = "'\\\n" + text; + offset = 3; + break; + case 1 /* InMultiLineCommentTrivia */: + text = "/*\n" + text; + offset = 3; + break; + case 4 /* InTemplateHeadOrNoSubstitutionTemplate */: + text = "`\n" + text; + offset = 2; + break; + case 5 /* InTemplateMiddleOrTail */: + text = "}\n" + text; + offset = 2; + // fallthrough + case 6 /* InTemplateSubstitutionPosition */: + templateStack.push(12 /* TemplateHead */); + break; + } + scanner.setText(text); + var result = { + endOfLineState: 0 /* None */, + spans: [] + }; + // We can run into an unfortunate interaction between the lexical and syntactic classifier + // when the user is typing something generic. Consider the case where the user types: + // + // Foo tokens. It's a weak heuristic, but should + // work well enough in practice. + var angleBracketStack = 0; + do { + token = scanner.scan(); + if (!ts.isTrivia(token)) { + if ((token === 39 /* SlashToken */ || token === 61 /* SlashEqualsToken */) && !noRegexTable[lastNonTriviaToken]) { + if (scanner.reScanSlashToken() === 10 /* RegularExpressionLiteral */) { + token = 10 /* RegularExpressionLiteral */; + } } - else { - // candidate should be in this node - return find(child); + else if (lastNonTriviaToken === 21 /* DotToken */ && isKeyword(token)) { + token = 69 /* Identifier */; + } + else if (isKeyword(lastNonTriviaToken) && isKeyword(token) && !canFollow(lastNonTriviaToken, token)) { + // We have two keywords in a row. Only treat the second as a keyword if + // it's a sequence that could legally occur in the language. Otherwise + // treat it as an identifier. This way, if someone writes "private var" + // we recognize that 'var' is actually an identifier here. + token = 69 /* Identifier */; + } + else if (lastNonTriviaToken === 69 /* Identifier */ && + token === 25 /* LessThanToken */) { + // Could be the start of something generic. Keep track of that by bumping + // up the current count of generic contexts we may be in. + angleBracketStack++; + } + else if (token === 27 /* GreaterThanToken */ && angleBracketStack > 0) { + // If we think we're currently in something generic, then mark that that + // generic entity is complete. + angleBracketStack--; + } + else if (token === 117 /* AnyKeyword */ || + token === 132 /* StringKeyword */ || + token === 130 /* NumberKeyword */ || + token === 120 /* BooleanKeyword */ || + token === 133 /* SymbolKeyword */) { + if (angleBracketStack > 0 && !syntacticClassifierAbsent) { + // If it looks like we're could be in something generic, don't classify this + // as a keyword. We may just get overwritten by the syntactic classifier, + // causing a noisy experience for the user. + token = 69 /* Identifier */; + } + } + else if (token === 12 /* TemplateHead */) { + templateStack.push(token); + } + else if (token === 15 /* OpenBraceToken */) { + // If we don't have anything on the template stack, + // then we aren't trying to keep track of a previously scanned template head. + if (templateStack.length > 0) { + templateStack.push(token); + } + } + else if (token === 16 /* CloseBraceToken */) { + // If we don't have anything on the template stack, + // then we aren't trying to keep track of a previously scanned template head. + if (templateStack.length > 0) { + var lastTemplateStackToken = ts.lastOrUndefined(templateStack); + if (lastTemplateStackToken === 12 /* TemplateHead */) { + token = scanner.reScanTemplateToken(); + // Only pop on a TemplateTail; a TemplateMiddle indicates there is more for us. + if (token === 14 /* TemplateTail */) { + templateStack.pop(); + } + else { + ts.Debug.assert(token === 13 /* TemplateMiddle */, "Should have been a template middle. Was " + token); + } + } + else { + ts.Debug.assert(lastTemplateStackToken === 15 /* OpenBraceToken */, "Should have been an open brace. Was: " + token); + templateStack.pop(); + } + } + } + lastNonTriviaToken = token; + } + processToken(); + } while (token !== 1 /* EndOfFileToken */); + return result; + function processToken() { + var start = scanner.getTokenPos(); + var end = scanner.getTextPos(); + addResult(start, end, classFromKind(token)); + if (end >= text.length) { + if (token === 9 /* StringLiteral */) { + // Check to see if we finished up on a multiline string literal. + var tokenText = scanner.getTokenText(); + if (scanner.isUnterminated()) { + var lastCharIndex = tokenText.length - 1; + var numBackslashes = 0; + while (tokenText.charCodeAt(lastCharIndex - numBackslashes) === 92 /* backslash */) { + numBackslashes++; + } + // If we have an odd number of backslashes, then the multiline string is unclosed + if (numBackslashes & 1) { + var quoteChar = tokenText.charCodeAt(0); + result.endOfLineState = quoteChar === 34 /* doubleQuote */ + ? 3 /* InDoubleQuoteStringLiteral */ + : 2 /* InSingleQuoteStringLiteral */; + } + } + } + else if (token === 3 /* MultiLineCommentTrivia */) { + // Check to see if the multiline comment was unclosed. + if (scanner.isUnterminated()) { + result.endOfLineState = 1 /* InMultiLineCommentTrivia */; + } + } + else if (ts.isTemplateLiteralKind(token)) { + if (scanner.isUnterminated()) { + if (token === 14 /* TemplateTail */) { + result.endOfLineState = 5 /* InTemplateMiddleOrTail */; + } + else if (token === 11 /* NoSubstitutionTemplateLiteral */) { + result.endOfLineState = 4 /* InTemplateHeadOrNoSubstitutionTemplate */; + } + else { + ts.Debug.fail("Only 'NoSubstitutionTemplateLiteral's and 'TemplateTail's can be unterminated; got SyntaxKind #" + token); + } + } + } + else if (templateStack.length > 0 && ts.lastOrUndefined(templateStack) === 12 /* TemplateHead */) { + result.endOfLineState = 6 /* InTemplateSubstitutionPosition */; } } } - ts.Debug.assert(startNode !== undefined || n.kind === 256 /* SourceFile */); - // Here we know that none of child token nodes embrace the position, - // the only known case is when position is at the end of the file. - // Try to find the rightmost token in the file without filtering. - // Namely we are skipping the check: 'position < node.end' - if (children.length) { - var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length); - return candidate && findRightmostToken(candidate); - } - } - /// finds last node that is considered as candidate for search (isCandidate(node) === true) starting from 'exclusiveStartPosition' - function findRightmostChildNodeWithTokens(children, exclusiveStartPosition) { - for (var i = exclusiveStartPosition - 1; i >= 0; i--) { - if (nodeHasTokens(children[i])) { - return children[i]; + function addResult(start, end, classification) { + if (classification === 8 /* whiteSpace */) { + // Don't bother with whitespace classifications. They're not needed. + return; + } + if (start === 0 && offset > 0) { + // We're classifying the first token, and this was a case where we prepended + // text. We should consider the start of this token to be at the start of + // the original text. + start += offset; + } + // All our tokens are in relation to the augmented text. Move them back to be + // relative to the original text. + start -= offset; + end -= offset; + var length = end - start; + if (length > 0) { + result.spans.push(start); + result.spans.push(length); + result.spans.push(classification); } } } - } - ts.findPrecedingToken = findPrecedingToken; - function isInString(sourceFile, position) { - var previousToken = findPrecedingToken(position, sourceFile); - if (previousToken && previousToken.kind === 9 /* StringLiteral */) { - var start = previousToken.getStart(); - var end = previousToken.getEnd(); - // To be "in" one of these literals, the position has to be: - // 1. entirely within the token text. - // 2. at the end position of an unterminated token. - // 3. at the end of a regular expression (due to trailing flags like '/foo/g'). - if (start < position && position < end) { - return true; - } - if (position === end) { - return !!previousToken.isUnterminated; + function isBinaryExpressionOperatorToken(token) { + switch (token) { + case 37 /* AsteriskToken */: + case 39 /* SlashToken */: + case 40 /* PercentToken */: + case 35 /* PlusToken */: + case 36 /* MinusToken */: + case 43 /* LessThanLessThanToken */: + case 44 /* GreaterThanGreaterThanToken */: + case 45 /* GreaterThanGreaterThanGreaterThanToken */: + case 25 /* LessThanToken */: + case 27 /* GreaterThanToken */: + case 28 /* LessThanEqualsToken */: + case 29 /* GreaterThanEqualsToken */: + case 91 /* InstanceOfKeyword */: + case 90 /* InKeyword */: + case 116 /* AsKeyword */: + case 30 /* EqualsEqualsToken */: + case 31 /* ExclamationEqualsToken */: + case 32 /* EqualsEqualsEqualsToken */: + case 33 /* ExclamationEqualsEqualsToken */: + case 46 /* AmpersandToken */: + case 48 /* CaretToken */: + case 47 /* BarToken */: + case 51 /* AmpersandAmpersandToken */: + case 52 /* BarBarToken */: + case 67 /* BarEqualsToken */: + case 66 /* AmpersandEqualsToken */: + case 68 /* CaretEqualsToken */: + case 63 /* LessThanLessThanEqualsToken */: + case 64 /* GreaterThanGreaterThanEqualsToken */: + case 65 /* GreaterThanGreaterThanGreaterThanEqualsToken */: + case 57 /* PlusEqualsToken */: + case 58 /* MinusEqualsToken */: + case 59 /* AsteriskEqualsToken */: + case 61 /* SlashEqualsToken */: + case 62 /* PercentEqualsToken */: + case 56 /* EqualsToken */: + case 24 /* CommaToken */: + return true; + default: + return false; } } - return false; - } - ts.isInString = isInString; - function isInComment(sourceFile, position) { - return isInCommentHelper(sourceFile, position, /*predicate*/ undefined); - } - ts.isInComment = isInComment; - /** - * returns true if the position is in between the open and close elements of an JSX expression. - */ - function isInsideJsxElementOrAttribute(sourceFile, position) { - var token = getTokenAtPosition(sourceFile, position); - if (!token) { - return false; - } - if (token.kind === 244 /* JsxText */) { - return true; - } - //
Hello |
- if (token.kind === 25 /* LessThanToken */ && token.parent.kind === 244 /* JsxText */) { - return true; - } - //
{ |
or
- if (token.kind === 25 /* LessThanToken */ && token.parent.kind === 248 /* JsxExpression */) { - return true; - } - //
{ - // | - // } < /div> - if (token && token.kind === 16 /* CloseBraceToken */ && token.parent.kind === 248 /* JsxExpression */) { - return true; + function isPrefixUnaryExpressionOperatorToken(token) { + switch (token) { + case 35 /* PlusToken */: + case 36 /* MinusToken */: + case 50 /* TildeToken */: + case 49 /* ExclamationToken */: + case 41 /* PlusPlusToken */: + case 42 /* MinusMinusToken */: + return true; + default: + return false; + } } - //
|
- if (token.kind === 25 /* LessThanToken */ && token.parent.kind === 245 /* JsxClosingElement */) { - return true; + function isKeyword(token) { + return token >= 70 /* FirstKeyword */ && token <= 138 /* LastKeyword */; } - return false; - } - ts.isInsideJsxElementOrAttribute = isInsideJsxElementOrAttribute; - function isInTemplateString(sourceFile, position) { - var token = getTokenAtPosition(sourceFile, position); - return ts.isTemplateLiteralKind(token.kind) && position > token.getStart(sourceFile); - } - ts.isInTemplateString = isInTemplateString; - /** - * Returns true if the cursor at position in sourceFile is within a comment that additionally - * satisfies predicate, and false otherwise. - */ - function isInCommentHelper(sourceFile, position, predicate) { - var token = getTokenAtPosition(sourceFile, position); - if (token && position <= token.getStart(sourceFile)) { - var commentRanges = ts.getLeadingCommentRanges(sourceFile.text, token.pos); - // The end marker of a single-line comment does not include the newline character. - // In the following case, we are inside a comment (^ denotes the cursor position): - // - // // asdf ^\n - // - // But for multi-line comments, we don't want to be inside the comment in the following case: - // - // /* asdf */^ - // - // Internally, we represent the end of the comment at the newline and closing '/', respectively. - return predicate ? - ts.forEach(commentRanges, function (c) { return c.pos < position && - (c.kind == 2 /* SingleLineCommentTrivia */ ? position <= c.end : position < c.end) && - predicate(c); }) : - ts.forEach(commentRanges, function (c) { return c.pos < position && - (c.kind == 2 /* SingleLineCommentTrivia */ ? position <= c.end : position < c.end); }); + function classFromKind(token) { + if (isKeyword(token)) { + return 3 /* keyword */; + } + else if (isBinaryExpressionOperatorToken(token) || isPrefixUnaryExpressionOperatorToken(token)) { + return 5 /* operator */; + } + else if (token >= 15 /* FirstPunctuation */ && token <= 68 /* LastPunctuation */) { + return 10 /* punctuation */; + } + switch (token) { + case 8 /* NumericLiteral */: + return 4 /* numericLiteral */; + case 9 /* StringLiteral */: + return 6 /* stringLiteral */; + case 10 /* RegularExpressionLiteral */: + return 7 /* regularExpressionLiteral */; + case 7 /* ConflictMarkerTrivia */: + case 3 /* MultiLineCommentTrivia */: + case 2 /* SingleLineCommentTrivia */: + return 1 /* comment */; + case 5 /* WhitespaceTrivia */: + case 4 /* NewLineTrivia */: + return 8 /* whiteSpace */; + case 69 /* Identifier */: + default: + if (ts.isTemplateLiteralKind(token)) { + return 6 /* stringLiteral */; + } + return 2 /* identifier */; + } } - return false; + return { + getClassificationsForLine: getClassificationsForLine, + getEncodedLexicalClassifications: getEncodedLexicalClassifications + }; } - ts.isInCommentHelper = isInCommentHelper; - function hasDocComment(sourceFile, position) { - var token = getTokenAtPosition(sourceFile, position); - // First, we have to see if this position actually landed in a comment. - var commentRanges = ts.getLeadingCommentRanges(sourceFile.text, token.pos); - return ts.forEach(commentRanges, jsDocPrefix); - function jsDocPrefix(c) { - var text = sourceFile.text; - return text.length >= c.pos + 3 && text[c.pos] === "/" && text[c.pos + 1] === "*" && text[c.pos + 2] === "*"; + ts.createClassifier = createClassifier; + /* @internal */ + function getSemanticClassifications(typeChecker, cancellationToken, sourceFile, classifiableNames, span) { + return convertClassifications(getEncodedSemanticClassifications(typeChecker, cancellationToken, sourceFile, classifiableNames, span)); + } + ts.getSemanticClassifications = getSemanticClassifications; + function checkForClassificationCancellation(cancellationToken, kind) { + // We don't want to actually call back into our host on every node to find out if we've + // been canceled. That would be an enormous amount of chattyness, along with the all + // the overhead of marshalling the data to/from the host. So instead we pick a few + // reasonable node kinds to bother checking on. These node kinds represent high level + // constructs that we would expect to see commonly, but just at a far less frequent + // interval. + // + // For example, in checker.ts (around 750k) we only have around 600 of these constructs. + // That means we're calling back into the host around every 1.2k of the file we process. + // Lib.d.ts has similar numbers. + switch (kind) { + case 225 /* ModuleDeclaration */: + case 221 /* ClassDeclaration */: + case 222 /* InterfaceDeclaration */: + case 220 /* FunctionDeclaration */: + cancellationToken.throwIfCancellationRequested(); } } - ts.hasDocComment = hasDocComment; - /** - * Get the corresponding JSDocTag node if the position is in a jsDoc comment - */ - function getJsDocTagAtPosition(sourceFile, position) { - var node = ts.getTokenAtPosition(sourceFile, position); - if (isToken(node)) { - switch (node.kind) { - case 102 /* VarKeyword */: - case 108 /* LetKeyword */: - case 74 /* ConstKeyword */: - // if the current token is var, let or const, skip the VariableDeclarationList - node = node.parent === undefined ? undefined : node.parent.parent; - break; - default: - node = node.parent; - break; + /* @internal */ + function getEncodedSemanticClassifications(typeChecker, cancellationToken, sourceFile, classifiableNames, span) { + var result = []; + processNode(sourceFile); + return { spans: result, endOfLineState: 0 /* None */ }; + function pushClassification(start, length, type) { + result.push(start); + result.push(length); + result.push(type); + } + function classifySymbol(symbol, meaningAtPosition) { + var flags = symbol.getFlags(); + if ((flags & 788448 /* Classifiable */) === 0 /* None */) { + return; + } + if (flags & 32 /* Class */) { + return 11 /* className */; + } + else if (flags & 384 /* Enum */) { + return 12 /* enumName */; + } + else if (flags & 524288 /* TypeAlias */) { + return 16 /* typeAliasName */; + } + else if (meaningAtPosition & 2 /* Type */) { + if (flags & 64 /* Interface */) { + return 13 /* interfaceName */; + } + else if (flags & 262144 /* TypeParameter */) { + return 15 /* typeParameterName */; + } + } + else if (flags & 1536 /* Module */) { + // Only classify a module as such if + // - It appears in a namespace context. + // - There exists a module declaration which actually impacts the value side. + if (meaningAtPosition & 4 /* Namespace */ || + (meaningAtPosition & 1 /* Value */ && hasValueSideModule(symbol))) { + return 14 /* moduleName */; + } + } + return undefined; + /** + * Returns true if there exists a module that introduces entities on the value side. + */ + function hasValueSideModule(symbol) { + return ts.forEach(symbol.declarations, function (declaration) { + return declaration.kind === 225 /* ModuleDeclaration */ && + ts.getModuleInstanceState(declaration) === 1 /* Instantiated */; + }); } } - if (node) { - if (node.jsDocComments) { - for (var _i = 0, _a = node.jsDocComments; _i < _a.length; _i++) { - var jsDocComment = _a[_i]; - for (var _b = 0, _c = jsDocComment.tags; _b < _c.length; _b++) { - var tag = _c[_b]; - if (tag.pos <= position && position <= tag.end) { - return tag; + function processNode(node) { + // Only walk into nodes that intersect the requested span. + if (node && ts.textSpanIntersectsWith(span, node.getFullStart(), node.getFullWidth())) { + var kind = node.kind; + checkForClassificationCancellation(cancellationToken, kind); + if (kind === 69 /* Identifier */ && !ts.nodeIsMissing(node)) { + var identifier = node; + // Only bother calling into the typechecker if this is an identifier that + // could possibly resolve to a type name. This makes classification run + // in a third of the time it would normally take. + if (classifiableNames[identifier.text]) { + var symbol = typeChecker.getSymbolAtLocation(node); + if (symbol) { + var type = classifySymbol(symbol, ts.getMeaningFromLocation(node)); + if (type) { + pushClassification(node.getStart(), node.getWidth(), type); + } } } } + ts.forEachChild(node, processNode); } } - return undefined; } - ts.getJsDocTagAtPosition = getJsDocTagAtPosition; - function nodeHasTokens(n) { - // If we have a token or node that has a non-zero width, it must have tokens. - // Note, that getWidth() does not take trivia into account. - return n.getWidth() !== 0; + ts.getEncodedSemanticClassifications = getEncodedSemanticClassifications; + function getClassificationTypeName(type) { + switch (type) { + case 1 /* comment */: return ts.ClassificationTypeNames.comment; + case 2 /* identifier */: return ts.ClassificationTypeNames.identifier; + case 3 /* keyword */: return ts.ClassificationTypeNames.keyword; + case 4 /* numericLiteral */: return ts.ClassificationTypeNames.numericLiteral; + case 5 /* operator */: return ts.ClassificationTypeNames.operator; + case 6 /* stringLiteral */: return ts.ClassificationTypeNames.stringLiteral; + case 8 /* whiteSpace */: return ts.ClassificationTypeNames.whiteSpace; + case 9 /* text */: return ts.ClassificationTypeNames.text; + case 10 /* punctuation */: return ts.ClassificationTypeNames.punctuation; + case 11 /* className */: return ts.ClassificationTypeNames.className; + case 12 /* enumName */: return ts.ClassificationTypeNames.enumName; + case 13 /* interfaceName */: return ts.ClassificationTypeNames.interfaceName; + case 14 /* moduleName */: return ts.ClassificationTypeNames.moduleName; + case 15 /* typeParameterName */: return ts.ClassificationTypeNames.typeParameterName; + case 16 /* typeAliasName */: return ts.ClassificationTypeNames.typeAliasName; + case 17 /* parameterName */: return ts.ClassificationTypeNames.parameterName; + case 18 /* docCommentTagName */: return ts.ClassificationTypeNames.docCommentTagName; + case 19 /* jsxOpenTagName */: return ts.ClassificationTypeNames.jsxOpenTagName; + case 20 /* jsxCloseTagName */: return ts.ClassificationTypeNames.jsxCloseTagName; + case 21 /* jsxSelfClosingTagName */: return ts.ClassificationTypeNames.jsxSelfClosingTagName; + case 22 /* jsxAttribute */: return ts.ClassificationTypeNames.jsxAttribute; + case 23 /* jsxText */: return ts.ClassificationTypeNames.jsxText; + case 24 /* jsxAttributeStringLiteralValue */: return ts.ClassificationTypeNames.jsxAttributeStringLiteralValue; + } } - function getNodeModifiers(node) { - var flags = ts.getCombinedNodeFlags(node); + function convertClassifications(classifications) { + ts.Debug.assert(classifications.spans.length % 3 === 0); + var dense = classifications.spans; var result = []; - if (flags & 8 /* Private */) - result.push(ts.ScriptElementKindModifier.privateMemberModifier); - if (flags & 16 /* Protected */) - result.push(ts.ScriptElementKindModifier.protectedMemberModifier); - if (flags & 4 /* Public */) - result.push(ts.ScriptElementKindModifier.publicMemberModifier); - if (flags & 32 /* Static */) - result.push(ts.ScriptElementKindModifier.staticModifier); - if (flags & 128 /* Abstract */) - result.push(ts.ScriptElementKindModifier.abstractModifier); - if (flags & 1 /* Export */) - result.push(ts.ScriptElementKindModifier.exportedModifier); - if (ts.isInAmbientContext(node)) - result.push(ts.ScriptElementKindModifier.ambientModifier); - return result.length > 0 ? result.join(",") : ts.ScriptElementKindModifier.none; - } - ts.getNodeModifiers = getNodeModifiers; - function getTypeArgumentOrTypeParameterList(node) { - if (node.kind === 155 /* TypeReference */ || node.kind === 174 /* CallExpression */) { - return node.typeArguments; - } - if (ts.isFunctionLike(node) || node.kind === 221 /* ClassDeclaration */ || node.kind === 222 /* InterfaceDeclaration */) { - return node.typeParameters; + for (var i = 0, n = dense.length; i < n; i += 3) { + result.push({ + textSpan: ts.createTextSpan(dense[i], dense[i + 1]), + classificationType: getClassificationTypeName(dense[i + 2]) + }); } - return undefined; - } - ts.getTypeArgumentOrTypeParameterList = getTypeArgumentOrTypeParameterList; - function isToken(n) { - return n.kind >= 0 /* FirstToken */ && n.kind <= 138 /* LastToken */; - } - ts.isToken = isToken; - function isWord(kind) { - return kind === 69 /* Identifier */ || ts.isKeyword(kind); - } - ts.isWord = isWord; - function isPropertyName(kind) { - return kind === 9 /* StringLiteral */ || kind === 8 /* NumericLiteral */ || isWord(kind); + return result; } - function isComment(kind) { - return kind === 2 /* SingleLineCommentTrivia */ || kind === 3 /* MultiLineCommentTrivia */; + /* @internal */ + function getSyntacticClassifications(cancellationToken, sourceFile, span) { + return convertClassifications(getEncodedSyntacticClassifications(cancellationToken, sourceFile, span)); } - ts.isComment = isComment; - function isStringOrRegularExpressionOrTemplateLiteral(kind) { - if (kind === 9 /* StringLiteral */ - || kind === 10 /* RegularExpressionLiteral */ - || ts.isTemplateLiteralKind(kind)) { - return true; + ts.getSyntacticClassifications = getSyntacticClassifications; + /* @internal */ + function getEncodedSyntacticClassifications(cancellationToken, sourceFile, span) { + var spanStart = span.start; + var spanLength = span.length; + // Make a scanner we can get trivia from. + var triviaScanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text); + var mergeConflictScanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text); + var result = []; + processElement(sourceFile); + return { spans: result, endOfLineState: 0 /* None */ }; + function pushClassification(start, length, type) { + result.push(start); + result.push(length); + result.push(type); + } + function classifyLeadingTriviaAndGetTokenStart(token) { + triviaScanner.setTextPos(token.pos); + while (true) { + var start = triviaScanner.getTextPos(); + // only bother scanning if we have something that could be trivia. + if (!ts.couldStartTrivia(sourceFile.text, start)) { + return start; + } + var kind = triviaScanner.scan(); + var end = triviaScanner.getTextPos(); + var width = end - start; + // The moment we get something that isn't trivia, then stop processing. + if (!ts.isTrivia(kind)) { + return start; + } + // Don't bother with newlines/whitespace. + if (kind === 4 /* NewLineTrivia */ || kind === 5 /* WhitespaceTrivia */) { + continue; + } + // Only bother with the trivia if it at least intersects the span of interest. + if (ts.isComment(kind)) { + classifyComment(token, kind, start, width); + // Classifying a comment might cause us to reuse the trivia scanner + // (because of jsdoc comments). So after we classify the comment make + // sure we set the scanner position back to where it needs to be. + triviaScanner.setTextPos(end); + continue; + } + if (kind === 7 /* ConflictMarkerTrivia */) { + var text = sourceFile.text; + var ch = text.charCodeAt(start); + // for the <<<<<<< and >>>>>>> markers, we just add them in as comments + // in the classification stream. + if (ch === 60 /* lessThan */ || ch === 62 /* greaterThan */) { + pushClassification(start, width, 1 /* comment */); + continue; + } + // for the ======== add a comment for the first line, and then lex all + // subsequent lines up until the end of the conflict marker. + ts.Debug.assert(ch === 61 /* equals */); + classifyDisabledMergeCode(text, start, end); + } + } } - return false; - } - ts.isStringOrRegularExpressionOrTemplateLiteral = isStringOrRegularExpressionOrTemplateLiteral; - function isPunctuation(kind) { - return 15 /* FirstPunctuation */ <= kind && kind <= 68 /* LastPunctuation */; - } - ts.isPunctuation = isPunctuation; - function isInsideTemplateLiteral(node, position) { - return ts.isTemplateLiteralKind(node.kind) - && (node.getStart() < position && position < node.getEnd()) || (!!node.isUnterminated && position === node.getEnd()); - } - ts.isInsideTemplateLiteral = isInsideTemplateLiteral; - function isAccessibilityModifier(kind) { - switch (kind) { - case 112 /* PublicKeyword */: - case 110 /* PrivateKeyword */: - case 111 /* ProtectedKeyword */: - return true; + function classifyComment(token, kind, start, width) { + if (kind === 3 /* MultiLineCommentTrivia */) { + // See if this is a doc comment. If so, we'll classify certain portions of it + // specially. + var docCommentAndDiagnostics = ts.parseIsolatedJSDocComment(sourceFile.text, start, width); + if (docCommentAndDiagnostics && docCommentAndDiagnostics.jsDoc) { + docCommentAndDiagnostics.jsDoc.parent = token; + classifyJSDocComment(docCommentAndDiagnostics.jsDoc); + return; + } + } + // Simple comment. Just add as is. + pushCommentRange(start, width); } - return false; - } - ts.isAccessibilityModifier = isAccessibilityModifier; - function compareDataObjects(dst, src) { - for (var e in dst) { - if (typeof dst[e] === "object") { - if (!compareDataObjects(dst[e], src[e])) { - return false; + function pushCommentRange(start, width) { + pushClassification(start, width, 1 /* comment */); + } + function classifyJSDocComment(docComment) { + var pos = docComment.pos; + if (docComment.tags) { + for (var _i = 0, _a = docComment.tags; _i < _a.length; _i++) { + var tag = _a[_i]; + // As we walk through each tag, classify the portion of text from the end of + // the last tag (or the start of the entire doc comment) as 'comment'. + if (tag.pos !== pos) { + pushCommentRange(pos, tag.pos - pos); + } + pushClassification(tag.atToken.pos, tag.atToken.end - tag.atToken.pos, 10 /* punctuation */); + pushClassification(tag.tagName.pos, tag.tagName.end - tag.tagName.pos, 18 /* docCommentTagName */); + pos = tag.tagName.end; + switch (tag.kind) { + case 275 /* JSDocParameterTag */: + processJSDocParameterTag(tag); + break; + case 278 /* JSDocTemplateTag */: + processJSDocTemplateTag(tag); + break; + case 277 /* JSDocTypeTag */: + processElement(tag.typeExpression); + break; + case 276 /* JSDocReturnTag */: + processElement(tag.typeExpression); + break; + } + pos = tag.end; } } - else if (typeof dst[e] !== "function") { - if (dst[e] !== src[e]) { - return false; + if (pos !== docComment.end) { + pushCommentRange(pos, docComment.end - pos); + } + return; + function processJSDocParameterTag(tag) { + if (tag.preParameterName) { + pushCommentRange(pos, tag.preParameterName.pos - pos); + pushClassification(tag.preParameterName.pos, tag.preParameterName.end - tag.preParameterName.pos, 17 /* parameterName */); + pos = tag.preParameterName.end; + } + if (tag.typeExpression) { + pushCommentRange(pos, tag.typeExpression.pos - pos); + processElement(tag.typeExpression); + pos = tag.typeExpression.end; + } + if (tag.postParameterName) { + pushCommentRange(pos, tag.postParameterName.pos - pos); + pushClassification(tag.postParameterName.pos, tag.postParameterName.end - tag.postParameterName.pos, 17 /* parameterName */); + pos = tag.postParameterName.end; } } } - return true; - } - ts.compareDataObjects = compareDataObjects; - function isArrayLiteralOrObjectLiteralDestructuringPattern(node) { - if (node.kind === 170 /* ArrayLiteralExpression */ || - node.kind === 171 /* ObjectLiteralExpression */) { - // [a,b,c] from: - // [a, b, c] = someExpression; - if (node.parent.kind === 187 /* BinaryExpression */ && - node.parent.left === node && - node.parent.operatorToken.kind === 56 /* EqualsToken */) { - return true; + function processJSDocTemplateTag(tag) { + for (var _i = 0, _a = tag.getChildren(); _i < _a.length; _i++) { + var child = _a[_i]; + processElement(child); } - // [a, b, c] from: - // for([a, b, c] of expression) - if (node.parent.kind === 208 /* ForOfStatement */ && - node.parent.initializer === node) { + } + function classifyDisabledMergeCode(text, start, end) { + // Classify the line that the ======= marker is on as a comment. Then just lex + // all further tokens and add them to the result. + var i; + for (i = start; i < end; i++) { + if (ts.isLineBreak(text.charCodeAt(i))) { + break; + } + } + pushClassification(start, i - start, 1 /* comment */); + mergeConflictScanner.setTextPos(i); + while (mergeConflictScanner.getTextPos() < end) { + classifyDisabledCodeToken(); + } + } + function classifyDisabledCodeToken() { + var start = mergeConflictScanner.getTextPos(); + var tokenKind = mergeConflictScanner.scan(); + var end = mergeConflictScanner.getTextPos(); + var type = classifyTokenType(tokenKind); + if (type) { + pushClassification(start, end - start, type); + } + } + /** + * Returns true if node should be treated as classified and no further processing is required. + * False will mean that node is not classified and traverse routine should recurse into node contents. + */ + function tryClassifyNode(node) { + if (ts.isJSDocTag(node)) { return true; } - // [a, b, c] of - // [x, [a, b, c] ] = someExpression - // or - // {x, a: {a, b, c} } = someExpression - if (isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent.kind === 253 /* PropertyAssignment */ ? node.parent.parent : node.parent)) { + if (ts.nodeIsMissing(node)) { return true; } + var classifiedElementName = tryClassifyJsxElementName(node); + if (!ts.isToken(node) && node.kind !== 244 /* JsxText */ && classifiedElementName === undefined) { + return false; + } + var tokenStart = node.kind === 244 /* JsxText */ ? node.pos : classifyLeadingTriviaAndGetTokenStart(node); + var tokenWidth = node.end - tokenStart; + ts.Debug.assert(tokenWidth >= 0); + if (tokenWidth > 0) { + var type = classifiedElementName || classifyTokenType(node.kind, node); + if (type) { + pushClassification(tokenStart, tokenWidth, type); + } + } + return true; + } + function tryClassifyJsxElementName(token) { + switch (token.parent && token.parent.kind) { + case 243 /* JsxOpeningElement */: + if (token.parent.tagName === token) { + return 19 /* jsxOpenTagName */; + } + break; + case 245 /* JsxClosingElement */: + if (token.parent.tagName === token) { + return 20 /* jsxCloseTagName */; + } + break; + case 242 /* JsxSelfClosingElement */: + if (token.parent.tagName === token) { + return 21 /* jsxSelfClosingTagName */; + } + break; + case 246 /* JsxAttribute */: + if (token.parent.name === token) { + return 22 /* jsxAttribute */; + } + break; + } + return undefined; + } + // for accurate classification, the actual token should be passed in. however, for + // cases like 'disabled merge code' classification, we just get the token kind and + // classify based on that instead. + function classifyTokenType(tokenKind, token) { + if (ts.isKeyword(tokenKind)) { + return 3 /* keyword */; + } + // Special case < and > If they appear in a generic context they are punctuation, + // not operators. + if (tokenKind === 25 /* LessThanToken */ || tokenKind === 27 /* GreaterThanToken */) { + // If the node owning the token has a type argument list or type parameter list, then + // we can effectively assume that a '<' and '>' belong to those lists. + if (token && ts.getTypeArgumentOrTypeParameterList(token.parent)) { + return 10 /* punctuation */; + } + } + if (ts.isPunctuation(tokenKind)) { + if (token) { + if (tokenKind === 56 /* EqualsToken */) { + // the '=' in a variable declaration is special cased here. + if (token.parent.kind === 218 /* VariableDeclaration */ || + token.parent.kind === 145 /* PropertyDeclaration */ || + token.parent.kind === 142 /* Parameter */ || + token.parent.kind === 246 /* JsxAttribute */) { + return 5 /* operator */; + } + } + if (token.parent.kind === 187 /* BinaryExpression */ || + token.parent.kind === 185 /* PrefixUnaryExpression */ || + token.parent.kind === 186 /* PostfixUnaryExpression */ || + token.parent.kind === 188 /* ConditionalExpression */) { + return 5 /* operator */; + } + } + return 10 /* punctuation */; + } + else if (tokenKind === 8 /* NumericLiteral */) { + return 4 /* numericLiteral */; + } + else if (tokenKind === 9 /* StringLiteral */) { + return token.parent.kind === 246 /* JsxAttribute */ ? 24 /* jsxAttributeStringLiteralValue */ : 6 /* stringLiteral */; + } + else if (tokenKind === 10 /* RegularExpressionLiteral */) { + // TODO: we should get another classification type for these literals. + return 6 /* stringLiteral */; + } + else if (ts.isTemplateLiteralKind(tokenKind)) { + // TODO (drosen): we should *also* get another classification type for these literals. + return 6 /* stringLiteral */; + } + else if (tokenKind === 244 /* JsxText */) { + return 23 /* jsxText */; + } + else if (tokenKind === 69 /* Identifier */) { + if (token) { + switch (token.parent.kind) { + case 221 /* ClassDeclaration */: + if (token.parent.name === token) { + return 11 /* className */; + } + return; + case 141 /* TypeParameter */: + if (token.parent.name === token) { + return 15 /* typeParameterName */; + } + return; + case 222 /* InterfaceDeclaration */: + if (token.parent.name === token) { + return 13 /* interfaceName */; + } + return; + case 224 /* EnumDeclaration */: + if (token.parent.name === token) { + return 12 /* enumName */; + } + return; + case 225 /* ModuleDeclaration */: + if (token.parent.name === token) { + return 14 /* moduleName */; + } + return; + case 142 /* Parameter */: + if (token.parent.name === token) { + var isThis_1 = token.kind === 69 /* Identifier */ && token.originalKeywordKind === 97 /* ThisKeyword */; + return isThis_1 ? 3 /* keyword */ : 17 /* parameterName */; + } + return; + } + } + return 2 /* identifier */; + } + } + function processElement(element) { + if (!element) { + return; + } + // Ignore nodes that don't intersect the original span to classify. + if (ts.decodedTextSpanIntersectsWith(spanStart, spanLength, element.pos, element.getFullWidth())) { + checkForClassificationCancellation(cancellationToken, element.kind); + var children = element.getChildren(sourceFile); + for (var i = 0, n = children.length; i < n; i++) { + var child = children[i]; + if (!tryClassifyNode(child)) { + // Recurse into our child nodes. + processElement(child); + } + } + } } - return false; } - ts.isArrayLiteralOrObjectLiteralDestructuringPattern = isArrayLiteralOrObjectLiteralDestructuringPattern; + ts.getEncodedSyntacticClassifications = getEncodedSyntacticClassifications; })(ts || (ts = {})); -// Display-part writer helpers /* @internal */ var ts; (function (ts) { - function isFirstDeclarationOfSymbolParameter(symbol) { - return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === 142 /* Parameter */; - } - ts.isFirstDeclarationOfSymbolParameter = isFirstDeclarationOfSymbolParameter; - var displayPartWriter = getDisplayPartWriter(); - function getDisplayPartWriter() { - var displayParts; - var lineStart; - var indent; - resetWriter(); - return { - displayParts: function () { return displayParts; }, - writeKeyword: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.keyword); }, - writeOperator: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.operator); }, - writePunctuation: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.punctuation); }, - writeSpace: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.space); }, - writeStringLiteral: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.stringLiteral); }, - writeParameter: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.parameterName); }, - writeSymbol: writeSymbol, - writeLine: writeLine, - increaseIndent: function () { indent++; }, - decreaseIndent: function () { indent--; }, - clear: resetWriter, - trackSymbol: function () { }, - reportInaccessibleThisError: function () { } - }; - function writeIndent() { - if (lineStart) { - var indentString = ts.getIndentString(indent); - if (indentString) { - displayParts.push(displayPart(indentString, ts.SymbolDisplayPartKind.space)); + var Completions; + (function (Completions) { + function getCompletionsAtPosition(host, typeChecker, log, compilerOptions, sourceFile, position) { + if (ts.isInReferenceComment(sourceFile, position)) { + return getTripleSlashReferenceCompletion(sourceFile, position); + } + if (ts.isInString(sourceFile, position)) { + return getStringLiteralCompletionEntries(sourceFile, position); + } + var completionData = getCompletionData(typeChecker, log, sourceFile, position); + if (!completionData) { + return undefined; + } + var symbols = completionData.symbols, isMemberCompletion = completionData.isMemberCompletion, isNewIdentifierLocation = completionData.isNewIdentifierLocation, location = completionData.location, isJsDocTagName = completionData.isJsDocTagName; + if (isJsDocTagName) { + // If the current position is a jsDoc tag name, only tag names should be provided for completion + return { isMemberCompletion: false, isNewIdentifierLocation: false, entries: ts.JsDoc.getAllJsDocCompletionEntries() }; + } + var entries = []; + if (ts.isSourceFileJavaScript(sourceFile)) { + var uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, /*performCharacterChecks*/ false); + ts.addRange(entries, getJavaScriptCompletionEntries(sourceFile, location.pos, uniqueNames)); + } + else { + if (!symbols || symbols.length === 0) { + if (sourceFile.languageVariant === 1 /* JSX */ && + location.parent && location.parent.kind === 245 /* JsxClosingElement */) { + // In the TypeScript JSX element, if such element is not defined. When users query for completion at closing tag, + // instead of simply giving unknown value, the completion will return the tag-name of an associated opening-element. + // For example: + // var x =
completion list at "1" will contain "div" with type any + var tagName = location.parent.parent.openingElement.tagName; + entries.push({ + name: tagName.text, + kind: undefined, + kindModifiers: undefined, + sortText: "0", + }); + } + else { + return undefined; + } + } + getCompletionEntriesFromSymbols(symbols, entries, location, /*performCharacterChecks*/ true); + } + // Add keywords if this is not a member completion list + if (!isMemberCompletion && !isJsDocTagName) { + ts.addRange(entries, keywordCompletions); + } + return { isMemberCompletion: isMemberCompletion, isNewIdentifierLocation: isNewIdentifierLocation, entries: entries }; + function getJavaScriptCompletionEntries(sourceFile, position, uniqueNames) { + var entries = []; + var nameTable = ts.getNameTable(sourceFile); + for (var name_49 in nameTable) { + // Skip identifiers produced only from the current location + if (nameTable[name_49] === position) { + continue; + } + if (!uniqueNames[name_49]) { + uniqueNames[name_49] = name_49; + var displayName = getCompletionEntryDisplayName(ts.unescapeIdentifier(name_49), compilerOptions.target, /*performCharacterChecks*/ true); + if (displayName) { + var entry = { + name: displayName, + kind: ts.ScriptElementKind.warning, + kindModifiers: "", + sortText: "1" + }; + entries.push(entry); + } + } + } + return entries; + } + function createCompletionEntry(symbol, location, performCharacterChecks) { + // Try to get a valid display name for this symbol, if we could not find one, then ignore it. + // We would like to only show things that can be added after a dot, so for instance numeric properties can + // not be accessed with a dot (a.1 <- invalid) + var displayName = getCompletionEntryDisplayNameForSymbol(typeChecker, symbol, compilerOptions.target, performCharacterChecks, location); + if (!displayName) { + return undefined; + } + // TODO(drosen): Right now we just permit *all* semantic meanings when calling + // 'getSymbolKind' which is permissible given that it is backwards compatible; but + // really we should consider passing the meaning for the node so that we don't report + // that a suggestion for a value is an interface. We COULD also just do what + // 'getSymbolModifiers' does, which is to use the first declaration. + // Use a 'sortText' of 0' so that all symbol completion entries come before any other + // entries (like JavaScript identifier entries). + return { + name: displayName, + kind: ts.SymbolDisplay.getSymbolKind(typeChecker, symbol, location), + kindModifiers: ts.SymbolDisplay.getSymbolModifiers(symbol), + sortText: "0", + }; + } + function getCompletionEntriesFromSymbols(symbols, entries, location, performCharacterChecks) { + var start = ts.timestamp(); + var uniqueNames = ts.createMap(); + if (symbols) { + for (var _i = 0, symbols_4 = symbols; _i < symbols_4.length; _i++) { + var symbol = symbols_4[_i]; + var entry = createCompletionEntry(symbol, location, performCharacterChecks); + if (entry) { + var id = ts.escapeIdentifier(entry.name); + if (!uniqueNames[id]) { + entries.push(entry); + uniqueNames[id] = id; + } + } + } + } + log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (ts.timestamp() - start)); + return uniqueNames; + } + function getStringLiteralCompletionEntries(sourceFile, position) { + var node = ts.findPrecedingToken(position, sourceFile); + if (!node || node.kind !== 9 /* StringLiteral */) { + return undefined; + } + if (node.parent.kind === 253 /* PropertyAssignment */ && node.parent.parent.kind === 171 /* ObjectLiteralExpression */) { + // Get quoted name of properties of the object literal expression + // i.e. interface ConfigFiles { + // 'jspm:dev': string + // } + // let files: ConfigFiles = { + // '/*completion position*/' + // } + // + // function foo(c: ConfigFiles) {} + // foo({ + // '/*completion position*/' + // }); + return getStringLiteralCompletionEntriesFromPropertyAssignment(node.parent); + } + else if (ts.isElementAccessExpression(node.parent) && node.parent.argumentExpression === node) { + // Get all names of properties on the expression + // i.e. interface A { + // 'prop1': string + // } + // let a: A; + // a['/*completion position*/'] + return getStringLiteralCompletionEntriesFromElementAccess(node.parent); + } + else if (node.parent.kind === 230 /* ImportDeclaration */ || ts.isExpressionOfExternalModuleImportEqualsDeclaration(node) || ts.isRequireCall(node.parent, false)) { + // Get all known external module names or complete a path to a module + // i.e. import * as ns from "/*completion position*/"; + // import x = require("/*completion position*/"); + // var y = require("/*completion position*/"); + return getStringLiteralCompletionEntriesFromModuleNames(node); + } + else { + var argumentInfo = ts.SignatureHelp.getContainingArgumentInfo(node, position, sourceFile); + if (argumentInfo) { + // Get string literal completions from specialized signatures of the target + // i.e. declare function f(a: 'A'); + // f("/*completion position*/") + return getStringLiteralCompletionEntriesFromCallExpression(argumentInfo, node); + } + // Get completion for string literal from string literal type + // i.e. var x: "hi" | "hello" = "/*completion position*/" + return getStringLiteralCompletionEntriesFromContextualType(node); + } + } + function getStringLiteralCompletionEntriesFromPropertyAssignment(element) { + var type = typeChecker.getContextualType(element.parent); + var entries = []; + if (type) { + getCompletionEntriesFromSymbols(type.getApparentProperties(), entries, element, /*performCharacterChecks*/ false); + if (entries.length) { + return { isMemberCompletion: true, isNewIdentifierLocation: true, entries: entries }; + } + } + } + function getStringLiteralCompletionEntriesFromCallExpression(argumentInfo, location) { + var candidates = []; + var entries = []; + typeChecker.getResolvedSignature(argumentInfo.invocation, candidates); + for (var _i = 0, candidates_3 = candidates; _i < candidates_3.length; _i++) { + var candidate = candidates_3[_i]; + if (candidate.parameters.length > argumentInfo.argumentIndex) { + var parameter = candidate.parameters[argumentInfo.argumentIndex]; + addStringLiteralCompletionsFromType(typeChecker.getTypeAtLocation(parameter.valueDeclaration), entries); + } } - lineStart = false; + if (entries.length) { + return { isMemberCompletion: false, isNewIdentifierLocation: true, entries: entries }; + } + return undefined; } - } - function writeKind(text, kind) { - writeIndent(); - displayParts.push(displayPart(text, kind)); - } - function writeSymbol(text, symbol) { - writeIndent(); - displayParts.push(symbolPart(text, symbol)); - } - function writeLine() { - displayParts.push(lineBreakPart()); - lineStart = true; - } - function resetWriter() { - displayParts = []; - lineStart = true; - indent = 0; - } - } - function symbolPart(text, symbol) { - return displayPart(text, displayPartKind(symbol), symbol); - function displayPartKind(symbol) { - var flags = symbol.flags; - if (flags & 3 /* Variable */) { - return isFirstDeclarationOfSymbolParameter(symbol) ? ts.SymbolDisplayPartKind.parameterName : ts.SymbolDisplayPartKind.localName; + function getStringLiteralCompletionEntriesFromElementAccess(node) { + var type = typeChecker.getTypeAtLocation(node.expression); + var entries = []; + if (type) { + getCompletionEntriesFromSymbols(type.getApparentProperties(), entries, node, /*performCharacterChecks*/ false); + if (entries.length) { + return { isMemberCompletion: true, isNewIdentifierLocation: true, entries: entries }; + } + } + return undefined; } - else if (flags & 4 /* Property */) { - return ts.SymbolDisplayPartKind.propertyName; + function getStringLiteralCompletionEntriesFromContextualType(node) { + var type = typeChecker.getContextualType(node); + if (type) { + var entries_2 = []; + addStringLiteralCompletionsFromType(type, entries_2); + if (entries_2.length) { + return { isMemberCompletion: false, isNewIdentifierLocation: false, entries: entries_2 }; + } + } + return undefined; } - else if (flags & 32768 /* GetAccessor */) { - return ts.SymbolDisplayPartKind.propertyName; + function addStringLiteralCompletionsFromType(type, result) { + if (!type) { + return; + } + if (type.flags & 524288 /* Union */) { + ts.forEach(type.types, function (t) { return addStringLiteralCompletionsFromType(t, result); }); + } + else { + if (type.flags & 32 /* StringLiteral */) { + result.push({ + name: type.text, + kindModifiers: ts.ScriptElementKindModifier.none, + kind: ts.ScriptElementKind.variableElement, + sortText: "0" + }); + } + } } - else if (flags & 65536 /* SetAccessor */) { - return ts.SymbolDisplayPartKind.propertyName; + function getStringLiteralCompletionEntriesFromModuleNames(node) { + var literalValue = ts.normalizeSlashes(node.text); + var scriptPath = node.getSourceFile().path; + var scriptDirectory = ts.getDirectoryPath(scriptPath); + var span = getDirectoryFragmentTextSpan(node.text, node.getStart() + 1); + var entries; + if (isPathRelativeToScript(literalValue) || ts.isRootedDiskPath(literalValue)) { + if (compilerOptions.rootDirs) { + entries = getCompletionEntriesForDirectoryFragmentWithRootDirs(compilerOptions.rootDirs, literalValue, scriptDirectory, ts.getSupportedExtensions(compilerOptions), /*includeExtensions*/ false, span, scriptPath); + } + else { + entries = getCompletionEntriesForDirectoryFragment(literalValue, scriptDirectory, ts.getSupportedExtensions(compilerOptions), /*includeExtensions*/ false, span, scriptPath); + } + } + else { + // Check for node modules + entries = getCompletionEntriesForNonRelativeModules(literalValue, scriptDirectory, span); + } + return { + isMemberCompletion: false, + isNewIdentifierLocation: true, + entries: entries + }; } - else if (flags & 8 /* EnumMember */) { - return ts.SymbolDisplayPartKind.enumMemberName; + /** + * Takes a script path and returns paths for all potential folders that could be merged with its + * containing folder via the "rootDirs" compiler option + */ + function getBaseDirectoriesFromRootDirs(rootDirs, basePath, scriptPath, ignoreCase) { + // Make all paths absolute/normalized if they are not already + rootDirs = ts.map(rootDirs, function (rootDirectory) { return ts.normalizePath(ts.isRootedDiskPath(rootDirectory) ? rootDirectory : ts.combinePaths(basePath, rootDirectory)); }); + // Determine the path to the directory containing the script relative to the root directory it is contained within + var relativeDirectory; + for (var _i = 0, rootDirs_1 = rootDirs; _i < rootDirs_1.length; _i++) { + var rootDirectory = rootDirs_1[_i]; + if (ts.containsPath(rootDirectory, scriptPath, basePath, ignoreCase)) { + relativeDirectory = scriptPath.substr(rootDirectory.length); + break; + } + } + // Now find a path for each potential directory that is to be merged with the one containing the script + return ts.deduplicate(ts.map(rootDirs, function (rootDirectory) { return ts.combinePaths(rootDirectory, relativeDirectory); })); } - else if (flags & 16 /* Function */) { - return ts.SymbolDisplayPartKind.functionName; + function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs, fragment, scriptPath, extensions, includeExtensions, span, exclude) { + var basePath = compilerOptions.project || host.getCurrentDirectory(); + var ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames()); + var baseDirectories = getBaseDirectoriesFromRootDirs(rootDirs, basePath, scriptPath, ignoreCase); + var result = []; + for (var _i = 0, baseDirectories_1 = baseDirectories; _i < baseDirectories_1.length; _i++) { + var baseDirectory = baseDirectories_1[_i]; + getCompletionEntriesForDirectoryFragment(fragment, baseDirectory, extensions, includeExtensions, span, exclude, result); + } + return result; } - else if (flags & 32 /* Class */) { - return ts.SymbolDisplayPartKind.className; + function getCompletionEntriesForDirectoryFragment(fragment, scriptPath, extensions, includeExtensions, span, exclude, result) { + if (result === void 0) { result = []; } + fragment = ts.getDirectoryPath(fragment); + if (!fragment) { + fragment = "./"; + } + else { + fragment = ts.ensureTrailingDirectorySeparator(fragment); + } + var absolutePath = normalizeAndPreserveTrailingSlash(ts.isRootedDiskPath(fragment) ? fragment : ts.combinePaths(scriptPath, fragment)); + var baseDirectory = ts.getDirectoryPath(absolutePath); + var ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames()); + if (tryDirectoryExists(host, baseDirectory)) { + // Enumerate the available files if possible + var files = tryReadDirectory(host, baseDirectory, extensions, /*exclude*/ undefined, /*include*/ ["./*"]); + if (files) { + var foundFiles = ts.createMap(); + for (var _i = 0, files_4 = files; _i < files_4.length; _i++) { + var filePath = files_4[_i]; + filePath = ts.normalizePath(filePath); + if (exclude && ts.comparePaths(filePath, exclude, scriptPath, ignoreCase) === 0 /* EqualTo */) { + continue; + } + var foundFileName = includeExtensions ? ts.getBaseFileName(filePath) : ts.removeFileExtension(ts.getBaseFileName(filePath)); + if (!foundFiles[foundFileName]) { + foundFiles[foundFileName] = true; + } + } + for (var foundFile in foundFiles) { + result.push(createCompletionEntryForModule(foundFile, ts.ScriptElementKind.scriptElement, span)); + } + } + // If possible, get folder completion as well + var directories = tryGetDirectories(host, baseDirectory); + if (directories) { + for (var _a = 0, directories_2 = directories; _a < directories_2.length; _a++) { + var directory = directories_2[_a]; + var directoryName = ts.getBaseFileName(ts.normalizePath(directory)); + result.push(createCompletionEntryForModule(directoryName, ts.ScriptElementKind.directory, span)); + } + } + } + return result; } - else if (flags & 64 /* Interface */) { - return ts.SymbolDisplayPartKind.interfaceName; + /** + * Check all of the declared modules and those in node modules. Possible sources of modules: + * Modules that are found by the type checker + * Modules found relative to "baseUrl" compliler options (including patterns from "paths" compiler option) + * Modules from node_modules (i.e. those listed in package.json) + * This includes all files that are found in node_modules/moduleName/ with acceptable file extensions + */ + function getCompletionEntriesForNonRelativeModules(fragment, scriptPath, span) { + var baseUrl = compilerOptions.baseUrl, paths = compilerOptions.paths; + var result; + if (baseUrl) { + var fileExtensions = ts.getSupportedExtensions(compilerOptions); + var projectDir = compilerOptions.project || host.getCurrentDirectory(); + var absolute = ts.isRootedDiskPath(baseUrl) ? baseUrl : ts.combinePaths(projectDir, baseUrl); + result = getCompletionEntriesForDirectoryFragment(fragment, ts.normalizePath(absolute), fileExtensions, /*includeExtensions*/ false, span); + if (paths) { + for (var path in paths) { + if (paths.hasOwnProperty(path)) { + if (path === "*") { + if (paths[path]) { + for (var _i = 0, _a = paths[path]; _i < _a.length; _i++) { + var pattern = _a[_i]; + for (var _b = 0, _c = getModulesForPathsPattern(fragment, baseUrl, pattern, fileExtensions); _b < _c.length; _b++) { + var match = _c[_b]; + result.push(createCompletionEntryForModule(match, ts.ScriptElementKind.externalModuleName, span)); + } + } + } + } + else if (ts.startsWith(path, fragment)) { + var entry = paths[path] && paths[path].length === 1 && paths[path][0]; + if (entry) { + result.push(createCompletionEntryForModule(path, ts.ScriptElementKind.externalModuleName, span)); + } + } + } + } + } + } + else { + result = []; + } + getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, span, result); + for (var _d = 0, _e = enumeratePotentialNonRelativeModules(fragment, scriptPath, compilerOptions); _d < _e.length; _d++) { + var moduleName = _e[_d]; + result.push(createCompletionEntryForModule(moduleName, ts.ScriptElementKind.externalModuleName, span)); + } + return result; } - else if (flags & 384 /* Enum */) { - return ts.SymbolDisplayPartKind.enumName; + function getModulesForPathsPattern(fragment, baseUrl, pattern, fileExtensions) { + if (host.readDirectory) { + var parsed = ts.hasZeroOrOneAsteriskCharacter(pattern) ? ts.tryParsePattern(pattern) : undefined; + if (parsed) { + // The prefix has two effective parts: the directory path and the base component after the filepath that is not a + // full directory component. For example: directory/path/of/prefix/base* + var normalizedPrefix = normalizeAndPreserveTrailingSlash(parsed.prefix); + var normalizedPrefixDirectory = ts.getDirectoryPath(normalizedPrefix); + var normalizedPrefixBase = ts.getBaseFileName(normalizedPrefix); + var fragmentHasPath = fragment.indexOf(ts.directorySeparator) !== -1; + // Try and expand the prefix to include any path from the fragment so that we can limit the readDirectory call + var expandedPrefixDirectory = fragmentHasPath ? ts.combinePaths(normalizedPrefixDirectory, normalizedPrefixBase + ts.getDirectoryPath(fragment)) : normalizedPrefixDirectory; + var normalizedSuffix = ts.normalizePath(parsed.suffix); + var baseDirectory = ts.combinePaths(baseUrl, expandedPrefixDirectory); + var completePrefix = fragmentHasPath ? baseDirectory : ts.ensureTrailingDirectorySeparator(baseDirectory) + normalizedPrefixBase; + // If we have a suffix, then we need to read the directory all the way down. We could create a glob + // that encodes the suffix, but we would have to escape the character "?" which readDirectory + // doesn't support. For now, this is safer but slower + var includeGlob = normalizedSuffix ? "**/*" : "./*"; + var matches = tryReadDirectory(host, baseDirectory, fileExtensions, undefined, [includeGlob]); + if (matches) { + var result = []; + // Trim away prefix and suffix + for (var _i = 0, matches_1 = matches; _i < matches_1.length; _i++) { + var match = matches_1[_i]; + var normalizedMatch = ts.normalizePath(match); + if (!ts.endsWith(normalizedMatch, normalizedSuffix) || !ts.startsWith(normalizedMatch, completePrefix)) { + continue; + } + var start = completePrefix.length; + var length_6 = normalizedMatch.length - start - normalizedSuffix.length; + result.push(ts.removeFileExtension(normalizedMatch.substr(start, length_6))); + } + return result; + } + } + } + return undefined; } - else if (flags & 1536 /* Module */) { - return ts.SymbolDisplayPartKind.moduleName; + function enumeratePotentialNonRelativeModules(fragment, scriptPath, options) { + // Check If this is a nested module + var isNestedModule = fragment.indexOf(ts.directorySeparator) !== -1; + var moduleNameFragment = isNestedModule ? fragment.substr(0, fragment.lastIndexOf(ts.directorySeparator)) : undefined; + // Get modules that the type checker picked up + var ambientModules = ts.map(typeChecker.getAmbientModules(), function (sym) { return ts.stripQuotes(sym.name); }); + var nonRelativeModules = ts.filter(ambientModules, function (moduleName) { return ts.startsWith(moduleName, fragment); }); + // Nested modules of the form "module-name/sub" need to be adjusted to only return the string + // after the last '/' that appears in the fragment because that's where the replacement span + // starts + if (isNestedModule) { + var moduleNameWithSeperator_1 = ts.ensureTrailingDirectorySeparator(moduleNameFragment); + nonRelativeModules = ts.map(nonRelativeModules, function (moduleName) { + if (ts.startsWith(fragment, moduleNameWithSeperator_1)) { + return moduleName.substr(moduleNameWithSeperator_1.length); + } + return moduleName; + }); + } + if (!options.moduleResolution || options.moduleResolution === ts.ModuleResolutionKind.NodeJs) { + for (var _i = 0, _a = enumerateNodeModulesVisibleToScript(host, scriptPath); _i < _a.length; _i++) { + var visibleModule = _a[_i]; + if (!isNestedModule) { + nonRelativeModules.push(visibleModule.moduleName); + } + else if (ts.startsWith(visibleModule.moduleName, moduleNameFragment)) { + var nestedFiles = tryReadDirectory(host, visibleModule.moduleDir, ts.supportedTypeScriptExtensions, /*exclude*/ undefined, /*include*/ ["./*"]); + if (nestedFiles) { + for (var _b = 0, nestedFiles_1 = nestedFiles; _b < nestedFiles_1.length; _b++) { + var f = nestedFiles_1[_b]; + f = ts.normalizePath(f); + var nestedModule = ts.removeFileExtension(ts.getBaseFileName(f)); + nonRelativeModules.push(nestedModule); + } + } + } + } + } + return ts.deduplicate(nonRelativeModules); } - else if (flags & 8192 /* Method */) { - return ts.SymbolDisplayPartKind.methodName; + function getTripleSlashReferenceCompletion(sourceFile, position) { + var token = ts.getTokenAtPosition(sourceFile, position); + if (!token) { + return undefined; + } + var commentRanges = ts.getLeadingCommentRanges(sourceFile.text, token.pos); + if (!commentRanges || !commentRanges.length) { + return undefined; + } + var range = ts.forEach(commentRanges, function (commentRange) { return position >= commentRange.pos && position <= commentRange.end && commentRange; }); + if (!range) { + return undefined; + } + var text = sourceFile.text.substr(range.pos, position - range.pos); + var match = tripleSlashDirectiveFragmentRegex.exec(text); + if (match) { + var prefix = match[1]; + var kind = match[2]; + var toComplete = match[3]; + var scriptPath = ts.getDirectoryPath(sourceFile.path); + var entries_3; + if (kind === "path") { + // Give completions for a relative path + var span_10 = getDirectoryFragmentTextSpan(toComplete, range.pos + prefix.length); + entries_3 = getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, ts.getSupportedExtensions(compilerOptions), /*includeExtensions*/ true, span_10, sourceFile.path); + } + else { + // Give completions based on the typings available + var span_11 = { start: range.pos + prefix.length, length: match[0].length - prefix.length }; + entries_3 = getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, span_11); + } + return { + isMemberCompletion: false, + isNewIdentifierLocation: true, + entries: entries_3 + }; + } + return undefined; } - else if (flags & 262144 /* TypeParameter */) { - return ts.SymbolDisplayPartKind.typeParameterName; + function getCompletionEntriesFromTypings(host, options, scriptPath, span, result) { + if (result === void 0) { result = []; } + // Check for typings specified in compiler options + if (options.types) { + for (var _i = 0, _a = options.types; _i < _a.length; _i++) { + var moduleName = _a[_i]; + result.push(createCompletionEntryForModule(moduleName, ts.ScriptElementKind.externalModuleName, span)); + } + } + else if (host.getDirectories) { + var typeRoots = void 0; + try { + // Wrap in try catch because getEffectiveTypeRoots touches the filesystem + typeRoots = ts.getEffectiveTypeRoots(options, host); + } + catch (e) { } + if (typeRoots) { + for (var _b = 0, typeRoots_2 = typeRoots; _b < typeRoots_2.length; _b++) { + var root = typeRoots_2[_b]; + getCompletionEntriesFromDirectories(host, options, root, span, result); + } + } + } + if (host.getDirectories) { + // Also get all @types typings installed in visible node_modules directories + for (var _c = 0, _d = findPackageJsons(scriptPath); _c < _d.length; _c++) { + var packageJson = _d[_c]; + var typesDir = ts.combinePaths(ts.getDirectoryPath(packageJson), "node_modules/@types"); + getCompletionEntriesFromDirectories(host, options, typesDir, span, result); + } + } + return result; } - else if (flags & 524288 /* TypeAlias */) { - return ts.SymbolDisplayPartKind.aliasName; + function getCompletionEntriesFromDirectories(host, options, directory, span, result) { + if (host.getDirectories && tryDirectoryExists(host, directory)) { + var directories = tryGetDirectories(host, directory); + if (directories) { + for (var _i = 0, directories_3 = directories; _i < directories_3.length; _i++) { + var typeDirectory = directories_3[_i]; + typeDirectory = ts.normalizePath(typeDirectory); + result.push(createCompletionEntryForModule(ts.getBaseFileName(typeDirectory), ts.ScriptElementKind.externalModuleName, span)); + } + } + } } - else if (flags & 8388608 /* Alias */) { - return ts.SymbolDisplayPartKind.aliasName; + function findPackageJsons(currentDir) { + var paths = []; + var currentConfigPath; + while (true) { + currentConfigPath = ts.findConfigFile(currentDir, function (f) { return tryFileExists(host, f); }, "package.json"); + if (currentConfigPath) { + paths.push(currentConfigPath); + currentDir = ts.getDirectoryPath(currentConfigPath); + var parent_16 = ts.getDirectoryPath(currentDir); + if (currentDir === parent_16) { + break; + } + currentDir = parent_16; + } + else { + break; + } + } + return paths; } - return ts.SymbolDisplayPartKind.text; - } - } - ts.symbolPart = symbolPart; - function displayPart(text, kind, symbol) { - return { - text: text, - kind: ts.SymbolDisplayPartKind[kind] - }; - } - ts.displayPart = displayPart; - function spacePart() { - return displayPart(" ", ts.SymbolDisplayPartKind.space); - } - ts.spacePart = spacePart; - function keywordPart(kind) { - return displayPart(ts.tokenToString(kind), ts.SymbolDisplayPartKind.keyword); - } - ts.keywordPart = keywordPart; - function punctuationPart(kind) { - return displayPart(ts.tokenToString(kind), ts.SymbolDisplayPartKind.punctuation); - } - ts.punctuationPart = punctuationPart; - function operatorPart(kind) { - return displayPart(ts.tokenToString(kind), ts.SymbolDisplayPartKind.operator); - } - ts.operatorPart = operatorPart; - function textOrKeywordPart(text) { - var kind = ts.stringToToken(text); - return kind === undefined - ? textPart(text) - : keywordPart(kind); - } - ts.textOrKeywordPart = textOrKeywordPart; - function textPart(text) { - return displayPart(text, ts.SymbolDisplayPartKind.text); - } - ts.textPart = textPart; - var carriageReturnLineFeed = "\r\n"; - /** - * The default is CRLF. - */ - function getNewLineOrDefaultFromHost(host) { - return host.getNewLine ? host.getNewLine() : carriageReturnLineFeed; - } - ts.getNewLineOrDefaultFromHost = getNewLineOrDefaultFromHost; - function lineBreakPart() { - return displayPart("\n", ts.SymbolDisplayPartKind.lineBreak); - } - ts.lineBreakPart = lineBreakPart; - function mapToDisplayParts(writeDisplayParts) { - writeDisplayParts(displayPartWriter); - var result = displayPartWriter.displayParts(); - displayPartWriter.clear(); - return result; - } - ts.mapToDisplayParts = mapToDisplayParts; - function typeToDisplayParts(typechecker, type, enclosingDeclaration, flags) { - return mapToDisplayParts(function (writer) { - typechecker.getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags); - }); - } - ts.typeToDisplayParts = typeToDisplayParts; - function symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration, meaning, flags) { - return mapToDisplayParts(function (writer) { - typeChecker.getSymbolDisplayBuilder().buildSymbolDisplay(symbol, writer, enclosingDeclaration, meaning, flags); - }); - } - ts.symbolToDisplayParts = symbolToDisplayParts; - function signatureToDisplayParts(typechecker, signature, enclosingDeclaration, flags) { - return mapToDisplayParts(function (writer) { - typechecker.getSymbolDisplayBuilder().buildSignatureDisplay(signature, writer, enclosingDeclaration, flags); - }); - } - ts.signatureToDisplayParts = signatureToDisplayParts; - function getDeclaredName(typeChecker, symbol, location) { - // If this is an export or import specifier it could have been renamed using the 'as' syntax. - // If so we want to search for whatever is under the cursor. - if (isImportOrExportSpecifierName(location)) { - return location.getText(); - } - else if (ts.isStringOrNumericLiteral(location.kind) && - location.parent.kind === 140 /* ComputedPropertyName */) { - return location.text; - } - // Try to get the local symbol if we're dealing with an 'export default' - // since that symbol has the "true" name. - var localExportDefaultSymbol = ts.getLocalSymbolForExportDefault(symbol); - var name = typeChecker.symbolToString(localExportDefaultSymbol || symbol); - return name; - } - ts.getDeclaredName = getDeclaredName; - function isImportOrExportSpecifierName(location) { - return location.parent && - (location.parent.kind === 234 /* ImportSpecifier */ || location.parent.kind === 238 /* ExportSpecifier */) && - location.parent.propertyName === location; - } - ts.isImportOrExportSpecifierName = isImportOrExportSpecifierName; - /** - * Strip off existed single quotes or double quotes from a given string - * - * @return non-quoted string - */ - function stripQuotes(name) { - var length = name.length; - if (length >= 2 && - name.charCodeAt(0) === name.charCodeAt(length - 1) && - (name.charCodeAt(0) === 34 /* doubleQuote */ || name.charCodeAt(0) === 39 /* singleQuote */)) { - return name.substring(1, length - 1); - } - ; - return name; - } - ts.stripQuotes = stripQuotes; - function scriptKindIs(fileName, host) { - var scriptKinds = []; - for (var _i = 2; _i < arguments.length; _i++) { - scriptKinds[_i - 2] = arguments[_i]; - } - var scriptKind = getScriptKind(fileName, host); - return ts.forEach(scriptKinds, function (k) { return k === scriptKind; }); - } - ts.scriptKindIs = scriptKindIs; - function getScriptKind(fileName, host) { - // First check to see if the script kind was specified by the host. Chances are the host - // may override the default script kind for the file extension. - var scriptKind; - if (host && host.getScriptKind) { - scriptKind = host.getScriptKind(fileName); - } - if (!scriptKind) { - scriptKind = ts.getScriptKindFromFileName(fileName); - } - return ts.ensureScriptKind(fileName, scriptKind); - } - ts.getScriptKind = getScriptKind; - function parseAndReEmitConfigJSONFile(content) { - var options = { - fileName: "config.js", - compilerOptions: { - target: 2 /* ES6 */, - removeComments: true - }, - reportDiagnostics: true - }; - var _a = ts.transpileModule("(" + content + ")", options), outputText = _a.outputText, diagnostics = _a.diagnostics; - // Becasue the content was wrapped in "()", the start position of diagnostics needs to be subtract by 1 - // also, the emitted result will have "(" in the beginning and ");" in the end. We need to strip these - // as well - var trimmedOutput = outputText.trim(); - var configJsonObject = JSON.parse(trimmedOutput.substring(1, trimmedOutput.length - 2)); - for (var _i = 0, diagnostics_4 = diagnostics; _i < diagnostics_4.length; _i++) { - var diagnostic = diagnostics_4[_i]; - diagnostic.start = diagnostic.start - 1; - } - return { configJsonObject: configJsonObject, diagnostics: diagnostics }; - } - ts.parseAndReEmitConfigJSONFile = parseAndReEmitConfigJSONFile; -})(ts || (ts = {})); -// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0. -// See LICENSE.txt in the project root for complete license information. -/// -/* @internal */ -var ts; -(function (ts) { - var JsTyping; - (function (JsTyping) { - ; - ; - // A map of loose file names to library names - // that we are confident require typings - var safeList; - /** - * @param host is the object providing I/O related operations. - * @param fileNames are the file names that belong to the same project - * @param projectRootPath is the path to the project root directory - * @param safeListPath is the path used to retrieve the safe list - * @param packageNameToTypingLocation is the map of package names to their cached typing locations - * @param typingOptions are used to customize the typing inference process - * @param compilerOptions are used as a source for typing inference - */ - function discoverTypings(host, fileNames, projectRootPath, safeListPath, packageNameToTypingLocation, typingOptions, compilerOptions) { - // A typing name to typing file path mapping - var inferredTypings = ts.createMap(); - if (!typingOptions || !typingOptions.enableAutoDiscovery) { - return { cachedTypingPaths: [], newTypingNames: [], filesToWatch: [] }; + function enumerateNodeModulesVisibleToScript(host, scriptPath) { + var result = []; + if (host.readFile && host.fileExists) { + for (var _i = 0, _a = findPackageJsons(scriptPath); _i < _a.length; _i++) { + var packageJson = _a[_i]; + var contents = tryReadingPackageJson(packageJson); + if (!contents) { + return; + } + var nodeModulesDir = ts.combinePaths(ts.getDirectoryPath(packageJson), "node_modules"); + var foundModuleNames = []; + // Provide completions for all non @types dependencies + for (var _b = 0, nodeModulesDependencyKeys_1 = nodeModulesDependencyKeys; _b < nodeModulesDependencyKeys_1.length; _b++) { + var key = nodeModulesDependencyKeys_1[_b]; + addPotentialPackageNames(contents[key], foundModuleNames); + } + for (var _c = 0, foundModuleNames_1 = foundModuleNames; _c < foundModuleNames_1.length; _c++) { + var moduleName = foundModuleNames_1[_c]; + var moduleDir = ts.combinePaths(nodeModulesDir, moduleName); + result.push({ + moduleName: moduleName, + moduleDir: moduleDir + }); + } + } + } + return result; + function tryReadingPackageJson(filePath) { + try { + var fileText = tryReadFile(host, filePath); + return fileText ? JSON.parse(fileText) : undefined; + } + catch (e) { + return undefined; + } + } + function addPotentialPackageNames(dependencies, result) { + if (dependencies) { + for (var dep in dependencies) { + if (dependencies.hasOwnProperty(dep) && !ts.startsWith(dep, "@types/")) { + result.push(dep); + } + } + } + } } - // Only infer typings for .js and .jsx files - fileNames = ts.filter(ts.map(fileNames, ts.normalizePath), function (f) { return ts.scriptKindIs(f, /*LanguageServiceHost*/ undefined, 1 /* JS */, 2 /* JSX */); }); - if (!safeList) { - var result = ts.readConfigFile(safeListPath, function (path) { return host.readFile(path); }); - safeList = ts.createMap(result.config); + function createCompletionEntryForModule(name, kind, replacementSpan) { + return { name: name, kind: kind, kindModifiers: ts.ScriptElementKindModifier.none, sortText: name, replacementSpan: replacementSpan }; } - var filesToWatch = []; - // Directories to search for package.json, bower.json and other typing information - var searchDirs = []; - var exclude = []; - mergeTypings(typingOptions.include); - exclude = typingOptions.exclude || []; - var possibleSearchDirs = ts.map(fileNames, ts.getDirectoryPath); - if (projectRootPath !== undefined) { - possibleSearchDirs.push(projectRootPath); + // Replace everything after the last directory seperator that appears + function getDirectoryFragmentTextSpan(text, textStart) { + var index = text.lastIndexOf(ts.directorySeparator); + var offset = index !== -1 ? index + 1 : 0; + return { start: textStart + offset, length: text.length - offset }; } - searchDirs = ts.deduplicate(possibleSearchDirs); - for (var _i = 0, searchDirs_1 = searchDirs; _i < searchDirs_1.length; _i++) { - var searchDir = searchDirs_1[_i]; - var packageJsonPath = ts.combinePaths(searchDir, "package.json"); - getTypingNamesFromJson(packageJsonPath, filesToWatch); - var bowerJsonPath = ts.combinePaths(searchDir, "bower.json"); - getTypingNamesFromJson(bowerJsonPath, filesToWatch); - var nodeModulesPath = ts.combinePaths(searchDir, "node_modules"); - getTypingNamesFromNodeModuleFolder(nodeModulesPath); + // Returns true if the path is explicitly relative to the script (i.e. relative to . or ..) + function isPathRelativeToScript(path) { + if (path && path.length >= 2 && path.charCodeAt(0) === 46 /* dot */) { + var slashIndex = path.length >= 3 && path.charCodeAt(1) === 46 /* dot */ ? 2 : 1; + var slashCharCode = path.charCodeAt(slashIndex); + return slashCharCode === 47 /* slash */ || slashCharCode === 92 /* backslash */; + } + return false; } - getTypingNamesFromSourceFileNames(fileNames); - // Add the cached typing locations for inferred typings that are already installed - for (var name_39 in packageNameToTypingLocation) { - if (name_39 in inferredTypings && !inferredTypings[name_39]) { - inferredTypings[name_39] = packageNameToTypingLocation[name_39]; + function normalizeAndPreserveTrailingSlash(path) { + return ts.hasTrailingDirectorySeparator(path) ? ts.ensureTrailingDirectorySeparator(ts.normalizePath(path)) : ts.normalizePath(path); + } + } + Completions.getCompletionsAtPosition = getCompletionsAtPosition; + function getCompletionEntryDetails(typeChecker, log, compilerOptions, sourceFile, position, entryName) { + // Compute all the completion symbols again. + var completionData = getCompletionData(typeChecker, log, sourceFile, position); + if (completionData) { + var symbols = completionData.symbols, location_2 = completionData.location; + // Find the symbol with the matching entry name. + // We don't need to perform character checks here because we're only comparing the + // name against 'entryName' (which is known to be good), not building a new + // completion entry. + var symbol = ts.forEach(symbols, function (s) { return getCompletionEntryDisplayNameForSymbol(typeChecker, s, compilerOptions.target, /*performCharacterChecks*/ false, location_2) === entryName ? s : undefined; }); + if (symbol) { + var _a = ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, sourceFile, location_2, location_2, 7 /* All */), displayParts = _a.displayParts, documentation = _a.documentation, symbolKind = _a.symbolKind; + return { + name: entryName, + kindModifiers: ts.SymbolDisplay.getSymbolModifiers(symbol), + kind: symbolKind, + displayParts: displayParts, + documentation: documentation + }; } } - // Remove typings that the user has added to the exclude list - for (var _a = 0, exclude_1 = exclude; _a < exclude_1.length; _a++) { - var excludeTypingName = exclude_1[_a]; - delete inferredTypings[excludeTypingName]; + // Didn't find a symbol with this name. See if we can find a keyword instead. + var keywordCompletion = ts.forEach(keywordCompletions, function (c) { return c.name === entryName; }); + if (keywordCompletion) { + return { + name: entryName, + kind: ts.ScriptElementKind.keyword, + kindModifiers: ts.ScriptElementKindModifier.none, + displayParts: [ts.displayPart(entryName, ts.SymbolDisplayPartKind.keyword)], + documentation: undefined + }; } - var newTypingNames = []; - var cachedTypingPaths = []; - for (var typing in inferredTypings) { - if (inferredTypings[typing] !== undefined) { - cachedTypingPaths.push(inferredTypings[typing]); + return undefined; + } + Completions.getCompletionEntryDetails = getCompletionEntryDetails; + function getCompletionEntrySymbol(typeChecker, log, compilerOptions, sourceFile, position, entryName) { + // Compute all the completion symbols again. + var completionData = getCompletionData(typeChecker, log, sourceFile, position); + if (completionData) { + var symbols = completionData.symbols, location_3 = completionData.location; + // Find the symbol with the matching entry name. + // We don't need to perform character checks here because we're only comparing the + // name against 'entryName' (which is known to be good), not building a new + // completion entry. + return ts.forEach(symbols, function (s) { return getCompletionEntryDisplayNameForSymbol(typeChecker, s, compilerOptions.target, /*performCharacterChecks*/ false, location_3) === entryName ? s : undefined; }); + } + return undefined; + } + Completions.getCompletionEntrySymbol = getCompletionEntrySymbol; + function getCompletionData(typeChecker, log, sourceFile, position) { + var isJavaScriptFile = ts.isSourceFileJavaScript(sourceFile); + var isJsDocTagName = false; + var start = ts.timestamp(); + var currentToken = ts.getTokenAtPosition(sourceFile, position); + log("getCompletionData: Get current token: " + (ts.timestamp() - start)); + start = ts.timestamp(); + // Completion not allowed inside comments, bail out if this is the case + var insideComment = ts.isInsideComment(sourceFile, currentToken, position); + log("getCompletionData: Is inside comment: " + (ts.timestamp() - start)); + if (insideComment) { + // The current position is next to the '@' sign, when no tag name being provided yet. + // Provide a full list of tag names + if (ts.hasDocComment(sourceFile, position) && sourceFile.text.charCodeAt(position - 1) === 64 /* at */) { + isJsDocTagName = true; } - else { - newTypingNames.push(typing); + // Completion should work inside certain JsDoc tags. For example: + // /** @type {number | string} */ + // Completion should work in the brackets + var insideJsDocTagExpression = false; + var tag = ts.getJsDocTagAtPosition(sourceFile, position); + if (tag) { + if (tag.tagName.pos <= position && position <= tag.tagName.end) { + isJsDocTagName = true; + } + switch (tag.kind) { + case 277 /* JSDocTypeTag */: + case 275 /* JSDocParameterTag */: + case 276 /* JSDocReturnTag */: + var tagWithExpression = tag; + if (tagWithExpression.typeExpression) { + insideJsDocTagExpression = tagWithExpression.typeExpression.pos < position && position < tagWithExpression.typeExpression.end; + } + break; + } } + if (isJsDocTagName) { + return { symbols: undefined, isMemberCompletion: false, isNewIdentifierLocation: false, location: undefined, isRightOfDot: false, isJsDocTagName: isJsDocTagName }; + } + if (!insideJsDocTagExpression) { + // Proceed if the current position is in jsDoc tag expression; otherwise it is a normal + // comment or the plain text part of a jsDoc comment, so no completion should be available + log("Returning an empty list because completion was inside a regular comment or plain text part of a JsDoc comment."); + return undefined; + } + } + start = ts.timestamp(); + var previousToken = ts.findPrecedingToken(position, sourceFile); + log("getCompletionData: Get previous token 1: " + (ts.timestamp() - start)); + // The decision to provide completion depends on the contextToken, which is determined through the previousToken. + // Note: 'previousToken' (and thus 'contextToken') can be undefined if we are the beginning of the file + var contextToken = previousToken; + // Check if the caret is at the end of an identifier; this is a partial identifier that we want to complete: e.g. a.toS| + // Skip this partial identifier and adjust the contextToken to the token that precedes it. + if (contextToken && position <= contextToken.end && ts.isWord(contextToken.kind)) { + var start_2 = ts.timestamp(); + contextToken = ts.findPrecedingToken(contextToken.getFullStart(), sourceFile); + log("getCompletionData: Get previous token 2: " + (ts.timestamp() - start_2)); } - return { cachedTypingPaths: cachedTypingPaths, newTypingNames: newTypingNames, filesToWatch: filesToWatch }; - /** - * Merge a given list of typingNames to the inferredTypings map - */ - function mergeTypings(typingNames) { - if (!typingNames) { - return; + // Find the node where completion is requested on. + // Also determine whether we are trying to complete with members of that node + // or attributes of a JSX tag. + var node = currentToken; + var isRightOfDot = false; + var isRightOfOpenTag = false; + var isStartingCloseTag = false; + var location = ts.getTouchingPropertyName(sourceFile, position); + if (contextToken) { + // Bail out if this is a known invalid completion location + if (isCompletionListBlocker(contextToken)) { + log("Returning an empty list because completion was requested in an invalid position."); + return undefined; } - for (var _i = 0, typingNames_1 = typingNames; _i < typingNames_1.length; _i++) { - var typing = typingNames_1[_i]; - if (!(typing in inferredTypings)) { - inferredTypings[typing] = undefined; + var parent_17 = contextToken.parent, kind = contextToken.kind; + if (kind === 21 /* DotToken */) { + if (parent_17.kind === 172 /* PropertyAccessExpression */) { + node = contextToken.parent.expression; + isRightOfDot = true; } - } - } - /** - * Get the typing info from common package manager json files like package.json or bower.json - */ - function getTypingNamesFromJson(jsonPath, filesToWatch) { - var result = ts.readConfigFile(jsonPath, function (path) { return host.readFile(path); }); - if (result.config) { - var jsonConfig = result.config; - filesToWatch.push(jsonPath); - if (jsonConfig.dependencies) { - mergeTypings(ts.getOwnKeys(jsonConfig.dependencies)); + else if (parent_17.kind === 139 /* QualifiedName */) { + node = contextToken.parent.left; + isRightOfDot = true; } - if (jsonConfig.devDependencies) { - mergeTypings(ts.getOwnKeys(jsonConfig.devDependencies)); + else { + // There is nothing that precedes the dot, so this likely just a stray character + // or leading into a '...' token. Just bail out instead. + return undefined; } - if (jsonConfig.optionalDependencies) { - mergeTypings(ts.getOwnKeys(jsonConfig.optionalDependencies)); + } + else if (sourceFile.languageVariant === 1 /* JSX */) { + if (kind === 25 /* LessThanToken */) { + isRightOfOpenTag = true; + location = contextToken; } - if (jsonConfig.peerDependencies) { - mergeTypings(ts.getOwnKeys(jsonConfig.peerDependencies)); + else if (kind === 39 /* SlashToken */ && contextToken.parent.kind === 245 /* JsxClosingElement */) { + isStartingCloseTag = true; + location = contextToken; } } } - /** - * Infer typing names from given file names. For example, the file name "jquery-min.2.3.4.js" - * should be inferred to the 'jquery' typing name; and "angular-route.1.2.3.js" should be inferred - * to the 'angular-route' typing name. - * @param fileNames are the names for source files in the project - */ - function getTypingNamesFromSourceFileNames(fileNames) { - var jsFileNames = ts.filter(fileNames, ts.hasJavaScriptFileExtension); - var inferredTypingNames = ts.map(jsFileNames, function (f) { return ts.removeFileExtension(ts.getBaseFileName(f.toLowerCase())); }); - var cleanedTypingNames = ts.map(inferredTypingNames, function (f) { return f.replace(/((?:\.|-)min(?=\.|$))|((?:-|\.)\d+)/g, ""); }); - if (safeList === undefined) { - mergeTypings(cleanedTypingNames); + var semanticStart = ts.timestamp(); + var isMemberCompletion; + var isNewIdentifierLocation; + var symbols = []; + if (isRightOfDot) { + getTypeScriptMemberSymbols(); + } + else if (isRightOfOpenTag) { + var tagSymbols = typeChecker.getJsxIntrinsicTagNames(); + if (tryGetGlobalSymbols()) { + symbols = tagSymbols.concat(symbols.filter(function (s) { return !!(s.flags & (107455 /* Value */ | 8388608 /* Alias */)); })); } else { - mergeTypings(ts.filter(cleanedTypingNames, function (f) { return f in safeList; })); + symbols = tagSymbols; } - var hasJsxFile = ts.forEach(fileNames, function (f) { return ts.scriptKindIs(f, /*LanguageServiceHost*/ undefined, 2 /* JSX */); }); - if (hasJsxFile) { - mergeTypings(["react"]); + isMemberCompletion = true; + isNewIdentifierLocation = false; + } + else if (isStartingCloseTag) { + var tagName = contextToken.parent.parent.openingElement.tagName; + var tagSymbol = typeChecker.getSymbolAtLocation(tagName); + if (!typeChecker.isUnknownSymbol(tagSymbol)) { + symbols = [tagSymbol]; } + isMemberCompletion = true; + isNewIdentifierLocation = false; } - /** - * Infer typing names from node_module folder - * @param nodeModulesPath is the path to the "node_modules" folder - */ - function getTypingNamesFromNodeModuleFolder(nodeModulesPath) { - // Todo: add support for ModuleResolutionHost too - if (!host.directoryExists(nodeModulesPath)) { - return; + else { + // For JavaScript or TypeScript, if we're not after a dot, then just try to get the + // global symbols in scope. These results should be valid for either language as + // the set of symbols that can be referenced from this location. + if (!tryGetGlobalSymbols()) { + return undefined; } - var typingNames = []; - var fileNames = host.readDirectory(nodeModulesPath, ["*.json"], /*excludes*/ undefined, /*includes*/ undefined, /*depth*/ 2); - for (var _i = 0, fileNames_2 = fileNames; _i < fileNames_2.length; _i++) { - var fileName = fileNames_2[_i]; - var normalizedFileName = ts.normalizePath(fileName); - if (ts.getBaseFileName(normalizedFileName) !== "package.json") { - continue; - } - var result = ts.readConfigFile(normalizedFileName, function (path) { return host.readFile(path); }); - if (!result.config) { - continue; - } - var packageJson = result.config; - // npm 3's package.json contains a "_requiredBy" field - // we should include all the top level module names for npm 2, and only module names whose - // "_requiredBy" field starts with "#" or equals "/" for npm 3. - if (packageJson._requiredBy && - ts.filter(packageJson._requiredBy, function (r) { return r[0] === "#" || r === "/"; }).length === 0) { - continue; + } + log("getCompletionData: Semantic work: " + (ts.timestamp() - semanticStart)); + return { symbols: symbols, isMemberCompletion: isMemberCompletion, isNewIdentifierLocation: isNewIdentifierLocation, location: location, isRightOfDot: (isRightOfDot || isRightOfOpenTag), isJsDocTagName: isJsDocTagName }; + function getTypeScriptMemberSymbols() { + // Right of dot member completion list + isMemberCompletion = true; + isNewIdentifierLocation = false; + if (node.kind === 69 /* Identifier */ || node.kind === 139 /* QualifiedName */ || node.kind === 172 /* PropertyAccessExpression */) { + var symbol = typeChecker.getSymbolAtLocation(node); + // This is an alias, follow what it aliases + if (symbol && symbol.flags & 8388608 /* Alias */) { + symbol = typeChecker.getAliasedSymbol(symbol); } - // If the package has its own d.ts typings, those will take precedence. Otherwise the package name will be used - // to download d.ts files from DefinitelyTyped - if (!packageJson.name) { - continue; + if (symbol && symbol.flags & 1952 /* HasExports */) { + // Extract module or enum members + var exportedSymbols = typeChecker.getExportsOfModule(symbol); + ts.forEach(exportedSymbols, function (symbol) { + if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) { + symbols.push(symbol); + } + }); } - if (packageJson.typings) { - var absolutePath = ts.getNormalizedAbsolutePath(packageJson.typings, ts.getDirectoryPath(normalizedFileName)); - inferredTypings[packageJson.name] = absolutePath; + } + var type = typeChecker.getTypeAtLocation(node); + addTypeProperties(type); + } + function addTypeProperties(type) { + if (type) { + // Filter private properties + for (var _i = 0, _a = type.getApparentProperties(); _i < _a.length; _i++) { + var symbol = _a[_i]; + if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) { + symbols.push(symbol); + } } - else { - typingNames.push(packageJson.name); + if (isJavaScriptFile && type.flags & 524288 /* Union */) { + // In javascript files, for union types, we don't just get the members that + // the individual types have in common, we also include all the members that + // each individual type has. This is because we're going to add all identifiers + // anyways. So we might as well elevate the members that were at least part + // of the individual types to a higher status since we know what they are. + var unionType = type; + for (var _b = 0, _c = unionType.types; _b < _c.length; _b++) { + var elementType = _c[_b]; + addTypeProperties(elementType); + } } } - mergeTypings(typingNames); } - } - JsTyping.discoverTypings = discoverTypings; - })(JsTyping = ts.JsTyping || (ts.JsTyping = {})); -})(ts || (ts = {})); -/// -/// -/* @internal */ -var ts; -(function (ts) { - var formatting; - (function (formatting) { - var standardScanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ false, 0 /* Standard */); - var jsxScanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ false, 1 /* JSX */); - /** - * Scanner that is currently used for formatting - */ - var scanner; - var ScanAction; - (function (ScanAction) { - ScanAction[ScanAction["Scan"] = 0] = "Scan"; - ScanAction[ScanAction["RescanGreaterThanToken"] = 1] = "RescanGreaterThanToken"; - ScanAction[ScanAction["RescanSlashToken"] = 2] = "RescanSlashToken"; - ScanAction[ScanAction["RescanTemplateToken"] = 3] = "RescanTemplateToken"; - ScanAction[ScanAction["RescanJsxIdentifier"] = 4] = "RescanJsxIdentifier"; - ScanAction[ScanAction["RescanJsxText"] = 5] = "RescanJsxText"; - })(ScanAction || (ScanAction = {})); - function getFormattingScanner(sourceFile, startPos, endPos) { - ts.Debug.assert(scanner === undefined); - scanner = sourceFile.languageVariant === 1 /* JSX */ ? jsxScanner : standardScanner; - scanner.setText(sourceFile.text); - scanner.setTextPos(startPos); - var wasNewLine = true; - var leadingTrivia; - var trailingTrivia; - var savedPos; - var lastScanAction; - var lastTokenInfo; - return { - advance: advance, - readTokenInfo: readTokenInfo, - isOnToken: isOnToken, - getCurrentLeadingTrivia: function () { return leadingTrivia; }, - lastTrailingTriviaWasNewLine: function () { return wasNewLine; }, - skipToEndOf: skipToEndOf, - close: function () { - ts.Debug.assert(scanner !== undefined); - lastTokenInfo = undefined; - scanner.setText(undefined); - scanner = undefined; + function tryGetGlobalSymbols() { + var objectLikeContainer; + var namedImportsOrExports; + var jsxContainer; + if (objectLikeContainer = tryGetObjectLikeCompletionContainer(contextToken)) { + return tryGetObjectLikeCompletionSymbols(objectLikeContainer); } - }; - function advance() { - ts.Debug.assert(scanner !== undefined); - lastTokenInfo = undefined; - var isStarted = scanner.getStartPos() !== startPos; - if (isStarted) { - if (trailingTrivia) { - ts.Debug.assert(trailingTrivia.length !== 0); - wasNewLine = ts.lastOrUndefined(trailingTrivia).kind === 4 /* NewLineTrivia */; - } - else { - wasNewLine = false; + if (namedImportsOrExports = tryGetNamedImportsOrExportsForCompletion(contextToken)) { + // cursor is in an import clause + // try to show exported member for imported module + return tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports); + } + if (jsxContainer = tryGetContainingJsxElement(contextToken)) { + var attrsType = void 0; + if ((jsxContainer.kind === 242 /* JsxSelfClosingElement */) || (jsxContainer.kind === 243 /* JsxOpeningElement */)) { + // Cursor is inside a JSX self-closing element or opening element + attrsType = typeChecker.getJsxElementAttributesType(jsxContainer); + if (attrsType) { + symbols = filterJsxAttributes(typeChecker.getPropertiesOfType(attrsType), jsxContainer.attributes); + isMemberCompletion = true; + isNewIdentifierLocation = false; + return true; + } } } - leadingTrivia = undefined; - trailingTrivia = undefined; - if (!isStarted) { - scanner.scan(); + // Get all entities in the current scope. + isMemberCompletion = false; + isNewIdentifierLocation = isNewIdentifierDefinitionLocation(contextToken); + if (previousToken !== contextToken) { + ts.Debug.assert(!!previousToken, "Expected 'contextToken' to be defined when different from 'previousToken'."); } - var pos = scanner.getStartPos(); - // Read leading trivia and token - while (pos < endPos) { - var t = scanner.getToken(); - if (!ts.isTrivia(t)) { - break; + // We need to find the node that will give us an appropriate scope to begin + // aggregating completion candidates. This is achieved in 'getScopeNode' + // by finding the first node that encompasses a position, accounting for whether a node + // is "complete" to decide whether a position belongs to the node. + // + // However, at the end of an identifier, we are interested in the scope of the identifier + // itself, but fall outside of the identifier. For instance: + // + // xyz => x$ + // + // the cursor is outside of both the 'x' and the arrow function 'xyz => x', + // so 'xyz' is not returned in our results. + // + // We define 'adjustedPosition' so that we may appropriately account for + // being at the end of an identifier. The intention is that if requesting completion + // at the end of an identifier, it should be effectively equivalent to requesting completion + // anywhere inside/at the beginning of the identifier. So in the previous case, the + // 'adjustedPosition' will work as if requesting completion in the following: + // + // xyz => $x + // + // If previousToken !== contextToken, then + // - 'contextToken' was adjusted to the token prior to 'previousToken' + // because we were at the end of an identifier. + // - 'previousToken' is defined. + var adjustedPosition = previousToken !== contextToken ? + previousToken.getStart() : + position; + var scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile; + /// TODO filter meaning based on the current context + var symbolMeanings = 793064 /* Type */ | 107455 /* Value */ | 1920 /* Namespace */ | 8388608 /* Alias */; + symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings); + return true; + } + /** + * Finds the first node that "embraces" the position, so that one may + * accurately aggregate locals from the closest containing scope. + */ + function getScopeNode(initialToken, position, sourceFile) { + var scope = initialToken; + while (scope && !ts.positionBelongsToNode(scope, position, sourceFile)) { + scope = scope.parent; + } + return scope; + } + function isCompletionListBlocker(contextToken) { + var start = ts.timestamp(); + var result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) || + isSolelyIdentifierDefinitionLocation(contextToken) || + isDotOfNumericLiteral(contextToken) || + isInJsxText(contextToken); + log("getCompletionsAtPosition: isCompletionListBlocker: " + (ts.timestamp() - start)); + return result; + } + function isInJsxText(contextToken) { + if (contextToken.kind === 244 /* JsxText */) { + return true; + } + if (contextToken.kind === 27 /* GreaterThanToken */ && contextToken.parent) { + if (contextToken.parent.kind === 243 /* JsxOpeningElement */) { + return true; } - // consume leading trivia - scanner.scan(); - var item = { - pos: pos, - end: scanner.getStartPos(), - kind: t - }; - pos = scanner.getStartPos(); - if (!leadingTrivia) { - leadingTrivia = []; + if (contextToken.parent.kind === 245 /* JsxClosingElement */ || contextToken.parent.kind === 242 /* JsxSelfClosingElement */) { + return contextToken.parent.parent && contextToken.parent.parent.kind === 241 /* JsxElement */; } - leadingTrivia.push(item); } - savedPos = scanner.getStartPos(); + return false; } - function shouldRescanGreaterThanToken(node) { - if (node) { - switch (node.kind) { - case 29 /* GreaterThanEqualsToken */: - case 64 /* GreaterThanGreaterThanEqualsToken */: - case 65 /* GreaterThanGreaterThanGreaterThanEqualsToken */: - case 45 /* GreaterThanGreaterThanGreaterThanToken */: - case 44 /* GreaterThanGreaterThanToken */: + function isNewIdentifierDefinitionLocation(previousToken) { + if (previousToken) { + var containingNodeKind = previousToken.parent.kind; + switch (previousToken.kind) { + case 24 /* CommaToken */: + return containingNodeKind === 174 /* CallExpression */ // func( a, | + || containingNodeKind === 148 /* Constructor */ // constructor( a, | /* public, protected, private keywords are allowed here, so show completion */ + || containingNodeKind === 175 /* NewExpression */ // new C(a, | + || containingNodeKind === 170 /* ArrayLiteralExpression */ // [a, | + || containingNodeKind === 187 /* BinaryExpression */ // const x = (a, | + || containingNodeKind === 156 /* FunctionType */; // var x: (s: string, list| + case 17 /* OpenParenToken */: + return containingNodeKind === 174 /* CallExpression */ // func( | + || containingNodeKind === 148 /* Constructor */ // constructor( | + || containingNodeKind === 175 /* NewExpression */ // new C(a| + || containingNodeKind === 178 /* ParenthesizedExpression */ // const x = (a| + || containingNodeKind === 164 /* ParenthesizedType */; // function F(pred: (a| /* this can become an arrow function, where 'a' is the argument */ + case 19 /* OpenBracketToken */: + return containingNodeKind === 170 /* ArrayLiteralExpression */ // [ | + || containingNodeKind === 153 /* IndexSignature */ // [ | : string ] + || containingNodeKind === 140 /* ComputedPropertyName */; // [ | /* this can become an index signature */ + case 125 /* ModuleKeyword */: // module | + case 126 /* NamespaceKeyword */: + return true; + case 21 /* DotToken */: + return containingNodeKind === 225 /* ModuleDeclaration */; // module A.| + case 15 /* OpenBraceToken */: + return containingNodeKind === 221 /* ClassDeclaration */; // class A{ | + case 56 /* EqualsToken */: + return containingNodeKind === 218 /* VariableDeclaration */ // const x = a| + || containingNodeKind === 187 /* BinaryExpression */; // x = a| + case 12 /* TemplateHead */: + return containingNodeKind === 189 /* TemplateExpression */; // `aa ${| + case 13 /* TemplateMiddle */: + return containingNodeKind === 197 /* TemplateSpan */; // `aa ${10} dd ${| + case 112 /* PublicKeyword */: + case 110 /* PrivateKeyword */: + case 111 /* ProtectedKeyword */: + return containingNodeKind === 145 /* PropertyDeclaration */; // class A{ public | + } + // Previous token may have been a keyword that was converted to an identifier. + switch (previousToken.getText()) { + case "public": + case "protected": + case "private": return true; } } return false; } - function shouldRescanJsxIdentifier(node) { - if (node.parent) { - switch (node.parent.kind) { - case 246 /* JsxAttribute */: - case 243 /* JsxOpeningElement */: - case 245 /* JsxClosingElement */: - case 242 /* JsxSelfClosingElement */: - return node.kind === 69 /* Identifier */; + function isInStringOrRegularExpressionOrTemplateLiteral(contextToken) { + if (contextToken.kind === 9 /* StringLiteral */ + || contextToken.kind === 10 /* RegularExpressionLiteral */ + || ts.isTemplateLiteralKind(contextToken.kind)) { + var start_3 = contextToken.getStart(); + var end = contextToken.getEnd(); + // To be "in" one of these literals, the position has to be: + // 1. entirely within the token text. + // 2. at the end position of an unterminated token. + // 3. at the end of a regular expression (due to trailing flags like '/foo/g'). + if (start_3 < position && position < end) { + return true; + } + if (position === end) { + return !!contextToken.isUnterminated + || contextToken.kind === 10 /* RegularExpressionLiteral */; } } return false; } - function shouldRescanJsxText(node) { - return node && node.kind === 244 /* JsxText */; - } - function shouldRescanSlashToken(container) { - return container.kind === 10 /* RegularExpressionLiteral */; - } - function shouldRescanTemplateToken(container) { - return container.kind === 13 /* TemplateMiddle */ || - container.kind === 14 /* TemplateTail */; - } - function startsWithSlashToken(t) { - return t === 39 /* SlashToken */ || t === 61 /* SlashEqualsToken */; - } - function readTokenInfo(n) { - ts.Debug.assert(scanner !== undefined); - if (!isOnToken()) { - // scanner is not on the token (either advance was not called yet or scanner is already past the end position) - return { - leadingTrivia: leadingTrivia, - trailingTrivia: undefined, - token: undefined - }; - } - // normally scanner returns the smallest available token - // check the kind of context node to determine if scanner should have more greedy behavior and consume more text. - var expectedScanAction = shouldRescanGreaterThanToken(n) - ? 1 /* RescanGreaterThanToken */ - : shouldRescanSlashToken(n) - ? 2 /* RescanSlashToken */ - : shouldRescanTemplateToken(n) - ? 3 /* RescanTemplateToken */ - : shouldRescanJsxIdentifier(n) - ? 4 /* RescanJsxIdentifier */ - : shouldRescanJsxText(n) - ? 5 /* RescanJsxText */ - : 0 /* Scan */; - if (lastTokenInfo && expectedScanAction === lastScanAction) { - // readTokenInfo was called before with the same expected scan action. - // No need to re-scan text, return existing 'lastTokenInfo' - // it is ok to call fixTokenKind here since it does not affect - // what portion of text is consumed. In contrast rescanning can change it, - // i.e. for '>=' when originally scanner eats just one character - // and rescanning forces it to consume more. - return fixTokenKind(lastTokenInfo, n); - } - if (scanner.getStartPos() !== savedPos) { - ts.Debug.assert(lastTokenInfo !== undefined); - // readTokenInfo was called before but scan action differs - rescan text - scanner.setTextPos(savedPos); - scanner.scan(); - } - var currentToken = scanner.getToken(); - if (expectedScanAction === 1 /* RescanGreaterThanToken */ && currentToken === 27 /* GreaterThanToken */) { - currentToken = scanner.reScanGreaterToken(); - ts.Debug.assert(n.kind === currentToken); - lastScanAction = 1 /* RescanGreaterThanToken */; + /** + * Aggregates relevant symbols for completion in object literals and object binding patterns. + * Relevant symbols are stored in the captured 'symbols' variable. + * + * @returns true if 'symbols' was successfully populated; false otherwise. + */ + function tryGetObjectLikeCompletionSymbols(objectLikeContainer) { + // We're looking up possible property names from contextual/inferred/declared type. + isMemberCompletion = true; + var typeForObject; + var existingMembers; + if (objectLikeContainer.kind === 171 /* ObjectLiteralExpression */) { + // We are completing on contextual types, but may also include properties + // other than those within the declared type. + isNewIdentifierLocation = true; + // If the object literal is being assigned to something of type 'null | { hello: string }', + // it clearly isn't trying to satisfy the 'null' type. So we grab the non-nullable type if possible. + typeForObject = typeChecker.getContextualType(objectLikeContainer); + typeForObject = typeForObject && typeForObject.getNonNullableType(); + existingMembers = objectLikeContainer.properties; } - else if (expectedScanAction === 2 /* RescanSlashToken */ && startsWithSlashToken(currentToken)) { - currentToken = scanner.reScanSlashToken(); - ts.Debug.assert(n.kind === currentToken); - lastScanAction = 2 /* RescanSlashToken */; + else if (objectLikeContainer.kind === 167 /* ObjectBindingPattern */) { + // We are *only* completing on properties from the type being destructured. + isNewIdentifierLocation = false; + var rootDeclaration = ts.getRootDeclaration(objectLikeContainer.parent); + if (ts.isVariableLike(rootDeclaration)) { + // We don't want to complete using the type acquired by the shape + // of the binding pattern; we are only interested in types acquired + // through type declaration or inference. + // Also proceed if rootDeclaration is a parameter and if its containing function expression/arrow function is contextually typed - + // type of parameter will flow in from the contextual type of the function + var canGetType = !!(rootDeclaration.initializer || rootDeclaration.type); + if (!canGetType && rootDeclaration.kind === 142 /* Parameter */) { + if (ts.isExpression(rootDeclaration.parent)) { + canGetType = !!typeChecker.getContextualType(rootDeclaration.parent); + } + else if (rootDeclaration.parent.kind === 147 /* MethodDeclaration */ || rootDeclaration.parent.kind === 150 /* SetAccessor */) { + canGetType = ts.isExpression(rootDeclaration.parent.parent) && !!typeChecker.getContextualType(rootDeclaration.parent.parent); + } + } + if (canGetType) { + typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer); + existingMembers = objectLikeContainer.elements; + } + } + else { + ts.Debug.fail("Root declaration is not variable-like."); + } } - else if (expectedScanAction === 3 /* RescanTemplateToken */ && currentToken === 16 /* CloseBraceToken */) { - currentToken = scanner.reScanTemplateToken(); - lastScanAction = 3 /* RescanTemplateToken */; + else { + ts.Debug.fail("Expected object literal or binding pattern, got " + objectLikeContainer.kind); } - else if (expectedScanAction === 4 /* RescanJsxIdentifier */ && currentToken === 69 /* Identifier */) { - currentToken = scanner.scanJsxIdentifier(); - lastScanAction = 4 /* RescanJsxIdentifier */; + if (!typeForObject) { + return false; } - else if (expectedScanAction === 5 /* RescanJsxText */) { - currentToken = scanner.reScanJsxToken(); - lastScanAction = 5 /* RescanJsxText */; + var typeMembers = typeChecker.getPropertiesOfType(typeForObject); + if (typeMembers && typeMembers.length > 0) { + // Add filtered items to the completion list + symbols = filterObjectMembersList(typeMembers, existingMembers); } - else { - lastScanAction = 0 /* Scan */; + return true; + } + /** + * Aggregates relevant symbols for completion in import clauses and export clauses + * whose declarations have a module specifier; for instance, symbols will be aggregated for + * + * import { | } from "moduleName"; + * export { a as foo, | } from "moduleName"; + * + * but not for + * + * export { | }; + * + * Relevant symbols are stored in the captured 'symbols' variable. + * + * @returns true if 'symbols' was successfully populated; false otherwise. + */ + function tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports) { + var declarationKind = namedImportsOrExports.kind === 233 /* NamedImports */ ? + 230 /* ImportDeclaration */ : + 236 /* ExportDeclaration */; + var importOrExportDeclaration = ts.getAncestor(namedImportsOrExports, declarationKind); + var moduleSpecifier = importOrExportDeclaration.moduleSpecifier; + if (!moduleSpecifier) { + return false; } - var token = { - pos: scanner.getStartPos(), - end: scanner.getTextPos(), - kind: currentToken - }; - // consume trailing trivia - if (trailingTrivia) { - trailingTrivia = undefined; + isMemberCompletion = true; + isNewIdentifierLocation = false; + var exports; + var moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importOrExportDeclaration.moduleSpecifier); + if (moduleSpecifierSymbol) { + exports = typeChecker.getExportsOfModule(moduleSpecifierSymbol); } - while (scanner.getStartPos() < endPos) { - currentToken = scanner.scan(); - if (!ts.isTrivia(currentToken)) { - break; - } - var trivia = { - pos: scanner.getStartPos(), - end: scanner.getTextPos(), - kind: currentToken - }; - if (!trailingTrivia) { - trailingTrivia = []; - } - trailingTrivia.push(trivia); - if (currentToken === 4 /* NewLineTrivia */) { - // move past new line - scanner.scan(); - break; + symbols = exports ? filterNamedImportOrExportCompletionItems(exports, namedImportsOrExports.elements) : ts.emptyArray; + return true; + } + /** + * Returns the immediate owning object literal or binding pattern of a context token, + * on the condition that one exists and that the context implies completion should be given. + */ + function tryGetObjectLikeCompletionContainer(contextToken) { + if (contextToken) { + switch (contextToken.kind) { + case 15 /* OpenBraceToken */: // const x = { | + case 24 /* CommaToken */: + var parent_18 = contextToken.parent; + if (parent_18 && (parent_18.kind === 171 /* ObjectLiteralExpression */ || parent_18.kind === 167 /* ObjectBindingPattern */)) { + return parent_18; + } + break; } } - lastTokenInfo = { - leadingTrivia: leadingTrivia, - trailingTrivia: trailingTrivia, - token: token - }; - return fixTokenKind(lastTokenInfo, n); - } - function isOnToken() { - ts.Debug.assert(scanner !== undefined); - var current = (lastTokenInfo && lastTokenInfo.token.kind) || scanner.getToken(); - var startPos = (lastTokenInfo && lastTokenInfo.token.pos) || scanner.getStartPos(); - return startPos < endPos && current !== 1 /* EndOfFileToken */ && !ts.isTrivia(current); + return undefined; } - // when containing node in the tree is token - // but its kind differs from the kind that was returned by the scanner, - // then kind needs to be fixed. This might happen in cases - // when parser interprets token differently, i.e keyword treated as identifier - function fixTokenKind(tokenInfo, container) { - if (ts.isToken(container) && tokenInfo.token.kind !== container.kind) { - tokenInfo.token.kind = container.kind; + /** + * Returns the containing list of named imports or exports of a context token, + * on the condition that one exists and that the context implies completion should be given. + */ + function tryGetNamedImportsOrExportsForCompletion(contextToken) { + if (contextToken) { + switch (contextToken.kind) { + case 15 /* OpenBraceToken */: // import { | + case 24 /* CommaToken */: + switch (contextToken.parent.kind) { + case 233 /* NamedImports */: + case 237 /* NamedExports */: + return contextToken.parent; + } + } } - return tokenInfo; - } - function skipToEndOf(node) { - scanner.setTextPos(node.end); - savedPos = scanner.getStartPos(); - lastScanAction = undefined; - lastTokenInfo = undefined; - wasNewLine = false; - leadingTrivia = undefined; - trailingTrivia = undefined; - } - } - formatting.getFormattingScanner = getFormattingScanner; - })(formatting = ts.formatting || (ts.formatting = {})); -})(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - var formatting; - (function (formatting) { - var FormattingContext = (function () { - function FormattingContext(sourceFile, formattingRequestKind) { - this.sourceFile = sourceFile; - this.formattingRequestKind = formattingRequestKind; + return undefined; } - FormattingContext.prototype.updateContext = function (currentRange, currentTokenParent, nextRange, nextTokenParent, commonParent) { - ts.Debug.assert(currentRange !== undefined, "currentTokenSpan is null"); - ts.Debug.assert(currentTokenParent !== undefined, "currentTokenParent is null"); - ts.Debug.assert(nextRange !== undefined, "nextTokenSpan is null"); - ts.Debug.assert(nextTokenParent !== undefined, "nextTokenParent is null"); - ts.Debug.assert(commonParent !== undefined, "commonParent is null"); - this.currentTokenSpan = currentRange; - this.currentTokenParent = currentTokenParent; - this.nextTokenSpan = nextRange; - this.nextTokenParent = nextTokenParent; - this.contextNode = commonParent; - // drop cached results - this.contextNodeAllOnSameLine = undefined; - this.nextNodeAllOnSameLine = undefined; - this.tokensAreOnSameLine = undefined; - this.contextNodeBlockIsOnOneLine = undefined; - this.nextNodeBlockIsOnOneLine = undefined; - }; - FormattingContext.prototype.ContextNodeAllOnSameLine = function () { - if (this.contextNodeAllOnSameLine === undefined) { - this.contextNodeAllOnSameLine = this.NodeIsOnOneLine(this.contextNode); - } - return this.contextNodeAllOnSameLine; - }; - FormattingContext.prototype.NextNodeAllOnSameLine = function () { - if (this.nextNodeAllOnSameLine === undefined) { - this.nextNodeAllOnSameLine = this.NodeIsOnOneLine(this.nextTokenParent); - } - return this.nextNodeAllOnSameLine; - }; - FormattingContext.prototype.TokensAreOnSameLine = function () { - if (this.tokensAreOnSameLine === undefined) { - var startLine = this.sourceFile.getLineAndCharacterOfPosition(this.currentTokenSpan.pos).line; - var endLine = this.sourceFile.getLineAndCharacterOfPosition(this.nextTokenSpan.pos).line; - this.tokensAreOnSameLine = (startLine === endLine); + function tryGetContainingJsxElement(contextToken) { + if (contextToken) { + var parent_19 = contextToken.parent; + switch (contextToken.kind) { + case 26 /* LessThanSlashToken */: + case 39 /* SlashToken */: + case 69 /* Identifier */: + case 246 /* JsxAttribute */: + case 247 /* JsxSpreadAttribute */: + if (parent_19 && (parent_19.kind === 242 /* JsxSelfClosingElement */ || parent_19.kind === 243 /* JsxOpeningElement */)) { + return parent_19; + } + else if (parent_19.kind === 246 /* JsxAttribute */) { + return parent_19.parent; + } + break; + // The context token is the closing } or " of an attribute, which means + // its parent is a JsxExpression, whose parent is a JsxAttribute, + // whose parent is a JsxOpeningLikeElement + case 9 /* StringLiteral */: + if (parent_19 && ((parent_19.kind === 246 /* JsxAttribute */) || (parent_19.kind === 247 /* JsxSpreadAttribute */))) { + return parent_19.parent; + } + break; + case 16 /* CloseBraceToken */: + if (parent_19 && + parent_19.kind === 248 /* JsxExpression */ && + parent_19.parent && + (parent_19.parent.kind === 246 /* JsxAttribute */)) { + return parent_19.parent.parent; + } + if (parent_19 && parent_19.kind === 247 /* JsxSpreadAttribute */) { + return parent_19.parent; + } + break; + } } - return this.tokensAreOnSameLine; - }; - FormattingContext.prototype.ContextNodeBlockIsOnOneLine = function () { - if (this.contextNodeBlockIsOnOneLine === undefined) { - this.contextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.contextNode); + return undefined; + } + function isFunction(kind) { + switch (kind) { + case 179 /* FunctionExpression */: + case 180 /* ArrowFunction */: + case 220 /* FunctionDeclaration */: + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 151 /* CallSignature */: + case 152 /* ConstructSignature */: + case 153 /* IndexSignature */: + return true; } - return this.contextNodeBlockIsOnOneLine; - }; - FormattingContext.prototype.NextNodeBlockIsOnOneLine = function () { - if (this.nextNodeBlockIsOnOneLine === undefined) { - this.nextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.nextTokenParent); + return false; + } + /** + * @returns true if we are certain that the currently edited location must define a new location; false otherwise. + */ + function isSolelyIdentifierDefinitionLocation(contextToken) { + var containingNodeKind = contextToken.parent.kind; + switch (contextToken.kind) { + case 24 /* CommaToken */: + return containingNodeKind === 218 /* VariableDeclaration */ || + containingNodeKind === 219 /* VariableDeclarationList */ || + containingNodeKind === 200 /* VariableStatement */ || + containingNodeKind === 224 /* EnumDeclaration */ || + isFunction(containingNodeKind) || + containingNodeKind === 221 /* ClassDeclaration */ || + containingNodeKind === 192 /* ClassExpression */ || + containingNodeKind === 222 /* InterfaceDeclaration */ || + containingNodeKind === 168 /* ArrayBindingPattern */ || + containingNodeKind === 223 /* TypeAliasDeclaration */; // type Map, K, | + case 21 /* DotToken */: + return containingNodeKind === 168 /* ArrayBindingPattern */; // var [.| + case 54 /* ColonToken */: + return containingNodeKind === 169 /* BindingElement */; // var {x :html| + case 19 /* OpenBracketToken */: + return containingNodeKind === 168 /* ArrayBindingPattern */; // var [x| + case 17 /* OpenParenToken */: + return containingNodeKind === 252 /* CatchClause */ || + isFunction(containingNodeKind); + case 15 /* OpenBraceToken */: + return containingNodeKind === 224 /* EnumDeclaration */ || + containingNodeKind === 222 /* InterfaceDeclaration */ || + containingNodeKind === 159 /* TypeLiteral */; // const x : { | + case 23 /* SemicolonToken */: + return containingNodeKind === 144 /* PropertySignature */ && + contextToken.parent && contextToken.parent.parent && + (contextToken.parent.parent.kind === 222 /* InterfaceDeclaration */ || + contextToken.parent.parent.kind === 159 /* TypeLiteral */); // const x : { a; | + case 25 /* LessThanToken */: + return containingNodeKind === 221 /* ClassDeclaration */ || + containingNodeKind === 192 /* ClassExpression */ || + containingNodeKind === 222 /* InterfaceDeclaration */ || + containingNodeKind === 223 /* TypeAliasDeclaration */ || + isFunction(containingNodeKind); + case 113 /* StaticKeyword */: + return containingNodeKind === 145 /* PropertyDeclaration */; + case 22 /* DotDotDotToken */: + return containingNodeKind === 142 /* Parameter */ || + (contextToken.parent && contextToken.parent.parent && + contextToken.parent.parent.kind === 168 /* ArrayBindingPattern */); // var [...z| + case 112 /* PublicKeyword */: + case 110 /* PrivateKeyword */: + case 111 /* ProtectedKeyword */: + return containingNodeKind === 142 /* Parameter */; + case 116 /* AsKeyword */: + return containingNodeKind === 234 /* ImportSpecifier */ || + containingNodeKind === 238 /* ExportSpecifier */ || + containingNodeKind === 232 /* NamespaceImport */; + case 73 /* ClassKeyword */: + case 81 /* EnumKeyword */: + case 107 /* InterfaceKeyword */: + case 87 /* FunctionKeyword */: + case 102 /* VarKeyword */: + case 123 /* GetKeyword */: + case 131 /* SetKeyword */: + case 89 /* ImportKeyword */: + case 108 /* LetKeyword */: + case 74 /* ConstKeyword */: + case 114 /* YieldKeyword */: + case 134 /* TypeKeyword */: + return true; } - return this.nextNodeBlockIsOnOneLine; - }; - FormattingContext.prototype.NodeIsOnOneLine = function (node) { - var startLine = this.sourceFile.getLineAndCharacterOfPosition(node.getStart(this.sourceFile)).line; - var endLine = this.sourceFile.getLineAndCharacterOfPosition(node.getEnd()).line; - return startLine === endLine; - }; - FormattingContext.prototype.BlockIsOnOneLine = function (node) { - var openBrace = ts.findChildOfKind(node, 15 /* OpenBraceToken */, this.sourceFile); - var closeBrace = ts.findChildOfKind(node, 16 /* CloseBraceToken */, this.sourceFile); - if (openBrace && closeBrace) { - var startLine = this.sourceFile.getLineAndCharacterOfPosition(openBrace.getEnd()).line; - var endLine = this.sourceFile.getLineAndCharacterOfPosition(closeBrace.getStart(this.sourceFile)).line; - return startLine === endLine; + // Previous token may have been a keyword that was converted to an identifier. + switch (contextToken.getText()) { + case "abstract": + case "async": + case "class": + case "const": + case "declare": + case "enum": + case "function": + case "interface": + case "let": + case "private": + case "protected": + case "public": + case "static": + case "var": + case "yield": + return true; } return false; - }; - return FormattingContext; - }()); - formatting.FormattingContext = FormattingContext; - })(formatting = ts.formatting || (ts.formatting = {})); -})(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - var formatting; - (function (formatting) { - (function (FormattingRequestKind) { - FormattingRequestKind[FormattingRequestKind["FormatDocument"] = 0] = "FormatDocument"; - FormattingRequestKind[FormattingRequestKind["FormatSelection"] = 1] = "FormatSelection"; - FormattingRequestKind[FormattingRequestKind["FormatOnEnter"] = 2] = "FormatOnEnter"; - FormattingRequestKind[FormattingRequestKind["FormatOnSemicolon"] = 3] = "FormatOnSemicolon"; - FormattingRequestKind[FormattingRequestKind["FormatOnClosingCurlyBrace"] = 4] = "FormatOnClosingCurlyBrace"; - })(formatting.FormattingRequestKind || (formatting.FormattingRequestKind = {})); - var FormattingRequestKind = formatting.FormattingRequestKind; - })(formatting = ts.formatting || (ts.formatting = {})); -})(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - var formatting; - (function (formatting) { - var Rule = (function () { - function Rule(Descriptor, Operation, Flag) { - if (Flag === void 0) { Flag = 0 /* None */; } - this.Descriptor = Descriptor; - this.Operation = Operation; - this.Flag = Flag; - } - Rule.prototype.toString = function () { - return "[desc=" + this.Descriptor + "," + - "operation=" + this.Operation + "," + - "flag=" + this.Flag + "]"; - }; - return Rule; - }()); - formatting.Rule = Rule; - })(formatting = ts.formatting || (ts.formatting = {})); -})(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - var formatting; - (function (formatting) { - (function (RuleAction) { - RuleAction[RuleAction["Ignore"] = 1] = "Ignore"; - RuleAction[RuleAction["Space"] = 2] = "Space"; - RuleAction[RuleAction["NewLine"] = 4] = "NewLine"; - RuleAction[RuleAction["Delete"] = 8] = "Delete"; - })(formatting.RuleAction || (formatting.RuleAction = {})); - var RuleAction = formatting.RuleAction; - })(formatting = ts.formatting || (ts.formatting = {})); -})(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - var formatting; - (function (formatting) { - var RuleDescriptor = (function () { - function RuleDescriptor(LeftTokenRange, RightTokenRange) { - this.LeftTokenRange = LeftTokenRange; - this.RightTokenRange = RightTokenRange; } - RuleDescriptor.prototype.toString = function () { - return "[leftRange=" + this.LeftTokenRange + "," + - "rightRange=" + this.RightTokenRange + "]"; - }; - RuleDescriptor.create1 = function (left, right) { - return RuleDescriptor.create4(formatting.Shared.TokenRange.FromToken(left), formatting.Shared.TokenRange.FromToken(right)); - }; - RuleDescriptor.create2 = function (left, right) { - return RuleDescriptor.create4(left, formatting.Shared.TokenRange.FromToken(right)); - }; - RuleDescriptor.create3 = function (left, right) { - return RuleDescriptor.create4(formatting.Shared.TokenRange.FromToken(left), right); - }; - RuleDescriptor.create4 = function (left, right) { - return new RuleDescriptor(left, right); - }; - return RuleDescriptor; - }()); - formatting.RuleDescriptor = RuleDescriptor; - })(formatting = ts.formatting || (ts.formatting = {})); -})(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - var formatting; - (function (formatting) { - (function (RuleFlags) { - RuleFlags[RuleFlags["None"] = 0] = "None"; - RuleFlags[RuleFlags["CanDeleteNewLines"] = 1] = "CanDeleteNewLines"; - })(formatting.RuleFlags || (formatting.RuleFlags = {})); - var RuleFlags = formatting.RuleFlags; - })(formatting = ts.formatting || (ts.formatting = {})); -})(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - var formatting; - (function (formatting) { - var RuleOperation = (function () { - function RuleOperation(Context, Action) { - this.Context = Context; - this.Action = Action; + function isDotOfNumericLiteral(contextToken) { + if (contextToken.kind === 8 /* NumericLiteral */) { + var text = contextToken.getFullText(); + return text.charAt(text.length - 1) === "."; + } + return false; } - RuleOperation.prototype.toString = function () { - return "[context=" + this.Context + "," + - "action=" + this.Action + "]"; - }; - RuleOperation.create1 = function (action) { - return RuleOperation.create2(formatting.RuleOperationContext.Any, action); - }; - RuleOperation.create2 = function (context, action) { - return new RuleOperation(context, action); - }; - return RuleOperation; - }()); - formatting.RuleOperation = RuleOperation; - })(formatting = ts.formatting || (ts.formatting = {})); -})(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - var formatting; - (function (formatting) { - var RuleOperationContext = (function () { - function RuleOperationContext() { - var funcs = []; - for (var _i = 0; _i < arguments.length; _i++) { - funcs[_i - 0] = arguments[_i]; + /** + * Filters out completion suggestions for named imports or exports. + * + * @param exportsOfModule The list of symbols which a module exposes. + * @param namedImportsOrExports The list of existing import/export specifiers in the import/export clause. + * + * @returns Symbols to be suggested at an import/export clause, barring those whose named imports/exports + * do not occur at the current position and have not otherwise been typed. + */ + function filterNamedImportOrExportCompletionItems(exportsOfModule, namedImportsOrExports) { + var existingImportsOrExports = ts.createMap(); + for (var _i = 0, namedImportsOrExports_1 = namedImportsOrExports; _i < namedImportsOrExports_1.length; _i++) { + var element = namedImportsOrExports_1[_i]; + // If this is the current item we are editing right now, do not filter it out + if (element.getStart() <= position && position <= element.getEnd()) { + continue; + } + var name_50 = element.propertyName || element.name; + existingImportsOrExports[name_50.text] = true; } - this.customContextChecks = funcs; + if (!ts.someProperties(existingImportsOrExports)) { + return ts.filter(exportsOfModule, function (e) { return e.name !== "default"; }); + } + return ts.filter(exportsOfModule, function (e) { return e.name !== "default" && !existingImportsOrExports[e.name]; }); } - RuleOperationContext.prototype.IsAny = function () { - return this === RuleOperationContext.Any; - }; - RuleOperationContext.prototype.InContext = function (context) { - if (this.IsAny()) { - return true; + /** + * Filters out completion suggestions for named imports or exports. + * + * @returns Symbols to be suggested in an object binding pattern or object literal expression, barring those whose declarations + * do not occur at the current position and have not otherwise been typed. + */ + function filterObjectMembersList(contextualMemberSymbols, existingMembers) { + if (!existingMembers || existingMembers.length === 0) { + return contextualMemberSymbols; } - for (var _i = 0, _a = this.customContextChecks; _i < _a.length; _i++) { - var check = _a[_i]; - if (!check(context)) { - return false; + var existingMemberNames = ts.createMap(); + for (var _i = 0, existingMembers_1 = existingMembers; _i < existingMembers_1.length; _i++) { + var m = existingMembers_1[_i]; + // Ignore omitted expressions for missing members + if (m.kind !== 253 /* PropertyAssignment */ && + m.kind !== 254 /* ShorthandPropertyAssignment */ && + m.kind !== 169 /* BindingElement */ && + m.kind !== 147 /* MethodDeclaration */) { + continue; + } + // If this is the current item we are editing right now, do not filter it out + if (m.getStart() <= position && position <= m.getEnd()) { + continue; + } + var existingName = void 0; + if (m.kind === 169 /* BindingElement */ && m.propertyName) { + // include only identifiers in completion list + if (m.propertyName.kind === 69 /* Identifier */) { + existingName = m.propertyName.text; + } + } + else { + // TODO(jfreeman): Account for computed property name + // NOTE: if one only performs this step when m.name is an identifier, + // things like '__proto__' are not filtered out. + existingName = m.name.text; } + existingMemberNames[existingName] = true; } - return true; - }; - RuleOperationContext.Any = new RuleOperationContext(); - return RuleOperationContext; - }()); - formatting.RuleOperationContext = RuleOperationContext; - })(formatting = ts.formatting || (ts.formatting = {})); + return ts.filter(contextualMemberSymbols, function (m) { return !existingMemberNames[m.name]; }); + } + /** + * Filters out completion suggestions from 'symbols' according to existing JSX attributes. + * + * @returns Symbols to be suggested in a JSX element, barring those whose attributes + * do not occur at the current position and have not otherwise been typed. + */ + function filterJsxAttributes(symbols, attributes) { + var seenNames = ts.createMap(); + for (var _i = 0, attributes_1 = attributes; _i < attributes_1.length; _i++) { + var attr = attributes_1[_i]; + // If this is the current item we are editing right now, do not filter it out + if (attr.getStart() <= position && position <= attr.getEnd()) { + continue; + } + if (attr.kind === 246 /* JsxAttribute */) { + seenNames[attr.name.text] = true; + } + } + return ts.filter(symbols, function (a) { return !seenNames[a.name]; }); + } + } + /** + * Get the name to be display in completion from a given symbol. + * + * @return undefined if the name is of external module otherwise a name with striped of any quote + */ + function getCompletionEntryDisplayNameForSymbol(typeChecker, symbol, target, performCharacterChecks, location) { + var displayName = ts.getDeclaredName(typeChecker, symbol, location); + if (displayName) { + var firstCharCode = displayName.charCodeAt(0); + // First check of the displayName is not external module; if it is an external module, it is not valid entry + if ((symbol.flags & 1920 /* Namespace */) && (firstCharCode === 39 /* singleQuote */ || firstCharCode === 34 /* doubleQuote */)) { + // If the symbol is external module, don't show it in the completion list + // (i.e declare module "http" { const x; } | // <= request completion here, "http" should not be there) + return undefined; + } + } + return getCompletionEntryDisplayName(displayName, target, performCharacterChecks); + } + /** + * Get a displayName from a given for completion list, performing any necessary quotes stripping + * and checking whether the name is valid identifier name. + */ + function getCompletionEntryDisplayName(name, target, performCharacterChecks) { + if (!name) { + return undefined; + } + name = ts.stripQuotes(name); + if (!name) { + return undefined; + } + // If the user entered name for the symbol was quoted, removing the quotes is not enough, as the name could be an + // invalid identifier name. We need to check if whatever was inside the quotes is actually a valid identifier name. + // e.g "b a" is valid quoted name but when we strip off the quotes, it is invalid. + // We, thus, need to check if whatever was inside the quotes is actually a valid identifier name. + if (performCharacterChecks) { + if (!ts.isIdentifierText(name, target)) { + return undefined; + } + } + return name; + } + // A cache of completion entries for keywords, these do not change between sessions + var keywordCompletions = []; + for (var i = 70 /* FirstKeyword */; i <= 138 /* LastKeyword */; i++) { + keywordCompletions.push({ + name: ts.tokenToString(i), + kind: ts.ScriptElementKind.keyword, + kindModifiers: ts.ScriptElementKindModifier.none, + sortText: "0" + }); + } + /** + * Matches a triple slash reference directive with an incomplete string literal for its path. Used + * to determine if the caret is currently within the string literal and capture the literal fragment + * for completions. + * For example, this matches /// /* @internal */ var ts; (function (ts) { - var formatting; - (function (formatting) { - var Rules = (function () { - function Rules() { - /// - /// Common Rules - /// - // Leave comments alone - this.IgnoreBeforeComment = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.Comments), formatting.RuleOperation.create1(1 /* Ignore */)); - this.IgnoreAfterLineComment = new formatting.Rule(formatting.RuleDescriptor.create3(2 /* SingleLineCommentTrivia */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create1(1 /* Ignore */)); - // Space after keyword but not before ; or : or ? - this.NoSpaceBeforeSemicolon = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 23 /* SemicolonToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceBeforeColon = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 54 /* ColonToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), 8 /* Delete */)); - this.NoSpaceBeforeQuestionMark = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 53 /* QuestionToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), 8 /* Delete */)); - this.SpaceAfterColon = new formatting.Rule(formatting.RuleDescriptor.create3(54 /* ColonToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), 2 /* Space */)); - this.SpaceAfterQuestionMarkInConditionalOperator = new formatting.Rule(formatting.RuleDescriptor.create3(53 /* QuestionToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsConditionalOperatorContext), 2 /* Space */)); - this.NoSpaceAfterQuestionMark = new formatting.Rule(formatting.RuleDescriptor.create3(53 /* QuestionToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.SpaceAfterSemicolon = new formatting.Rule(formatting.RuleDescriptor.create3(23 /* SemicolonToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - // Space after }. - this.SpaceAfterCloseBrace = new formatting.Rule(formatting.RuleDescriptor.create3(16 /* CloseBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsAfterCodeBlockContext), 2 /* Space */)); - // Special case for (}, else) and (}, while) since else & while tokens are not part of the tree which makes SpaceAfterCloseBrace rule not applied - this.SpaceBetweenCloseBraceAndElse = new formatting.Rule(formatting.RuleDescriptor.create1(16 /* CloseBraceToken */, 80 /* ElseKeyword */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.SpaceBetweenCloseBraceAndWhile = new formatting.Rule(formatting.RuleDescriptor.create1(16 /* CloseBraceToken */, 104 /* WhileKeyword */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.NoSpaceAfterCloseBrace = new formatting.Rule(formatting.RuleDescriptor.create3(16 /* CloseBraceToken */, formatting.Shared.TokenRange.FromTokens([18 /* CloseParenToken */, 20 /* CloseBracketToken */, 24 /* CommaToken */, 23 /* SemicolonToken */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - // No space for dot - this.NoSpaceBeforeDot = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 21 /* DotToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceAfterDot = new formatting.Rule(formatting.RuleDescriptor.create3(21 /* DotToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - // No space before and after indexer - this.NoSpaceBeforeOpenBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 19 /* OpenBracketToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceAfterCloseBracket = new formatting.Rule(formatting.RuleDescriptor.create3(20 /* CloseBracketToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBeforeBlockInFunctionDeclarationContext), 8 /* Delete */)); - // Place a space before open brace in a function declaration - this.FunctionOpenBraceLeftTokenRange = formatting.Shared.TokenRange.AnyIncludingMultilineComments; - this.SpaceBeforeOpenBraceInFunction = new formatting.Rule(formatting.RuleDescriptor.create2(this.FunctionOpenBraceLeftTokenRange, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext, Rules.IsBeforeBlockContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), 2 /* Space */), 1 /* CanDeleteNewLines */); - // Place a space before open brace in a TypeScript declaration that has braces as children (class, module, enum, etc) - this.TypeScriptOpenBraceLeftTokenRange = formatting.Shared.TokenRange.FromTokens([69 /* Identifier */, 3 /* MultiLineCommentTrivia */, 73 /* ClassKeyword */, 82 /* ExportKeyword */, 89 /* ImportKeyword */]); - this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock = new formatting.Rule(formatting.RuleDescriptor.create2(this.TypeScriptOpenBraceLeftTokenRange, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsTypeScriptDeclWithBlockContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), 2 /* Space */), 1 /* CanDeleteNewLines */); - // Place a space before open brace in a control flow construct - this.ControlOpenBraceLeftTokenRange = formatting.Shared.TokenRange.FromTokens([18 /* CloseParenToken */, 3 /* MultiLineCommentTrivia */, 79 /* DoKeyword */, 100 /* TryKeyword */, 85 /* FinallyKeyword */, 80 /* ElseKeyword */]); - this.SpaceBeforeOpenBraceInControl = new formatting.Rule(formatting.RuleDescriptor.create2(this.ControlOpenBraceLeftTokenRange, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), 2 /* Space */), 1 /* CanDeleteNewLines */); - // Insert a space after { and before } in single-line contexts, but remove space from empty object literals {}. - this.SpaceAfterOpenBrace = new formatting.Rule(formatting.RuleDescriptor.create3(15 /* OpenBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSingleLineBlockContext), 2 /* Space */)); - this.SpaceBeforeCloseBrace = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSingleLineBlockContext), 2 /* Space */)); - this.NoSpaceBetweenEmptyBraceBrackets = new formatting.Rule(formatting.RuleDescriptor.create1(15 /* OpenBraceToken */, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsObjectContext), 8 /* Delete */)); - // Insert new line after { and before } in multi-line contexts. - this.NewLineAfterOpenBraceInBlockContext = new formatting.Rule(formatting.RuleDescriptor.create3(15 /* OpenBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsMultilineBlockContext), 4 /* NewLine */)); - // For functions and control block place } on a new line [multi-line rule] - this.NewLineBeforeCloseBraceInBlockContext = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.AnyIncludingMultilineComments, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsMultilineBlockContext), 4 /* NewLine */)); - // Special handling of unary operators. - // Prefix operators generally shouldn't have a space between - // them and their target unary expression. - this.NoSpaceAfterUnaryPrefixOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.UnaryPrefixOperators, formatting.Shared.TokenRange.UnaryPrefixExpressions), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), 8 /* Delete */)); - this.NoSpaceAfterUnaryPreincrementOperator = new formatting.Rule(formatting.RuleDescriptor.create3(41 /* PlusPlusToken */, formatting.Shared.TokenRange.UnaryPreincrementExpressions), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceAfterUnaryPredecrementOperator = new formatting.Rule(formatting.RuleDescriptor.create3(42 /* MinusMinusToken */, formatting.Shared.TokenRange.UnaryPredecrementExpressions), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceBeforeUnaryPostincrementOperator = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.UnaryPostincrementExpressions, 41 /* PlusPlusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceBeforeUnaryPostdecrementOperator = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.UnaryPostdecrementExpressions, 42 /* MinusMinusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - // More unary operator special-casing. - // DevDiv 181814: Be careful when removing leading whitespace - // around unary operators. Examples: - // 1 - -2 --X--> 1--2 - // a + ++b --X--> a+++b - this.SpaceAfterPostincrementWhenFollowedByAdd = new formatting.Rule(formatting.RuleDescriptor.create1(41 /* PlusPlusToken */, 35 /* PlusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); - this.SpaceAfterAddWhenFollowedByUnaryPlus = new formatting.Rule(formatting.RuleDescriptor.create1(35 /* PlusToken */, 35 /* PlusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); - this.SpaceAfterAddWhenFollowedByPreincrement = new formatting.Rule(formatting.RuleDescriptor.create1(35 /* PlusToken */, 41 /* PlusPlusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); - this.SpaceAfterPostdecrementWhenFollowedBySubtract = new formatting.Rule(formatting.RuleDescriptor.create1(42 /* MinusMinusToken */, 36 /* MinusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); - this.SpaceAfterSubtractWhenFollowedByUnaryMinus = new formatting.Rule(formatting.RuleDescriptor.create1(36 /* MinusToken */, 36 /* MinusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); - this.SpaceAfterSubtractWhenFollowedByPredecrement = new formatting.Rule(formatting.RuleDescriptor.create1(36 /* MinusToken */, 42 /* MinusMinusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); - this.NoSpaceBeforeComma = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 24 /* CommaToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.SpaceAfterCertainKeywords = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([102 /* VarKeyword */, 98 /* ThrowKeyword */, 92 /* NewKeyword */, 78 /* DeleteKeyword */, 94 /* ReturnKeyword */, 101 /* TypeOfKeyword */, 119 /* AwaitKeyword */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.SpaceAfterLetConstInVariableDeclaration = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([108 /* LetKeyword */, 74 /* ConstKeyword */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsStartOfVariableDeclarationList), 2 /* Space */)); - this.NoSpaceBeforeOpenParenInFuncCall = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsFunctionCallOrNewContext, Rules.IsPreviousTokenNotComma), 8 /* Delete */)); - this.SpaceAfterFunctionInFuncDecl = new formatting.Rule(formatting.RuleDescriptor.create3(87 /* FunctionKeyword */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 2 /* Space */)); - this.NoSpaceBeforeOpenParenInFuncDecl = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsFunctionDeclContext), 8 /* Delete */)); - this.SpaceAfterVoidOperator = new formatting.Rule(formatting.RuleDescriptor.create3(103 /* VoidKeyword */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsVoidOpContext), 2 /* Space */)); - this.NoSpaceBetweenReturnAndSemicolon = new formatting.Rule(formatting.RuleDescriptor.create1(94 /* ReturnKeyword */, 23 /* SemicolonToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - // Add a space between statements. All keywords except (do,else,case) has open/close parens after them. - // So, we have a rule to add a space for [),Any], [do,Any], [else,Any], and [case,Any] - this.SpaceBetweenStatements = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([18 /* CloseParenToken */, 79 /* DoKeyword */, 80 /* ElseKeyword */, 71 /* CaseKeyword */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNonJsxElementContext, Rules.IsNotForContext), 2 /* Space */)); - // This low-pri rule takes care of "try {" and "finally {" in case the rule SpaceBeforeOpenBraceInControl didn't execute on FormatOnEnter. - this.SpaceAfterTryFinally = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.FromTokens([100 /* TryKeyword */, 85 /* FinallyKeyword */]), 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - // get x() {} - // set x(val) {} - this.SpaceAfterGetSetInMember = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.FromTokens([123 /* GetKeyword */, 131 /* SetKeyword */]), 69 /* Identifier */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 2 /* Space */)); - // Special case for binary operators (that are keywords). For these we have to add a space and shouldn't follow any user options. - this.SpaceBeforeBinaryKeywordOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.BinaryKeywordOperators), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); - this.SpaceAfterBinaryKeywordOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.BinaryKeywordOperators, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); - // TypeScript-specific higher priority rules - // Treat constructor as an identifier in a function declaration, and remove spaces between constructor and following left parentheses - this.NoSpaceAfterConstructor = new formatting.Rule(formatting.RuleDescriptor.create1(121 /* ConstructorKeyword */, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - // Use of module as a function call. e.g.: import m2 = module("m2"); - this.NoSpaceAfterModuleImport = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.FromTokens([125 /* ModuleKeyword */, 129 /* RequireKeyword */]), 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - // Add a space around certain TypeScript keywords - this.SpaceAfterCertainTypeScriptKeywords = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([115 /* AbstractKeyword */, 73 /* ClassKeyword */, 122 /* DeclareKeyword */, 77 /* DefaultKeyword */, 81 /* EnumKeyword */, 82 /* ExportKeyword */, 83 /* ExtendsKeyword */, 123 /* GetKeyword */, 106 /* ImplementsKeyword */, 89 /* ImportKeyword */, 107 /* InterfaceKeyword */, 125 /* ModuleKeyword */, 126 /* NamespaceKeyword */, 110 /* PrivateKeyword */, 112 /* PublicKeyword */, 111 /* ProtectedKeyword */, 131 /* SetKeyword */, 113 /* StaticKeyword */, 134 /* TypeKeyword */, 136 /* FromKeyword */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.SpaceBeforeCertainTypeScriptKeywords = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.FromTokens([83 /* ExtendsKeyword */, 106 /* ImplementsKeyword */, 136 /* FromKeyword */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - // Treat string literals in module names as identifiers, and add a space between the literal and the opening Brace braces, e.g.: module "m2" { - this.SpaceAfterModuleName = new formatting.Rule(formatting.RuleDescriptor.create1(9 /* StringLiteral */, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsModuleDeclContext), 2 /* Space */)); - // Lambda expressions - this.SpaceBeforeArrow = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 34 /* EqualsGreaterThanToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.SpaceAfterArrow = new formatting.Rule(formatting.RuleDescriptor.create3(34 /* EqualsGreaterThanToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - // Optional parameters and let args - this.NoSpaceAfterEllipsis = new formatting.Rule(formatting.RuleDescriptor.create1(22 /* DotDotDotToken */, 69 /* Identifier */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceAfterOptionalParameters = new formatting.Rule(formatting.RuleDescriptor.create3(53 /* QuestionToken */, formatting.Shared.TokenRange.FromTokens([18 /* CloseParenToken */, 24 /* CommaToken */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), 8 /* Delete */)); - // generics and type assertions - this.NoSpaceBeforeOpenAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.TypeNames, 25 /* LessThanToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), 8 /* Delete */)); - this.NoSpaceBetweenCloseParenAndAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create1(18 /* CloseParenToken */, 25 /* LessThanToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), 8 /* Delete */)); - this.NoSpaceAfterOpenAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create3(25 /* LessThanToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), 8 /* Delete */)); - this.NoSpaceBeforeCloseAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 27 /* GreaterThanToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), 8 /* Delete */)); - this.NoSpaceAfterCloseAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create3(27 /* GreaterThanToken */, formatting.Shared.TokenRange.FromTokens([17 /* OpenParenToken */, 19 /* OpenBracketToken */, 27 /* GreaterThanToken */, 24 /* CommaToken */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), 8 /* Delete */)); - this.NoSpaceAfterTypeAssertion = new formatting.Rule(formatting.RuleDescriptor.create3(27 /* GreaterThanToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeAssertionContext), 8 /* Delete */)); - // Remove spaces in empty interface literals. e.g.: x: {} - this.NoSpaceBetweenEmptyInterfaceBraceBrackets = new formatting.Rule(formatting.RuleDescriptor.create1(15 /* OpenBraceToken */, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsObjectTypeContext), 8 /* Delete */)); - // decorators - this.SpaceBeforeAt = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 55 /* AtToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.NoSpaceAfterAt = new formatting.Rule(formatting.RuleDescriptor.create3(55 /* AtToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.SpaceAfterDecorator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.FromTokens([115 /* AbstractKeyword */, 69 /* Identifier */, 82 /* ExportKeyword */, 77 /* DefaultKeyword */, 73 /* ClassKeyword */, 113 /* StaticKeyword */, 112 /* PublicKeyword */, 110 /* PrivateKeyword */, 111 /* ProtectedKeyword */, 123 /* GetKeyword */, 131 /* SetKeyword */, 19 /* OpenBracketToken */, 37 /* AsteriskToken */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsEndOfDecoratorContextOnSameLine), 2 /* Space */)); - this.NoSpaceBetweenFunctionKeywordAndStar = new formatting.Rule(formatting.RuleDescriptor.create1(87 /* FunctionKeyword */, 37 /* AsteriskToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclarationOrFunctionExpressionContext), 8 /* Delete */)); - this.SpaceAfterStarInGeneratorDeclaration = new formatting.Rule(formatting.RuleDescriptor.create3(37 /* AsteriskToken */, formatting.Shared.TokenRange.FromTokens([69 /* Identifier */, 17 /* OpenParenToken */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclarationOrFunctionExpressionContext), 2 /* Space */)); - this.NoSpaceBetweenYieldKeywordAndStar = new formatting.Rule(formatting.RuleDescriptor.create1(114 /* YieldKeyword */, 37 /* AsteriskToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsYieldOrYieldStarWithOperand), 8 /* Delete */)); - this.SpaceBetweenYieldOrYieldStarAndOperand = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([114 /* YieldKeyword */, 37 /* AsteriskToken */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsYieldOrYieldStarWithOperand), 2 /* Space */)); - // Async-await - this.SpaceBetweenAsyncAndOpenParen = new formatting.Rule(formatting.RuleDescriptor.create1(118 /* AsyncKeyword */, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsArrowFunctionContext, Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.SpaceBetweenAsyncAndFunctionKeyword = new formatting.Rule(formatting.RuleDescriptor.create1(118 /* AsyncKeyword */, 87 /* FunctionKeyword */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - // template string - this.NoSpaceBetweenTagAndTemplateString = new formatting.Rule(formatting.RuleDescriptor.create3(69 /* Identifier */, formatting.Shared.TokenRange.FromTokens([11 /* NoSubstitutionTemplateLiteral */, 12 /* TemplateHead */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - // jsx opening element - this.SpaceBeforeJsxAttribute = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 69 /* Identifier */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNextTokenParentJsxAttribute, Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.SpaceBeforeSlashInJsxOpeningElement = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 39 /* SlashToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsJsxSelfClosingElementContext, Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.NoSpaceBeforeGreaterThanTokenInJsxOpeningElement = new formatting.Rule(formatting.RuleDescriptor.create1(39 /* SlashToken */, 27 /* GreaterThanToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsJsxSelfClosingElementContext, Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceBeforeEqualInJsxAttribute = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 56 /* EqualsToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsJsxAttributeContext, Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceAfterEqualInJsxAttribute = new formatting.Rule(formatting.RuleDescriptor.create3(56 /* EqualsToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsJsxAttributeContext, Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - // These rules are higher in priority than user-configurable rules. - this.HighPriorityCommonRules = [ - this.IgnoreBeforeComment, this.IgnoreAfterLineComment, - this.NoSpaceBeforeColon, this.SpaceAfterColon, this.NoSpaceBeforeQuestionMark, this.SpaceAfterQuestionMarkInConditionalOperator, - this.NoSpaceAfterQuestionMark, - this.NoSpaceBeforeDot, this.NoSpaceAfterDot, - this.NoSpaceAfterUnaryPrefixOperator, - this.NoSpaceAfterUnaryPreincrementOperator, this.NoSpaceAfterUnaryPredecrementOperator, - this.NoSpaceBeforeUnaryPostincrementOperator, this.NoSpaceBeforeUnaryPostdecrementOperator, - this.SpaceAfterPostincrementWhenFollowedByAdd, - this.SpaceAfterAddWhenFollowedByUnaryPlus, this.SpaceAfterAddWhenFollowedByPreincrement, - this.SpaceAfterPostdecrementWhenFollowedBySubtract, - this.SpaceAfterSubtractWhenFollowedByUnaryMinus, this.SpaceAfterSubtractWhenFollowedByPredecrement, - this.NoSpaceAfterCloseBrace, - this.SpaceAfterOpenBrace, this.SpaceBeforeCloseBrace, this.NewLineBeforeCloseBraceInBlockContext, - this.SpaceAfterCloseBrace, this.SpaceBetweenCloseBraceAndElse, this.SpaceBetweenCloseBraceAndWhile, this.NoSpaceBetweenEmptyBraceBrackets, - this.NoSpaceBetweenFunctionKeywordAndStar, this.SpaceAfterStarInGeneratorDeclaration, - this.SpaceAfterFunctionInFuncDecl, this.NewLineAfterOpenBraceInBlockContext, this.SpaceAfterGetSetInMember, - this.NoSpaceBetweenYieldKeywordAndStar, this.SpaceBetweenYieldOrYieldStarAndOperand, - this.NoSpaceBetweenReturnAndSemicolon, - this.SpaceAfterCertainKeywords, - this.SpaceAfterLetConstInVariableDeclaration, - this.NoSpaceBeforeOpenParenInFuncCall, - this.SpaceBeforeBinaryKeywordOperator, this.SpaceAfterBinaryKeywordOperator, - this.SpaceAfterVoidOperator, - this.SpaceBetweenAsyncAndOpenParen, this.SpaceBetweenAsyncAndFunctionKeyword, - this.NoSpaceBetweenTagAndTemplateString, - this.SpaceBeforeJsxAttribute, this.SpaceBeforeSlashInJsxOpeningElement, this.NoSpaceBeforeGreaterThanTokenInJsxOpeningElement, - this.NoSpaceBeforeEqualInJsxAttribute, this.NoSpaceAfterEqualInJsxAttribute, - // TypeScript-specific rules - this.NoSpaceAfterConstructor, this.NoSpaceAfterModuleImport, - this.SpaceAfterCertainTypeScriptKeywords, this.SpaceBeforeCertainTypeScriptKeywords, - this.SpaceAfterModuleName, - this.SpaceBeforeArrow, this.SpaceAfterArrow, - this.NoSpaceAfterEllipsis, - this.NoSpaceAfterOptionalParameters, - this.NoSpaceBetweenEmptyInterfaceBraceBrackets, - this.NoSpaceBeforeOpenAngularBracket, - this.NoSpaceBetweenCloseParenAndAngularBracket, - this.NoSpaceAfterOpenAngularBracket, - this.NoSpaceBeforeCloseAngularBracket, - this.NoSpaceAfterCloseAngularBracket, - this.NoSpaceAfterTypeAssertion, - this.SpaceBeforeAt, - this.NoSpaceAfterAt, - this.SpaceAfterDecorator, - ]; - // These rules are lower in priority than user-configurable rules. - this.LowPriorityCommonRules = [ - this.NoSpaceBeforeSemicolon, - this.SpaceBeforeOpenBraceInControl, this.SpaceBeforeOpenBraceInFunction, this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock, - this.NoSpaceBeforeComma, - this.NoSpaceBeforeOpenBracket, - this.NoSpaceAfterCloseBracket, - this.SpaceAfterSemicolon, - this.NoSpaceBeforeOpenParenInFuncDecl, - this.SpaceBetweenStatements, this.SpaceAfterTryFinally - ]; - /// - /// Rules controlled by user options - /// - // Insert space after comma delimiter - this.SpaceAfterComma = new formatting.Rule(formatting.RuleDescriptor.create3(24 /* CommaToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNonJsxElementContext, Rules.IsNextTokenNotCloseBracket), 2 /* Space */)); - this.NoSpaceAfterComma = new formatting.Rule(formatting.RuleDescriptor.create3(24 /* CommaToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNonJsxElementContext), 8 /* Delete */)); - // Insert space before and after binary operators - this.SpaceBeforeBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.BinaryOperators), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); - this.SpaceAfterBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.BinaryOperators, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); - this.NoSpaceBeforeBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.BinaryOperators), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 8 /* Delete */)); - this.NoSpaceAfterBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.BinaryOperators, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 8 /* Delete */)); - // Insert space after keywords in control flow statements - this.SpaceAfterKeywordInControl = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Keywords, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext), 2 /* Space */)); - this.NoSpaceAfterKeywordInControl = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Keywords, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext), 8 /* Delete */)); - // Open Brace braces after function - // TypeScript: Function can have return types, which can be made of tons of different token kinds - this.NewLineBeforeOpenBraceInFunction = new formatting.Rule(formatting.RuleDescriptor.create2(this.FunctionOpenBraceLeftTokenRange, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext, Rules.IsBeforeMultilineBlockContext), 4 /* NewLine */), 1 /* CanDeleteNewLines */); - // Open Brace braces after TypeScript module/class/interface - this.NewLineBeforeOpenBraceInTypeScriptDeclWithBlock = new formatting.Rule(formatting.RuleDescriptor.create2(this.TypeScriptOpenBraceLeftTokenRange, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsTypeScriptDeclWithBlockContext, Rules.IsBeforeMultilineBlockContext), 4 /* NewLine */), 1 /* CanDeleteNewLines */); - // Open Brace braces after control block - this.NewLineBeforeOpenBraceInControl = new formatting.Rule(formatting.RuleDescriptor.create2(this.ControlOpenBraceLeftTokenRange, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext, Rules.IsBeforeMultilineBlockContext), 4 /* NewLine */), 1 /* CanDeleteNewLines */); - // Insert space after semicolon in for statement - this.SpaceAfterSemicolonInFor = new formatting.Rule(formatting.RuleDescriptor.create3(23 /* SemicolonToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsForContext), 2 /* Space */)); - this.NoSpaceAfterSemicolonInFor = new formatting.Rule(formatting.RuleDescriptor.create3(23 /* SemicolonToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsForContext), 8 /* Delete */)); - // Insert space after opening and before closing nonempty parenthesis - this.SpaceAfterOpenParen = new formatting.Rule(formatting.RuleDescriptor.create3(17 /* OpenParenToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.SpaceBeforeCloseParen = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 18 /* CloseParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.NoSpaceBetweenParens = new formatting.Rule(formatting.RuleDescriptor.create1(17 /* OpenParenToken */, 18 /* CloseParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceAfterOpenParen = new formatting.Rule(formatting.RuleDescriptor.create3(17 /* OpenParenToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceBeforeCloseParen = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 18 /* CloseParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - // Insert space after opening and before closing nonempty brackets - this.SpaceAfterOpenBracket = new formatting.Rule(formatting.RuleDescriptor.create3(19 /* OpenBracketToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.SpaceBeforeCloseBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 20 /* CloseBracketToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.NoSpaceBetweenBrackets = new formatting.Rule(formatting.RuleDescriptor.create1(19 /* OpenBracketToken */, 20 /* CloseBracketToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceAfterOpenBracket = new formatting.Rule(formatting.RuleDescriptor.create3(19 /* OpenBracketToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceBeforeCloseBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 20 /* CloseBracketToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - // Insert space after opening and before closing template string braces - this.NoSpaceAfterTemplateHeadAndMiddle = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([12 /* TemplateHead */, 13 /* TemplateMiddle */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.SpaceAfterTemplateHeadAndMiddle = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([12 /* TemplateHead */, 13 /* TemplateMiddle */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.NoSpaceBeforeTemplateMiddleAndTail = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.FromTokens([13 /* TemplateMiddle */, 14 /* TemplateTail */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.SpaceBeforeTemplateMiddleAndTail = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.FromTokens([13 /* TemplateMiddle */, 14 /* TemplateTail */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - // No space after { and before } in JSX expression - this.NoSpaceAfterOpenBraceInJsxExpression = new formatting.Rule(formatting.RuleDescriptor.create3(15 /* OpenBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsJsxExpressionContext), 8 /* Delete */)); - this.SpaceAfterOpenBraceInJsxExpression = new formatting.Rule(formatting.RuleDescriptor.create3(15 /* OpenBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsJsxExpressionContext), 2 /* Space */)); - this.NoSpaceBeforeCloseBraceInJsxExpression = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsJsxExpressionContext), 8 /* Delete */)); - this.SpaceBeforeCloseBraceInJsxExpression = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsJsxExpressionContext), 2 /* Space */)); - // Insert space after function keyword for anonymous functions - this.SpaceAfterAnonymousFunctionKeyword = new formatting.Rule(formatting.RuleDescriptor.create1(87 /* FunctionKeyword */, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 2 /* Space */)); - this.NoSpaceAfterAnonymousFunctionKeyword = new formatting.Rule(formatting.RuleDescriptor.create1(87 /* FunctionKeyword */, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 8 /* Delete */)); + var DocumentHighlights; + (function (DocumentHighlights) { + function getDocumentHighlights(typeChecker, cancellationToken, sourceFile, position, sourceFilesToSearch) { + var node = ts.getTouchingWord(sourceFile, position); + if (!node) { + return undefined; } - Rules.prototype.getRuleName = function (rule) { - var o = this; - for (var name_40 in o) { - if (o[name_40] === rule) { - return name_40; - } - } - throw new Error("Unknown rule"); - }; - /// - /// Contexts - /// - Rules.IsForContext = function (context) { - return context.contextNode.kind === 206 /* ForStatement */; - }; - Rules.IsNotForContext = function (context) { - return !Rules.IsForContext(context); - }; - Rules.IsBinaryOpContext = function (context) { - switch (context.contextNode.kind) { - case 187 /* BinaryExpression */: - case 188 /* ConditionalExpression */: - case 195 /* AsExpression */: - case 238 /* ExportSpecifier */: - case 234 /* ImportSpecifier */: - case 154 /* TypePredicate */: - case 162 /* UnionType */: - case 163 /* IntersectionType */: - return true; - // equals in binding elements: function foo([[x, y] = [1, 2]]) - case 169 /* BindingElement */: - // equals in type X = ... - case 223 /* TypeAliasDeclaration */: - // equal in import a = module('a'); - case 229 /* ImportEqualsDeclaration */: - // equal in let a = 0; - case 218 /* VariableDeclaration */: - // equal in p = 0; - case 142 /* Parameter */: - case 255 /* EnumMember */: - case 145 /* PropertyDeclaration */: - case 144 /* PropertySignature */: - return context.currentTokenSpan.kind === 56 /* EqualsToken */ || context.nextTokenSpan.kind === 56 /* EqualsToken */; - // "in" keyword in for (let x in []) { } - case 207 /* ForInStatement */: - return context.currentTokenSpan.kind === 90 /* InKeyword */ || context.nextTokenSpan.kind === 90 /* InKeyword */; - // Technically, "of" is not a binary operator, but format it the same way as "in" - case 208 /* ForOfStatement */: - return context.currentTokenSpan.kind === 138 /* OfKeyword */ || context.nextTokenSpan.kind === 138 /* OfKeyword */; + return getSemanticDocumentHighlights(node) || getSyntacticDocumentHighlights(node); + function getHighlightSpanForNode(node) { + var start = node.getStart(); + var end = node.getEnd(); + return { + fileName: sourceFile.fileName, + textSpan: ts.createTextSpanFromBounds(start, end), + kind: ts.HighlightSpanKind.none + }; + } + function getSemanticDocumentHighlights(node) { + if (node.kind === 69 /* Identifier */ || + node.kind === 97 /* ThisKeyword */ || + node.kind === 165 /* ThisType */ || + node.kind === 95 /* SuperKeyword */ || + node.kind === 9 /* StringLiteral */ || + ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(node)) { + var referencedSymbols = ts.FindAllReferences.getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFilesToSearch, /*findInStrings*/ false, /*findInComments*/ false, /*implementations*/ false); + return convertReferencedSymbols(referencedSymbols); } - return false; - }; - Rules.IsNotBinaryOpContext = function (context) { - return !Rules.IsBinaryOpContext(context); - }; - Rules.IsConditionalOperatorContext = function (context) { - return context.contextNode.kind === 188 /* ConditionalExpression */; - }; - Rules.IsSameLineTokenOrBeforeMultilineBlockContext = function (context) { - //// This check is mainly used inside SpaceBeforeOpenBraceInControl and SpaceBeforeOpenBraceInFunction. - //// - //// Ex: - //// if (1) { .... - //// * ) and { are on the same line so apply the rule. Here we don't care whether it's same or multi block context - //// - //// Ex: - //// if (1) - //// { ... } - //// * ) and { are on different lines. We only need to format if the block is multiline context. So in this case we don't format. - //// - //// Ex: - //// if (1) - //// { ... - //// } - //// * ) and { are on different lines. We only need to format if the block is multiline context. So in this case we format. - return context.TokensAreOnSameLine() || Rules.IsBeforeMultilineBlockContext(context); - }; - // This check is done before an open brace in a control construct, a function, or a typescript block declaration - Rules.IsBeforeMultilineBlockContext = function (context) { - return Rules.IsBeforeBlockContext(context) && !(context.NextNodeAllOnSameLine() || context.NextNodeBlockIsOnOneLine()); - }; - Rules.IsMultilineBlockContext = function (context) { - return Rules.IsBlockContext(context) && !(context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine()); - }; - Rules.IsSingleLineBlockContext = function (context) { - return Rules.IsBlockContext(context) && (context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine()); - }; - Rules.IsBlockContext = function (context) { - return Rules.NodeIsBlockContext(context.contextNode); - }; - Rules.IsBeforeBlockContext = function (context) { - return Rules.NodeIsBlockContext(context.nextTokenParent); - }; - // IMPORTANT!!! This method must return true ONLY for nodes with open and close braces as immediate children - Rules.NodeIsBlockContext = function (node) { - if (Rules.NodeIsTypeScriptDeclWithBlockContext(node)) { - // This means we are in a context that looks like a block to the user, but in the grammar is actually not a node (it's a class, module, enum, object type literal, etc). - return true; + return undefined; + function convertReferencedSymbols(referencedSymbols) { + if (!referencedSymbols) { + return undefined; + } + var fileNameToDocumentHighlights = ts.createMap(); + var result = []; + for (var _i = 0, referencedSymbols_1 = referencedSymbols; _i < referencedSymbols_1.length; _i++) { + var referencedSymbol = referencedSymbols_1[_i]; + for (var _a = 0, _b = referencedSymbol.references; _a < _b.length; _a++) { + var referenceEntry = _b[_a]; + var fileName = referenceEntry.fileName; + var documentHighlights = fileNameToDocumentHighlights[fileName]; + if (!documentHighlights) { + documentHighlights = { fileName: fileName, highlightSpans: [] }; + fileNameToDocumentHighlights[fileName] = documentHighlights; + result.push(documentHighlights); + } + documentHighlights.highlightSpans.push({ + textSpan: referenceEntry.textSpan, + kind: referenceEntry.isWriteAccess ? ts.HighlightSpanKind.writtenReference : ts.HighlightSpanKind.reference + }); + } + } + return result; } - switch (node.kind) { - case 199 /* Block */: - case 227 /* CaseBlock */: - case 171 /* ObjectLiteralExpression */: - case 226 /* ModuleBlock */: - return true; + } + function getSyntacticDocumentHighlights(node) { + var fileName = sourceFile.fileName; + var highlightSpans = getHighlightSpans(node); + if (!highlightSpans || highlightSpans.length === 0) { + return undefined; } - return false; - }; - Rules.IsFunctionDeclContext = function (context) { - switch (context.contextNode.kind) { - case 220 /* FunctionDeclaration */: - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - // case SyntaxKind.MemberFunctionDeclaration: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - // case SyntaxKind.MethodSignature: - case 151 /* CallSignature */: - case 179 /* FunctionExpression */: - case 148 /* Constructor */: - case 180 /* ArrowFunction */: - // case SyntaxKind.ConstructorDeclaration: - // case SyntaxKind.SimpleArrowFunctionExpression: - // case SyntaxKind.ParenthesizedArrowFunctionExpression: - case 222 /* InterfaceDeclaration */: - return true; + return [{ fileName: fileName, highlightSpans: highlightSpans }]; + // returns true if 'node' is defined and has a matching 'kind'. + function hasKind(node, kind) { + return node !== undefined && node.kind === kind; } - return false; - }; - Rules.IsFunctionDeclarationOrFunctionExpressionContext = function (context) { - return context.contextNode.kind === 220 /* FunctionDeclaration */ || context.contextNode.kind === 179 /* FunctionExpression */; - }; - Rules.IsTypeScriptDeclWithBlockContext = function (context) { - return Rules.NodeIsTypeScriptDeclWithBlockContext(context.contextNode); - }; - Rules.NodeIsTypeScriptDeclWithBlockContext = function (node) { - switch (node.kind) { - case 221 /* ClassDeclaration */: - case 192 /* ClassExpression */: - case 222 /* InterfaceDeclaration */: - case 224 /* EnumDeclaration */: - case 159 /* TypeLiteral */: - case 225 /* ModuleDeclaration */: - case 236 /* ExportDeclaration */: - case 237 /* NamedExports */: - case 230 /* ImportDeclaration */: - case 233 /* NamedImports */: - return true; + // Null-propagating 'parent' function. + function parent(node) { + return node && node.parent; } - return false; - }; - Rules.IsAfterCodeBlockContext = function (context) { - switch (context.currentTokenParent.kind) { - case 221 /* ClassDeclaration */: - case 225 /* ModuleDeclaration */: - case 224 /* EnumDeclaration */: - case 199 /* Block */: - case 252 /* CatchClause */: - case 226 /* ModuleBlock */: - case 213 /* SwitchStatement */: - return true; + function getHighlightSpans(node) { + if (node) { + switch (node.kind) { + case 88 /* IfKeyword */: + case 80 /* ElseKeyword */: + if (hasKind(node.parent, 203 /* IfStatement */)) { + return getIfElseOccurrences(node.parent); + } + break; + case 94 /* ReturnKeyword */: + if (hasKind(node.parent, 211 /* ReturnStatement */)) { + return getReturnOccurrences(node.parent); + } + break; + case 98 /* ThrowKeyword */: + if (hasKind(node.parent, 215 /* ThrowStatement */)) { + return getThrowOccurrences(node.parent); + } + break; + case 72 /* CatchKeyword */: + if (hasKind(parent(parent(node)), 216 /* TryStatement */)) { + return getTryCatchFinallyOccurrences(node.parent.parent); + } + break; + case 100 /* TryKeyword */: + case 85 /* FinallyKeyword */: + if (hasKind(parent(node), 216 /* TryStatement */)) { + return getTryCatchFinallyOccurrences(node.parent); + } + break; + case 96 /* SwitchKeyword */: + if (hasKind(node.parent, 213 /* SwitchStatement */)) { + return getSwitchCaseDefaultOccurrences(node.parent); + } + break; + case 71 /* CaseKeyword */: + case 77 /* DefaultKeyword */: + if (hasKind(parent(parent(parent(node))), 213 /* SwitchStatement */)) { + return getSwitchCaseDefaultOccurrences(node.parent.parent.parent); + } + break; + case 70 /* BreakKeyword */: + case 75 /* ContinueKeyword */: + if (hasKind(node.parent, 210 /* BreakStatement */) || hasKind(node.parent, 209 /* ContinueStatement */)) { + return getBreakOrContinueStatementOccurrences(node.parent); + } + break; + case 86 /* ForKeyword */: + if (hasKind(node.parent, 206 /* ForStatement */) || + hasKind(node.parent, 207 /* ForInStatement */) || + hasKind(node.parent, 208 /* ForOfStatement */)) { + return getLoopBreakContinueOccurrences(node.parent); + } + break; + case 104 /* WhileKeyword */: + case 79 /* DoKeyword */: + if (hasKind(node.parent, 205 /* WhileStatement */) || hasKind(node.parent, 204 /* DoStatement */)) { + return getLoopBreakContinueOccurrences(node.parent); + } + break; + case 121 /* ConstructorKeyword */: + if (hasKind(node.parent, 148 /* Constructor */)) { + return getConstructorOccurrences(node.parent); + } + break; + case 123 /* GetKeyword */: + case 131 /* SetKeyword */: + if (hasKind(node.parent, 149 /* GetAccessor */) || hasKind(node.parent, 150 /* SetAccessor */)) { + return getGetAndSetOccurrences(node.parent); + } + break; + default: + if (ts.isModifierKind(node.kind) && node.parent && + (ts.isDeclaration(node.parent) || node.parent.kind === 200 /* VariableStatement */)) { + return getModifierOccurrences(node.kind, node.parent); + } + } + } + return undefined; } - return false; - }; - Rules.IsControlDeclContext = function (context) { - switch (context.contextNode.kind) { - case 203 /* IfStatement */: - case 213 /* SwitchStatement */: - case 206 /* ForStatement */: - case 207 /* ForInStatement */: - case 208 /* ForOfStatement */: - case 205 /* WhileStatement */: - case 216 /* TryStatement */: - case 204 /* DoStatement */: - case 212 /* WithStatement */: - // TODO - // case SyntaxKind.ElseClause: - case 252 /* CatchClause */: - return true; - default: - return false; + /** + * Aggregates all throw-statements within this node *without* crossing + * into function boundaries and try-blocks with catch-clauses. + */ + function aggregateOwnedThrowStatements(node) { + var statementAccumulator = []; + aggregate(node); + return statementAccumulator; + function aggregate(node) { + if (node.kind === 215 /* ThrowStatement */) { + statementAccumulator.push(node); + } + else if (node.kind === 216 /* TryStatement */) { + var tryStatement = node; + if (tryStatement.catchClause) { + aggregate(tryStatement.catchClause); + } + else { + // Exceptions thrown within a try block lacking a catch clause + // are "owned" in the current context. + aggregate(tryStatement.tryBlock); + } + if (tryStatement.finallyBlock) { + aggregate(tryStatement.finallyBlock); + } + } + else if (!ts.isFunctionLike(node)) { + ts.forEachChild(node, aggregate); + } + } } - }; - Rules.IsObjectContext = function (context) { - return context.contextNode.kind === 171 /* ObjectLiteralExpression */; - }; - Rules.IsFunctionCallContext = function (context) { - return context.contextNode.kind === 174 /* CallExpression */; - }; - Rules.IsNewContext = function (context) { - return context.contextNode.kind === 175 /* NewExpression */; - }; - Rules.IsFunctionCallOrNewContext = function (context) { - return Rules.IsFunctionCallContext(context) || Rules.IsNewContext(context); - }; - Rules.IsPreviousTokenNotComma = function (context) { - return context.currentTokenSpan.kind !== 24 /* CommaToken */; - }; - Rules.IsNextTokenNotCloseBracket = function (context) { - return context.nextTokenSpan.kind !== 20 /* CloseBracketToken */; - }; - Rules.IsArrowFunctionContext = function (context) { - return context.contextNode.kind === 180 /* ArrowFunction */; - }; - Rules.IsNonJsxSameLineTokenContext = function (context) { - return context.TokensAreOnSameLine() && context.contextNode.kind !== 244 /* JsxText */; - }; - Rules.IsNonJsxElementContext = function (context) { - return context.contextNode.kind !== 241 /* JsxElement */; - }; - Rules.IsJsxExpressionContext = function (context) { - return context.contextNode.kind === 248 /* JsxExpression */; - }; - Rules.IsNextTokenParentJsxAttribute = function (context) { - return context.nextTokenParent.kind === 246 /* JsxAttribute */; - }; - Rules.IsJsxAttributeContext = function (context) { - return context.contextNode.kind === 246 /* JsxAttribute */; - }; - Rules.IsJsxSelfClosingElementContext = function (context) { - return context.contextNode.kind === 242 /* JsxSelfClosingElement */; - }; - Rules.IsNotBeforeBlockInFunctionDeclarationContext = function (context) { - return !Rules.IsFunctionDeclContext(context) && !Rules.IsBeforeBlockContext(context); - }; - Rules.IsEndOfDecoratorContextOnSameLine = function (context) { - return context.TokensAreOnSameLine() && - context.contextNode.decorators && - Rules.NodeIsInDecoratorContext(context.currentTokenParent) && - !Rules.NodeIsInDecoratorContext(context.nextTokenParent); - }; - Rules.NodeIsInDecoratorContext = function (node) { - while (ts.isExpression(node)) { - node = node.parent; + /** + * For lack of a better name, this function takes a throw statement and returns the + * nearest ancestor that is a try-block (whose try statement has a catch clause), + * function-block, or source file. + */ + function getThrowStatementOwner(throwStatement) { + var child = throwStatement; + while (child.parent) { + var parent_20 = child.parent; + if (ts.isFunctionBlock(parent_20) || parent_20.kind === 256 /* SourceFile */) { + return parent_20; + } + // A throw-statement is only owned by a try-statement if the try-statement has + // a catch clause, and if the throw-statement occurs within the try block. + if (parent_20.kind === 216 /* TryStatement */) { + var tryStatement = parent_20; + if (tryStatement.tryBlock === child && tryStatement.catchClause) { + return child; + } + } + child = parent_20; + } + return undefined; } - return node.kind === 143 /* Decorator */; - }; - Rules.IsStartOfVariableDeclarationList = function (context) { - return context.currentTokenParent.kind === 219 /* VariableDeclarationList */ && - context.currentTokenParent.getStart(context.sourceFile) === context.currentTokenSpan.pos; - }; - Rules.IsNotFormatOnEnter = function (context) { - return context.formattingRequestKind !== 2 /* FormatOnEnter */; - }; - Rules.IsModuleDeclContext = function (context) { - return context.contextNode.kind === 225 /* ModuleDeclaration */; - }; - Rules.IsObjectTypeContext = function (context) { - return context.contextNode.kind === 159 /* TypeLiteral */; // && context.contextNode.parent.kind !== SyntaxKind.InterfaceDeclaration; - }; - Rules.IsTypeArgumentOrParameterOrAssertion = function (token, parent) { - if (token.kind !== 25 /* LessThanToken */ && token.kind !== 27 /* GreaterThanToken */) { - return false; + function aggregateAllBreakAndContinueStatements(node) { + var statementAccumulator = []; + aggregate(node); + return statementAccumulator; + function aggregate(node) { + if (node.kind === 210 /* BreakStatement */ || node.kind === 209 /* ContinueStatement */) { + statementAccumulator.push(node); + } + else if (!ts.isFunctionLike(node)) { + ts.forEachChild(node, aggregate); + } + } } - switch (parent.kind) { - case 155 /* TypeReference */: - case 177 /* TypeAssertionExpression */: - case 221 /* ClassDeclaration */: - case 192 /* ClassExpression */: - case 222 /* InterfaceDeclaration */: - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - case 180 /* ArrowFunction */: - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - case 151 /* CallSignature */: - case 152 /* ConstructSignature */: - case 174 /* CallExpression */: - case 175 /* NewExpression */: - case 194 /* ExpressionWithTypeArguments */: - return true; - default: - return false; + function ownsBreakOrContinueStatement(owner, statement) { + var actualOwner = getBreakOrContinueOwner(statement); + return actualOwner && actualOwner === owner; } - }; - Rules.IsTypeArgumentOrParameterOrAssertionContext = function (context) { - return Rules.IsTypeArgumentOrParameterOrAssertion(context.currentTokenSpan, context.currentTokenParent) || - Rules.IsTypeArgumentOrParameterOrAssertion(context.nextTokenSpan, context.nextTokenParent); - }; - Rules.IsTypeAssertionContext = function (context) { - return context.contextNode.kind === 177 /* TypeAssertionExpression */; - }; - Rules.IsVoidOpContext = function (context) { - return context.currentTokenSpan.kind === 103 /* VoidKeyword */ && context.currentTokenParent.kind === 183 /* VoidExpression */; - }; - Rules.IsYieldOrYieldStarWithOperand = function (context) { - return context.contextNode.kind === 190 /* YieldExpression */ && context.contextNode.expression !== undefined; - }; - return Rules; - }()); - formatting.Rules = Rules; - })(formatting = ts.formatting || (ts.formatting = {})); -})(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - var formatting; - (function (formatting) { - var RulesMap = (function () { - function RulesMap() { - this.map = []; - this.mapRowLength = 0; - } - RulesMap.create = function (rules) { - var result = new RulesMap(); - result.Initialize(rules); - return result; - }; - RulesMap.prototype.Initialize = function (rules) { - this.mapRowLength = 138 /* LastToken */ + 1; - this.map = new Array(this.mapRowLength * this.mapRowLength); // new Array(this.mapRowLength * this.mapRowLength); - // This array is used only during construction of the rulesbucket in the map - var rulesBucketConstructionStateList = new Array(this.map.length); // new Array(this.map.length); - this.FillRules(rules, rulesBucketConstructionStateList); - return this.map; - }; - RulesMap.prototype.FillRules = function (rules, rulesBucketConstructionStateList) { - var _this = this; - rules.forEach(function (rule) { - _this.FillRule(rule, rulesBucketConstructionStateList); - }); - }; - RulesMap.prototype.GetRuleBucketIndex = function (row, column) { - var rulesBucketIndex = (row * this.mapRowLength) + column; - // Debug.Assert(rulesBucketIndex < this.map.Length, "Trying to access an index outside the array."); - return rulesBucketIndex; - }; - RulesMap.prototype.FillRule = function (rule, rulesBucketConstructionStateList) { - var _this = this; - var specificRule = rule.Descriptor.LeftTokenRange !== formatting.Shared.TokenRange.Any && - rule.Descriptor.RightTokenRange !== formatting.Shared.TokenRange.Any; - rule.Descriptor.LeftTokenRange.GetTokens().forEach(function (left) { - rule.Descriptor.RightTokenRange.GetTokens().forEach(function (right) { - var rulesBucketIndex = _this.GetRuleBucketIndex(left, right); - var rulesBucket = _this.map[rulesBucketIndex]; - if (rulesBucket === undefined) { - rulesBucket = _this.map[rulesBucketIndex] = new RulesBucket(); + function getBreakOrContinueOwner(statement) { + for (var node_1 = statement.parent; node_1; node_1 = node_1.parent) { + switch (node_1.kind) { + case 213 /* SwitchStatement */: + if (statement.kind === 209 /* ContinueStatement */) { + continue; + } + // Fall through. + case 206 /* ForStatement */: + case 207 /* ForInStatement */: + case 208 /* ForOfStatement */: + case 205 /* WhileStatement */: + case 204 /* DoStatement */: + if (!statement.label || isLabeledBy(node_1, statement.label.text)) { + return node_1; + } + break; + default: + // Don't cross function boundaries. + if (ts.isFunctionLike(node_1)) { + return undefined; + } + break; + } + } + return undefined; + } + function getModifierOccurrences(modifier, declaration) { + var container = declaration.parent; + // Make sure we only highlight the keyword when it makes sense to do so. + if (ts.isAccessibilityModifier(modifier)) { + if (!(container.kind === 221 /* ClassDeclaration */ || + container.kind === 192 /* ClassExpression */ || + (declaration.kind === 142 /* Parameter */ && hasKind(container, 148 /* Constructor */)))) { + return undefined; + } + } + else if (modifier === 113 /* StaticKeyword */) { + if (!(container.kind === 221 /* ClassDeclaration */ || container.kind === 192 /* ClassExpression */)) { + return undefined; + } + } + else if (modifier === 82 /* ExportKeyword */ || modifier === 122 /* DeclareKeyword */) { + if (!(container.kind === 226 /* ModuleBlock */ || container.kind === 256 /* SourceFile */)) { + return undefined; + } + } + else if (modifier === 115 /* AbstractKeyword */) { + if (!(container.kind === 221 /* ClassDeclaration */ || declaration.kind === 221 /* ClassDeclaration */)) { + return undefined; + } + } + else { + // unsupported modifier + return undefined; + } + var keywords = []; + var modifierFlag = getFlagFromModifier(modifier); + var nodes; + switch (container.kind) { + case 226 /* ModuleBlock */: + case 256 /* SourceFile */: + // Container is either a class declaration or the declaration is a classDeclaration + if (modifierFlag & 128 /* Abstract */) { + nodes = declaration.members.concat(declaration); + } + else { + nodes = container.statements; + } + break; + case 148 /* Constructor */: + nodes = container.parameters.concat(container.parent.members); + break; + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + nodes = container.members; + // If we're an accessibility modifier, we're in an instance member and should search + // the constructor's parameter list for instance members as well. + if (modifierFlag & 28 /* AccessibilityModifier */) { + var constructor = ts.forEach(container.members, function (member) { + return member.kind === 148 /* Constructor */ && member; + }); + if (constructor) { + nodes = nodes.concat(constructor.parameters); + } + } + else if (modifierFlag & 128 /* Abstract */) { + nodes = nodes.concat(container); + } + break; + default: + ts.Debug.fail("Invalid container kind."); + } + ts.forEach(nodes, function (node) { + if (ts.getModifierFlags(node) & modifierFlag) { + ts.forEach(node.modifiers, function (child) { return pushKeywordIf(keywords, child, modifier); }); } - rulesBucket.AddRule(rule, specificRule, rulesBucketConstructionStateList, rulesBucketIndex); }); - }); - }; - RulesMap.prototype.GetRule = function (context) { - var bucketIndex = this.GetRuleBucketIndex(context.currentTokenSpan.kind, context.nextTokenSpan.kind); - var bucket = this.map[bucketIndex]; - if (bucket) { - for (var _i = 0, _a = bucket.Rules(); _i < _a.length; _i++) { - var rule = _a[_i]; - if (rule.Operation.Context.InContext(context)) { - return rule; + return ts.map(keywords, getHighlightSpanForNode); + function getFlagFromModifier(modifier) { + switch (modifier) { + case 112 /* PublicKeyword */: + return 4 /* Public */; + case 110 /* PrivateKeyword */: + return 8 /* Private */; + case 111 /* ProtectedKeyword */: + return 16 /* Protected */; + case 113 /* StaticKeyword */: + return 32 /* Static */; + case 82 /* ExportKeyword */: + return 1 /* Export */; + case 122 /* DeclareKeyword */: + return 2 /* Ambient */; + case 115 /* AbstractKeyword */: + return 128 /* Abstract */; + default: + ts.Debug.fail(); } } } - return undefined; - }; - return RulesMap; - }()); - formatting.RulesMap = RulesMap; - var MaskBitSize = 5; - var Mask = 0x1f; - (function (RulesPosition) { - RulesPosition[RulesPosition["IgnoreRulesSpecific"] = 0] = "IgnoreRulesSpecific"; - RulesPosition[RulesPosition["IgnoreRulesAny"] = MaskBitSize * 1] = "IgnoreRulesAny"; - RulesPosition[RulesPosition["ContextRulesSpecific"] = MaskBitSize * 2] = "ContextRulesSpecific"; - RulesPosition[RulesPosition["ContextRulesAny"] = MaskBitSize * 3] = "ContextRulesAny"; - RulesPosition[RulesPosition["NoContextRulesSpecific"] = MaskBitSize * 4] = "NoContextRulesSpecific"; - RulesPosition[RulesPosition["NoContextRulesAny"] = MaskBitSize * 5] = "NoContextRulesAny"; - })(formatting.RulesPosition || (formatting.RulesPosition = {})); - var RulesPosition = formatting.RulesPosition; - var RulesBucketConstructionState = (function () { - function RulesBucketConstructionState() { - //// The Rules list contains all the inserted rules into a rulebucket in the following order: - //// 1- Ignore rules with specific token combination - //// 2- Ignore rules with any token combination - //// 3- Context rules with specific token combination - //// 4- Context rules with any token combination - //// 5- Non-context rules with specific token combination - //// 6- Non-context rules with any token combination - //// - //// The member rulesInsertionIndexBitmap is used to describe the number of rules - //// in each sub-bucket (above) hence can be used to know the index of where to insert - //// the next rule. It's a bitmap which contains 6 different sections each is given 5 bits. - //// - //// Example: - //// In order to insert a rule to the end of sub-bucket (3), we get the index by adding - //// the values in the bitmap segments 3rd, 2nd, and 1st. - this.rulesInsertionIndexBitmap = 0; - } - RulesBucketConstructionState.prototype.GetInsertionIndex = function (maskPosition) { - var index = 0; - var pos = 0; - var indexBitmap = this.rulesInsertionIndexBitmap; - while (pos <= maskPosition) { - index += (indexBitmap & Mask); - indexBitmap >>= MaskBitSize; - pos += MaskBitSize; - } - return index; - }; - RulesBucketConstructionState.prototype.IncreaseInsertionIndex = function (maskPosition) { - var value = (this.rulesInsertionIndexBitmap >> maskPosition) & Mask; - value++; - ts.Debug.assert((value & Mask) === value, "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules."); - var temp = this.rulesInsertionIndexBitmap & ~(Mask << maskPosition); - temp |= value << maskPosition; - this.rulesInsertionIndexBitmap = temp; - }; - return RulesBucketConstructionState; - }()); - formatting.RulesBucketConstructionState = RulesBucketConstructionState; - var RulesBucket = (function () { - function RulesBucket() { - this.rules = []; - } - RulesBucket.prototype.Rules = function () { - return this.rules; - }; - RulesBucket.prototype.AddRule = function (rule, specificTokens, constructionState, rulesBucketIndex) { - var position; - if (rule.Operation.Action === 1 /* Ignore */) { - position = specificTokens ? - RulesPosition.IgnoreRulesSpecific : - RulesPosition.IgnoreRulesAny; + function pushKeywordIf(keywordList, token) { + var expected = []; + for (var _i = 2; _i < arguments.length; _i++) { + expected[_i - 2] = arguments[_i]; + } + if (token && ts.contains(expected, token.kind)) { + keywordList.push(token); + return true; + } + return false; } - else if (!rule.Operation.Context.IsAny()) { - position = specificTokens ? - RulesPosition.ContextRulesSpecific : - RulesPosition.ContextRulesAny; + function getGetAndSetOccurrences(accessorDeclaration) { + var keywords = []; + tryPushAccessorKeyword(accessorDeclaration.symbol, 149 /* GetAccessor */); + tryPushAccessorKeyword(accessorDeclaration.symbol, 150 /* SetAccessor */); + return ts.map(keywords, getHighlightSpanForNode); + function tryPushAccessorKeyword(accessorSymbol, accessorKind) { + var accessor = ts.getDeclarationOfKind(accessorSymbol, accessorKind); + if (accessor) { + ts.forEach(accessor.getChildren(), function (child) { return pushKeywordIf(keywords, child, 123 /* GetKeyword */, 131 /* SetKeyword */); }); + } + } } - else { - position = specificTokens ? - RulesPosition.NoContextRulesSpecific : - RulesPosition.NoContextRulesAny; + function getConstructorOccurrences(constructorDeclaration) { + var declarations = constructorDeclaration.symbol.getDeclarations(); + var keywords = []; + ts.forEach(declarations, function (declaration) { + ts.forEach(declaration.getChildren(), function (token) { + return pushKeywordIf(keywords, token, 121 /* ConstructorKeyword */); + }); + }); + return ts.map(keywords, getHighlightSpanForNode); } - var state = constructionState[rulesBucketIndex]; - if (state === undefined) { - state = constructionState[rulesBucketIndex] = new RulesBucketConstructionState(); + function getLoopBreakContinueOccurrences(loopNode) { + var keywords = []; + if (pushKeywordIf(keywords, loopNode.getFirstToken(), 86 /* ForKeyword */, 104 /* WhileKeyword */, 79 /* DoKeyword */)) { + // If we succeeded and got a do-while loop, then start looking for a 'while' keyword. + if (loopNode.kind === 204 /* DoStatement */) { + var loopTokens = loopNode.getChildren(); + for (var i = loopTokens.length - 1; i >= 0; i--) { + if (pushKeywordIf(keywords, loopTokens[i], 104 /* WhileKeyword */)) { + break; + } + } + } + } + var breaksAndContinues = aggregateAllBreakAndContinueStatements(loopNode.statement); + ts.forEach(breaksAndContinues, function (statement) { + if (ownsBreakOrContinueStatement(loopNode, statement)) { + pushKeywordIf(keywords, statement.getFirstToken(), 70 /* BreakKeyword */, 75 /* ContinueKeyword */); + } + }); + return ts.map(keywords, getHighlightSpanForNode); } - var index = state.GetInsertionIndex(position); - this.rules.splice(index, 0, rule); - state.IncreaseInsertionIndex(position); - }; - return RulesBucket; - }()); - formatting.RulesBucket = RulesBucket; - })(formatting = ts.formatting || (ts.formatting = {})); -})(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - var formatting; - (function (formatting) { - var Shared; - (function (Shared) { - var TokenRangeAccess = (function () { - function TokenRangeAccess(from, to, except) { - this.tokens = []; - for (var token = from; token <= to; token++) { - if (ts.indexOf(except, token) < 0) { - this.tokens.push(token); + function getBreakOrContinueStatementOccurrences(breakOrContinueStatement) { + var owner = getBreakOrContinueOwner(breakOrContinueStatement); + if (owner) { + switch (owner.kind) { + case 206 /* ForStatement */: + case 207 /* ForInStatement */: + case 208 /* ForOfStatement */: + case 204 /* DoStatement */: + case 205 /* WhileStatement */: + return getLoopBreakContinueOccurrences(owner); + case 213 /* SwitchStatement */: + return getSwitchCaseDefaultOccurrences(owner); } } + return undefined; } - TokenRangeAccess.prototype.GetTokens = function () { - return this.tokens; - }; - TokenRangeAccess.prototype.Contains = function (token) { - return this.tokens.indexOf(token) >= 0; - }; - return TokenRangeAccess; - }()); - Shared.TokenRangeAccess = TokenRangeAccess; - var TokenValuesAccess = (function () { - function TokenValuesAccess(tks) { - this.tokens = tks && tks.length ? tks : []; + function getSwitchCaseDefaultOccurrences(switchStatement) { + var keywords = []; + pushKeywordIf(keywords, switchStatement.getFirstToken(), 96 /* SwitchKeyword */); + // Go through each clause in the switch statement, collecting the 'case'/'default' keywords. + ts.forEach(switchStatement.caseBlock.clauses, function (clause) { + pushKeywordIf(keywords, clause.getFirstToken(), 71 /* CaseKeyword */, 77 /* DefaultKeyword */); + var breaksAndContinues = aggregateAllBreakAndContinueStatements(clause); + ts.forEach(breaksAndContinues, function (statement) { + if (ownsBreakOrContinueStatement(switchStatement, statement)) { + pushKeywordIf(keywords, statement.getFirstToken(), 70 /* BreakKeyword */); + } + }); + }); + return ts.map(keywords, getHighlightSpanForNode); } - TokenValuesAccess.prototype.GetTokens = function () { - return this.tokens; - }; - TokenValuesAccess.prototype.Contains = function (token) { - return this.tokens.indexOf(token) >= 0; - }; - return TokenValuesAccess; - }()); - Shared.TokenValuesAccess = TokenValuesAccess; - var TokenSingleValueAccess = (function () { - function TokenSingleValueAccess(token) { - this.token = token; + function getTryCatchFinallyOccurrences(tryStatement) { + var keywords = []; + pushKeywordIf(keywords, tryStatement.getFirstToken(), 100 /* TryKeyword */); + if (tryStatement.catchClause) { + pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken(), 72 /* CatchKeyword */); + } + if (tryStatement.finallyBlock) { + var finallyKeyword = ts.findChildOfKind(tryStatement, 85 /* FinallyKeyword */, sourceFile); + pushKeywordIf(keywords, finallyKeyword, 85 /* FinallyKeyword */); + } + return ts.map(keywords, getHighlightSpanForNode); } - TokenSingleValueAccess.prototype.GetTokens = function () { - return [this.token]; - }; - TokenSingleValueAccess.prototype.Contains = function (tokenValue) { - return tokenValue === this.token; - }; - return TokenSingleValueAccess; - }()); - Shared.TokenSingleValueAccess = TokenSingleValueAccess; - var TokenAllAccess = (function () { - function TokenAllAccess() { + function getThrowOccurrences(throwStatement) { + var owner = getThrowStatementOwner(throwStatement); + if (!owner) { + return undefined; + } + var keywords = []; + ts.forEach(aggregateOwnedThrowStatements(owner), function (throwStatement) { + pushKeywordIf(keywords, throwStatement.getFirstToken(), 98 /* ThrowKeyword */); + }); + // If the "owner" is a function, then we equate 'return' and 'throw' statements in their + // ability to "jump out" of the function, and include occurrences for both. + if (ts.isFunctionBlock(owner)) { + ts.forEachReturnStatement(owner, function (returnStatement) { + pushKeywordIf(keywords, returnStatement.getFirstToken(), 94 /* ReturnKeyword */); + }); + } + return ts.map(keywords, getHighlightSpanForNode); } - TokenAllAccess.prototype.GetTokens = function () { + function getReturnOccurrences(returnStatement) { + var func = ts.getContainingFunction(returnStatement); + // If we didn't find a containing function with a block body, bail out. + if (!(func && hasKind(func.body, 199 /* Block */))) { + return undefined; + } + var keywords = []; + ts.forEachReturnStatement(func.body, function (returnStatement) { + pushKeywordIf(keywords, returnStatement.getFirstToken(), 94 /* ReturnKeyword */); + }); + // Include 'throw' statements that do not occur within a try block. + ts.forEach(aggregateOwnedThrowStatements(func.body), function (throwStatement) { + pushKeywordIf(keywords, throwStatement.getFirstToken(), 98 /* ThrowKeyword */); + }); + return ts.map(keywords, getHighlightSpanForNode); + } + function getIfElseOccurrences(ifStatement) { + var keywords = []; + // Traverse upwards through all parent if-statements linked by their else-branches. + while (hasKind(ifStatement.parent, 203 /* IfStatement */) && ifStatement.parent.elseStatement === ifStatement) { + ifStatement = ifStatement.parent; + } + // Now traverse back down through the else branches, aggregating if/else keywords of if-statements. + while (ifStatement) { + var children = ifStatement.getChildren(); + pushKeywordIf(keywords, children[0], 88 /* IfKeyword */); + // Generally the 'else' keyword is second-to-last, so we traverse backwards. + for (var i = children.length - 1; i >= 0; i--) { + if (pushKeywordIf(keywords, children[i], 80 /* ElseKeyword */)) { + break; + } + } + if (!hasKind(ifStatement.elseStatement, 203 /* IfStatement */)) { + break; + } + ifStatement = ifStatement.elseStatement; + } var result = []; - for (var token = 0 /* FirstToken */; token <= 138 /* LastToken */; token++) { - result.push(token); + // We'd like to highlight else/ifs together if they are only separated by whitespace + // (i.e. the keywords are separated by no comments, no newlines). + for (var i = 0; i < keywords.length; i++) { + if (keywords[i].kind === 80 /* ElseKeyword */ && i < keywords.length - 1) { + var elseKeyword = keywords[i]; + var ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword. + var shouldCombindElseAndIf = true; + // Avoid recalculating getStart() by iterating backwards. + for (var j = ifKeyword.getStart() - 1; j >= elseKeyword.end; j--) { + if (!ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(j))) { + shouldCombindElseAndIf = false; + break; + } + } + if (shouldCombindElseAndIf) { + result.push({ + fileName: fileName, + textSpan: ts.createTextSpanFromBounds(elseKeyword.getStart(), ifKeyword.end), + kind: ts.HighlightSpanKind.reference + }); + i++; // skip the next keyword + continue; + } + } + // Ordinary case: just highlight the keyword. + result.push(getHighlightSpanForNode(keywords[i])); } return result; - }; - TokenAllAccess.prototype.Contains = function (tokenValue) { + } + } + } + DocumentHighlights.getDocumentHighlights = getDocumentHighlights; + /** + * Whether or not a 'node' is preceded by a label of the given string. + * Note: 'node' cannot be a SourceFile. + */ + function isLabeledBy(node, labelName) { + for (var owner = node.parent; owner.kind === 214 /* LabeledStatement */; owner = owner.parent) { + if (owner.label.text === labelName) { return true; - }; - TokenAllAccess.prototype.toString = function () { - return "[allTokens]"; - }; - return TokenAllAccess; - }()); - Shared.TokenAllAccess = TokenAllAccess; - var TokenRange = (function () { - function TokenRange(tokenAccess) { - this.tokenAccess = tokenAccess; } - TokenRange.FromToken = function (token) { - return new TokenRange(new TokenSingleValueAccess(token)); - }; - TokenRange.FromTokens = function (tokens) { - return new TokenRange(new TokenValuesAccess(tokens)); - }; - TokenRange.FromRange = function (f, to, except) { - if (except === void 0) { except = []; } - return new TokenRange(new TokenRangeAccess(f, to, except)); - }; - TokenRange.AllTokens = function () { - return new TokenRange(new TokenAllAccess()); - }; - TokenRange.prototype.GetTokens = function () { - return this.tokenAccess.GetTokens(); - }; - TokenRange.prototype.Contains = function (token) { - return this.tokenAccess.Contains(token); + } + return false; + } + })(DocumentHighlights = ts.DocumentHighlights || (ts.DocumentHighlights = {})); +})(ts || (ts = {})); +var ts; +(function (ts) { + function createDocumentRegistry(useCaseSensitiveFileNames, currentDirectory) { + if (currentDirectory === void 0) { currentDirectory = ""; } + // Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have + // for those settings. + var buckets = ts.createMap(); + var getCanonicalFileName = ts.createGetCanonicalFileName(!!useCaseSensitiveFileNames); + function getKeyForCompilationSettings(settings) { + return "_" + settings.target + "|" + settings.module + "|" + settings.noResolve + "|" + settings.jsx + "|" + settings.allowJs + "|" + settings.baseUrl + "|" + JSON.stringify(settings.typeRoots) + "|" + JSON.stringify(settings.rootDirs) + "|" + JSON.stringify(settings.paths); + } + function getBucketForCompilationSettings(key, createIfMissing) { + var bucket = buckets[key]; + if (!bucket && createIfMissing) { + buckets[key] = bucket = ts.createFileMap(); + } + return bucket; + } + function reportStats() { + var bucketInfoArray = Object.keys(buckets).filter(function (name) { return name && name.charAt(0) === "_"; }).map(function (name) { + var entries = buckets[name]; + var sourceFiles = []; + entries.forEachValue(function (key, entry) { + sourceFiles.push({ + name: key, + refCount: entry.languageServiceRefCount, + references: entry.owners.slice(0) + }); + }); + sourceFiles.sort(function (x, y) { return y.refCount - x.refCount; }); + return { + bucket: name, + sourceFiles: sourceFiles }; - TokenRange.prototype.toString = function () { - return this.tokenAccess.toString(); + }); + return JSON.stringify(bucketInfoArray, undefined, 2); + } + function acquireDocument(fileName, compilationSettings, scriptSnapshot, version, scriptKind) { + var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); + var key = getKeyForCompilationSettings(compilationSettings); + return acquireDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind); + } + function acquireDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind) { + return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, /*acquiring*/ true, scriptKind); + } + function updateDocument(fileName, compilationSettings, scriptSnapshot, version, scriptKind) { + var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); + var key = getKeyForCompilationSettings(compilationSettings); + return updateDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind); + } + function updateDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind) { + return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, /*acquiring*/ false, scriptKind); + } + function acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, acquiring, scriptKind) { + var bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ true); + var entry = bucket.get(path); + if (!entry) { + ts.Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?"); + // Have never seen this file with these settings. Create a new source file for it. + var sourceFile = ts.createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false, scriptKind); + entry = { + sourceFile: sourceFile, + languageServiceRefCount: 0, + owners: [] }; - TokenRange.Any = TokenRange.AllTokens(); - TokenRange.AnyIncludingMultilineComments = TokenRange.FromTokens(TokenRange.Any.GetTokens().concat([3 /* MultiLineCommentTrivia */])); - TokenRange.Keywords = TokenRange.FromRange(70 /* FirstKeyword */, 138 /* LastKeyword */); - TokenRange.BinaryOperators = TokenRange.FromRange(25 /* FirstBinaryOperator */, 68 /* LastBinaryOperator */); - TokenRange.BinaryKeywordOperators = TokenRange.FromTokens([90 /* InKeyword */, 91 /* InstanceOfKeyword */, 138 /* OfKeyword */, 116 /* AsKeyword */, 124 /* IsKeyword */]); - TokenRange.UnaryPrefixOperators = TokenRange.FromTokens([41 /* PlusPlusToken */, 42 /* MinusMinusToken */, 50 /* TildeToken */, 49 /* ExclamationToken */]); - TokenRange.UnaryPrefixExpressions = TokenRange.FromTokens([8 /* NumericLiteral */, 69 /* Identifier */, 17 /* OpenParenToken */, 19 /* OpenBracketToken */, 15 /* OpenBraceToken */, 97 /* ThisKeyword */, 92 /* NewKeyword */]); - TokenRange.UnaryPreincrementExpressions = TokenRange.FromTokens([69 /* Identifier */, 17 /* OpenParenToken */, 97 /* ThisKeyword */, 92 /* NewKeyword */]); - TokenRange.UnaryPostincrementExpressions = TokenRange.FromTokens([69 /* Identifier */, 18 /* CloseParenToken */, 20 /* CloseBracketToken */, 92 /* NewKeyword */]); - TokenRange.UnaryPredecrementExpressions = TokenRange.FromTokens([69 /* Identifier */, 17 /* OpenParenToken */, 97 /* ThisKeyword */, 92 /* NewKeyword */]); - TokenRange.UnaryPostdecrementExpressions = TokenRange.FromTokens([69 /* Identifier */, 18 /* CloseParenToken */, 20 /* CloseBracketToken */, 92 /* NewKeyword */]); - TokenRange.Comments = TokenRange.FromTokens([2 /* SingleLineCommentTrivia */, 3 /* MultiLineCommentTrivia */]); - TokenRange.TypeNames = TokenRange.FromTokens([69 /* Identifier */, 130 /* NumberKeyword */, 132 /* StringKeyword */, 120 /* BooleanKeyword */, 133 /* SymbolKeyword */, 103 /* VoidKeyword */, 117 /* AnyKeyword */]); - return TokenRange; - }()); - Shared.TokenRange = TokenRange; - })(Shared = formatting.Shared || (formatting.Shared = {})); - })(formatting = ts.formatting || (ts.formatting = {})); + bucket.set(path, entry); + } + else { + // We have an entry for this file. However, it may be for a different version of + // the script snapshot. If so, update it appropriately. Otherwise, we can just + // return it as is. + if (entry.sourceFile.version !== version) { + entry.sourceFile = ts.updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version, scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot)); + } + } + // If we're acquiring, then this is the first time this LS is asking for this document. + // Increase our ref count so we know there's another LS using the document. If we're + // not acquiring, then that means the LS is 'updating' the file instead, and that means + // it has already acquired the document previously. As such, we do not need to increase + // the ref count. + if (acquiring) { + entry.languageServiceRefCount++; + } + return entry.sourceFile; + } + function releaseDocument(fileName, compilationSettings) { + var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); + var key = getKeyForCompilationSettings(compilationSettings); + return releaseDocumentWithKey(path, key); + } + function releaseDocumentWithKey(path, key) { + var bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ false); + ts.Debug.assert(bucket !== undefined); + var entry = bucket.get(path); + entry.languageServiceRefCount--; + ts.Debug.assert(entry.languageServiceRefCount >= 0); + if (entry.languageServiceRefCount === 0) { + bucket.remove(path); + } + } + return { + acquireDocument: acquireDocument, + acquireDocumentWithKey: acquireDocumentWithKey, + updateDocument: updateDocument, + updateDocumentWithKey: updateDocumentWithKey, + releaseDocument: releaseDocument, + releaseDocumentWithKey: releaseDocumentWithKey, + reportStats: reportStats, + getKeyForCompilationSettings: getKeyForCompilationSettings + }; + } + ts.createDocumentRegistry = createDocumentRegistry; })(ts || (ts = {})); -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// /* @internal */ var ts; (function (ts) { - var formatting; - (function (formatting) { - var RulesProvider = (function () { - function RulesProvider() { - this.globalRules = new formatting.Rules(); + var FindAllReferences; + (function (FindAllReferences) { + function findReferencedSymbols(typeChecker, cancellationToken, sourceFiles, sourceFile, position, findInStrings, findInComments) { + var node = ts.getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true); + if (node === sourceFile) { + return undefined; } - RulesProvider.prototype.getRuleName = function (rule) { - return this.globalRules.getRuleName(rule); - }; - RulesProvider.prototype.getRuleByName = function (name) { - return this.globalRules[name]; - }; - RulesProvider.prototype.getRulesMap = function () { - return this.rulesMap; - }; - RulesProvider.prototype.ensureUpToDate = function (options) { - if (!this.options || !ts.compareDataObjects(this.options, options)) { - var activeRules = this.createActiveRules(options); - var rulesMap = formatting.RulesMap.create(activeRules); - this.activeRules = activeRules; - this.rulesMap = rulesMap; - this.options = ts.clone(options); + switch (node.kind) { + case 8 /* NumericLiteral */: + if (!ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(node)) { + break; + } + // Fallthrough + case 69 /* Identifier */: + case 97 /* ThisKeyword */: + // case SyntaxKind.SuperKeyword: TODO:GH#9268 + case 121 /* ConstructorKeyword */: + case 9 /* StringLiteral */: + return getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFiles, findInStrings, findInComments, /*implementations*/ false); + } + return undefined; + } + FindAllReferences.findReferencedSymbols = findReferencedSymbols; + function getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFiles, findInStrings, findInComments, implementations) { + if (!implementations) { + // Labels + if (ts.isLabelName(node)) { + if (ts.isJumpStatementTarget(node)) { + var labelDefinition = ts.getTargetLabel(node.parent, node.text); + // if we have a label definition, look within its statement for references, if not, then + // the label is undefined and we have no results.. + return labelDefinition ? getLabelReferencesInNode(labelDefinition.parent, labelDefinition) : undefined; + } + else { + // it is a label definition and not a target, search within the parent labeledStatement + return getLabelReferencesInNode(node.parent, node); + } } - }; - RulesProvider.prototype.createActiveRules = function (options) { - var rules = this.globalRules.HighPriorityCommonRules.slice(0); - if (options.InsertSpaceAfterCommaDelimiter) { - rules.push(this.globalRules.SpaceAfterComma); + if (ts.isThis(node)) { + return getReferencesForThisKeyword(node, sourceFiles); } - else { - rules.push(this.globalRules.NoSpaceAfterComma); + if (node.kind === 95 /* SuperKeyword */) { + return getReferencesForSuperKeyword(node); } - if (options.InsertSpaceAfterFunctionKeywordForAnonymousFunctions) { - rules.push(this.globalRules.SpaceAfterAnonymousFunctionKeyword); + } + // `getSymbolAtLocation` normally returns the symbol of the class when given the constructor keyword, + // so we have to specify that we want the constructor symbol. + var symbol = typeChecker.getSymbolAtLocation(node); + if (!implementations && !symbol && node.kind === 9 /* StringLiteral */) { + return getReferencesForStringLiteral(node, sourceFiles); + } + // Could not find a symbol e.g. unknown identifier + if (!symbol) { + // Can't have references to something that we have no symbol for. + return undefined; + } + var declarations = symbol.declarations; + // The symbol was an internal symbol and does not have a declaration e.g. undefined symbol + if (!declarations || !declarations.length) { + return undefined; + } + var result; + // Compute the meaning from the location and the symbol it references + var searchMeaning = getIntersectingMeaningFromDeclarations(ts.getMeaningFromLocation(node), declarations); + // Get the text to search for. + // Note: if this is an external module symbol, the name doesn't include quotes. + var declaredName = ts.stripQuotes(ts.getDeclaredName(typeChecker, symbol, node)); + // Try to get the smallest valid scope that we can limit our search to; + // otherwise we'll need to search globally (i.e. include each file). + var scope = getSymbolScope(symbol); + // Maps from a symbol ID to the ReferencedSymbol entry in 'result'. + var symbolToIndex = []; + if (scope) { + result = []; + getReferencesInNode(scope, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex); + } + else { + var internedName = getInternedName(symbol, node, declarations); + for (var _i = 0, sourceFiles_8 = sourceFiles; _i < sourceFiles_8.length; _i++) { + var sourceFile = sourceFiles_8[_i]; + cancellationToken.throwIfCancellationRequested(); + var nameTable = ts.getNameTable(sourceFile); + if (nameTable[internedName] !== undefined) { + result = result || []; + getReferencesInNode(sourceFile, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex); + } } - else { - rules.push(this.globalRules.NoSpaceAfterAnonymousFunctionKeyword); + } + return result; + function getDefinition(symbol) { + var info = ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, node.getSourceFile(), ts.getContainerNode(node), node); + var name = ts.map(info.displayParts, function (p) { return p.text; }).join(""); + var declarations = symbol.declarations; + if (!declarations || declarations.length === 0) { + return undefined; } - if (options.InsertSpaceAfterKeywordsInControlFlowStatements) { - rules.push(this.globalRules.SpaceAfterKeywordInControl); + return { + containerKind: "", + containerName: "", + name: name, + kind: info.symbolKind, + fileName: declarations[0].getSourceFile().fileName, + textSpan: ts.createTextSpan(declarations[0].getStart(), 0), + displayParts: info.displayParts + }; + } + function getAliasSymbolForPropertyNameSymbol(symbol, location) { + if (symbol.flags & 8388608 /* Alias */) { + // Default import get alias + var defaultImport = ts.getDeclarationOfKind(symbol, 231 /* ImportClause */); + if (defaultImport) { + return typeChecker.getAliasedSymbol(symbol); + } + var importOrExportSpecifier = ts.forEach(symbol.declarations, function (declaration) { return (declaration.kind === 234 /* ImportSpecifier */ || + declaration.kind === 238 /* ExportSpecifier */) ? declaration : undefined; }); + if (importOrExportSpecifier && + // export { a } + (!importOrExportSpecifier.propertyName || + // export {a as class } where a is location + importOrExportSpecifier.propertyName === location)) { + // If Import specifier -> get alias + // else Export specifier -> get local target + return importOrExportSpecifier.kind === 234 /* ImportSpecifier */ ? + typeChecker.getAliasedSymbol(symbol) : + typeChecker.getExportSpecifierLocalTargetSymbol(importOrExportSpecifier); + } } - else { - rules.push(this.globalRules.NoSpaceAfterKeywordInControl); + return undefined; + } + function followAliasIfNecessary(symbol, location) { + return getAliasSymbolForPropertyNameSymbol(symbol, location) || symbol; + } + function getPropertySymbolOfDestructuringAssignment(location) { + return ts.isArrayLiteralOrObjectLiteralDestructuringPattern(location.parent.parent) && + typeChecker.getPropertySymbolOfDestructuringAssignment(location); + } + function isObjectBindingPatternElementWithoutPropertyName(symbol) { + var bindingElement = ts.getDeclarationOfKind(symbol, 169 /* BindingElement */); + return bindingElement && + bindingElement.parent.kind === 167 /* ObjectBindingPattern */ && + !bindingElement.propertyName; + } + function getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol) { + if (isObjectBindingPatternElementWithoutPropertyName(symbol)) { + var bindingElement = ts.getDeclarationOfKind(symbol, 169 /* BindingElement */); + var typeOfPattern = typeChecker.getTypeAtLocation(bindingElement.parent); + return typeOfPattern && typeChecker.getPropertyOfType(typeOfPattern, bindingElement.name.text); } - if (options.InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis) { - rules.push(this.globalRules.SpaceAfterOpenParen); - rules.push(this.globalRules.SpaceBeforeCloseParen); - rules.push(this.globalRules.NoSpaceBetweenParens); + return undefined; + } + function getInternedName(symbol, location, declarations) { + // If this is an export or import specifier it could have been renamed using the 'as' syntax. + // If so we want to search for whatever under the cursor. + if (ts.isImportOrExportSpecifierName(location)) { + return location.getText(); } - else { - rules.push(this.globalRules.NoSpaceAfterOpenParen); - rules.push(this.globalRules.NoSpaceBeforeCloseParen); - rules.push(this.globalRules.NoSpaceBetweenParens); + // Try to get the local symbol if we're dealing with an 'export default' + // since that symbol has the "true" name. + var localExportDefaultSymbol = ts.getLocalSymbolForExportDefault(symbol); + symbol = localExportDefaultSymbol || symbol; + return ts.stripQuotes(symbol.name); + } + /** + * Determines the smallest scope in which a symbol may have named references. + * Note that not every construct has been accounted for. This function can + * probably be improved. + * + * @returns undefined if the scope cannot be determined, implying that + * a reference to a symbol can occur anywhere. + */ + function getSymbolScope(symbol) { + // If this is the symbol of a named function expression or named class expression, + // then named references are limited to its own scope. + var valueDeclaration = symbol.valueDeclaration; + if (valueDeclaration && (valueDeclaration.kind === 179 /* FunctionExpression */ || valueDeclaration.kind === 192 /* ClassExpression */)) { + return valueDeclaration; } - if (options.InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets) { - rules.push(this.globalRules.SpaceAfterOpenBracket); - rules.push(this.globalRules.SpaceBeforeCloseBracket); - rules.push(this.globalRules.NoSpaceBetweenBrackets); + // If this is private property or method, the scope is the containing class + if (symbol.flags & (4 /* Property */ | 8192 /* Method */)) { + var privateDeclaration = ts.forEach(symbol.getDeclarations(), function (d) { return (ts.getModifierFlags(d) & 8 /* Private */) ? d : undefined; }); + if (privateDeclaration) { + return ts.getAncestor(privateDeclaration, 221 /* ClassDeclaration */); + } } - else { - rules.push(this.globalRules.NoSpaceAfterOpenBracket); - rules.push(this.globalRules.NoSpaceBeforeCloseBracket); - rules.push(this.globalRules.NoSpaceBetweenBrackets); + // If the symbol is an import we would like to find it if we are looking for what it imports. + // So consider it visible outside its declaration scope. + if (symbol.flags & 8388608 /* Alias */) { + return undefined; } - if (options.InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces) { - rules.push(this.globalRules.SpaceAfterTemplateHeadAndMiddle); - rules.push(this.globalRules.SpaceBeforeTemplateMiddleAndTail); + // If symbol is of object binding pattern element without property name we would want to + // look for property too and that could be anywhere + if (isObjectBindingPatternElementWithoutPropertyName(symbol)) { + return undefined; } - else { - rules.push(this.globalRules.NoSpaceAfterTemplateHeadAndMiddle); - rules.push(this.globalRules.NoSpaceBeforeTemplateMiddleAndTail); + // if this symbol is visible from its parent container, e.g. exported, then bail out + // if symbol correspond to the union property - bail out + if (symbol.parent || (symbol.flags & 268435456 /* SyntheticProperty */)) { + return undefined; } - if (options.InsertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces) { - rules.push(this.globalRules.SpaceAfterOpenBraceInJsxExpression); - rules.push(this.globalRules.SpaceBeforeCloseBraceInJsxExpression); + var scope; + var declarations = symbol.getDeclarations(); + if (declarations) { + for (var _i = 0, declarations_7 = declarations; _i < declarations_7.length; _i++) { + var declaration = declarations_7[_i]; + var container = ts.getContainerNode(declaration); + if (!container) { + return undefined; + } + if (scope && scope !== container) { + // Different declarations have different containers, bail out + return undefined; + } + if (container.kind === 256 /* SourceFile */ && !ts.isExternalModule(container)) { + // This is a global variable and not an external module, any declaration defined + // within this scope is visible outside the file + return undefined; + } + // The search scope is the container node + scope = container; + } } - else { - rules.push(this.globalRules.NoSpaceAfterOpenBraceInJsxExpression); - rules.push(this.globalRules.NoSpaceBeforeCloseBraceInJsxExpression); + return scope; + } + function getPossibleSymbolReferencePositions(sourceFile, symbolName, start, end) { + var positions = []; + /// TODO: Cache symbol existence for files to save text search + // Also, need to make this work for unicode escapes. + // Be resilient in the face of a symbol with no name or zero length name + if (!symbolName || !symbolName.length) { + return positions; } - if (options.InsertSpaceAfterSemicolonInForStatements) { - rules.push(this.globalRules.SpaceAfterSemicolonInFor); + var text = sourceFile.text; + var sourceLength = text.length; + var symbolNameLength = symbolName.length; + var position = text.indexOf(symbolName, start); + while (position >= 0) { + cancellationToken.throwIfCancellationRequested(); + // If we are past the end, stop looking + if (position > end) + break; + // We found a match. Make sure it's not part of a larger word (i.e. the char + // before and after it have to be a non-identifier char). + var endPosition = position + symbolNameLength; + if ((position === 0 || !ts.isIdentifierPart(text.charCodeAt(position - 1), 2 /* Latest */)) && + (endPosition === sourceLength || !ts.isIdentifierPart(text.charCodeAt(endPosition), 2 /* Latest */))) { + // Found a real match. Keep searching. + positions.push(position); + } + position = text.indexOf(symbolName, position + symbolNameLength + 1); } - else { - rules.push(this.globalRules.NoSpaceAfterSemicolonInFor); + return positions; + } + function getLabelReferencesInNode(container, targetLabel) { + var references = []; + var sourceFile = container.getSourceFile(); + var labelName = targetLabel.text; + var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container.getStart(), container.getEnd()); + ts.forEach(possiblePositions, function (position) { + cancellationToken.throwIfCancellationRequested(); + var node = ts.getTouchingWord(sourceFile, position); + if (!node || node.getWidth() !== labelName.length) { + return; + } + // Only pick labels that are either the target label, or have a target that is the target label + if (node === targetLabel || + (ts.isJumpStatementTarget(node) && ts.getTargetLabel(node, labelName) === targetLabel)) { + references.push(getReferenceEntryFromNode(node)); + } + }); + var definition = { + containerKind: "", + containerName: "", + fileName: targetLabel.getSourceFile().fileName, + kind: ts.ScriptElementKind.label, + name: labelName, + textSpan: ts.createTextSpanFromBounds(targetLabel.getStart(), targetLabel.getEnd()), + displayParts: [ts.displayPart(labelName, ts.SymbolDisplayPartKind.text)] + }; + return [{ definition: definition, references: references }]; + } + function isValidReferencePosition(node, searchSymbolName) { + if (node) { + // Compare the length so we filter out strict superstrings of the symbol we are looking for + switch (node.kind) { + case 69 /* Identifier */: + return node.getWidth() === searchSymbolName.length; + case 9 /* StringLiteral */: + if (ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || + isNameOfExternalModuleImportOrDeclaration(node)) { + // For string literals we have two additional chars for the quotes + return node.getWidth() === searchSymbolName.length + 2; + } + break; + case 8 /* NumericLiteral */: + if (ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(node)) { + return node.getWidth() === searchSymbolName.length; + } + break; + } } - if (options.InsertSpaceBeforeAndAfterBinaryOperators) { - rules.push(this.globalRules.SpaceBeforeBinaryOperator); - rules.push(this.globalRules.SpaceAfterBinaryOperator); + return false; + } + /** Search within node "container" for references for a search value, where the search value is defined as a + * tuple of(searchSymbol, searchText, searchLocation, and searchMeaning). + * searchLocation: a node where the search value + */ + function getReferencesInNode(container, searchSymbol, searchText, searchLocation, searchMeaning, findInStrings, findInComments, result, symbolToIndex) { + var sourceFile = container.getSourceFile(); + var start = findInComments ? container.getFullStart() : container.getStart(); + var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, start, container.getEnd()); + var parents = getParentSymbolsOfPropertyAccess(); + var inheritsFromCache = ts.createMap(); + if (possiblePositions.length) { + // Build the set of symbols to search for, initially it has only the current symbol + var searchSymbols_1 = populateSearchSymbolSet(searchSymbol, searchLocation); + ts.forEach(possiblePositions, function (position) { + cancellationToken.throwIfCancellationRequested(); + var referenceLocation = ts.getTouchingPropertyName(sourceFile, position); + if (!isValidReferencePosition(referenceLocation, searchText)) { + // This wasn't the start of a token. Check to see if it might be a + // match in a comment or string if that's what the caller is asking + // for. + if (!implementations && ((findInStrings && ts.isInString(sourceFile, position)) || + (findInComments && ts.isInNonReferenceComment(sourceFile, position)))) { + // In the case where we're looking inside comments/strings, we don't have + // an actual definition. So just use 'undefined' here. Features like + // 'Rename' won't care (as they ignore the definitions), and features like + // 'FindReferences' will just filter out these results. + result.push({ + definition: undefined, + references: [{ + fileName: sourceFile.fileName, + textSpan: ts.createTextSpan(position, searchText.length), + isWriteAccess: false, + isDefinition: false + }] + }); + } + return; + } + if (!(ts.getMeaningFromLocation(referenceLocation) & searchMeaning)) { + return; + } + var referenceSymbol = typeChecker.getSymbolAtLocation(referenceLocation); + if (referenceSymbol) { + var referenceSymbolDeclaration = referenceSymbol.valueDeclaration; + var shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration); + var relatedSymbol = getRelatedSymbol(searchSymbols_1, referenceSymbol, referenceLocation, + /*searchLocationIsConstructor*/ searchLocation.kind === 121 /* ConstructorKeyword */, parents, inheritsFromCache); + if (relatedSymbol) { + addReferenceToRelatedSymbol(referenceLocation, relatedSymbol); + } + else if (!(referenceSymbol.flags & 67108864 /* Transient */) && searchSymbols_1.indexOf(shorthandValueSymbol) >= 0) { + addReferenceToRelatedSymbol(referenceSymbolDeclaration.name, shorthandValueSymbol); + } + else if (searchLocation.kind === 121 /* ConstructorKeyword */) { + findAdditionalConstructorReferences(referenceSymbol, referenceLocation); + } + } + }); } - else { - rules.push(this.globalRules.NoSpaceBeforeBinaryOperator); - rules.push(this.globalRules.NoSpaceAfterBinaryOperator); + return; + /* If we are just looking for implementations and this is a property access expression, we need to get the + * symbol of the local type of the symbol the property is being accessed on. This is because our search + * symbol may have a different parent symbol if the local type's symbol does not declare the property + * being accessed (i.e. it is declared in some parent class or interface) + */ + function getParentSymbolsOfPropertyAccess() { + if (implementations) { + var propertyAccessExpression = getPropertyAccessExpressionFromRightHandSide(searchLocation); + if (propertyAccessExpression) { + var localParentType = typeChecker.getTypeAtLocation(propertyAccessExpression.expression); + if (localParentType) { + if (localParentType.symbol && localParentType.symbol.flags & (32 /* Class */ | 64 /* Interface */) && localParentType.symbol !== searchSymbol.parent) { + return [localParentType.symbol]; + } + else if (localParentType.flags & 1572864 /* UnionOrIntersection */) { + return getSymbolsForClassAndInterfaceComponents(localParentType); + } + } + } + } } - if (options.PlaceOpenBraceOnNewLineForControlBlocks) { - rules.push(this.globalRules.NewLineBeforeOpenBraceInControl); + function getPropertyAccessExpressionFromRightHandSide(node) { + return ts.isRightSideOfPropertyAccess(node) && node.parent; } - if (options.PlaceOpenBraceOnNewLineForFunctions) { - rules.push(this.globalRules.NewLineBeforeOpenBraceInFunction); - rules.push(this.globalRules.NewLineBeforeOpenBraceInTypeScriptDeclWithBlock); + /** Adds references when a constructor is used with `new this()` in its own class and `super()` calls in subclasses. */ + function findAdditionalConstructorReferences(referenceSymbol, referenceLocation) { + ts.Debug.assert(ts.isClassLike(searchSymbol.valueDeclaration)); + var referenceClass = referenceLocation.parent; + if (referenceSymbol === searchSymbol && ts.isClassLike(referenceClass)) { + ts.Debug.assert(referenceClass.name === referenceLocation); + // This is the class declaration containing the constructor. + addReferences(findOwnConstructorCalls(searchSymbol)); + } + else { + // If this class appears in `extends C`, then the extending class' "super" calls are references. + var classExtending = tryGetClassByExtendingIdentifier(referenceLocation); + if (classExtending && ts.isClassLike(classExtending) && followAliasIfNecessary(referenceSymbol, referenceLocation) === searchSymbol) { + addReferences(superConstructorAccesses(classExtending)); + } + } + } + function addReferences(references) { + if (references.length) { + var referencedSymbol = getReferencedSymbol(searchSymbol); + ts.addRange(referencedSymbol.references, ts.map(references, getReferenceEntryFromNode)); + } + } + /** `classSymbol` is the class where the constructor was defined. + * Reference the constructor and all calls to `new this()`. + */ + function findOwnConstructorCalls(classSymbol) { + var result = []; + for (var _i = 0, _a = classSymbol.members["__constructor"].declarations; _i < _a.length; _i++) { + var decl = _a[_i]; + ts.Debug.assert(decl.kind === 148 /* Constructor */); + var ctrKeyword = decl.getChildAt(0); + ts.Debug.assert(ctrKeyword.kind === 121 /* ConstructorKeyword */); + result.push(ctrKeyword); + } + ts.forEachProperty(classSymbol.exports, function (member) { + var decl = member.valueDeclaration; + if (decl && decl.kind === 147 /* MethodDeclaration */) { + var body = decl.body; + if (body) { + forEachDescendantOfKind(body, 97 /* ThisKeyword */, function (thisKeyword) { + if (ts.isNewExpressionTarget(thisKeyword)) { + result.push(thisKeyword); + } + }); + } + } + }); + return result; + } + /** Find references to `super` in the constructor of an extending class. */ + function superConstructorAccesses(cls) { + var symbol = cls.symbol; + var ctr = symbol.members["__constructor"]; + if (!ctr) { + return []; + } + var result = []; + for (var _i = 0, _a = ctr.declarations; _i < _a.length; _i++) { + var decl = _a[_i]; + ts.Debug.assert(decl.kind === 148 /* Constructor */); + var body = decl.body; + if (body) { + forEachDescendantOfKind(body, 95 /* SuperKeyword */, function (node) { + if (ts.isCallExpressionTarget(node)) { + result.push(node); + } + }); + } + } + ; + return result; + } + function getReferencedSymbol(symbol) { + var symbolId = ts.getSymbolId(symbol); + var index = symbolToIndex[symbolId]; + if (index === undefined) { + index = result.length; + symbolToIndex[symbolId] = index; + result.push({ + definition: getDefinition(symbol), + references: [] + }); + } + return result[index]; + } + function addReferenceToRelatedSymbol(node, relatedSymbol) { + var references = getReferencedSymbol(relatedSymbol).references; + if (implementations) { + getImplementationReferenceEntryForNode(node, references); + } + else { + references.push(getReferenceEntryFromNode(node)); + } } - rules = rules.concat(this.globalRules.LowPriorityCommonRules); - return rules; - }; - return RulesProvider; - }()); - formatting.RulesProvider = RulesProvider; - })(formatting = ts.formatting || (ts.formatting = {})); -})(ts || (ts = {})); -/// -/// -/// -/// -/* @internal */ -var ts; -(function (ts) { - var formatting; - (function (formatting) { - var Constants; - (function (Constants) { - Constants[Constants["Unknown"] = -1] = "Unknown"; - })(Constants || (Constants = {})); - function formatOnEnter(position, sourceFile, rulesProvider, options) { - var line = sourceFile.getLineAndCharacterOfPosition(position).line; - if (line === 0) { - return []; - } - // After the enter key, the cursor is now at a new line. The new line may or may not contain non-whitespace characters. - // If the new line has only whitespaces, we won't want to format this line, because that would remove the indentation as - // trailing whitespaces. So the end of the formatting span should be the later one between: - // 1. the end of the previous line - // 2. the last non-whitespace character in the current line - var endOfFormatSpan = ts.getEndLinePosition(line, sourceFile); - while (ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(endOfFormatSpan))) { - endOfFormatSpan--; - } - // if the character at the end of the span is a line break, we shouldn't include it, because it indicates we don't want to - // touch the current line at all. Also, on some OSes the line break consists of two characters (\r\n), we should test if the - // previous character before the end of format span is line break character as well. - if (ts.isLineBreak(sourceFile.text.charCodeAt(endOfFormatSpan))) { - endOfFormatSpan--; - } - var span = { - // get start position for the previous line - pos: ts.getStartPositionOfLine(line - 1, sourceFile), - // end value is exclusive so add 1 to the result - end: endOfFormatSpan + 1 - }; - return formatSpan(span, sourceFile, options, rulesProvider, 2 /* FormatOnEnter */); - } - formatting.formatOnEnter = formatOnEnter; - function formatOnSemicolon(position, sourceFile, rulesProvider, options) { - return formatOutermostParent(position, 23 /* SemicolonToken */, sourceFile, options, rulesProvider, 3 /* FormatOnSemicolon */); - } - formatting.formatOnSemicolon = formatOnSemicolon; - function formatOnClosingCurly(position, sourceFile, rulesProvider, options) { - return formatOutermostParent(position, 16 /* CloseBraceToken */, sourceFile, options, rulesProvider, 4 /* FormatOnClosingCurlyBrace */); - } - formatting.formatOnClosingCurly = formatOnClosingCurly; - function formatDocument(sourceFile, rulesProvider, options) { - var span = { - pos: 0, - end: sourceFile.text.length - }; - return formatSpan(span, sourceFile, options, rulesProvider, 0 /* FormatDocument */); - } - formatting.formatDocument = formatDocument; - function formatSelection(start, end, sourceFile, rulesProvider, options) { - // format from the beginning of the line - var span = { - pos: ts.getLineStartPositionForPosition(start, sourceFile), - end: end - }; - return formatSpan(span, sourceFile, options, rulesProvider, 1 /* FormatSelection */); - } - formatting.formatSelection = formatSelection; - function formatOutermostParent(position, expectedLastToken, sourceFile, options, rulesProvider, requestKind) { - var parent = findOutermostParent(position, expectedLastToken, sourceFile); - if (!parent) { - return []; - } - var span = { - pos: ts.getLineStartPositionForPosition(parent.getStart(sourceFile), sourceFile), - end: parent.end - }; - return formatSpan(span, sourceFile, options, rulesProvider, requestKind); - } - function findOutermostParent(position, expectedTokenKind, sourceFile) { - var precedingToken = ts.findPrecedingToken(position, sourceFile); - // when it is claimed that trigger character was typed at given position - // we verify that there is a token with a matching kind whose end is equal to position (because the character was just typed). - // If this condition is not hold - then trigger character was typed in some other context, - // i.e.in comment and thus should not trigger autoformatting - if (!precedingToken || - precedingToken.kind !== expectedTokenKind || - position !== precedingToken.getEnd()) { - return undefined; } - // walk up and search for the parent node that ends at the same position with precedingToken. - // for cases like this - // - // let x = 1; - // while (true) { - // } - // after typing close curly in while statement we want to reformat just the while statement. - // However if we just walk upwards searching for the parent that has the same end value - - // we'll end up with the whole source file. isListElement allows to stop on the list element level - var current = precedingToken; - while (current && - current.parent && - current.parent.end === precedingToken.end && - !isListElement(current.parent, current)) { - current = current.parent; + function getImplementationReferenceEntryForNode(refNode, result) { + // Check if we found a function/propertyAssignment/method with an implementation or initializer + if (ts.isDeclarationName(refNode) && isImplementation(refNode.parent)) { + result.push(getReferenceEntryFromNode(refNode.parent)); + } + else if (refNode.kind === 69 /* Identifier */) { + if (refNode.parent.kind === 254 /* ShorthandPropertyAssignment */) { + // Go ahead and dereference the shorthand assignment by going to its definition + getReferenceEntriesForShorthandPropertyAssignment(refNode, typeChecker, result); + } + // Check if the node is within an extends or implements clause + var containingClass = getContainingClassIfInHeritageClause(refNode); + if (containingClass) { + result.push(getReferenceEntryFromNode(containingClass)); + return; + } + // If we got a type reference, try and see if the reference applies to any expressions that can implement an interface + var containingTypeReference = getContainingTypeReference(refNode); + if (containingTypeReference) { + var parent_21 = containingTypeReference.parent; + if (ts.isVariableLike(parent_21) && parent_21.type === containingTypeReference && parent_21.initializer && isImplementationExpression(parent_21.initializer)) { + maybeAdd(getReferenceEntryFromNode(parent_21.initializer)); + } + else if (ts.isFunctionLike(parent_21) && parent_21.type === containingTypeReference && parent_21.body) { + if (parent_21.body.kind === 199 /* Block */) { + ts.forEachReturnStatement(parent_21.body, function (returnStatement) { + if (returnStatement.expression && isImplementationExpression(returnStatement.expression)) { + maybeAdd(getReferenceEntryFromNode(returnStatement.expression)); + } + }); + } + else if (isImplementationExpression(parent_21.body)) { + maybeAdd(getReferenceEntryFromNode(parent_21.body)); + } + } + else if (ts.isAssertionExpression(parent_21) && isImplementationExpression(parent_21.expression)) { + maybeAdd(getReferenceEntryFromNode(parent_21.expression)); + } + } + } + // Type nodes can contain multiple references to the same type. For example: + // let x: Foo & (Foo & Bar) = ... + // Because we are returning the implementation locations and not the identifier locations, + // duplicate entries would be returned here as each of the type references is part of + // the same implementation. For that reason, check before we add a new entry + function maybeAdd(a) { + if (!ts.forEach(result, function (b) { return a.fileName === b.fileName && a.textSpan.start === b.textSpan.start && a.textSpan.length === b.textSpan.length; })) { + result.push(a); + } + } } - return current; - } - // Returns true if node is a element in some list in parent - // i.e. parent is class declaration with the list of members and node is one of members. - function isListElement(parent, node) { - switch (parent.kind) { - case 221 /* ClassDeclaration */: - case 222 /* InterfaceDeclaration */: - return ts.rangeContainsRange(parent.members, node); - case 225 /* ModuleDeclaration */: - var body = parent.body; - return body && body.kind === 199 /* Block */ && ts.rangeContainsRange(body.statements, node); - case 256 /* SourceFile */: - case 199 /* Block */: - case 226 /* ModuleBlock */: - return ts.rangeContainsRange(parent.statements, node); - case 252 /* CatchClause */: - return ts.rangeContainsRange(parent.block.statements, node); + function getSymbolsForClassAndInterfaceComponents(type, result) { + if (result === void 0) { result = []; } + for (var _i = 0, _a = type.types; _i < _a.length; _i++) { + var componentType = _a[_i]; + if (componentType.symbol && componentType.symbol.getFlags() & (32 /* Class */ | 64 /* Interface */)) { + result.push(componentType.symbol); + } + if (componentType.getFlags() & 1572864 /* UnionOrIntersection */) { + getSymbolsForClassAndInterfaceComponents(componentType, result); + } + } + return result; } - return false; - } - /** find node that fully contains given text range */ - function findEnclosingNode(range, sourceFile) { - return find(sourceFile); - function find(n) { - var candidate = ts.forEachChild(n, function (c) { return ts.startEndContainsRange(c.getStart(sourceFile), c.end, range) && c; }); - if (candidate) { - var result = find(candidate); - if (result) { - return result; + function getContainingTypeReference(node) { + var topLevelTypeReference = undefined; + while (node) { + if (ts.isTypeNode(node)) { + topLevelTypeReference = node; } + node = node.parent; } - return n; + return topLevelTypeReference; } - } - /** formatting is not applied to ranges that contain parse errors. - * This function will return a predicate that for a given text range will tell - * if there are any parse errors that overlap with the range. - */ - function prepareRangeContainsErrorFunction(errors, originalRange) { - if (!errors.length) { - return rangeHasNoErrors; + function getContainingClassIfInHeritageClause(node) { + if (node && node.parent) { + if (node.kind === 194 /* ExpressionWithTypeArguments */ + && node.parent.kind === 251 /* HeritageClause */ + && ts.isClassLike(node.parent.parent)) { + return node.parent.parent; + } + else if (node.kind === 69 /* Identifier */ || node.kind === 172 /* PropertyAccessExpression */) { + return getContainingClassIfInHeritageClause(node.parent); + } + } + return undefined; } - // pick only errors that fall in range - var sorted = errors - .filter(function (d) { return ts.rangeOverlapsWithStartEnd(originalRange, d.start, d.start + d.length); }) - .sort(function (e1, e2) { return e1.start - e2.start; }); - if (!sorted.length) { - return rangeHasNoErrors; + /** + * Returns true if this is an expression that can be considered an implementation + */ + function isImplementationExpression(node) { + // Unwrap parentheses + if (node.kind === 178 /* ParenthesizedExpression */) { + return isImplementationExpression(node.expression); + } + return node.kind === 180 /* ArrowFunction */ || + node.kind === 179 /* FunctionExpression */ || + node.kind === 171 /* ObjectLiteralExpression */ || + node.kind === 192 /* ClassExpression */ || + node.kind === 170 /* ArrayLiteralExpression */; } - var index = 0; - return function (r) { - // in current implementation sequence of arguments [r1, r2...] is monotonically increasing. - // 'index' tracks the index of the most recent error that was checked. - while (true) { - if (index >= sorted.length) { - // all errors in the range were already checked -> no error in specified range - return false; + /** + * Determines if the parent symbol occurs somewhere in the child's ancestry. If the parent symbol + * is an interface, determines if some ancestor of the child symbol extends or inherits from it. + * Also takes in a cache of previous results which makes this slightly more efficient and is + * necessary to avoid potential loops like so: + * class A extends B { } + * class B extends A { } + * + * We traverse the AST rather than using the type checker because users are typically only interested + * in explicit implementations of an interface/class when calling "Go to Implementation". Sibling + * implementations of types that share a common ancestor with the type whose implementation we are + * searching for need to be filtered out of the results. The type checker doesn't let us make the + * distinction between structurally compatible implementations and explicit implementations, so we + * must use the AST. + * + * @param child A class or interface Symbol + * @param parent Another class or interface Symbol + * @param cachedResults A map of symbol id pairs (i.e. "child,parent") to booleans indicating previous results + */ + function explicitlyInheritsFrom(child, parent, cachedResults) { + var parentIsInterface = parent.getFlags() & 64 /* Interface */; + return searchHierarchy(child); + function searchHierarchy(symbol) { + if (symbol === parent) { + return true; } - var error = sorted[index]; - if (r.end <= error.start) { - // specified range ends before the error refered by 'index' - no error in range - return false; + var key = ts.getSymbolId(symbol) + "," + ts.getSymbolId(parent); + if (key in cachedResults) { + return cachedResults[key]; } - if (ts.startEndOverlapsWithStartEnd(r.pos, r.end, error.start, error.start + error.length)) { - // specified range overlaps with error range - return true; + // Set the key so that we don't infinitely recurse + cachedResults[key] = false; + var inherits = ts.forEach(symbol.getDeclarations(), function (declaration) { + if (ts.isClassLike(declaration)) { + if (parentIsInterface) { + var interfaceReferences = ts.getClassImplementsHeritageClauseElements(declaration); + if (interfaceReferences) { + for (var _i = 0, interfaceReferences_1 = interfaceReferences; _i < interfaceReferences_1.length; _i++) { + var typeReference = interfaceReferences_1[_i]; + if (searchTypeReference(typeReference)) { + return true; + } + } + } + } + return searchTypeReference(ts.getClassExtendsHeritageClauseElement(declaration)); + } + else if (declaration.kind === 222 /* InterfaceDeclaration */) { + if (parentIsInterface) { + return ts.forEach(ts.getInterfaceBaseTypeNodes(declaration), searchTypeReference); + } + } + return false; + }); + cachedResults[key] = inherits; + return inherits; + } + function searchTypeReference(typeReference) { + if (typeReference) { + var type = typeChecker.getTypeAtLocation(typeReference); + if (type && type.symbol) { + return searchHierarchy(type.symbol); + } } - index++; + return false; } - }; - function rangeHasNoErrors(r) { - return false; - } - } - /** - * Start of the original range might fall inside the comment - scanner will not yield appropriate results - * This function will look for token that is located before the start of target range - * and return its end as start position for the scanner. - */ - function getScanStartPosition(enclosingNode, originalRange, sourceFile) { - var start = enclosingNode.getStart(sourceFile); - if (start === originalRange.pos && enclosingNode.end === originalRange.end) { - return start; - } - var precedingToken = ts.findPrecedingToken(originalRange.pos, sourceFile); - if (!precedingToken) { - // no preceding token found - start from the beginning of enclosing node - return enclosingNode.pos; - } - // preceding token ends after the start of original range (i.e when originalRange.pos falls in the middle of literal) - // start from the beginning of enclosingNode to handle the entire 'originalRange' - if (precedingToken.end >= originalRange.pos) { - return enclosingNode.pos; } - return precedingToken.end; - } - /* - * For cases like - * if (a || - * b ||$ - * c) {...} - * If we hit Enter at $ we want line ' b ||' to be indented. - * Formatting will be applied to the last two lines. - * Node that fully encloses these lines is binary expression 'a ||...'. - * Initial indentation for this node will be 0. - * Binary expressions don't introduce new indentation scopes, however it is possible - * that some parent node on the same line does - like if statement in this case. - * Note that we are considering parents only from the same line with initial node - - * if parent is on the different line - its delta was already contributed - * to the initial indentation. - */ - function getOwnOrInheritedDelta(n, options, sourceFile) { - var previousLine = -1 /* Unknown */; - var child; - while (n) { - var line = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)).line; - if (previousLine !== -1 /* Unknown */ && line !== previousLine) { - break; + function getReferencesForSuperKeyword(superKeyword) { + var searchSpaceNode = ts.getSuperContainer(superKeyword, /*stopOnFunctions*/ false); + if (!searchSpaceNode) { + return undefined; } - if (formatting.SmartIndenter.shouldIndentChildNode(n, child)) { - return options.IndentSize; + // Whether 'super' occurs in a static context within a class. + var staticFlag = 32 /* Static */; + switch (searchSpaceNode.kind) { + case 145 /* PropertyDeclaration */: + case 144 /* PropertySignature */: + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + case 148 /* Constructor */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + staticFlag &= ts.getModifierFlags(searchSpaceNode); + searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class + break; + default: + return undefined; } - previousLine = line; - child = n; - n = n.parent; + var references = []; + var sourceFile = searchSpaceNode.getSourceFile(); + var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); + ts.forEach(possiblePositions, function (position) { + cancellationToken.throwIfCancellationRequested(); + var node = ts.getTouchingWord(sourceFile, position); + if (!node || node.kind !== 95 /* SuperKeyword */) { + return; + } + var container = ts.getSuperContainer(node, /*stopOnFunctions*/ false); + // If we have a 'super' container, we must have an enclosing class. + // Now make sure the owning class is the same as the search-space + // and has the same static qualifier as the original 'super's owner. + if (container && (32 /* Static */ & ts.getModifierFlags(container)) === staticFlag && container.parent.symbol === searchSpaceNode.symbol) { + references.push(getReferenceEntryFromNode(node)); + } + }); + var definition = getDefinition(searchSpaceNode.symbol); + return [{ definition: definition, references: references }]; } - return 0; - } - function formatSpan(originalRange, sourceFile, options, rulesProvider, requestKind) { - var rangeContainsError = prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange); - // formatting context is used by rules provider - var formattingContext = new formatting.FormattingContext(sourceFile, requestKind); - // find the smallest node that fully wraps the range and compute the initial indentation for the node - var enclosingNode = findEnclosingNode(originalRange, sourceFile); - var formattingScanner = formatting.getFormattingScanner(sourceFile, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end); - var initialIndentation = formatting.SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, options); - var previousRangeHasError; - var previousRange; - var previousParent; - var previousRangeStartLine; - var lastIndentedLine; - var indentationOnLastIndentedLine; - var edits = []; - formattingScanner.advance(); - if (formattingScanner.isOnToken()) { - var startLine = sourceFile.getLineAndCharacterOfPosition(enclosingNode.getStart(sourceFile)).line; - var undecoratedStartLine = startLine; - if (enclosingNode.decorators) { - undecoratedStartLine = sourceFile.getLineAndCharacterOfPosition(ts.getNonDecoratorTokenPosOfNode(enclosingNode, sourceFile)).line; + function getReferencesForThisKeyword(thisOrSuperKeyword, sourceFiles) { + var searchSpaceNode = ts.getThisContainer(thisOrSuperKeyword, /* includeArrowFunctions */ false); + // Whether 'this' occurs in a static context within a class. + var staticFlag = 32 /* Static */; + switch (searchSpaceNode.kind) { + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + if (ts.isObjectLiteralMethod(searchSpaceNode)) { + break; + } + // fall through + case 145 /* PropertyDeclaration */: + case 144 /* PropertySignature */: + case 148 /* Constructor */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + staticFlag &= ts.getModifierFlags(searchSpaceNode); + searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class + break; + case 256 /* SourceFile */: + if (ts.isExternalModule(searchSpaceNode)) { + return undefined; + } + // Fall through + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + break; + // Computed properties in classes are not handled here because references to this are illegal, + // so there is no point finding references to them. + default: + return undefined; + } + var references = []; + var possiblePositions; + if (searchSpaceNode.kind === 256 /* SourceFile */) { + ts.forEach(sourceFiles, function (sourceFile) { + possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", sourceFile.getStart(), sourceFile.getEnd()); + getThisReferencesInFile(sourceFile, sourceFile, possiblePositions, references); + }); + } + else { + var sourceFile = searchSpaceNode.getSourceFile(); + possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); + getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, references); + } + var thisOrSuperSymbol = typeChecker.getSymbolAtLocation(thisOrSuperKeyword); + var displayParts = thisOrSuperSymbol && ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, thisOrSuperSymbol, thisOrSuperKeyword.getSourceFile(), ts.getContainerNode(thisOrSuperKeyword), thisOrSuperKeyword).displayParts; + return [{ + definition: { + containerKind: "", + containerName: "", + fileName: node.getSourceFile().fileName, + kind: ts.ScriptElementKind.variableElement, + name: "this", + textSpan: ts.createTextSpanFromBounds(node.getStart(), node.getEnd()), + displayParts: displayParts + }, + references: references + }]; + function getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, result) { + ts.forEach(possiblePositions, function (position) { + cancellationToken.throwIfCancellationRequested(); + var node = ts.getTouchingWord(sourceFile, position); + if (!node || !ts.isThis(node)) { + return; + } + var container = ts.getThisContainer(node, /* includeArrowFunctions */ false); + switch (searchSpaceNode.kind) { + case 179 /* FunctionExpression */: + case 220 /* FunctionDeclaration */: + if (searchSpaceNode.symbol === container.symbol) { + result.push(getReferenceEntryFromNode(node)); + } + break; + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + if (ts.isObjectLiteralMethod(searchSpaceNode) && searchSpaceNode.symbol === container.symbol) { + result.push(getReferenceEntryFromNode(node)); + } + break; + case 192 /* ClassExpression */: + case 221 /* ClassDeclaration */: + // Make sure the container belongs to the same class + // and has the appropriate static modifier from the original container. + if (container.parent && searchSpaceNode.symbol === container.parent.symbol && (ts.getModifierFlags(container) & 32 /* Static */) === staticFlag) { + result.push(getReferenceEntryFromNode(node)); + } + break; + case 256 /* SourceFile */: + if (container.kind === 256 /* SourceFile */ && !ts.isExternalModule(container)) { + result.push(getReferenceEntryFromNode(node)); + } + break; + } + }); } - var delta = getOwnOrInheritedDelta(enclosingNode, options, sourceFile); - processNode(enclosingNode, enclosingNode, startLine, undecoratedStartLine, initialIndentation, delta); } - if (!formattingScanner.isOnToken()) { - var leadingTrivia = formattingScanner.getCurrentLeadingTrivia(); - if (leadingTrivia) { - processTrivia(leadingTrivia, enclosingNode, enclosingNode, undefined); - trimTrailingWhitespacesForRemainingRange(); + function getReferencesForStringLiteral(node, sourceFiles) { + var type = ts.getStringLiteralTypeForNode(node, typeChecker); + if (!type) { + // nothing to do here. moving on + return undefined; + } + var references = []; + for (var _i = 0, sourceFiles_9 = sourceFiles; _i < sourceFiles_9.length; _i++) { + var sourceFile = sourceFiles_9[_i]; + var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, type.text, sourceFile.getStart(), sourceFile.getEnd()); + getReferencesForStringLiteralInFile(sourceFile, type, possiblePositions, references); + } + return [{ + definition: { + containerKind: "", + containerName: "", + fileName: node.getSourceFile().fileName, + kind: ts.ScriptElementKind.variableElement, + name: type.text, + textSpan: ts.createTextSpanFromBounds(node.getStart(), node.getEnd()), + displayParts: [ts.displayPart(ts.getTextOfNode(node), ts.SymbolDisplayPartKind.stringLiteral)] + }, + references: references + }]; + function getReferencesForStringLiteralInFile(sourceFile, searchType, possiblePositions, references) { + for (var _i = 0, possiblePositions_1 = possiblePositions; _i < possiblePositions_1.length; _i++) { + var position = possiblePositions_1[_i]; + cancellationToken.throwIfCancellationRequested(); + var node_2 = ts.getTouchingWord(sourceFile, position); + if (!node_2 || node_2.kind !== 9 /* StringLiteral */) { + return; + } + var type_1 = ts.getStringLiteralTypeForNode(node_2, typeChecker); + if (type_1 === searchType) { + references.push(getReferenceEntryFromNode(node_2)); + } + } } } - formattingScanner.close(); - return edits; - // local functions - /** Tries to compute the indentation for a list element. - * If list element is not in range then - * function will pick its actual indentation - * so it can be pushed downstream as inherited indentation. - * If list element is in the range - its indentation will be equal - * to inherited indentation from its predecessors. - */ - function tryComputeIndentationForListItem(startPos, endPos, parentStartLine, range, inheritedIndentation) { - if (ts.rangeOverlapsWithStartEnd(range, startPos, endPos) || - ts.rangeContainsStartEnd(range, startPos, endPos) /* Not to miss zero-range nodes e.g. JsxText */) { - if (inheritedIndentation !== -1 /* Unknown */) { - return inheritedIndentation; + function populateSearchSymbolSet(symbol, location) { + // The search set contains at least the current symbol + var result = [symbol]; + // If the location is name of property symbol from object literal destructuring pattern + // Search the property symbol + // for ( { property: p2 } of elems) { } + var containingObjectLiteralElement = getContainingObjectLiteralElement(location); + if (containingObjectLiteralElement && containingObjectLiteralElement.kind !== 254 /* ShorthandPropertyAssignment */) { + var propertySymbol = getPropertySymbolOfDestructuringAssignment(location); + if (propertySymbol) { + result.push(propertySymbol); } } - else { - var startLine = sourceFile.getLineAndCharacterOfPosition(startPos).line; - var startLinePosition = ts.getLineStartPositionForPosition(startPos, sourceFile); - var column = formatting.SmartIndenter.findFirstNonWhitespaceColumn(startLinePosition, startPos, sourceFile, options); - if (startLine !== parentStartLine || startPos === column) { - // Use the base indent size if it is greater than - // the indentation of the inherited predecessor. - var baseIndentSize = formatting.SmartIndenter.getBaseIndentation(options); - return baseIndentSize > column ? baseIndentSize : column; + // If the symbol is an alias, add what it aliases to the list + // import {a} from "mod"; + // export {a} + // If the symbol is an alias to default declaration, add what it aliases to the list + // declare "mod" { export default class B { } } + // import B from "mod"; + //// For export specifiers, the exported name can be referring to a local symbol, e.g.: + //// import {a} from "mod"; + //// export {a as somethingElse} + //// We want the *local* declaration of 'a' as declared in the import, + //// *not* as declared within "mod" (or farther) + var aliasSymbol = getAliasSymbolForPropertyNameSymbol(symbol, location); + if (aliasSymbol) { + result = result.concat(populateSearchSymbolSet(aliasSymbol, location)); + } + // If the location is in a context sensitive location (i.e. in an object literal) try + // to get a contextual type for it, and add the property symbol from the contextual + // type to the search set + if (containingObjectLiteralElement) { + ts.forEach(getPropertySymbolsFromContextualType(containingObjectLiteralElement), function (contextualSymbol) { + ts.addRange(result, typeChecker.getRootSymbols(contextualSymbol)); + }); + /* Because in short-hand property assignment, location has two meaning : property name and as value of the property + * When we do findAllReference at the position of the short-hand property assignment, we would want to have references to position of + * property name and variable declaration of the identifier. + * Like in below example, when querying for all references for an identifier 'name', of the property assignment, the language service + * should show both 'name' in 'obj' and 'name' in variable declaration + * const name = "Foo"; + * const obj = { name }; + * In order to do that, we will populate the search set with the value symbol of the identifier as a value of the property assignment + * so that when matching with potential reference symbol, both symbols from property declaration and variable declaration + * will be included correctly. + */ + var shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(location.parent); + if (shorthandValueSymbol) { + result.push(shorthandValueSymbol); } } - return -1 /* Unknown */; - } - function computeIndentation(node, startLine, inheritedIndentation, parent, parentDynamicIndentation, effectiveParentStartLine) { - var indentation = inheritedIndentation; - var delta = formatting.SmartIndenter.shouldIndentChildNode(node) ? options.IndentSize : 0; - if (effectiveParentStartLine === startLine) { - // if node is located on the same line with the parent - // - inherit indentation from the parent - // - push children if either parent of node itself has non-zero delta - indentation = startLine === lastIndentedLine - ? indentationOnLastIndentedLine - : parentDynamicIndentation.getIndentation(); - delta = Math.min(options.IndentSize, parentDynamicIndentation.getDelta(node) + delta); + // If the symbol.valueDeclaration is a property parameter declaration, + // we should include both parameter declaration symbol and property declaration symbol + // Parameter Declaration symbol is only visible within function scope, so the symbol is stored in constructor.locals. + // Property Declaration symbol is a member of the class, so the symbol is stored in its class Declaration.symbol.members + if (symbol.valueDeclaration && symbol.valueDeclaration.kind === 142 /* Parameter */ && + ts.isParameterPropertyDeclaration(symbol.valueDeclaration)) { + result = result.concat(typeChecker.getSymbolsOfParameterPropertyDeclaration(symbol.valueDeclaration, symbol.name)); } - else if (indentation === -1 /* Unknown */) { - if (formatting.SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement(parent, node, startLine, sourceFile)) { - indentation = parentDynamicIndentation.getIndentation(); + // If this is symbol of binding element without propertyName declaration in Object binding pattern + // Include the property in the search + var bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol); + if (bindingElementPropertySymbol) { + result.push(bindingElementPropertySymbol); + } + // If this is a union property, add all the symbols from all its source symbols in all unioned types. + // If the symbol is an instantiation from a another symbol (e.g. widened symbol) , add the root the list + ts.forEach(typeChecker.getRootSymbols(symbol), function (rootSymbol) { + if (rootSymbol !== symbol) { + result.push(rootSymbol); } - else { - indentation = parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta(node); + // Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions + if (!implementations && rootSymbol.parent && rootSymbol.parent.flags & (32 /* Class */ | 64 /* Interface */)) { + getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ ts.createMap()); } - } - return { - indentation: indentation, - delta: delta - }; + }); + return result; } - function getFirstNonDecoratorTokenOfNode(node) { - if (node.modifiers && node.modifiers.length) { - return node.modifiers[0].kind; - } - switch (node.kind) { - case 221 /* ClassDeclaration */: return 73 /* ClassKeyword */; - case 222 /* InterfaceDeclaration */: return 107 /* InterfaceKeyword */; - case 220 /* FunctionDeclaration */: return 87 /* FunctionKeyword */; - case 224 /* EnumDeclaration */: return 224 /* EnumDeclaration */; - case 149 /* GetAccessor */: return 123 /* GetKeyword */; - case 150 /* SetAccessor */: return 131 /* SetKeyword */; - case 147 /* MethodDeclaration */: - if (node.asteriskToken) { - return 37 /* AsteriskToken */; - } /* - fall-through - */ - case 145 /* PropertyDeclaration */: - case 142 /* Parameter */: - return node.name.kind; + /** + * Find symbol of the given property-name and add the symbol to the given result array + * @param symbol a symbol to start searching for the given propertyName + * @param propertyName a name of property to search for + * @param result an array of symbol of found property symbols + * @param previousIterationSymbolsCache a cache of symbol from previous iterations of calling this function to prevent infinite revisiting of the same symbol. + * The value of previousIterationSymbol is undefined when the function is first called. + */ + function getPropertySymbolsFromBaseTypes(symbol, propertyName, result, previousIterationSymbolsCache) { + if (!symbol) { + return; } - } - function getDynamicIndentation(node, nodeStartLine, indentation, delta) { - return { - getIndentationForComment: function (kind, tokenIndentation, container) { - switch (kind) { - // preceding comment to the token that closes the indentation scope inherits the indentation from the scope - // .. { - // // comment - // } - case 16 /* CloseBraceToken */: - case 20 /* CloseBracketToken */: - case 18 /* CloseParenToken */: - return indentation + getEffectiveDelta(delta, container); - } - return tokenIndentation !== -1 /* Unknown */ ? tokenIndentation : indentation; - }, - getIndentationForToken: function (line, kind, container) { - if (nodeStartLine !== line && node.decorators) { - if (kind === getFirstNonDecoratorTokenOfNode(node)) { - // if this token is the first token following the list of decorators, we do not need to indent - return indentation; - } + // If the current symbol is the same as the previous-iteration symbol, we can just return the symbol that has already been visited + // This is particularly important for the following cases, so that we do not infinitely visit the same symbol. + // For example: + // interface C extends C { + // /*findRef*/propName: string; + // } + // The first time getPropertySymbolsFromBaseTypes is called when finding-all-references at propName, + // the symbol argument will be the symbol of an interface "C" and previousIterationSymbol is undefined, + // the function will add any found symbol of the property-name, then its sub-routine will call + // getPropertySymbolsFromBaseTypes again to walk up any base types to prevent revisiting already + // visited symbol, interface "C", the sub-routine will pass the current symbol as previousIterationSymbol. + if (symbol.name in previousIterationSymbolsCache) { + return; + } + if (symbol.flags & (32 /* Class */ | 64 /* Interface */)) { + ts.forEach(symbol.getDeclarations(), function (declaration) { + if (ts.isClassLike(declaration)) { + getPropertySymbolFromTypeReference(ts.getClassExtendsHeritageClauseElement(declaration)); + ts.forEach(ts.getClassImplementsHeritageClauseElements(declaration), getPropertySymbolFromTypeReference); } - switch (kind) { - // open and close brace, 'else' and 'while' (in do statement) tokens has indentation of the parent - case 15 /* OpenBraceToken */: - case 16 /* CloseBraceToken */: - case 19 /* OpenBracketToken */: - case 20 /* CloseBracketToken */: - case 17 /* OpenParenToken */: - case 18 /* CloseParenToken */: - case 80 /* ElseKeyword */: - case 104 /* WhileKeyword */: - case 55 /* AtToken */: - return indentation; - default: - // if token line equals to the line of containing node (this is a first token in the node) - use node indentation - return nodeStartLine !== line ? indentation + getEffectiveDelta(delta, container) : indentation; + else if (declaration.kind === 222 /* InterfaceDeclaration */) { + ts.forEach(ts.getInterfaceBaseTypeNodes(declaration), getPropertySymbolFromTypeReference); } - }, - getIndentation: function () { return indentation; }, - getDelta: function (child) { return getEffectiveDelta(delta, child); }, - recomputeIndentation: function (lineAdded) { - if (node.parent && formatting.SmartIndenter.shouldIndentChildNode(node.parent, node)) { - if (lineAdded) { - indentation += options.IndentSize; - } - else { - indentation -= options.IndentSize; - } - if (formatting.SmartIndenter.shouldIndentChildNode(node)) { - delta = options.IndentSize; - } - else { - delta = 0; + }); + } + return; + function getPropertySymbolFromTypeReference(typeReference) { + if (typeReference) { + var type = typeChecker.getTypeAtLocation(typeReference); + if (type) { + var propertySymbol = typeChecker.getPropertyOfType(type, propertyName); + if (propertySymbol) { + result.push.apply(result, typeChecker.getRootSymbols(propertySymbol)); } + // Visit the typeReference as well to see if it directly or indirectly use that property + previousIterationSymbolsCache[symbol.name] = symbol; + getPropertySymbolsFromBaseTypes(type.symbol, propertyName, result, previousIterationSymbolsCache); } } - }; - function getEffectiveDelta(delta, child) { - // Delta value should be zero when the node explicitly prevents indentation of the child node - return formatting.SmartIndenter.nodeWillIndentChild(node, child, true) ? delta : 0; } } - function processNode(node, contextNode, nodeStartLine, undecoratedNodeStartLine, indentation, delta) { - if (!ts.rangeOverlapsWithStartEnd(originalRange, node.getStart(sourceFile), node.getEnd())) { - return; + function getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation, searchLocationIsConstructor, parents, cache) { + if (ts.contains(searchSymbols, referenceSymbol)) { + // If we are searching for constructor uses, they must be 'new' expressions. + return (!searchLocationIsConstructor || ts.isNewExpressionTarget(referenceLocation)) && referenceSymbol; } - var nodeDynamicIndentation = getDynamicIndentation(node, nodeStartLine, indentation, delta); - // a useful observations when tracking context node - // / - // [a] - // / | \ - // [b] [c] [d] - // node 'a' is a context node for nodes 'b', 'c', 'd' - // except for the leftmost leaf token in [b] - in this case context node ('e') is located somewhere above 'a' - // this rule can be applied recursively to child nodes of 'a'. - // - // context node is set to parent node value after processing every child node - // context node is set to parent of the token after processing every token - var childContextNode = contextNode; - // if there are any tokens that logically belong to node and interleave child nodes - // such tokens will be consumed in processChildNode for for the child that follows them - ts.forEachChild(node, function (child) { - processChildNode(child, /*inheritedIndentation*/ -1 /* Unknown */, node, nodeDynamicIndentation, nodeStartLine, undecoratedNodeStartLine, /*isListItem*/ false); - }, function (nodes) { - processChildNodes(nodes, node, nodeStartLine, nodeDynamicIndentation); - }); - // proceed any tokens in the node that are located after child nodes - while (formattingScanner.isOnToken()) { - var tokenInfo = formattingScanner.readTokenInfo(node); - if (tokenInfo.token.end > node.end) { - break; - } - consumeTokenAndAdvanceScanner(tokenInfo, node, nodeDynamicIndentation); + // If the reference symbol is an alias, check if what it is aliasing is one of the search + // symbols but by looking up for related symbol of this alias so it can handle multiple level of indirectness. + var aliasSymbol = getAliasSymbolForPropertyNameSymbol(referenceSymbol, referenceLocation); + if (aliasSymbol) { + return getRelatedSymbol(searchSymbols, aliasSymbol, referenceLocation, searchLocationIsConstructor, parents, cache); } - function processChildNode(child, inheritedIndentation, parent, parentDynamicIndentation, parentStartLine, undecoratedParentStartLine, isListItem, isFirstListItem) { - var childStartPos = child.getStart(sourceFile); - var childStartLine = sourceFile.getLineAndCharacterOfPosition(childStartPos).line; - var undecoratedChildStartLine = childStartLine; - if (child.decorators) { - undecoratedChildStartLine = sourceFile.getLineAndCharacterOfPosition(ts.getNonDecoratorTokenPosOfNode(child, sourceFile)).line; - } - // if child is a list item - try to get its indentation - var childIndentationAmount = -1 /* Unknown */; - if (isListItem) { - childIndentationAmount = tryComputeIndentationForListItem(childStartPos, child.end, parentStartLine, originalRange, inheritedIndentation); - if (childIndentationAmount !== -1 /* Unknown */) { - inheritedIndentation = childIndentationAmount; - } + // If the reference location is in an object literal, try to get the contextual type for the + // object literal, lookup the property symbol in the contextual type, and use this symbol to + // compare to our searchSymbol + var containingObjectLiteralElement = getContainingObjectLiteralElement(referenceLocation); + if (containingObjectLiteralElement) { + var contextualSymbol = ts.forEach(getPropertySymbolsFromContextualType(containingObjectLiteralElement), function (contextualSymbol) { + return ts.forEach(typeChecker.getRootSymbols(contextualSymbol), function (s) { return searchSymbols.indexOf(s) >= 0 ? s : undefined; }); + }); + if (contextualSymbol) { + return contextualSymbol; } - // child node is outside the target range - do not dive inside - if (!ts.rangeOverlapsWithStartEnd(originalRange, child.pos, child.end)) { - if (child.end < originalRange.pos) { - formattingScanner.skipToEndOf(child); - } - return inheritedIndentation; + // If the reference location is the name of property from object literal destructuring pattern + // Get the property symbol from the object literal's type and look if thats the search symbol + // In below eg. get 'property' from type of elems iterating type + // for ( { property: p2 } of elems) { } + var propertySymbol = getPropertySymbolOfDestructuringAssignment(referenceLocation); + if (propertySymbol && searchSymbols.indexOf(propertySymbol) >= 0) { + return propertySymbol; } - if (child.getFullWidth() === 0) { - return inheritedIndentation; + } + // If the reference location is the binding element and doesn't have property name + // then include the binding element in the related symbols + // let { a } : { a }; + var bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(referenceSymbol); + if (bindingElementPropertySymbol && searchSymbols.indexOf(bindingElementPropertySymbol) >= 0) { + return bindingElementPropertySymbol; + } + // Unwrap symbols to get to the root (e.g. transient symbols as a result of widening) + // Or a union property, use its underlying unioned symbols + return ts.forEach(typeChecker.getRootSymbols(referenceSymbol), function (rootSymbol) { + // if it is in the list, then we are done + if (searchSymbols.indexOf(rootSymbol) >= 0) { + return rootSymbol; } - while (formattingScanner.isOnToken()) { - // proceed any parent tokens that are located prior to child.getStart() - var tokenInfo = formattingScanner.readTokenInfo(node); - if (tokenInfo.token.end > childStartPos) { - // stop when formatting scanner advances past the beginning of the child - break; + // Finally, try all properties with the same name in any type the containing type extended or implemented, and + // see if any is in the list. If we were passed a parent symbol, only include types that are subtypes of the + // parent symbol + if (rootSymbol.parent && rootSymbol.parent.flags & (32 /* Class */ | 64 /* Interface */)) { + // Parents will only be defined if implementations is true + if (parents) { + if (!ts.forEach(parents, function (parent) { return explicitlyInheritsFrom(rootSymbol.parent, parent, cache); })) { + return undefined; + } } - consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation); - } - if (!formattingScanner.isOnToken()) { - return inheritedIndentation; + var result_3 = []; + getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result_3, /*previousIterationSymbolsCache*/ ts.createMap()); + return ts.forEach(result_3, function (s) { return searchSymbols.indexOf(s) >= 0 ? s : undefined; }); } - if (ts.isToken(child)) { - // if child node is a token, it does not impact indentation, proceed it using parent indentation scope rules - var tokenInfo = formattingScanner.readTokenInfo(child); - ts.Debug.assert(tokenInfo.token.end === child.end); - consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation, child); - return inheritedIndentation; - } - var effectiveParentStartLine = child.kind === 143 /* Decorator */ ? childStartLine : undecoratedParentStartLine; - var childIndentation = computeIndentation(child, childStartLine, childIndentationAmount, node, parentDynamicIndentation, effectiveParentStartLine); - processNode(child, childContextNode, childStartLine, undecoratedChildStartLine, childIndentation.indentation, childIndentation.delta); - childContextNode = node; - if (isFirstListItem && parent.kind === 170 /* ArrayLiteralExpression */ && inheritedIndentation === -1 /* Unknown */) { - inheritedIndentation = childIndentation.indentation; + return undefined; + }); + } + function getNameFromObjectLiteralElement(node) { + if (node.name.kind === 140 /* ComputedPropertyName */) { + var nameExpression = node.name.expression; + // treat computed property names where expression is string/numeric literal as just string/numeric literal + if (ts.isStringOrNumericLiteral(nameExpression.kind)) { + return nameExpression.text; } - return inheritedIndentation; + return undefined; } - function processChildNodes(nodes, parent, parentStartLine, parentDynamicIndentation) { - var listStartToken = getOpenTokenForList(parent, nodes); - var listEndToken = getCloseTokenForOpenToken(listStartToken); - var listDynamicIndentation = parentDynamicIndentation; - var startLine = parentStartLine; - if (listStartToken !== 0 /* Unknown */) { - // introduce a new indentation scope for lists (including list start and end tokens) - while (formattingScanner.isOnToken()) { - var tokenInfo = formattingScanner.readTokenInfo(parent); - if (tokenInfo.token.end > nodes.pos) { - // stop when formatting scanner moves past the beginning of node list - break; - } - else if (tokenInfo.token.kind === listStartToken) { - // consume list start token - startLine = sourceFile.getLineAndCharacterOfPosition(tokenInfo.token.pos).line; - var indentation_1 = computeIndentation(tokenInfo.token, startLine, -1 /* Unknown */, parent, parentDynamicIndentation, parentStartLine); - listDynamicIndentation = getDynamicIndentation(parent, parentStartLine, indentation_1.indentation, indentation_1.delta); - consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation); - } - else { - // consume any tokens that precede the list as child elements of 'node' using its indentation scope - consumeTokenAndAdvanceScanner(tokenInfo, parent, parentDynamicIndentation); - } - } - } - var inheritedIndentation = -1 /* Unknown */; - for (var i = 0; i < nodes.length; i++) { - var child = nodes[i]; - inheritedIndentation = processChildNode(child, inheritedIndentation, node, listDynamicIndentation, startLine, startLine, /*isListItem*/ true, /*isFirstListItem*/ i === 0); + return node.name.text; + } + function getPropertySymbolsFromContextualType(node) { + var objectLiteral = node.parent; + var contextualType = typeChecker.getContextualType(objectLiteral); + var name = getNameFromObjectLiteralElement(node); + if (name && contextualType) { + var result_4 = []; + var symbol_2 = contextualType.getProperty(name); + if (symbol_2) { + result_4.push(symbol_2); } - if (listEndToken !== 0 /* Unknown */) { - if (formattingScanner.isOnToken()) { - var tokenInfo = formattingScanner.readTokenInfo(parent); - // consume the list end token only if it is still belong to the parent - // there might be the case when current token matches end token but does not considered as one - // function (x: function) <-- - // without this check close paren will be interpreted as list end token for function expression which is wrong - if (tokenInfo.token.kind === listEndToken && ts.rangeContainsRange(parent, tokenInfo.token)) { - // consume list end token - consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation); + if (contextualType.flags & 524288 /* Union */) { + ts.forEach(contextualType.types, function (t) { + var symbol = t.getProperty(name); + if (symbol) { + result_4.push(symbol); } - } + }); } + return result_4; } - function consumeTokenAndAdvanceScanner(currentTokenInfo, parent, dynamicIndentation, container) { - ts.Debug.assert(ts.rangeContainsRange(parent, currentTokenInfo.token)); - var lastTriviaWasNewLine = formattingScanner.lastTrailingTriviaWasNewLine(); - var indentToken = false; - if (currentTokenInfo.leadingTrivia) { - processTrivia(currentTokenInfo.leadingTrivia, parent, childContextNode, dynamicIndentation); - } - var lineAdded; - var isTokenInRange = ts.rangeContainsRange(originalRange, currentTokenInfo.token); - var tokenStart = sourceFile.getLineAndCharacterOfPosition(currentTokenInfo.token.pos); - if (isTokenInRange) { - var rangeHasError = rangeContainsError(currentTokenInfo.token); - // save previousRange since processRange will overwrite this value with current one - var savePreviousRange = previousRange; - lineAdded = processRange(currentTokenInfo.token, tokenStart, parent, childContextNode, dynamicIndentation); - if (rangeHasError) { - // do not indent comments\token if token range overlaps with some error - indentToken = false; - } - else { - if (lineAdded !== undefined) { - indentToken = lineAdded; - } - else { - // indent token only if end line of previous range does not match start line of the token - var prevEndLine = savePreviousRange && sourceFile.getLineAndCharacterOfPosition(savePreviousRange.end).line; - indentToken = lastTriviaWasNewLine && tokenStart.line !== prevEndLine; + return undefined; + } + /** Given an initial searchMeaning, extracted from a location, widen the search scope based on the declarations + * of the corresponding symbol. e.g. if we are searching for "Foo" in value position, but "Foo" references a class + * then we need to widen the search to include type positions as well. + * On the contrary, if we are searching for "Bar" in type position and we trace bar to an interface, and an uninstantiated + * module, we want to keep the search limited to only types, as the two declarations (interface and uninstantiated module) + * do not intersect in any of the three spaces. + */ + function getIntersectingMeaningFromDeclarations(meaning, declarations) { + if (declarations) { + var lastIterationMeaning = void 0; + do { + // The result is order-sensitive, for instance if initialMeaning === Namespace, and declarations = [class, instantiated module] + // we need to consider both as they initialMeaning intersects with the module in the namespace space, and the module + // intersects with the class in the value space. + // To achieve that we will keep iterating until the result stabilizes. + // Remember the last meaning + lastIterationMeaning = meaning; + for (var _i = 0, declarations_8 = declarations; _i < declarations_8.length; _i++) { + var declaration = declarations_8[_i]; + var declarationMeaning = ts.getMeaningFromDeclaration(declaration); + if (declarationMeaning & meaning) { + meaning |= declarationMeaning; } } + } while (meaning !== lastIterationMeaning); + } + return meaning; + } + } + FindAllReferences.getReferencedSymbolsForNode = getReferencedSymbolsForNode; + function convertReferences(referenceSymbols) { + if (!referenceSymbols) { + return undefined; + } + var referenceEntries = []; + for (var _i = 0, referenceSymbols_1 = referenceSymbols; _i < referenceSymbols_1.length; _i++) { + var referenceSymbol = referenceSymbols_1[_i]; + ts.addRange(referenceEntries, referenceSymbol.references); + } + return referenceEntries; + } + FindAllReferences.convertReferences = convertReferences; + function isImplementation(node) { + if (!node) { + return false; + } + else if (ts.isVariableLike(node)) { + if (node.initializer) { + return true; + } + else if (node.kind === 218 /* VariableDeclaration */) { + var parentStatement = getParentStatementOfVariableDeclaration(node); + return parentStatement && ts.hasModifier(parentStatement, 2 /* Ambient */); + } + } + else if (ts.isFunctionLike(node)) { + return !!node.body || ts.hasModifier(node, 2 /* Ambient */); + } + else { + switch (node.kind) { + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + case 224 /* EnumDeclaration */: + case 225 /* ModuleDeclaration */: + return true; + } + } + return false; + } + function getParentStatementOfVariableDeclaration(node) { + if (node.parent && node.parent.parent && node.parent.parent.kind === 200 /* VariableStatement */) { + ts.Debug.assert(node.parent.kind === 219 /* VariableDeclarationList */); + return node.parent.parent; + } + } + function getReferenceEntriesForShorthandPropertyAssignment(node, typeChecker, result) { + var refSymbol = typeChecker.getSymbolAtLocation(node); + var shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(refSymbol.valueDeclaration); + if (shorthandSymbol) { + for (var _i = 0, _a = shorthandSymbol.getDeclarations(); _i < _a.length; _i++) { + var declaration = _a[_i]; + if (ts.getMeaningFromDeclaration(declaration) & 1 /* Value */) { + result.push(getReferenceEntryFromNode(declaration)); } - if (currentTokenInfo.trailingTrivia) { - processTrivia(currentTokenInfo.trailingTrivia, parent, childContextNode, dynamicIndentation); - } - if (indentToken) { - var tokenIndentation = (isTokenInRange && !rangeContainsError(currentTokenInfo.token)) ? - dynamicIndentation.getIndentationForToken(tokenStart.line, currentTokenInfo.token.kind, container) : - -1 /* Unknown */; - var indentNextTokenOrTrivia = true; - if (currentTokenInfo.leadingTrivia) { - var commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind, tokenIndentation, container); - for (var _i = 0, _a = currentTokenInfo.leadingTrivia; _i < _a.length; _i++) { - var triviaItem = _a[_i]; - var triviaInRange = ts.rangeContainsRange(originalRange, triviaItem); - switch (triviaItem.kind) { - case 3 /* MultiLineCommentTrivia */: - if (triviaInRange) { - indentMultilineComment(triviaItem, commentIndentation, /*firstLineIsIndented*/ !indentNextTokenOrTrivia); - } - indentNextTokenOrTrivia = false; - break; - case 2 /* SingleLineCommentTrivia */: - if (indentNextTokenOrTrivia && triviaInRange) { - insertIndentation(triviaItem.pos, commentIndentation, /*lineAdded*/ false); - } - indentNextTokenOrTrivia = false; - break; - case 4 /* NewLineTrivia */: - indentNextTokenOrTrivia = true; - break; - } - } - } - // indent token only if is it is in target range and does not overlap with any error ranges - if (tokenIndentation !== -1 /* Unknown */ && indentNextTokenOrTrivia) { - insertIndentation(currentTokenInfo.token.pos, tokenIndentation, lineAdded); - lastIndentedLine = tokenStart.line; - indentationOnLastIndentedLine = tokenIndentation; - } + } + } + } + FindAllReferences.getReferenceEntriesForShorthandPropertyAssignment = getReferenceEntriesForShorthandPropertyAssignment; + function getReferenceEntryFromNode(node) { + var start = node.getStart(); + var end = node.getEnd(); + if (node.kind === 9 /* StringLiteral */) { + start += 1; + end -= 1; + } + return { + fileName: node.getSourceFile().fileName, + textSpan: ts.createTextSpanFromBounds(start, end), + isWriteAccess: isWriteAccess(node), + isDefinition: ts.isDeclarationName(node) || ts.isLiteralComputedPropertyDeclarationName(node) + }; + } + FindAllReferences.getReferenceEntryFromNode = getReferenceEntryFromNode; + /** A node is considered a writeAccess iff it is a name of a declaration or a target of an assignment */ + function isWriteAccess(node) { + if (node.kind === 69 /* Identifier */ && ts.isDeclarationName(node)) { + return true; + } + var parent = node.parent; + if (parent) { + if (parent.kind === 186 /* PostfixUnaryExpression */ || parent.kind === 185 /* PrefixUnaryExpression */) { + return true; + } + else if (parent.kind === 187 /* BinaryExpression */ && parent.left === node) { + var operator = parent.operatorToken.kind; + return 56 /* FirstAssignment */ <= operator && operator <= 68 /* LastAssignment */; + } + } + return false; + } + function forEachDescendantOfKind(node, kind, action) { + ts.forEachChild(node, function (child) { + if (child.kind === kind) { + action(child); + } + forEachDescendantOfKind(child, kind, action); + }); + } + /** + * Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 } + */ + function getContainingObjectLiteralElement(node) { + switch (node.kind) { + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: + if (node.parent.kind === 140 /* ComputedPropertyName */) { + return isObjectLiteralPropertyDeclaration(node.parent.parent) ? node.parent.parent : undefined; } - formattingScanner.advance(); - childContextNode = parent; + // intential fall through + case 69 /* Identifier */: + return isObjectLiteralPropertyDeclaration(node.parent) && node.parent.name === node ? node.parent : undefined; + } + return undefined; + } + function isObjectLiteralPropertyDeclaration(node) { + switch (node.kind) { + case 253 /* PropertyAssignment */: + case 254 /* ShorthandPropertyAssignment */: + case 147 /* MethodDeclaration */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + return true; + } + return false; + } + /** Get `C` given `N` if `N` is in the position `class C extends N` or `class C extends foo.N` where `N` is an identifier. */ + function tryGetClassByExtendingIdentifier(node) { + return ts.tryGetClassExtendingExpressionWithTypeArguments(ts.climbPastPropertyAccess(node).parent); + } + function isNameOfExternalModuleImportOrDeclaration(node) { + if (node.kind === 9 /* StringLiteral */) { + return ts.isNameOfModuleDeclaration(node) || ts.isExpressionOfExternalModuleImportEqualsDeclaration(node); + } + return false; + } + })(FindAllReferences = ts.FindAllReferences || (ts.FindAllReferences = {})); +})(ts || (ts = {})); +/* @internal */ +var ts; +(function (ts) { + var GoToDefinition; + (function (GoToDefinition) { + function getDefinitionAtPosition(program, sourceFile, position) { + /// Triple slash reference comments + var comment = findReferenceInPosition(sourceFile.referencedFiles, position); + if (comment) { + var referenceFile = ts.tryResolveScriptReference(program, sourceFile, comment); + if (referenceFile) { + return [getDefinitionInfoForFileReference(comment.fileName, referenceFile.fileName)]; + } + return undefined; + } + // Type reference directives + var typeReferenceDirective = findReferenceInPosition(sourceFile.typeReferenceDirectives, position); + if (typeReferenceDirective) { + var referenceFile = program.getResolvedTypeReferenceDirectives()[typeReferenceDirective.fileName]; + if (referenceFile && referenceFile.resolvedFileName) { + return [getDefinitionInfoForFileReference(typeReferenceDirective.fileName, referenceFile.resolvedFileName)]; + } + return undefined; + } + var node = ts.getTouchingPropertyName(sourceFile, position); + if (node === sourceFile) { + return undefined; + } + // Labels + if (ts.isJumpStatementTarget(node)) { + var labelName = node.text; + var label = ts.getTargetLabel(node.parent, node.text); + return label ? [createDefinitionInfo(label, ts.ScriptElementKind.label, labelName, /*containerName*/ undefined)] : undefined; + } + var typeChecker = program.getTypeChecker(); + var calledDeclaration = tryGetSignatureDeclaration(typeChecker, node); + if (calledDeclaration) { + return [createDefinitionFromSignatureDeclaration(typeChecker, calledDeclaration)]; + } + var symbol = typeChecker.getSymbolAtLocation(node); + // Could not find a symbol e.g. node is string or number keyword, + // or the symbol was an internal symbol and does not have a declaration e.g. undefined symbol + if (!symbol) { + return undefined; + } + // If this is an alias, and the request came at the declaration location + // get the aliased symbol instead. This allows for goto def on an import e.g. + // import {A, B} from "mod"; + // to jump to the implementation directly. + if (symbol.flags & 8388608 /* Alias */) { + var declaration = symbol.declarations[0]; + // Go to the original declaration for cases: + // + // (1) when the aliased symbol was declared in the location(parent). + // (2) when the aliased symbol is originating from a named import. + // + if (node.kind === 69 /* Identifier */ && + (node.parent === declaration || + (declaration.kind === 234 /* ImportSpecifier */ && declaration.parent && declaration.parent.kind === 233 /* NamedImports */))) { + symbol = typeChecker.getAliasedSymbol(symbol); } } - function processTrivia(trivia, parent, contextNode, dynamicIndentation) { - for (var _i = 0, trivia_1 = trivia; _i < trivia_1.length; _i++) { - var triviaItem = trivia_1[_i]; - if (ts.isComment(triviaItem.kind) && ts.rangeContainsRange(originalRange, triviaItem)) { - var triviaItemStart = sourceFile.getLineAndCharacterOfPosition(triviaItem.pos); - processRange(triviaItem, triviaItemStart, parent, contextNode, dynamicIndentation); - } + // Because name in short-hand property assignment has two different meanings: property name and property value, + // using go-to-definition at such position should go to the variable declaration of the property value rather than + // go to the declaration of the property name (in this case stay at the same position). However, if go-to-definition + // is performed at the location of property access, we would like to go to definition of the property in the short-hand + // assignment. This case and others are handled by the following code. + if (node.parent.kind === 254 /* ShorthandPropertyAssignment */) { + var shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration); + if (!shorthandSymbol) { + return []; } + var shorthandDeclarations = shorthandSymbol.getDeclarations(); + var shorthandSymbolKind_1 = ts.SymbolDisplay.getSymbolKind(typeChecker, shorthandSymbol, node); + var shorthandSymbolName_1 = typeChecker.symbolToString(shorthandSymbol); + var shorthandContainerName_1 = typeChecker.symbolToString(symbol.parent, node); + return ts.map(shorthandDeclarations, function (declaration) { return createDefinitionInfo(declaration, shorthandSymbolKind_1, shorthandSymbolName_1, shorthandContainerName_1); }); } - function processRange(range, rangeStart, parent, contextNode, dynamicIndentation) { - var rangeHasError = rangeContainsError(range); - var lineAdded; - if (!rangeHasError && !previousRangeHasError) { - if (!previousRange) { - // trim whitespaces starting from the beginning of the span up to the current line - var originalStart = sourceFile.getLineAndCharacterOfPosition(originalRange.pos); - trimTrailingWhitespacesForLines(originalStart.line, rangeStart.line); - } - else { - lineAdded = - processPair(range, rangeStart.line, parent, previousRange, previousRangeStartLine, previousParent, contextNode, dynamicIndentation); - } - } - previousRange = range; - previousParent = parent; - previousRangeStartLine = rangeStart.line; - previousRangeHasError = rangeHasError; - return lineAdded; + return getDefinitionFromSymbol(typeChecker, symbol, node); + } + GoToDefinition.getDefinitionAtPosition = getDefinitionAtPosition; + /// Goto type + function getTypeDefinitionAtPosition(typeChecker, sourceFile, position) { + var node = ts.getTouchingPropertyName(sourceFile, position); + if (node === sourceFile) { + return undefined; } - function processPair(currentItem, currentStartLine, currentParent, previousItem, previousStartLine, previousParent, contextNode, dynamicIndentation) { - formattingContext.updateContext(previousItem, previousParent, currentItem, currentParent, contextNode); - var rule = rulesProvider.getRulesMap().GetRule(formattingContext); - var trimTrailingWhitespaces; - var lineAdded; - if (rule) { - applyRuleEdits(rule, previousItem, previousStartLine, currentItem, currentStartLine); - if (rule.Operation.Action & (2 /* Space */ | 8 /* Delete */) && currentStartLine !== previousStartLine) { - lineAdded = false; - // Handle the case where the next line is moved to be the end of this line. - // In this case we don't indent the next line in the next pass. - if (currentParent.getStart(sourceFile) === currentItem.pos) { - dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ false); - } - } - else if (rule.Operation.Action & 4 /* NewLine */ && currentStartLine === previousStartLine) { - lineAdded = true; - // Handle the case where token2 is moved to the new line. - // In this case we indent token2 in the next pass but we set - // sameLineIndent flag to notify the indenter that the indentation is within the line. - if (currentParent.getStart(sourceFile) === currentItem.pos) { - dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ true); - } - } - // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line - trimTrailingWhitespaces = !(rule.Operation.Action & 8 /* Delete */) && rule.Flag !== 1 /* CanDeleteNewLines */; - } - else { - trimTrailingWhitespaces = true; - } - if (currentStartLine !== previousStartLine && trimTrailingWhitespaces) { - // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line - trimTrailingWhitespacesForLines(previousStartLine, currentStartLine, previousItem); - } - return lineAdded; + var symbol = typeChecker.getSymbolAtLocation(node); + if (!symbol) { + return undefined; } - function insertIndentation(pos, indentation, lineAdded) { - var indentationString = getIndentationString(indentation, options); - if (lineAdded) { - // new line is added before the token by the formatting rules - // insert indentation string at the very beginning of the token - recordReplace(pos, 0, indentationString); - } - else { - var tokenStart = sourceFile.getLineAndCharacterOfPosition(pos); - var startLinePosition = ts.getStartPositionOfLine(tokenStart.line, sourceFile); - if (indentation !== tokenStart.character || indentationIsDifferent(indentationString, startLinePosition)) { - recordReplace(startLinePosition, tokenStart.character, indentationString); + var type = typeChecker.getTypeOfSymbolAtLocation(symbol, node); + if (!type) { + return undefined; + } + if (type.flags & 524288 /* Union */ && !(type.flags & 16 /* Enum */)) { + var result_5 = []; + ts.forEach(type.types, function (t) { + if (t.symbol) { + ts.addRange(/*to*/ result_5, /*from*/ getDefinitionFromSymbol(typeChecker, t.symbol, node)); } - } + }); + return result_5; } - function indentationIsDifferent(indentationString, startLinePosition) { - return indentationString !== sourceFile.text.substr(startLinePosition, indentationString.length); + if (!type.symbol) { + return undefined; } - function indentMultilineComment(commentRange, indentation, firstLineIsIndented) { - // split comment in lines - var startLine = sourceFile.getLineAndCharacterOfPosition(commentRange.pos).line; - var endLine = sourceFile.getLineAndCharacterOfPosition(commentRange.end).line; - var parts; - if (startLine === endLine) { - if (!firstLineIsIndented) { - // treat as single line comment - insertIndentation(commentRange.pos, indentation, /*lineAdded*/ false); - } - return; - } - else { - parts = []; - var startPos = commentRange.pos; - for (var line = startLine; line < endLine; line++) { - var endOfLine = ts.getEndLinePosition(line, sourceFile); - parts.push({ pos: startPos, end: endOfLine }); - startPos = ts.getStartPositionOfLine(line + 1, sourceFile); + return getDefinitionFromSymbol(typeChecker, type.symbol, node); + } + GoToDefinition.getTypeDefinitionAtPosition = getTypeDefinitionAtPosition; + function getDefinitionFromSymbol(typeChecker, symbol, node) { + var result = []; + var declarations = symbol.getDeclarations(); + var _a = getSymbolInfo(typeChecker, symbol, node), symbolName = _a.symbolName, symbolKind = _a.symbolKind, containerName = _a.containerName; + if (!tryAddConstructSignature(symbol, node, symbolKind, symbolName, containerName, result) && + !tryAddCallSignature(symbol, node, symbolKind, symbolName, containerName, result)) { + // Just add all the declarations. + ts.forEach(declarations, function (declaration) { + result.push(createDefinitionInfo(declaration, symbolKind, symbolName, containerName)); + }); + } + return result; + function tryAddConstructSignature(symbol, location, symbolKind, symbolName, containerName, result) { + // Applicable only if we are in a new expression, or we are on a constructor declaration + // and in either case the symbol has a construct signature definition, i.e. class + if (ts.isNewExpressionTarget(location) || location.kind === 121 /* ConstructorKeyword */) { + if (symbol.flags & 32 /* Class */) { + // Find the first class-like declaration and try to get the construct signature. + for (var _i = 0, _a = symbol.getDeclarations(); _i < _a.length; _i++) { + var declaration = _a[_i]; + if (ts.isClassLike(declaration)) { + return tryAddSignature(declaration.members, + /*selectConstructors*/ true, symbolKind, symbolName, containerName, result); + } + } + ts.Debug.fail("Expected declaration to have at least one class-like declaration"); } - parts.push({ pos: startPos, end: commentRange.end }); - } - var startLinePos = ts.getStartPositionOfLine(startLine, sourceFile); - var nonWhitespaceColumnInFirstPart = formatting.SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(startLinePos, parts[0].pos, sourceFile, options); - if (indentation === nonWhitespaceColumnInFirstPart.column) { - return; - } - var startIndex = 0; - if (firstLineIsIndented) { - startIndex = 1; - startLine++; } - // shift all parts on the delta size - var delta = indentation - nonWhitespaceColumnInFirstPart.column; - for (var i = startIndex, len = parts.length; i < len; i++, startLine++) { - var startLinePos_1 = ts.getStartPositionOfLine(startLine, sourceFile); - var nonWhitespaceCharacterAndColumn = i === 0 - ? nonWhitespaceColumnInFirstPart - : formatting.SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(parts[i].pos, parts[i].end, sourceFile, options); - var newIndentation = nonWhitespaceCharacterAndColumn.column + delta; - if (newIndentation > 0) { - var indentationString = getIndentationString(newIndentation, options); - recordReplace(startLinePos_1, nonWhitespaceCharacterAndColumn.character, indentationString); - } - else { - recordDelete(startLinePos_1, nonWhitespaceCharacterAndColumn.character); - } + return false; + } + function tryAddCallSignature(symbol, location, symbolKind, symbolName, containerName, result) { + if (ts.isCallExpressionTarget(location) || ts.isNewExpressionTarget(location) || ts.isNameOfFunctionDeclaration(location)) { + return tryAddSignature(symbol.declarations, /*selectConstructors*/ false, symbolKind, symbolName, containerName, result); } + return false; } - function trimTrailingWhitespacesForLines(line1, line2, range) { - for (var line = line1; line < line2; line++) { - var lineStartPosition = ts.getStartPositionOfLine(line, sourceFile); - var lineEndPosition = ts.getEndLinePosition(line, sourceFile); - // do not trim whitespaces in comments or template expression - if (range && (ts.isComment(range.kind) || ts.isStringOrRegularExpressionOrTemplateLiteral(range.kind)) && range.pos <= lineEndPosition && range.end > lineEndPosition) { - continue; - } - var whitespaceStart = getTrailingWhitespaceStartPosition(lineStartPosition, lineEndPosition); - if (whitespaceStart !== -1) { - ts.Debug.assert(whitespaceStart === lineStartPosition || !ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(whitespaceStart - 1))); - recordDelete(whitespaceStart, lineEndPosition + 1 - whitespaceStart); + function tryAddSignature(signatureDeclarations, selectConstructors, symbolKind, symbolName, containerName, result) { + var declarations = []; + var definition; + ts.forEach(signatureDeclarations, function (d) { + if ((selectConstructors && d.kind === 148 /* Constructor */) || + (!selectConstructors && (d.kind === 220 /* FunctionDeclaration */ || d.kind === 147 /* MethodDeclaration */ || d.kind === 146 /* MethodSignature */))) { + declarations.push(d); + if (d.body) + definition = d; } + }); + if (definition) { + result.push(createDefinitionInfo(definition, symbolKind, symbolName, containerName)); + return true; } - } - /** - * @param start The position of the first character in range - * @param end The position of the last character in range - */ - function getTrailingWhitespaceStartPosition(start, end) { - var pos = end; - while (pos >= start && ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(pos))) { - pos--; + else if (declarations.length) { + result.push(createDefinitionInfo(ts.lastOrUndefined(declarations), symbolKind, symbolName, containerName)); + return true; } - if (pos !== end) { - return pos + 1; + return false; + } + } + function createDefinitionInfo(node, symbolKind, symbolName, containerName) { + return { + fileName: node.getSourceFile().fileName, + textSpan: ts.createTextSpanFromBounds(node.getStart(), node.getEnd()), + kind: symbolKind, + name: symbolName, + containerKind: undefined, + containerName: containerName + }; + } + function getSymbolInfo(typeChecker, symbol, node) { + return { + symbolName: typeChecker.symbolToString(symbol), + symbolKind: ts.SymbolDisplay.getSymbolKind(typeChecker, symbol, node), + containerName: symbol.parent ? typeChecker.symbolToString(symbol.parent, node) : "" + }; + } + function createDefinitionFromSignatureDeclaration(typeChecker, decl) { + var _a = getSymbolInfo(typeChecker, decl.symbol, decl), symbolName = _a.symbolName, symbolKind = _a.symbolKind, containerName = _a.containerName; + return createDefinitionInfo(decl, symbolKind, symbolName, containerName); + } + function findReferenceInPosition(refs, pos) { + for (var _i = 0, refs_1 = refs; _i < refs_1.length; _i++) { + var ref = refs_1[_i]; + if (ref.pos <= pos && pos < ref.end) { + return ref; } - return -1; } - /** - * Trimming will be done for lines after the previous range - */ - function trimTrailingWhitespacesForRemainingRange() { - var startPosition = previousRange ? previousRange.end : originalRange.pos; - var startLine = sourceFile.getLineAndCharacterOfPosition(startPosition).line; - var endLine = sourceFile.getLineAndCharacterOfPosition(originalRange.end).line; - trimTrailingWhitespacesForLines(startLine, endLine + 1, previousRange); + return undefined; + } + function getDefinitionInfoForFileReference(name, targetFileName) { + return { + fileName: targetFileName, + textSpan: ts.createTextSpanFromBounds(0, 0), + kind: ts.ScriptElementKind.scriptElement, + name: name, + containerName: undefined, + containerKind: undefined + }; + } + /** Returns a CallLikeExpression where `node` is the target being invoked. */ + function getAncestorCallLikeExpression(node) { + var target = climbPastManyPropertyAccesses(node); + var callLike = target.parent; + return callLike && ts.isCallLikeExpression(callLike) && ts.getInvokedExpression(callLike) === target && callLike; + } + function climbPastManyPropertyAccesses(node) { + return ts.isRightSideOfPropertyAccess(node) ? climbPastManyPropertyAccesses(node.parent) : node; + } + function tryGetSignatureDeclaration(typeChecker, node) { + var callLike = getAncestorCallLikeExpression(node); + return callLike && typeChecker.getResolvedSignature(callLike).declaration; + } + })(GoToDefinition = ts.GoToDefinition || (ts.GoToDefinition = {})); +})(ts || (ts = {})); +/* @internal */ +var ts; +(function (ts) { + var GoToImplementation; + (function (GoToImplementation) { + function getImplementationAtPosition(typeChecker, cancellationToken, sourceFiles, node) { + // If invoked directly on a shorthand property assignment, then return + // the declaration of the symbol being assigned (not the symbol being assigned to). + if (node.parent.kind === 254 /* ShorthandPropertyAssignment */) { + var result = []; + ts.FindAllReferences.getReferenceEntriesForShorthandPropertyAssignment(node, typeChecker, result); + return result.length > 0 ? result : undefined; } - function newTextChange(start, len, newText) { - return { span: ts.createTextSpan(start, len), newText: newText }; + else if (node.kind === 95 /* SuperKeyword */ || ts.isSuperProperty(node.parent)) { + // References to and accesses on the super keyword only have one possible implementation, so no + // need to "Find all References" + var symbol = typeChecker.getSymbolAtLocation(node); + return symbol.valueDeclaration && [ts.FindAllReferences.getReferenceEntryFromNode(symbol.valueDeclaration)]; } - function recordDelete(start, len) { - if (len) { - edits.push(newTextChange(start, len, "")); - } + else { + // Perform "Find all References" and retrieve only those that are implementations + var referencedSymbols = ts.FindAllReferences.getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFiles, /*findInStrings*/ false, /*findInComments*/ false, /*implementations*/ true); + var result = ts.flatMap(referencedSymbols, function (symbol) { + return ts.map(symbol.references, function (_a) { + var textSpan = _a.textSpan, fileName = _a.fileName; + return ({ textSpan: textSpan, fileName: fileName }); + }); + }); + return result && result.length > 0 ? result : undefined; } - function recordReplace(start, len, newText) { - if (len || newText) { - edits.push(newTextChange(start, len, newText)); + } + GoToImplementation.getImplementationAtPosition = getImplementationAtPosition; + })(GoToImplementation = ts.GoToImplementation || (ts.GoToImplementation = {})); +})(ts || (ts = {})); +/* @internal */ +var ts; +(function (ts) { + var JsDoc; + (function (JsDoc) { + var jsDocTagNames = [ + "augments", + "author", + "argument", + "borrows", + "class", + "constant", + "constructor", + "constructs", + "default", + "deprecated", + "description", + "event", + "example", + "extends", + "field", + "fileOverview", + "function", + "ignore", + "inner", + "lends", + "link", + "memberOf", + "name", + "namespace", + "param", + "private", + "property", + "public", + "requires", + "returns", + "see", + "since", + "static", + "throws", + "type", + "typedef", + "property", + "prop", + "version" + ]; + var jsDocCompletionEntries; + function getJsDocCommentsFromDeclarations(declarations, name, canUseParsedParamTagComments) { + // Only collect doc comments from duplicate declarations once: + // In case of a union property there might be same declaration multiple times + // which only varies in type parameter + // Eg. const a: Array | Array; a.length + // The property length will have two declarations of property length coming + // from Array - Array and Array + var documentationComment = []; + forEachUnique(declarations, function (declaration) { + var comments = ts.getJSDocComments(declaration, /*checkParentVariableStatement*/ true); + if (!comments) { + return; } - } - function applyRuleEdits(rule, previousRange, previousStartLine, currentRange, currentStartLine) { - switch (rule.Operation.Action) { - case 1 /* Ignore */: - // no action required - return; - case 8 /* Delete */: - if (previousRange.end !== currentRange.pos) { - // delete characters starting from t1.end up to t2.pos exclusive - recordDelete(previousRange.end, currentRange.pos - previousRange.end); - } - break; - case 4 /* NewLine */: - // exit early if we on different lines and rule cannot change number of newlines - // if line1 and line2 are on subsequent lines then no edits are required - ok to exit - // if line1 and line2 are separated with more than one newline - ok to exit since we cannot delete extra new lines - if (rule.Flag !== 1 /* CanDeleteNewLines */ && previousStartLine !== currentStartLine) { - return; - } - // edit should not be applied only if we have one line feed between elements - var lineDelta = currentStartLine - previousStartLine; - if (lineDelta !== 1) { - recordReplace(previousRange.end, currentRange.pos - previousRange.end, options.NewLineCharacter); - } - break; - case 2 /* Space */: - // exit early if we on different lines and rule cannot change number of newlines - if (rule.Flag !== 1 /* CanDeleteNewLines */ && previousStartLine !== currentStartLine) { - return; + for (var _i = 0, comments_3 = comments; _i < comments_3.length; _i++) { + var comment = comments_3[_i]; + if (comment) { + if (documentationComment.length) { + documentationComment.push(ts.lineBreakPart()); } - var posDelta = currentRange.pos - previousRange.end; - if (posDelta !== 1 || sourceFile.text.charCodeAt(previousRange.end) !== 32 /* space */) { - recordReplace(previousRange.end, currentRange.pos - previousRange.end, " "); - } - break; + documentationComment.push(ts.textPart(comment)); + } } - } + }); + return documentationComment; } - function getOpenTokenForList(node, list) { - switch (node.kind) { - case 148 /* Constructor */: - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - case 180 /* ArrowFunction */: - if (node.typeParameters === list) { - return 25 /* LessThanToken */; - } - else if (node.parameters === list) { - return 17 /* OpenParenToken */; - } - break; - case 174 /* CallExpression */: - case 175 /* NewExpression */: - if (node.typeArguments === list) { - return 25 /* LessThanToken */; - } - else if (node.arguments === list) { - return 17 /* OpenParenToken */; - } - break; - case 155 /* TypeReference */: - if (node.typeArguments === list) { - return 25 /* LessThanToken */; + JsDoc.getJsDocCommentsFromDeclarations = getJsDocCommentsFromDeclarations; + /** + * Iterates through 'array' by index and performs the callback on each element of array until the callback + * returns a truthy value, then returns that value. + * If no such value is found, the callback is applied to each element of array and undefined is returned. + */ + function forEachUnique(array, callback) { + if (array) { + for (var i = 0, len = array.length; i < len; i++) { + if (ts.indexOf(array, array[i]) === i) { + var result = callback(array[i], i); + if (result) { + return result; + } } + } } - return 0 /* Unknown */; + return undefined; } - function getCloseTokenForOpenToken(kind) { - switch (kind) { - case 17 /* OpenParenToken */: - return 18 /* CloseParenToken */; - case 25 /* LessThanToken */: - return 27 /* GreaterThanToken */; - } - return 0 /* Unknown */; + function getAllJsDocCompletionEntries() { + return jsDocCompletionEntries || (jsDocCompletionEntries = ts.map(jsDocTagNames, function (tagName) { + return { + name: tagName, + kind: ts.ScriptElementKind.keyword, + kindModifiers: "", + sortText: "0", + }; + })); } - var internedSizes; - var internedTabsIndentation; - var internedSpacesIndentation; - function getIndentationString(indentation, options) { - // reset interned strings if FormatCodeOptions were changed - var resetInternedStrings = !internedSizes || (internedSizes.tabSize !== options.TabSize || internedSizes.indentSize !== options.IndentSize); - if (resetInternedStrings) { - internedSizes = { tabSize: options.TabSize, indentSize: options.IndentSize }; - internedTabsIndentation = internedSpacesIndentation = undefined; + JsDoc.getAllJsDocCompletionEntries = getAllJsDocCompletionEntries; + /** + * Checks if position points to a valid position to add JSDoc comments, and if so, + * returns the appropriate template. Otherwise returns an empty string. + * Valid positions are + * - outside of comments, statements, and expressions, and + * - preceding a: + * - function/constructor/method declaration + * - class declarations + * - variable statements + * - namespace declarations + * + * Hosts should ideally check that: + * - The line is all whitespace up to 'position' before performing the insertion. + * - If the keystroke sequence "/\*\*" induced the call, we also check that the next + * non-whitespace character is '*', which (approximately) indicates whether we added + * the second '*' to complete an existing (JSDoc) comment. + * @param fileName The file in which to perform the check. + * @param position The (character-indexed) position in the file where the check should + * be performed. + */ + function getDocCommentTemplateAtPosition(newLine, sourceFile, position) { + // Check if in a context where we don't want to perform any insertion + if (ts.isInString(sourceFile, position) || ts.isInComment(sourceFile, position) || ts.hasDocComment(sourceFile, position)) { + return undefined; } - if (!options.ConvertTabsToSpaces) { - var tabs = Math.floor(indentation / options.TabSize); - var spaces = indentation - tabs * options.TabSize; - var tabString = void 0; - if (!internedTabsIndentation) { - internedTabsIndentation = []; - } - if (internedTabsIndentation[tabs] === undefined) { - internedTabsIndentation[tabs] = tabString = repeat("\t", tabs); - } - else { - tabString = internedTabsIndentation[tabs]; - } - return spaces ? tabString + repeat(" ", spaces) : tabString; + var tokenAtPos = ts.getTokenAtPosition(sourceFile, position); + var tokenStart = tokenAtPos.getStart(); + if (!tokenAtPos || tokenStart < position) { + return undefined; } - else { - var spacesString = void 0; - var quotient = Math.floor(indentation / options.IndentSize); - var remainder = indentation % options.IndentSize; - if (!internedSpacesIndentation) { - internedSpacesIndentation = []; - } - if (internedSpacesIndentation[quotient] === undefined) { - spacesString = repeat(" ", options.IndentSize * quotient); - internedSpacesIndentation[quotient] = spacesString; + // TODO: add support for: + // - enums/enum members + // - interfaces + // - property declarations + // - potentially property assignments + var commentOwner; + findOwner: for (commentOwner = tokenAtPos; commentOwner; commentOwner = commentOwner.parent) { + switch (commentOwner.kind) { + case 220 /* FunctionDeclaration */: + case 147 /* MethodDeclaration */: + case 148 /* Constructor */: + case 221 /* ClassDeclaration */: + case 200 /* VariableStatement */: + break findOwner; + case 256 /* SourceFile */: + return undefined; + case 225 /* ModuleDeclaration */: + // If in walking up the tree, we hit a a nested namespace declaration, + // then we must be somewhere within a dotted namespace name; however we don't + // want to give back a JSDoc template for the 'b' or 'c' in 'namespace a.b.c { }'. + if (commentOwner.parent.kind === 225 /* ModuleDeclaration */) { + return undefined; + } + break findOwner; } - else { - spacesString = internedSpacesIndentation[quotient]; + } + if (!commentOwner || commentOwner.getStart() < position) { + return undefined; + } + var parameters = getParametersForJsDocOwningNode(commentOwner); + var posLineAndChar = sourceFile.getLineAndCharacterOfPosition(position); + var lineStart = sourceFile.getLineStarts()[posLineAndChar.line]; + var indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character); + var docParams = ""; + for (var i = 0, numParams = parameters.length; i < numParams; i++) { + var currentName = parameters[i].name; + var paramName = currentName.kind === 69 /* Identifier */ ? + currentName.text : + "param" + i; + docParams += indentationStr + " * @param " + paramName + newLine; + } + // A doc comment consists of the following + // * The opening comment line + // * the first line (without a param) for the object's untagged info (this is also where the caret ends up) + // * the '@param'-tagged lines + // * TODO: other tags. + // * the closing comment line + // * if the caret was directly in front of the object, then we add an extra line and indentation. + var preamble = "/**" + newLine + + indentationStr + " * "; + var result = preamble + newLine + + docParams + + indentationStr + " */" + + (tokenStart === position ? newLine + indentationStr : ""); + return { newText: result, caretOffset: preamble.length }; + } + JsDoc.getDocCommentTemplateAtPosition = getDocCommentTemplateAtPosition; + function getParametersForJsDocOwningNode(commentOwner) { + if (ts.isFunctionLike(commentOwner)) { + return commentOwner.parameters; + } + if (commentOwner.kind === 200 /* VariableStatement */) { + var varStatement = commentOwner; + var varDeclarations = varStatement.declarationList.declarations; + if (varDeclarations.length === 1 && varDeclarations[0].initializer) { + return getParametersFromRightHandSideOfAssignment(varDeclarations[0].initializer); } - return remainder ? spacesString + repeat(" ", remainder) : spacesString; } - function repeat(value, count) { - var s = ""; - for (var i = 0; i < count; i++) { - s += value; - } - return s; + return ts.emptyArray; + } + /** + * Digs into an an initializer or RHS operand of an assignment operation + * to get the parameters of an apt signature corresponding to a + * function expression or a class expression. + * + * @param rightHandSide the expression which may contain an appropriate set of parameters + * @returns the parameters of a signature found on the RHS if one exists; otherwise 'emptyArray'. + */ + function getParametersFromRightHandSideOfAssignment(rightHandSide) { + while (rightHandSide.kind === 178 /* ParenthesizedExpression */) { + rightHandSide = rightHandSide.expression; + } + switch (rightHandSide.kind) { + case 179 /* FunctionExpression */: + case 180 /* ArrowFunction */: + return rightHandSide.parameters; + case 192 /* ClassExpression */: + for (var _i = 0, _a = rightHandSide.members; _i < _a.length; _i++) { + var member = _a[_i]; + if (member.kind === 148 /* Constructor */) { + return member.parameters; + } + } + break; } + return ts.emptyArray; } - formatting.getIndentationString = getIndentationString; - })(formatting = ts.formatting || (ts.formatting = {})); + })(JsDoc = ts.JsDoc || (ts.JsDoc = {})); })(ts || (ts = {})); -/// +// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0. +// See LICENSE.txt in the project root for complete license information. +/// +/// +/// /* @internal */ var ts; (function (ts) { - var formatting; - (function (formatting) { - var SmartIndenter; - (function (SmartIndenter) { - var Value; - (function (Value) { - Value[Value["Unknown"] = -1] = "Unknown"; - })(Value || (Value = {})); - function getIndentation(position, sourceFile, options) { - if (position > sourceFile.text.length) { - return getBaseIndentation(options); // past EOF - } - // no indentation when the indent style is set to none, - // so we can return fast - if (options.IndentStyle === ts.IndentStyle.None) { - return 0; - } - var precedingToken = ts.findPrecedingToken(position, sourceFile); - if (!precedingToken) { - return getBaseIndentation(options); + var JsTyping; + (function (JsTyping) { + ; + ; + // A map of loose file names to library names + // that we are confident require typings + var safeList; + var EmptySafeList = ts.createMap(); + /** + * @param host is the object providing I/O related operations. + * @param fileNames are the file names that belong to the same project + * @param projectRootPath is the path to the project root directory + * @param safeListPath is the path used to retrieve the safe list + * @param packageNameToTypingLocation is the map of package names to their cached typing locations + * @param typingOptions are used to customize the typing inference process + * @param compilerOptions are used as a source for typing inference + */ + function discoverTypings(host, fileNames, projectRootPath, safeListPath, packageNameToTypingLocation, typingOptions, compilerOptions) { + // A typing name to typing file path mapping + var inferredTypings = ts.createMap(); + if (!typingOptions || !typingOptions.enableAutoDiscovery) { + return { cachedTypingPaths: [], newTypingNames: [], filesToWatch: [] }; + } + // Only infer typings for .js and .jsx files + fileNames = ts.filter(ts.map(fileNames, ts.normalizePath), function (f) { + var kind = ts.ensureScriptKind(f, ts.getScriptKindFromFileName(f)); + return kind === 1 /* JS */ || kind === 2 /* JSX */; + }); + if (!safeList) { + var result = ts.readConfigFile(safeListPath, function (path) { return host.readFile(path); }); + safeList = result.config ? ts.createMap(result.config) : EmptySafeList; + } + var filesToWatch = []; + // Directories to search for package.json, bower.json and other typing information + var searchDirs = []; + var exclude = []; + mergeTypings(typingOptions.include); + exclude = typingOptions.exclude || []; + var possibleSearchDirs = ts.map(fileNames, ts.getDirectoryPath); + if (projectRootPath !== undefined) { + possibleSearchDirs.push(projectRootPath); + } + searchDirs = ts.deduplicate(possibleSearchDirs); + for (var _i = 0, searchDirs_1 = searchDirs; _i < searchDirs_1.length; _i++) { + var searchDir = searchDirs_1[_i]; + var packageJsonPath = ts.combinePaths(searchDir, "package.json"); + getTypingNamesFromJson(packageJsonPath, filesToWatch); + var bowerJsonPath = ts.combinePaths(searchDir, "bower.json"); + getTypingNamesFromJson(bowerJsonPath, filesToWatch); + var nodeModulesPath = ts.combinePaths(searchDir, "node_modules"); + getTypingNamesFromNodeModuleFolder(nodeModulesPath); + } + getTypingNamesFromSourceFileNames(fileNames); + // Add the cached typing locations for inferred typings that are already installed + for (var name_51 in packageNameToTypingLocation) { + if (name_51 in inferredTypings && !inferredTypings[name_51]) { + inferredTypings[name_51] = packageNameToTypingLocation[name_51]; } - // no indentation in string \regex\template literals - var precedingTokenIsLiteral = ts.isStringOrRegularExpressionOrTemplateLiteral(precedingToken.kind); - if (precedingTokenIsLiteral && precedingToken.getStart(sourceFile) <= position && precedingToken.end > position) { - return 0; + } + // Remove typings that the user has added to the exclude list + for (var _a = 0, exclude_1 = exclude; _a < exclude_1.length; _a++) { + var excludeTypingName = exclude_1[_a]; + delete inferredTypings[excludeTypingName]; + } + var newTypingNames = []; + var cachedTypingPaths = []; + for (var typing in inferredTypings) { + if (inferredTypings[typing] !== undefined) { + cachedTypingPaths.push(inferredTypings[typing]); } - var lineAtPosition = sourceFile.getLineAndCharacterOfPosition(position).line; - // indentation is first non-whitespace character in a previous line - // for block indentation, we should look for a line which contains something that's not - // whitespace. - if (options.IndentStyle === ts.IndentStyle.Block) { - // move backwards until we find a line with a non-whitespace character, - // then find the first non-whitespace character for that line. - var current_1 = position; - while (current_1 > 0) { - var char = sourceFile.text.charCodeAt(current_1); - if (!ts.isWhiteSpace(char)) { - break; - } - current_1--; - } - var lineStart = ts.getLineStartPositionForPosition(current_1, sourceFile); - return SmartIndenter.findFirstNonWhitespaceColumn(lineStart, current_1, sourceFile, options); + else { + newTypingNames.push(typing); } - if (precedingToken.kind === 24 /* CommaToken */ && precedingToken.parent.kind !== 187 /* BinaryExpression */) { - // previous token is comma that separates items in list - find the previous item and try to derive indentation from it - var actualIndentation = getActualIndentationForListItemBeforeComma(precedingToken, sourceFile, options); - if (actualIndentation !== -1 /* Unknown */) { - return actualIndentation; - } + } + return { cachedTypingPaths: cachedTypingPaths, newTypingNames: newTypingNames, filesToWatch: filesToWatch }; + /** + * Merge a given list of typingNames to the inferredTypings map + */ + function mergeTypings(typingNames) { + if (!typingNames) { + return; } - // try to find node that can contribute to indentation and includes 'position' starting from 'precedingToken' - // if such node is found - compute initial indentation for 'position' inside this node - var previous; - var current = precedingToken; - var currentStart; - var indentationDelta; - while (current) { - if (ts.positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(current, previous)) { - currentStart = getStartLineAndCharacterForNode(current, sourceFile); - if (nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile)) { - indentationDelta = 0; - } - else { - indentationDelta = lineAtPosition !== currentStart.line ? options.IndentSize : 0; - } - break; - } - // check if current node is a list item - if yes, take indentation from it - var actualIndentation = getActualIndentationForListItem(current, sourceFile, options); - if (actualIndentation !== -1 /* Unknown */) { - return actualIndentation; - } - actualIndentation = getLineIndentationWhenExpressionIsInMultiLine(current, sourceFile, options); - if (actualIndentation !== -1 /* Unknown */) { - return actualIndentation + options.IndentSize; + for (var _i = 0, typingNames_1 = typingNames; _i < typingNames_1.length; _i++) { + var typing = typingNames_1[_i]; + if (!(typing in inferredTypings)) { + inferredTypings[typing] = undefined; } - previous = current; - current = current.parent; - } - if (!current) { - // no parent was found - return the base indentation of the SourceFile - return getBaseIndentation(options); } - return getIndentationForNodeWorker(current, currentStart, /*ignoreActualIndentationRange*/ undefined, indentationDelta, sourceFile, options); - } - SmartIndenter.getIndentation = getIndentation; - function getBaseIndentation(options) { - return options.BaseIndentSize || 0; - } - SmartIndenter.getBaseIndentation = getBaseIndentation; - function getIndentationForNode(n, ignoreActualIndentationRange, sourceFile, options) { - var start = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)); - return getIndentationForNodeWorker(n, start, ignoreActualIndentationRange, /*indentationDelta*/ 0, sourceFile, options); } - SmartIndenter.getIndentationForNode = getIndentationForNode; - function getIndentationForNodeWorker(current, currentStart, ignoreActualIndentationRange, indentationDelta, sourceFile, options) { - var parent = current.parent; - var parentStart; - // walk upwards and collect indentations for pairs of parent-child nodes - // indentation is not added if parent and child nodes start on the same line or if parent is IfStatement and child starts on the same line with 'else clause' - while (parent) { - var useActualIndentation = true; - if (ignoreActualIndentationRange) { - var start = current.getStart(sourceFile); - useActualIndentation = start < ignoreActualIndentationRange.pos || start > ignoreActualIndentationRange.end; + /** + * Get the typing info from common package manager json files like package.json or bower.json + */ + function getTypingNamesFromJson(jsonPath, filesToWatch) { + var result = ts.readConfigFile(jsonPath, function (path) { return host.readFile(path); }); + if (result.config) { + var jsonConfig = result.config; + filesToWatch.push(jsonPath); + if (jsonConfig.dependencies) { + mergeTypings(ts.getOwnKeys(jsonConfig.dependencies)); } - if (useActualIndentation) { - // check if current node is a list item - if yes, take indentation from it - var actualIndentation = getActualIndentationForListItem(current, sourceFile, options); - if (actualIndentation !== -1 /* Unknown */) { - return actualIndentation + indentationDelta; - } + if (jsonConfig.devDependencies) { + mergeTypings(ts.getOwnKeys(jsonConfig.devDependencies)); } - parentStart = getParentStart(parent, current, sourceFile); - var parentAndChildShareLine = parentStart.line === currentStart.line || - childStartsOnTheSameLineWithElseInIfStatement(parent, current, currentStart.line, sourceFile); - if (useActualIndentation) { - // try to fetch actual indentation for current node from source text - var actualIndentation = getActualIndentationForNode(current, parent, currentStart, parentAndChildShareLine, sourceFile, options); - if (actualIndentation !== -1 /* Unknown */) { - return actualIndentation + indentationDelta; - } - actualIndentation = getLineIndentationWhenExpressionIsInMultiLine(current, sourceFile, options); - if (actualIndentation !== -1 /* Unknown */) { - return actualIndentation + indentationDelta; - } + if (jsonConfig.optionalDependencies) { + mergeTypings(ts.getOwnKeys(jsonConfig.optionalDependencies)); } - // increase indentation if parent node wants its content to be indented and parent and child nodes don't start on the same line - if (shouldIndentChildNode(parent, current) && !parentAndChildShareLine) { - indentationDelta += options.IndentSize; + if (jsonConfig.peerDependencies) { + mergeTypings(ts.getOwnKeys(jsonConfig.peerDependencies)); } - current = parent; - currentStart = parentStart; - parent = current.parent; - } - return indentationDelta + getBaseIndentation(options); - } - function getParentStart(parent, child, sourceFile) { - var containingList = getContainingList(child, sourceFile); - if (containingList) { - return sourceFile.getLineAndCharacterOfPosition(containingList.pos); } - return sourceFile.getLineAndCharacterOfPosition(parent.getStart(sourceFile)); } - /* - * Function returns Value.Unknown if indentation cannot be determined + /** + * Infer typing names from given file names. For example, the file name "jquery-min.2.3.4.js" + * should be inferred to the 'jquery' typing name; and "angular-route.1.2.3.js" should be inferred + * to the 'angular-route' typing name. + * @param fileNames are the names for source files in the project */ - function getActualIndentationForListItemBeforeComma(commaToken, sourceFile, options) { - // previous token is comma that separates items in list - find the previous item and try to derive indentation from it - var commaItemInfo = ts.findListItemInfo(commaToken); - if (commaItemInfo && commaItemInfo.listItemIndex > 0) { - return deriveActualIndentationFromList(commaItemInfo.list.getChildren(), commaItemInfo.listItemIndex - 1, sourceFile, options); + function getTypingNamesFromSourceFileNames(fileNames) { + var jsFileNames = ts.filter(fileNames, ts.hasJavaScriptFileExtension); + var inferredTypingNames = ts.map(jsFileNames, function (f) { return ts.removeFileExtension(ts.getBaseFileName(f.toLowerCase())); }); + var cleanedTypingNames = ts.map(inferredTypingNames, function (f) { return f.replace(/((?:\.|-)min(?=\.|$))|((?:-|\.)\d+)/g, ""); }); + if (safeList !== EmptySafeList) { + mergeTypings(ts.filter(cleanedTypingNames, function (f) { return f in safeList; })); } - else { - // handle broken code gracefully - return -1 /* Unknown */; + var hasJsxFile = ts.forEach(fileNames, function (f) { return ts.ensureScriptKind(f, ts.getScriptKindFromFileName(f)) === 2 /* JSX */; }); + if (hasJsxFile) { + mergeTypings(["react"]); } } - /* - * Function returns Value.Unknown if actual indentation for node should not be used (i.e because node is nested expression) + /** + * Infer typing names from node_module folder + * @param nodeModulesPath is the path to the "node_modules" folder */ - function getActualIndentationForNode(current, parent, currentLineAndChar, parentAndChildShareLine, sourceFile, options) { - // actual indentation is used for statements\declarations if one of cases below is true: - // - parent is SourceFile - by default immediate children of SourceFile are not indented except when user indents them manually - // - parent and child are not on the same line - var useActualIndentation = (ts.isDeclaration(current) || ts.isStatement(current)) && - (parent.kind === 256 /* SourceFile */ || !parentAndChildShareLine); - if (!useActualIndentation) { - return -1 /* Unknown */; - } - return findColumnForFirstNonWhitespaceCharacterInLine(currentLineAndChar, sourceFile, options); - } - function nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile) { - var nextToken = ts.findNextToken(precedingToken, current); - if (!nextToken) { - return false; - } - if (nextToken.kind === 15 /* OpenBraceToken */) { - // open braces are always indented at the parent level - return true; + function getTypingNamesFromNodeModuleFolder(nodeModulesPath) { + // Todo: add support for ModuleResolutionHost too + if (!host.directoryExists(nodeModulesPath)) { + return; } - else if (nextToken.kind === 16 /* CloseBraceToken */) { - // close braces are indented at the parent level if they are located on the same line with cursor - // this means that if new line will be added at $ position, this case will be indented - // class A { - // $ - // } - /// and this one - not - // class A { - // $} - var nextTokenStartLine = getStartLineAndCharacterForNode(nextToken, sourceFile).line; - return lineAtPosition === nextTokenStartLine; + var typingNames = []; + var fileNames = host.readDirectory(nodeModulesPath, [".json"], /*excludes*/ undefined, /*includes*/ undefined, /*depth*/ 2); + for (var _i = 0, fileNames_2 = fileNames; _i < fileNames_2.length; _i++) { + var fileName = fileNames_2[_i]; + var normalizedFileName = ts.normalizePath(fileName); + if (ts.getBaseFileName(normalizedFileName) !== "package.json") { + continue; + } + var result = ts.readConfigFile(normalizedFileName, function (path) { return host.readFile(path); }); + if (!result.config) { + continue; + } + var packageJson = result.config; + // npm 3's package.json contains a "_requiredBy" field + // we should include all the top level module names for npm 2, and only module names whose + // "_requiredBy" field starts with "#" or equals "/" for npm 3. + if (packageJson._requiredBy && + ts.filter(packageJson._requiredBy, function (r) { return r[0] === "#" || r === "/"; }).length === 0) { + continue; + } + // If the package has its own d.ts typings, those will take precedence. Otherwise the package name will be used + // to download d.ts files from DefinitelyTyped + if (!packageJson.name) { + continue; + } + if (packageJson.typings) { + var absolutePath = ts.getNormalizedAbsolutePath(packageJson.typings, ts.getDirectoryPath(normalizedFileName)); + inferredTypings[packageJson.name] = absolutePath; + } + else { + typingNames.push(packageJson.name); + } } - return false; - } - function getStartLineAndCharacterForNode(n, sourceFile) { - return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)); + mergeTypings(typingNames); } - function childStartsOnTheSameLineWithElseInIfStatement(parent, child, childStartLine, sourceFile) { - if (parent.kind === 203 /* IfStatement */ && parent.elseStatement === child) { - var elseKeyword = ts.findChildOfKind(parent, 80 /* ElseKeyword */, sourceFile); - ts.Debug.assert(elseKeyword !== undefined); - var elseKeywordStartLine = getStartLineAndCharacterForNode(elseKeyword, sourceFile).line; - return elseKeywordStartLine === childStartLine; + } + JsTyping.discoverTypings = discoverTypings; + })(JsTyping = ts.JsTyping || (ts.JsTyping = {})); +})(ts || (ts = {})); +/* @internal */ +var ts; +(function (ts) { + var NavigateTo; + (function (NavigateTo) { + function getNavigateToItems(sourceFiles, checker, cancellationToken, searchValue, maxResultCount, excludeDtsFiles) { + var patternMatcher = ts.createPatternMatcher(searchValue); + var rawItems = []; + // This means "compare in a case insensitive manner." + var baseSensitivity = { sensitivity: "base" }; + // Search the declarations in all files and output matched NavigateToItem into array of NavigateToItem[] + ts.forEach(sourceFiles, function (sourceFile) { + cancellationToken.throwIfCancellationRequested(); + if (excludeDtsFiles && ts.fileExtensionIs(sourceFile.fileName, ".d.ts")) { + return; } - return false; - } - SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement = childStartsOnTheSameLineWithElseInIfStatement; - function getContainingList(node, sourceFile) { - if (node.parent) { - switch (node.parent.kind) { - case 155 /* TypeReference */: - if (node.parent.typeArguments && - ts.rangeContainsStartEnd(node.parent.typeArguments, node.getStart(sourceFile), node.getEnd())) { - return node.parent.typeArguments; - } - break; - case 171 /* ObjectLiteralExpression */: - return node.parent.properties; - case 170 /* ArrayLiteralExpression */: - return node.parent.elements; - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - case 180 /* ArrowFunction */: - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - case 151 /* CallSignature */: - case 152 /* ConstructSignature */: { - var start = node.getStart(sourceFile); - if (node.parent.typeParameters && - ts.rangeContainsStartEnd(node.parent.typeParameters, start, node.getEnd())) { - return node.parent.typeParameters; - } - if (ts.rangeContainsStartEnd(node.parent.parameters, start, node.getEnd())) { - return node.parent.parameters; - } - break; + var nameToDeclarations = sourceFile.getNamedDeclarations(); + for (var name_52 in nameToDeclarations) { + var declarations = nameToDeclarations[name_52]; + if (declarations) { + // First do a quick check to see if the name of the declaration matches the + // last portion of the (possibly) dotted name they're searching for. + var matches = patternMatcher.getMatchesForLastSegmentOfPattern(name_52); + if (!matches) { + continue; } - case 175 /* NewExpression */: - case 174 /* CallExpression */: { - var start = node.getStart(sourceFile); - if (node.parent.typeArguments && - ts.rangeContainsStartEnd(node.parent.typeArguments, start, node.getEnd())) { - return node.parent.typeArguments; - } - if (node.parent.arguments && - ts.rangeContainsStartEnd(node.parent.arguments, start, node.getEnd())) { - return node.parent.arguments; + for (var _i = 0, declarations_9 = declarations; _i < declarations_9.length; _i++) { + var declaration = declarations_9[_i]; + // It was a match! If the pattern has dots in it, then also see if the + // declaration container matches as well. + if (patternMatcher.patternContainsDots) { + var containers = getContainers(declaration); + if (!containers) { + return undefined; + } + matches = patternMatcher.getMatches(containers, name_52); + if (!matches) { + continue; + } } - break; + var fileName = sourceFile.fileName; + var matchKind = bestMatchKind(matches); + rawItems.push({ name: name_52, fileName: fileName, matchKind: matchKind, isCaseSensitive: allMatchesAreCaseSensitive(matches), declaration: declaration }); } } } - return undefined; - } - function getActualIndentationForListItem(node, sourceFile, options) { - var containingList = getContainingList(node, sourceFile); - return containingList ? getActualIndentationFromList(containingList) : -1 /* Unknown */; - function getActualIndentationFromList(list) { - var index = ts.indexOf(list, node); - return index !== -1 ? deriveActualIndentationFromList(list, index, sourceFile, options) : -1 /* Unknown */; - } - } - function getLineIndentationWhenExpressionIsInMultiLine(node, sourceFile, options) { - // actual indentation should not be used when: - // - node is close parenthesis - this is the end of the expression - if (node.kind === 18 /* CloseParenToken */) { - return -1 /* Unknown */; - } - if (node.parent && (node.parent.kind === 174 /* CallExpression */ || - node.parent.kind === 175 /* NewExpression */) && - node.parent.expression !== node) { - var fullCallOrNewExpression = node.parent.expression; - var startingExpression = getStartingExpression(fullCallOrNewExpression); - if (fullCallOrNewExpression === startingExpression) { - return -1 /* Unknown */; - } - var fullCallOrNewExpressionEnd = sourceFile.getLineAndCharacterOfPosition(fullCallOrNewExpression.end); - var startingExpressionEnd = sourceFile.getLineAndCharacterOfPosition(startingExpression.end); - if (fullCallOrNewExpressionEnd.line === startingExpressionEnd.line) { - return -1 /* Unknown */; - } - return findColumnForFirstNonWhitespaceCharacterInLine(fullCallOrNewExpressionEnd, sourceFile, options); + }); + // Remove imports when the imported declaration is already in the list and has the same name. + rawItems = ts.filter(rawItems, function (item) { + var decl = item.declaration; + if (decl.kind === 231 /* ImportClause */ || decl.kind === 234 /* ImportSpecifier */ || decl.kind === 229 /* ImportEqualsDeclaration */) { + var importer = checker.getSymbolAtLocation(decl.name); + var imported = checker.getAliasedSymbol(importer); + return importer.name !== imported.name; } - return -1 /* Unknown */; - function getStartingExpression(node) { - while (true) { - switch (node.kind) { - case 174 /* CallExpression */: - case 175 /* NewExpression */: - case 172 /* PropertyAccessExpression */: - case 173 /* ElementAccessExpression */: - node = node.expression; - break; - default: - return node; - } - } + else { + return true; } + }); + rawItems.sort(compareNavigateToItems); + if (maxResultCount !== undefined) { + rawItems = rawItems.slice(0, maxResultCount); } - function deriveActualIndentationFromList(list, index, sourceFile, options) { - ts.Debug.assert(index >= 0 && index < list.length); - var node = list[index]; - // walk toward the start of the list starting from current node and check if the line is the same for all items. - // if end line for item [i - 1] differs from the start line for item [i] - find column of the first non-whitespace character on the line of item [i] - var lineAndCharacter = getStartLineAndCharacterForNode(node, sourceFile); - for (var i = index - 1; i >= 0; i--) { - if (list[i].kind === 24 /* CommaToken */) { - continue; - } - // skip list items that ends on the same line with the current list element - var prevEndLine = sourceFile.getLineAndCharacterOfPosition(list[i].end).line; - if (prevEndLine !== lineAndCharacter.line) { - return findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options); + var items = ts.map(rawItems, createNavigateToItem); + return items; + function allMatchesAreCaseSensitive(matches) { + ts.Debug.assert(matches.length > 0); + // This is a case sensitive match, only if all the submatches were case sensitive. + for (var _i = 0, matches_2 = matches; _i < matches_2.length; _i++) { + var match = matches_2[_i]; + if (!match.isCaseSensitive) { + return false; } - lineAndCharacter = getStartLineAndCharacterForNode(list[i], sourceFile); } - return -1 /* Unknown */; + return true; } - function findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options) { - var lineStart = sourceFile.getPositionOfLineAndCharacter(lineAndCharacter.line, 0); - return findFirstNonWhitespaceColumn(lineStart, lineStart + lineAndCharacter.character, sourceFile, options); + function getTextOfIdentifierOrLiteral(node) { + if (node) { + if (node.kind === 69 /* Identifier */ || + node.kind === 9 /* StringLiteral */ || + node.kind === 8 /* NumericLiteral */) { + return node.text; + } + } + return undefined; } - /* - Character is the actual index of the character since the beginning of the line. - Column - position of the character after expanding tabs to spaces - "0\t2$" - value of 'character' for '$' is 3 - value of 'column' for '$' is 6 (assuming that tab size is 4) - */ - function findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options) { - var character = 0; - var column = 0; - for (var pos = startPos; pos < endPos; pos++) { - var ch = sourceFile.text.charCodeAt(pos); - if (!ts.isWhiteSpaceSingleLine(ch)) { - break; + function tryAddSingleDeclarationName(declaration, containers) { + if (declaration && declaration.name) { + var text = getTextOfIdentifierOrLiteral(declaration.name); + if (text !== undefined) { + containers.unshift(text); } - if (ch === 9 /* tab */) { - column += options.TabSize + (column % options.TabSize); + else if (declaration.name.kind === 140 /* ComputedPropertyName */) { + return tryAddComputedPropertyName(declaration.name.expression, containers, /*includeLastPortion*/ true); } else { - column++; + // Don't know how to add this. + return false; } - character++; } - return { column: column, character: character }; - } - SmartIndenter.findFirstNonWhitespaceCharacterAndColumn = findFirstNonWhitespaceCharacterAndColumn; - function findFirstNonWhitespaceColumn(startPos, endPos, sourceFile, options) { - return findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options).column; + return true; } - SmartIndenter.findFirstNonWhitespaceColumn = findFirstNonWhitespaceColumn; - function nodeContentIsAlwaysIndented(kind) { - switch (kind) { - case 202 /* ExpressionStatement */: - case 221 /* ClassDeclaration */: - case 192 /* ClassExpression */: - case 222 /* InterfaceDeclaration */: - case 224 /* EnumDeclaration */: - case 223 /* TypeAliasDeclaration */: - case 170 /* ArrayLiteralExpression */: - case 199 /* Block */: - case 226 /* ModuleBlock */: - case 171 /* ObjectLiteralExpression */: - case 159 /* TypeLiteral */: - case 161 /* TupleType */: - case 227 /* CaseBlock */: - case 250 /* DefaultClause */: - case 249 /* CaseClause */: - case 178 /* ParenthesizedExpression */: - case 172 /* PropertyAccessExpression */: - case 174 /* CallExpression */: - case 175 /* NewExpression */: - case 200 /* VariableStatement */: - case 218 /* VariableDeclaration */: - case 235 /* ExportAssignment */: - case 211 /* ReturnStatement */: - case 188 /* ConditionalExpression */: - case 168 /* ArrayBindingPattern */: - case 167 /* ObjectBindingPattern */: - case 243 /* JsxOpeningElement */: - case 242 /* JsxSelfClosingElement */: - case 248 /* JsxExpression */: - case 146 /* MethodSignature */: - case 151 /* CallSignature */: - case 152 /* ConstructSignature */: - case 142 /* Parameter */: - case 156 /* FunctionType */: - case 157 /* ConstructorType */: - case 164 /* ParenthesizedType */: - case 176 /* TaggedTemplateExpression */: - case 184 /* AwaitExpression */: - case 237 /* NamedExports */: - case 233 /* NamedImports */: - case 238 /* ExportSpecifier */: - case 234 /* ImportSpecifier */: - return true; + // Only added the names of computed properties if they're simple dotted expressions, like: + // + // [X.Y.Z]() { } + function tryAddComputedPropertyName(expression, containers, includeLastPortion) { + var text = getTextOfIdentifierOrLiteral(expression); + if (text !== undefined) { + if (includeLastPortion) { + containers.unshift(text); + } + return true; + } + if (expression.kind === 172 /* PropertyAccessExpression */) { + var propertyAccess = expression; + if (includeLastPortion) { + containers.unshift(propertyAccess.name.text); + } + return tryAddComputedPropertyName(propertyAccess.expression, containers, /*includeLastPortion*/ true); } return false; } - /* @internal */ - function nodeWillIndentChild(parent, child, indentByDefault) { - var childKind = child ? child.kind : 0 /* Unknown */; - switch (parent.kind) { - case 204 /* DoStatement */: - case 205 /* WhileStatement */: - case 207 /* ForInStatement */: - case 208 /* ForOfStatement */: - case 206 /* ForStatement */: - case 203 /* IfStatement */: - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - case 147 /* MethodDeclaration */: - case 180 /* ArrowFunction */: - case 148 /* Constructor */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - return childKind !== 199 /* Block */; - case 236 /* ExportDeclaration */: - return childKind !== 237 /* NamedExports */; - case 230 /* ImportDeclaration */: - return childKind !== 231 /* ImportClause */ || - (child.namedBindings && child.namedBindings.kind !== 233 /* NamedImports */); - case 241 /* JsxElement */: - return childKind !== 245 /* JsxClosingElement */; + function getContainers(declaration) { + var containers = []; + // First, if we started with a computed property name, then add all but the last + // portion into the container array. + if (declaration.name.kind === 140 /* ComputedPropertyName */) { + if (!tryAddComputedPropertyName(declaration.name.expression, containers, /*includeLastPortion*/ false)) { + return undefined; + } } - // No explicit rule for given nodes so the result will follow the default value argument - return indentByDefault; - } - SmartIndenter.nodeWillIndentChild = nodeWillIndentChild; - /* - Function returns true when the parent node should indent the given child by an explicit rule - */ - function shouldIndentChildNode(parent, child) { - return nodeContentIsAlwaysIndented(parent.kind) || nodeWillIndentChild(parent, child, /*indentByDefault*/ false); - } - SmartIndenter.shouldIndentChildNode = shouldIndentChildNode; - })(SmartIndenter = formatting.SmartIndenter || (formatting.SmartIndenter = {})); - })(formatting = ts.formatting || (ts.formatting = {})); -})(ts || (ts = {})); -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -var ts; -(function (ts) { - /** The version of the language service API */ - ts.servicesVersion = "0.5"; - var scanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ true); - var emptyArray = []; - var jsDocTagNames = [ - "augments", - "author", - "argument", - "borrows", - "class", - "constant", - "constructor", - "constructs", - "default", - "deprecated", - "description", - "event", - "example", - "extends", - "field", - "fileOverview", - "function", - "ignore", - "inner", - "lends", - "link", - "memberOf", - "name", - "namespace", - "param", - "private", - "property", - "public", - "requires", - "returns", - "see", - "since", - "static", - "throws", - "type", - "typedef", - "property", - "prop", - "version" - ]; - var jsDocCompletionEntries; - function createNode(kind, pos, end, parent) { - var node = kind >= 139 /* FirstNode */ ? new NodeObject(kind, pos, end) : - kind === 69 /* Identifier */ ? new IdentifierObject(kind, pos, end) : - new TokenObject(kind, pos, end); - node.parent = parent; - return node; - } - var NodeObject = (function () { - function NodeObject(kind, pos, end) { - this.pos = pos; - this.end = end; - this.flags = 0 /* None */; - this.parent = undefined; - this.kind = kind; - } - NodeObject.prototype.getSourceFile = function () { - return ts.getSourceFileOfNode(this); - }; - NodeObject.prototype.getStart = function (sourceFile, includeJsDocComment) { - return ts.getTokenPosOfNode(this, sourceFile, includeJsDocComment); - }; - NodeObject.prototype.getFullStart = function () { - return this.pos; - }; - NodeObject.prototype.getEnd = function () { - return this.end; - }; - NodeObject.prototype.getWidth = function (sourceFile) { - return this.getEnd() - this.getStart(sourceFile); - }; - NodeObject.prototype.getFullWidth = function () { - return this.end - this.pos; - }; - NodeObject.prototype.getLeadingTriviaWidth = function (sourceFile) { - return this.getStart(sourceFile) - this.pos; - }; - NodeObject.prototype.getFullText = function (sourceFile) { - return (sourceFile || this.getSourceFile()).text.substring(this.pos, this.end); - }; - NodeObject.prototype.getText = function (sourceFile) { - return (sourceFile || this.getSourceFile()).text.substring(this.getStart(), this.getEnd()); - }; - NodeObject.prototype.addSyntheticNodes = function (nodes, pos, end, useJSDocScanner) { - scanner.setTextPos(pos); - while (pos < end) { - var token = useJSDocScanner ? scanner.scanJSDocToken() : scanner.scan(); - var textPos = scanner.getTextPos(); - if (textPos <= end) { - nodes.push(createNode(token, pos, textPos, this)); + // Now, walk up our containers, adding all their names to the container array. + declaration = ts.getContainerNode(declaration); + while (declaration) { + if (!tryAddSingleDeclarationName(declaration, containers)) { + return undefined; + } + declaration = ts.getContainerNode(declaration); } - pos = textPos; + return containers; } - return pos; - }; - NodeObject.prototype.createSyntaxList = function (nodes) { - var list = createNode(286 /* SyntaxList */, nodes.pos, nodes.end, this); - list._children = []; - var pos = nodes.pos; - for (var _i = 0, nodes_4 = nodes; _i < nodes_4.length; _i++) { - var node = nodes_4[_i]; - if (pos < node.pos) { - pos = this.addSyntheticNodes(list._children, pos, node.pos); + function bestMatchKind(matches) { + ts.Debug.assert(matches.length > 0); + var bestMatchKind = ts.PatternMatchKind.camelCase; + for (var _i = 0, matches_3 = matches; _i < matches_3.length; _i++) { + var match = matches_3[_i]; + var kind = match.kind; + if (kind < bestMatchKind) { + bestMatchKind = kind; + } } - list._children.push(node); - pos = node.end; + return bestMatchKind; } - if (pos < nodes.end) { - this.addSyntheticNodes(list._children, pos, nodes.end); + function compareNavigateToItems(i1, i2) { + // TODO(cyrusn): get the gamut of comparisons that VS already uses here. + // Right now we just sort by kind first, and then by name of the item. + // We first sort case insensitively. So "Aaa" will come before "bar". + // Then we sort case sensitively, so "aaa" will come before "Aaa". + return i1.matchKind - i2.matchKind || + i1.name.localeCompare(i2.name, undefined, baseSensitivity) || + i1.name.localeCompare(i2.name); } - return list; - }; - NodeObject.prototype.createChildren = function (sourceFile) { - var _this = this; - var children; - if (this.kind >= 139 /* FirstNode */) { - scanner.setText((sourceFile || this.getSourceFile()).text); - children = []; - var pos_3 = this.pos; - var useJSDocScanner_1 = this.kind >= 273 /* FirstJSDocTagNode */ && this.kind <= 285 /* LastJSDocTagNode */; - var processNode = function (node) { - var isJSDocTagNode = ts.isJSDocTag(node); - if (!isJSDocTagNode && pos_3 < node.pos) { - pos_3 = _this.addSyntheticNodes(children, pos_3, node.pos, useJSDocScanner_1); - } - children.push(node); - if (!isJSDocTagNode) { - pos_3 = node.end; - } - }; - var processNodes = function (nodes) { - if (pos_3 < nodes.pos) { - pos_3 = _this.addSyntheticNodes(children, pos_3, nodes.pos, useJSDocScanner_1); - } - children.push(_this.createSyntaxList(nodes)); - pos_3 = nodes.end; + function createNavigateToItem(rawItem) { + var declaration = rawItem.declaration; + var container = ts.getContainerNode(declaration); + return { + name: rawItem.name, + kind: ts.getNodeKind(declaration), + kindModifiers: ts.getNodeModifiers(declaration), + matchKind: ts.PatternMatchKind[rawItem.matchKind], + isCaseSensitive: rawItem.isCaseSensitive, + fileName: rawItem.fileName, + textSpan: ts.createTextSpanFromBounds(declaration.getStart(), declaration.getEnd()), + // TODO(jfreeman): What should be the containerName when the container has a computed name? + containerName: container && container.name ? container.name.text : "", + containerKind: container && container.name ? ts.getNodeKind(container) : "" }; - // jsDocComments need to be the first children - if (this.jsDocComments) { - for (var _i = 0, _a = this.jsDocComments; _i < _a.length; _i++) { - var jsDocComment = _a[_i]; - processNode(jsDocComment); - } - } - ts.forEachChild(this, processNode, processNodes); - if (pos_3 < this.end) { - this.addSyntheticNodes(children, pos_3, this.end); - } - scanner.setText(undefined); } - this._children = children || emptyArray; - }; - NodeObject.prototype.getChildCount = function (sourceFile) { - if (!this._children) - this.createChildren(sourceFile); - return this._children.length; - }; - NodeObject.prototype.getChildAt = function (index, sourceFile) { - if (!this._children) - this.createChildren(sourceFile); - return this._children[index]; - }; - NodeObject.prototype.getChildren = function (sourceFile) { - if (!this._children) - this.createChildren(sourceFile); - return this._children; - }; - NodeObject.prototype.getFirstToken = function (sourceFile) { - var children = this.getChildren(sourceFile); - if (!children.length) { - return undefined; + } + NavigateTo.getNavigateToItems = getNavigateToItems; + })(NavigateTo = ts.NavigateTo || (ts.NavigateTo = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var NavigationBar; + (function (NavigationBar) { + function getNavigationBarItems(sourceFile) { + curSourceFile = sourceFile; + var result = ts.map(topLevelItems(rootNavigationBarNode(sourceFile)), convertToTopLevelItem); + curSourceFile = undefined; + return result; + } + NavigationBar.getNavigationBarItems = getNavigationBarItems; + // Keep sourceFile handy so we don't have to search for it every time we need to call `getText`. + var curSourceFile; + function nodeText(node) { + return node.getText(curSourceFile); + } + function navigationBarNodeKind(n) { + return n.node.kind; + } + function pushChild(parent, child) { + if (parent.children) { + parent.children.push(child); } - var child = children[0]; - return child.kind < 139 /* FirstNode */ ? child : child.getFirstToken(sourceFile); - }; - NodeObject.prototype.getLastToken = function (sourceFile) { - var children = this.getChildren(sourceFile); - var child = ts.lastOrUndefined(children); - if (!child) { - return undefined; + else { + parent.children = [child]; } - return child.kind < 139 /* FirstNode */ ? child : child.getLastToken(sourceFile); - }; - return NodeObject; - }()); - var TokenOrIdentifierObject = (function () { - function TokenOrIdentifierObject(pos, end) { - // Set properties in same order as NodeObject - this.pos = pos; - this.end = end; - this.flags = 0 /* None */; - this.parent = undefined; } - TokenOrIdentifierObject.prototype.getSourceFile = function () { - return ts.getSourceFileOfNode(this); - }; - TokenOrIdentifierObject.prototype.getStart = function (sourceFile, includeJsDocComment) { - return ts.getTokenPosOfNode(this, sourceFile, includeJsDocComment); - }; - TokenOrIdentifierObject.prototype.getFullStart = function () { - return this.pos; - }; - TokenOrIdentifierObject.prototype.getEnd = function () { - return this.end; - }; - TokenOrIdentifierObject.prototype.getWidth = function (sourceFile) { - return this.getEnd() - this.getStart(sourceFile); - }; - TokenOrIdentifierObject.prototype.getFullWidth = function () { - return this.end - this.pos; - }; - TokenOrIdentifierObject.prototype.getLeadingTriviaWidth = function (sourceFile) { - return this.getStart(sourceFile) - this.pos; - }; - TokenOrIdentifierObject.prototype.getFullText = function (sourceFile) { - return (sourceFile || this.getSourceFile()).text.substring(this.pos, this.end); - }; - TokenOrIdentifierObject.prototype.getText = function (sourceFile) { - return (sourceFile || this.getSourceFile()).text.substring(this.getStart(), this.getEnd()); - }; - TokenOrIdentifierObject.prototype.getChildCount = function (sourceFile) { - return 0; - }; - TokenOrIdentifierObject.prototype.getChildAt = function (index, sourceFile) { - return undefined; - }; - TokenOrIdentifierObject.prototype.getChildren = function (sourceFile) { - return emptyArray; - }; - TokenOrIdentifierObject.prototype.getFirstToken = function (sourceFile) { - return undefined; - }; - TokenOrIdentifierObject.prototype.getLastToken = function (sourceFile) { - return undefined; - }; - return TokenOrIdentifierObject; - }()); - var TokenObject = (function (_super) { - __extends(TokenObject, _super); - function TokenObject(kind, pos, end) { - _super.call(this, pos, end); - this.kind = kind; + /* + For performance, we keep navigation bar parents on a stack rather than passing them through each recursion. + `parent` is the current parent and is *not* stored in parentsStack. + `startNode` sets a new parent and `endNode` returns to the previous parent. + */ + var parentsStack = []; + var parent; + function rootNavigationBarNode(sourceFile) { + ts.Debug.assert(!parentsStack.length); + var root = { node: sourceFile, additionalNodes: undefined, parent: undefined, children: undefined, indent: 0 }; + parent = root; + for (var _i = 0, _a = sourceFile.statements; _i < _a.length; _i++) { + var statement = _a[_i]; + addChildrenRecursively(statement); + } + endNode(); + ts.Debug.assert(!parent && !parentsStack.length); + return root; } - return TokenObject; - }(TokenOrIdentifierObject)); - var IdentifierObject = (function (_super) { - __extends(IdentifierObject, _super); - function IdentifierObject(kind, pos, end) { - _super.call(this, pos, end); + function addLeafNode(node) { + pushChild(parent, emptyNavigationBarNode(node)); } - return IdentifierObject; - }(TokenOrIdentifierObject)); - IdentifierObject.prototype.kind = 69 /* Identifier */; - var SymbolObject = (function () { - function SymbolObject(flags, name) { - this.flags = flags; - this.name = name; + function emptyNavigationBarNode(node) { + return { + node: node, + additionalNodes: undefined, + parent: parent, + children: undefined, + indent: parent.indent + 1 + }; } - SymbolObject.prototype.getFlags = function () { - return this.flags; - }; - SymbolObject.prototype.getName = function () { - return this.name; - }; - SymbolObject.prototype.getDeclarations = function () { - return this.declarations; - }; - SymbolObject.prototype.getDocumentationComment = function () { - if (this.documentationComment === undefined) { - this.documentationComment = getJsDocCommentsFromDeclarations(this.declarations, this.name, !(this.flags & 4 /* Property */)); + /** + * Add a new level of NavigationBarNodes. + * This pushes to the stack, so you must call `endNode` when you are done adding to this node. + */ + function startNode(node) { + var navNode = emptyNavigationBarNode(node); + pushChild(parent, navNode); + // Save the old parent + parentsStack.push(parent); + parent = navNode; + } + /** Call after calling `startNode` and adding children to it. */ + function endNode() { + if (parent.children) { + mergeChildren(parent.children); + sortChildren(parent.children); } - return this.documentationComment; - }; - return SymbolObject; - }()); - function getJsDocCommentsFromDeclarations(declarations, name, canUseParsedParamTagComments) { - var documentationComment = []; - var docComments = getJsDocCommentsSeparatedByNewLines(); - ts.forEach(docComments, function (docComment) { - if (documentationComment.length) { - documentationComment.push(ts.lineBreakPart()); - } - documentationComment.push(docComment); - }); - return documentationComment; - function getJsDocCommentsSeparatedByNewLines() { - var paramTag = "@param"; - var jsDocCommentParts = []; - ts.forEach(declarations, function (declaration, indexOfDeclaration) { - // Make sure we are collecting doc comment from declaration once, - // In case of union property there might be same declaration multiple times - // which only varies in type parameter - // Eg. const a: Array | Array; a.length - // The property length will have two declarations of property length coming - // from Array - Array and Array - if (ts.indexOf(declarations, declaration) === indexOfDeclaration) { - var sourceFileOfDeclaration = ts.getSourceFileOfNode(declaration); - // If it is parameter - try and get the jsDoc comment with @param tag from function declaration's jsDoc comments - if (canUseParsedParamTagComments && declaration.kind === 142 /* Parameter */) { - if ((declaration.parent.kind === 179 /* FunctionExpression */ || declaration.parent.kind === 180 /* ArrowFunction */) && - declaration.parent.parent.kind === 218 /* VariableDeclaration */) { - addCommentParts(declaration.parent.parent.parent, sourceFileOfDeclaration, getCleanedParamJsDocComment); - } - addCommentParts(declaration.parent, sourceFileOfDeclaration, getCleanedParamJsDocComment); - } - // If this is left side of dotted module declaration, there is no doc comments associated with this node - if (declaration.kind === 225 /* ModuleDeclaration */ && declaration.body && declaration.body.kind === 225 /* ModuleDeclaration */) { - return; + parent = parentsStack.pop(); + } + function addNodeWithRecursiveChild(node, child) { + startNode(node); + addChildrenRecursively(child); + endNode(); + } + /** Look for navigation bar items in node's subtree, adding them to the current `parent`. */ + function addChildrenRecursively(node) { + if (!node || ts.isToken(node)) { + return; + } + switch (node.kind) { + case 148 /* Constructor */: + // Get parameter properties, and treat them as being on the *same* level as the constructor, not under it. + var ctr = node; + addNodeWithRecursiveChild(ctr, ctr.body); + // Parameter properties are children of the class, not the constructor. + for (var _i = 0, _a = ctr.parameters; _i < _a.length; _i++) { + var param = _a[_i]; + if (ts.isParameterPropertyDeclaration(param)) { + addLeafNode(param); + } + } + break; + case 147 /* MethodDeclaration */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 146 /* MethodSignature */: + if (!ts.hasDynamicName(node)) { + addNodeWithRecursiveChild(node, node.body); + } + break; + case 145 /* PropertyDeclaration */: + case 144 /* PropertySignature */: + if (!ts.hasDynamicName(node)) { + addLeafNode(node); + } + break; + case 231 /* ImportClause */: + var importClause = node; + // Handle default import case e.g.: + // import d from "mod"; + if (importClause.name) { + addLeafNode(importClause); + } + // Handle named bindings in imports e.g.: + // import * as NS from "mod"; + // import {a, b as B} from "mod"; + var namedBindings = importClause.namedBindings; + if (namedBindings) { + if (namedBindings.kind === 232 /* NamespaceImport */) { + addLeafNode(namedBindings); + } + else { + for (var _b = 0, _c = namedBindings.elements; _b < _c.length; _b++) { + var element = _c[_b]; + addLeafNode(element); + } + } + } + break; + case 169 /* BindingElement */: + case 218 /* VariableDeclaration */: + var decl = node; + var name_53 = decl.name; + if (ts.isBindingPattern(name_53)) { + addChildrenRecursively(name_53); + } + else if (decl.initializer && isFunctionOrClassExpression(decl.initializer)) { + // For `const x = function() {}`, just use the function node, not the const. + addChildrenRecursively(decl.initializer); + } + else { + addNodeWithRecursiveChild(decl, decl.initializer); } - if ((declaration.kind === 179 /* FunctionExpression */ || declaration.kind === 180 /* ArrowFunction */) && - declaration.parent.kind === 218 /* VariableDeclaration */) { - addCommentParts(declaration.parent.parent, sourceFileOfDeclaration, getCleanedJsDocComment); + break; + case 180 /* ArrowFunction */: + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + addNodeWithRecursiveChild(node, node.body); + break; + case 224 /* EnumDeclaration */: + startNode(node); + for (var _d = 0, _e = node.members; _d < _e.length; _d++) { + var member = _e[_d]; + if (!isComputedProperty(member)) { + addLeafNode(member); + } } - // If this is dotted module name, get the doc comments from the parent - while (declaration.kind === 225 /* ModuleDeclaration */ && declaration.parent.kind === 225 /* ModuleDeclaration */) { - declaration = declaration.parent; + endNode(); + break; + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + case 222 /* InterfaceDeclaration */: + startNode(node); + for (var _f = 0, _g = node.members; _f < _g.length; _f++) { + var member = _g[_f]; + addChildrenRecursively(member); } - addCommentParts(declaration.kind === 218 /* VariableDeclaration */ ? declaration.parent.parent : declaration, sourceFileOfDeclaration, getCleanedJsDocComment); - if (declaration.kind === 218 /* VariableDeclaration */) { - var init = declaration.initializer; - if (init && (init.kind === 179 /* FunctionExpression */ || init.kind === 180 /* ArrowFunction */)) { - // Get the cleaned js doc comment text from the initializer - addCommentParts(init, sourceFileOfDeclaration, getCleanedJsDocComment); + endNode(); + break; + case 225 /* ModuleDeclaration */: + addNodeWithRecursiveChild(node, getInteriorModule(node).body); + break; + case 238 /* ExportSpecifier */: + case 229 /* ImportEqualsDeclaration */: + case 153 /* IndexSignature */: + case 151 /* CallSignature */: + case 152 /* ConstructSignature */: + case 223 /* TypeAliasDeclaration */: + addLeafNode(node); + break; + default: + ts.forEach(node.jsDocComments, function (jsDocComment) { + ts.forEach(jsDocComment.tags, function (tag) { + if (tag.kind === 279 /* JSDocTypedefTag */) { + addLeafNode(tag); + } + }); + }); + ts.forEachChild(node, addChildrenRecursively); + } + } + /** Merge declarations of the same kind. */ + function mergeChildren(children) { + var nameToItems = ts.createMap(); + ts.filterMutate(children, function (child) { + var decl = child.node; + var name = decl.name && nodeText(decl.name); + if (!name) { + // Anonymous items are never merged. + return true; + } + var itemsWithSameName = nameToItems[name]; + if (!itemsWithSameName) { + nameToItems[name] = child; + return true; + } + if (itemsWithSameName instanceof Array) { + for (var _i = 0, itemsWithSameName_1 = itemsWithSameName; _i < itemsWithSameName_1.length; _i++) { + var itemWithSameName = itemsWithSameName_1[_i]; + if (tryMerge(itemWithSameName, child)) { + return false; } } + itemsWithSameName.push(child); + return true; + } + else { + var itemWithSameName = itemsWithSameName; + if (tryMerge(itemWithSameName, child)) { + return false; + } + nameToItems[name] = [itemWithSameName, child]; + return true; + } + function tryMerge(a, b) { + if (shouldReallyMerge(a.node, b.node)) { + merge(a, b); + return true; + } + return false; } }); - return jsDocCommentParts; - function addCommentParts(commented, sourceFileOfDeclaration, getCommentPart) { - var ranges = getJsDocCommentTextRange(commented, sourceFileOfDeclaration); - // Get the cleaned js doc comment text from the declaration - ts.forEach(ranges, function (jsDocCommentTextRange) { - var cleanedComment = getCommentPart(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); - if (cleanedComment) { - ts.addRange(jsDocCommentParts, cleanedComment); + /** a and b have the same name, but they may not be mergeable. */ + function shouldReallyMerge(a, b) { + return a.kind === b.kind && (a.kind !== 225 /* ModuleDeclaration */ || areSameModule(a, b)); + // We use 1 NavNode to represent 'A.B.C', but there are multiple source nodes. + // Only merge module nodes that have the same chain. Don't merge 'A.B.C' with 'A'! + function areSameModule(a, b) { + if (a.body.kind !== b.body.kind) { + return false; } - }); - } - function getJsDocCommentTextRange(node, sourceFile) { - return ts.map(ts.getJsDocComments(node, sourceFile), function (jsDocComment) { - return { - pos: jsDocComment.pos + "/*".length, - end: jsDocComment.end - "*/".length // Trim off comment end indicator - }; - }); + if (a.body.kind !== 225 /* ModuleDeclaration */) { + return true; + } + return areSameModule(a.body, b.body); + } } - function consumeWhiteSpacesOnTheLine(pos, end, sourceFile, maxSpacesToRemove) { - if (maxSpacesToRemove !== undefined) { - end = Math.min(end, pos + maxSpacesToRemove); + /** Merge source into target. Source should be thrown away after this is called. */ + function merge(target, source) { + target.additionalNodes = target.additionalNodes || []; + target.additionalNodes.push(source.node); + if (source.additionalNodes) { + (_a = target.additionalNodes).push.apply(_a, source.additionalNodes); } - for (; pos < end; pos++) { - var ch = sourceFile.text.charCodeAt(pos); - if (!ts.isWhiteSpaceSingleLine(ch)) { - return pos; - } + target.children = ts.concatenate(target.children, source.children); + if (target.children) { + mergeChildren(target.children); + sortChildren(target.children); } - return end; + var _a; } - function consumeLineBreaks(pos, end, sourceFile) { - while (pos < end && ts.isLineBreak(sourceFile.text.charCodeAt(pos))) { - pos++; + } + /** Recursively ensure that each NavNode's children are in sorted order. */ + function sortChildren(children) { + children.sort(compareChildren); + } + function compareChildren(child1, child2) { + var name1 = tryGetName(child1.node), name2 = tryGetName(child2.node); + if (name1 && name2) { + var cmp = localeCompareFix(name1, name2); + return cmp !== 0 ? cmp : navigationBarNodeKind(child1) - navigationBarNodeKind(child2); + } + else { + return name1 ? 1 : name2 ? -1 : navigationBarNodeKind(child1) - navigationBarNodeKind(child2); + } + } + // More efficient to create a collator once and use its `compare` than to call `a.localeCompare(b)` many times. + var collator = typeof Intl === "undefined" ? undefined : new Intl.Collator(); + // Intl is missing in Safari, and node 0.10 treats "a" as greater than "B". + var localeCompareIsCorrect = collator && collator.compare("a", "B") < 0; + var localeCompareFix = localeCompareIsCorrect ? collator.compare : function (a, b) { + // This isn't perfect, but it passes all of our tests. + for (var i = 0; i < Math.min(a.length, b.length); i++) { + var chA = a.charAt(i), chB = b.charAt(i); + if (chA === "\"" && chB === "'") { + return 1; + } + if (chA === "'" && chB === "\"") { + return -1; + } + var cmp = chA.toLocaleLowerCase().localeCompare(chB.toLocaleLowerCase()); + if (cmp !== 0) { + return cmp; } - return pos; } - function isName(pos, end, sourceFile, name) { - return pos + name.length < end && - sourceFile.text.substr(pos, name.length) === name && - ts.isWhiteSpace(sourceFile.text.charCodeAt(pos + name.length)); + return a.length - b.length; + }; + /** + * This differs from getItemName because this is just used for sorting. + * We only sort nodes by name that have a more-or-less "direct" name, as opposed to `new()` and the like. + * So `new()` can still come before an `aardvark` method. + */ + function tryGetName(node) { + if (node.kind === 225 /* ModuleDeclaration */) { + return getModuleName(node); + } + var decl = node; + if (decl.name) { + return ts.getPropertyNameForPropertyNameNode(decl.name); + } + switch (node.kind) { + case 179 /* FunctionExpression */: + case 180 /* ArrowFunction */: + case 192 /* ClassExpression */: + return getFunctionOrClassName(node); + case 279 /* JSDocTypedefTag */: + return getJSDocTypedefTagName(node); + default: + return undefined; } - function isParamTag(pos, end, sourceFile) { - // If it is @param tag - return isName(pos, end, sourceFile, paramTag); + } + function getItemName(node) { + if (node.kind === 225 /* ModuleDeclaration */) { + return getModuleName(node); } - function pushDocCommentLineText(docComments, text, blankLineCount) { - // Add the empty lines in between texts - while (blankLineCount) { - blankLineCount--; - docComments.push(ts.textPart("")); + var name = node.name; + if (name) { + var text = nodeText(name); + if (text.length > 0) { + return text; } - docComments.push(ts.textPart(text)); } - function getCleanedJsDocComment(pos, end, sourceFile) { - var spacesToRemoveAfterAsterisk; - var docComments = []; - var blankLineCount = 0; - var isInParamTag = false; - while (pos < end) { - var docCommentTextOfLine = ""; - // First consume leading white space - pos = consumeWhiteSpacesOnTheLine(pos, end, sourceFile); - // If the comment starts with '*' consume the spaces on this line - if (pos < end && sourceFile.text.charCodeAt(pos) === 42 /* asterisk */) { - var lineStartPos = pos + 1; - pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, spacesToRemoveAfterAsterisk); - // Set the spaces to remove after asterisk as margin if not already set - if (spacesToRemoveAfterAsterisk === undefined && pos < end && !ts.isLineBreak(sourceFile.text.charCodeAt(pos))) { - spacesToRemoveAfterAsterisk = pos - lineStartPos; - } - } - else if (spacesToRemoveAfterAsterisk === undefined) { - spacesToRemoveAfterAsterisk = 0; - } - // Analyze text on this line - while (pos < end && !ts.isLineBreak(sourceFile.text.charCodeAt(pos))) { - var ch = sourceFile.text.charAt(pos); - if (ch === "@") { - // If it is @param tag - if (isParamTag(pos, end, sourceFile)) { - isInParamTag = true; - pos += paramTag.length; - continue; - } - else { - isInParamTag = false; - } - } - // Add the ch to doc text if we arent in param tag - if (!isInParamTag) { - docCommentTextOfLine += ch; - } - // Scan next character - pos++; - } - // Continue with next line - pos = consumeLineBreaks(pos, end, sourceFile); - if (docCommentTextOfLine) { - pushDocCommentLineText(docComments, docCommentTextOfLine, blankLineCount); - blankLineCount = 0; + switch (node.kind) { + case 256 /* SourceFile */: + var sourceFile = node; + return ts.isExternalModule(sourceFile) + ? "\"" + ts.escapeString(ts.getBaseFileName(ts.removeFileExtension(ts.normalizePath(sourceFile.fileName)))) + "\"" + : ""; + case 180 /* ArrowFunction */: + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + if (ts.getModifierFlags(node) & 512 /* Default */) { + return "default"; } - else if (!isInParamTag && docComments.length) { - // This is blank line when there is text already parsed - blankLineCount++; + return getFunctionOrClassName(node); + case 148 /* Constructor */: + return "constructor"; + case 152 /* ConstructSignature */: + return "new()"; + case 151 /* CallSignature */: + return "()"; + case 153 /* IndexSignature */: + return "[]"; + case 279 /* JSDocTypedefTag */: + return getJSDocTypedefTagName(node); + default: + return ""; + } + } + function getJSDocTypedefTagName(node) { + if (node.name) { + return node.name.text; + } + else { + var parentNode = node.parent && node.parent.parent; + if (parentNode && parentNode.kind === 200 /* VariableStatement */) { + if (parentNode.declarationList.declarations.length > 0) { + var nameIdentifier = parentNode.declarationList.declarations[0].name; + if (nameIdentifier.kind === 69 /* Identifier */) { + return nameIdentifier.text; + } } } - return docComments; + return ""; } - function getCleanedParamJsDocComment(pos, end, sourceFile) { - var paramHelpStringMargin; - var paramDocComments = []; - while (pos < end) { - if (isParamTag(pos, end, sourceFile)) { - var blankLineCount = 0; - var recordedParamTag = false; - // Consume leading spaces - pos = consumeWhiteSpaces(pos + paramTag.length); - if (pos >= end) { - break; - } - // Ignore type expression - if (sourceFile.text.charCodeAt(pos) === 123 /* openBrace */) { - pos++; - for (var curlies = 1; pos < end; pos++) { - var charCode = sourceFile.text.charCodeAt(pos); - // { character means we need to find another } to match the found one - if (charCode === 123 /* openBrace */) { - curlies++; - continue; - } - // } char - if (charCode === 125 /* closeBrace */) { - curlies--; - if (curlies === 0) { - // We do not have any more } to match the type expression is ignored completely - pos++; - break; - } - else { - // there are more { to be matched with } - continue; - } - } - // Found start of another tag - if (charCode === 64 /* at */) { - break; - } - } - // Consume white spaces - pos = consumeWhiteSpaces(pos); - if (pos >= end) { - break; - } - } - // Parameter name - if (isName(pos, end, sourceFile, name)) { - // Found the parameter we are looking for consume white spaces - pos = consumeWhiteSpaces(pos + name.length); - if (pos >= end) { - break; - } - var paramHelpString = ""; - var firstLineParamHelpStringPos = pos; - while (pos < end) { - var ch = sourceFile.text.charCodeAt(pos); - // at line break, set this comment line text and go to next line - if (ts.isLineBreak(ch)) { - if (paramHelpString) { - pushDocCommentLineText(paramDocComments, paramHelpString, blankLineCount); - paramHelpString = ""; - blankLineCount = 0; - recordedParamTag = true; - } - else if (recordedParamTag) { - blankLineCount++; - } - // Get the pos after cleaning start of the line - setPosForParamHelpStringOnNextLine(firstLineParamHelpStringPos); - continue; - } - // Done scanning param help string - next tag found - if (ch === 64 /* at */) { - break; - } - paramHelpString += sourceFile.text.charAt(pos); - // Go to next character - pos++; - } - // If there is param help text, add it top the doc comments - if (paramHelpString) { - pushDocCommentLineText(paramDocComments, paramHelpString, blankLineCount); - } - paramHelpStringMargin = undefined; - } - // If this is the start of another tag, continue with the loop in search of param tag with symbol name - if (sourceFile.text.charCodeAt(pos) === 64 /* at */) { - continue; + } + /** Flattens the NavNode tree to a list, keeping only the top-level items. */ + function topLevelItems(root) { + var topLevel = []; + function recur(item) { + if (isTopLevel(item)) { + topLevel.push(item); + if (item.children) { + for (var _i = 0, _a = item.children; _i < _a.length; _i++) { + var child = _a[_i]; + recur(child); } } - // Next character - pos++; } - return paramDocComments; - function consumeWhiteSpaces(pos) { - while (pos < end && ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(pos))) { - pos++; - } - return pos; + } + recur(root); + return topLevel; + function isTopLevel(item) { + switch (navigationBarNodeKind(item)) { + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + case 224 /* EnumDeclaration */: + case 222 /* InterfaceDeclaration */: + case 225 /* ModuleDeclaration */: + case 256 /* SourceFile */: + case 223 /* TypeAliasDeclaration */: + case 279 /* JSDocTypedefTag */: + return true; + case 148 /* Constructor */: + case 147 /* MethodDeclaration */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 218 /* VariableDeclaration */: + return hasSomeImportantChild(item); + case 180 /* ArrowFunction */: + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + return isTopLevelFunctionDeclaration(item); + default: + return false; } - function setPosForParamHelpStringOnNextLine(firstLineParamHelpStringPos) { - // Get the pos after consuming line breaks - pos = consumeLineBreaks(pos, end, sourceFile); - if (pos >= end) { - return; - } - if (paramHelpStringMargin === undefined) { - paramHelpStringMargin = sourceFile.getLineAndCharacterOfPosition(firstLineParamHelpStringPos).character; + function isTopLevelFunctionDeclaration(item) { + if (!item.node.body) { + return false; } - // Now consume white spaces max - var startOfLinePos = pos; - pos = consumeWhiteSpacesOnTheLine(pos, end, sourceFile, paramHelpStringMargin); - if (pos >= end) { - return; + switch (navigationBarNodeKind(item.parent)) { + case 226 /* ModuleBlock */: + case 256 /* SourceFile */: + case 147 /* MethodDeclaration */: + case 148 /* Constructor */: + return true; + default: + return hasSomeImportantChild(item); } - var consumedSpaces = pos - startOfLinePos; - if (consumedSpaces < paramHelpStringMargin) { - var ch = sourceFile.text.charCodeAt(pos); - if (ch === 42 /* asterisk */) { - // Consume more spaces after asterisk - pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, paramHelpStringMargin - consumedSpaces - 1); - } + } + function hasSomeImportantChild(item) { + return ts.forEach(item.children, function (child) { + var childKind = navigationBarNodeKind(child); + return childKind !== 218 /* VariableDeclaration */ && childKind !== 169 /* BindingElement */; + }); + } + } + } + // NavigationBarItem requires an array, but will not mutate it, so just give it this for performance. + var emptyChildItemArray = []; + function convertToTopLevelItem(n) { + return { + text: getItemName(n.node), + kind: ts.getNodeKind(n.node), + kindModifiers: ts.getNodeModifiers(n.node), + spans: getSpans(n), + childItems: ts.map(n.children, convertToChildItem) || emptyChildItemArray, + indent: n.indent, + bolded: false, + grayed: false + }; + function convertToChildItem(n) { + return { + text: getItemName(n.node), + kind: ts.getNodeKind(n.node), + kindModifiers: ts.getNodeModifiers(n.node), + spans: getSpans(n), + childItems: emptyChildItemArray, + indent: 0, + bolded: false, + grayed: false + }; + } + function getSpans(n) { + var spans = [getNodeSpan(n.node)]; + if (n.additionalNodes) { + for (var _i = 0, _a = n.additionalNodes; _i < _a.length; _i++) { + var node = _a[_i]; + spans.push(getNodeSpan(node)); } } + return spans; } } - } - var TypeObject = (function () { - function TypeObject(checker, flags) { - this.checker = checker; - this.flags = flags; + function getModuleName(moduleDeclaration) { + // We want to maintain quotation marks. + if (ts.isAmbientModule(moduleDeclaration)) { + return ts.getTextOfNode(moduleDeclaration.name); + } + // Otherwise, we need to aggregate each identifier to build up the qualified name. + var result = []; + result.push(moduleDeclaration.name.text); + while (moduleDeclaration.body && moduleDeclaration.body.kind === 225 /* ModuleDeclaration */) { + moduleDeclaration = moduleDeclaration.body; + result.push(moduleDeclaration.name.text); + } + return result.join("."); } - TypeObject.prototype.getFlags = function () { - return this.flags; - }; - TypeObject.prototype.getSymbol = function () { - return this.symbol; - }; - TypeObject.prototype.getProperties = function () { - return this.checker.getPropertiesOfType(this); - }; - TypeObject.prototype.getProperty = function (propertyName) { - return this.checker.getPropertyOfType(this, propertyName); - }; - TypeObject.prototype.getApparentProperties = function () { - return this.checker.getAugmentedPropertiesOfType(this); - }; - TypeObject.prototype.getCallSignatures = function () { - return this.checker.getSignaturesOfType(this, 0 /* Call */); - }; - TypeObject.prototype.getConstructSignatures = function () { - return this.checker.getSignaturesOfType(this, 1 /* Construct */); - }; - TypeObject.prototype.getStringIndexType = function () { - return this.checker.getIndexTypeOfType(this, 0 /* String */); - }; - TypeObject.prototype.getNumberIndexType = function () { - return this.checker.getIndexTypeOfType(this, 1 /* Number */); - }; - TypeObject.prototype.getBaseTypes = function () { - return this.flags & (32768 /* Class */ | 65536 /* Interface */) - ? this.checker.getBaseTypes(this) - : undefined; - }; - TypeObject.prototype.getNonNullableType = function () { - return this.checker.getNonNullableType(this); - }; - return TypeObject; - }()); - var SignatureObject = (function () { - function SignatureObject(checker) { - this.checker = checker; + /** + * For 'module A.B.C', we want to get the node for 'C'. + * We store 'A' as associated with a NavNode, and use getModuleName to traverse down again. + */ + function getInteriorModule(decl) { + return decl.body.kind === 225 /* ModuleDeclaration */ ? getInteriorModule(decl.body) : decl; } - SignatureObject.prototype.getDeclaration = function () { - return this.declaration; - }; - SignatureObject.prototype.getTypeParameters = function () { - return this.typeParameters; - }; - SignatureObject.prototype.getParameters = function () { - return this.parameters; - }; - SignatureObject.prototype.getReturnType = function () { - return this.checker.getReturnTypeOfSignature(this); - }; - SignatureObject.prototype.getDocumentationComment = function () { - if (this.documentationComment === undefined) { - this.documentationComment = this.declaration ? getJsDocCommentsFromDeclarations([this.declaration], - /*name*/ undefined, - /*canUseParsedParamTagComments*/ false) : []; + function isComputedProperty(member) { + return !member.name || member.name.kind === 140 /* ComputedPropertyName */; + } + function getNodeSpan(node) { + return node.kind === 256 /* SourceFile */ + ? ts.createTextSpanFromBounds(node.getFullStart(), node.getEnd()) + : ts.createTextSpanFromBounds(node.getStart(curSourceFile), node.getEnd()); + } + function getFunctionOrClassName(node) { + if (node.name && ts.getFullWidth(node.name) > 0) { + return ts.declarationNameToString(node.name); + } + else if (node.parent.kind === 218 /* VariableDeclaration */) { + return ts.declarationNameToString(node.parent.name); + } + else if (node.parent.kind === 187 /* BinaryExpression */ && + node.parent.operatorToken.kind === 56 /* EqualsToken */) { + return nodeText(node.parent.left); + } + else if (node.parent.kind === 253 /* PropertyAssignment */ && node.parent.name) { + return nodeText(node.parent.name); + } + else if (ts.getModifierFlags(node) & 512 /* Default */) { + return "default"; + } + else { + return ts.isClassLike(node) ? "" : ""; } - return this.documentationComment; - }; - return SignatureObject; - }()); - var SourceFileObject = (function (_super) { - __extends(SourceFileObject, _super); - function SourceFileObject(kind, pos, end) { - _super.call(this, kind, pos, end); } - SourceFileObject.prototype.update = function (newText, textChangeRange) { - return ts.updateSourceFile(this, newText, textChangeRange); - }; - SourceFileObject.prototype.getLineAndCharacterOfPosition = function (position) { - return ts.getLineAndCharacterOfPosition(this, position); - }; - SourceFileObject.prototype.getLineStarts = function () { - return ts.getLineStarts(this); - }; - SourceFileObject.prototype.getPositionOfLineAndCharacter = function (line, character) { - return ts.getPositionOfLineAndCharacter(this, line, character); - }; - SourceFileObject.prototype.getNamedDeclarations = function () { - if (!this.namedDeclarations) { - this.namedDeclarations = this.computeNamedDeclarations(); - } - return this.namedDeclarations; - }; - SourceFileObject.prototype.computeNamedDeclarations = function () { - var result = ts.createMap(); - ts.forEachChild(this, visit); - return result; - function addDeclaration(declaration) { - var name = getDeclarationName(declaration); - if (name) { - ts.multiMapAdd(result, name, declaration); + function isFunctionOrClassExpression(node) { + return node.kind === 179 /* FunctionExpression */ || node.kind === 180 /* ArrowFunction */ || node.kind === 192 /* ClassExpression */; + } + })(NavigationBar = ts.NavigationBar || (ts.NavigationBar = {})); +})(ts || (ts = {})); +/* @internal */ +var ts; +(function (ts) { + var OutliningElementsCollector; + (function (OutliningElementsCollector) { + function collectElements(sourceFile) { + var elements = []; + var collapseText = "..."; + function addOutliningSpan(hintSpanNode, startElement, endElement, autoCollapse) { + if (hintSpanNode && startElement && endElement) { + var span_12 = { + textSpan: ts.createTextSpanFromBounds(startElement.pos, endElement.end), + hintSpan: ts.createTextSpanFromBounds(hintSpanNode.getStart(), hintSpanNode.end), + bannerText: collapseText, + autoCollapse: autoCollapse + }; + elements.push(span_12); } } - function getDeclarations(name) { - return result[name] || (result[name] = []); + function addOutliningSpanComments(commentSpan, autoCollapse) { + if (commentSpan) { + var span_13 = { + textSpan: ts.createTextSpanFromBounds(commentSpan.pos, commentSpan.end), + hintSpan: ts.createTextSpanFromBounds(commentSpan.pos, commentSpan.end), + bannerText: collapseText, + autoCollapse: autoCollapse + }; + elements.push(span_13); + } } - function getDeclarationName(declaration) { - if (declaration.name) { - var result_3 = getTextOfIdentifierOrLiteral(declaration.name); - if (result_3 !== undefined) { - return result_3; - } - if (declaration.name.kind === 140 /* ComputedPropertyName */) { - var expr = declaration.name.expression; - if (expr.kind === 172 /* PropertyAccessExpression */) { - return expr.name.text; + function addOutliningForLeadingCommentsForNode(n) { + var comments = ts.getLeadingCommentRangesOfNode(n, sourceFile); + if (comments) { + var firstSingleLineCommentStart = -1; + var lastSingleLineCommentEnd = -1; + var isFirstSingleLineComment = true; + var singleLineCommentCount = 0; + for (var _i = 0, comments_4 = comments; _i < comments_4.length; _i++) { + var currentComment = comments_4[_i]; + // For single line comments, combine consecutive ones (2 or more) into + // a single span from the start of the first till the end of the last + if (currentComment.kind === 2 /* SingleLineCommentTrivia */) { + if (isFirstSingleLineComment) { + firstSingleLineCommentStart = currentComment.pos; + } + isFirstSingleLineComment = false; + lastSingleLineCommentEnd = currentComment.end; + singleLineCommentCount++; + } + else if (currentComment.kind === 3 /* MultiLineCommentTrivia */) { + combineAndAddMultipleSingleLineComments(singleLineCommentCount, firstSingleLineCommentStart, lastSingleLineCommentEnd); + addOutliningSpanComments(currentComment, /*autoCollapse*/ false); + singleLineCommentCount = 0; + lastSingleLineCommentEnd = -1; + isFirstSingleLineComment = true; } - return getTextOfIdentifierOrLiteral(expr); } + combineAndAddMultipleSingleLineComments(singleLineCommentCount, firstSingleLineCommentStart, lastSingleLineCommentEnd); } - return undefined; } - function getTextOfIdentifierOrLiteral(node) { - if (node) { - if (node.kind === 69 /* Identifier */ || - node.kind === 9 /* StringLiteral */ || - node.kind === 8 /* NumericLiteral */) { - return node.text; - } + function combineAndAddMultipleSingleLineComments(count, start, end) { + // Only outline spans of two or more consecutive single line comments + if (count > 1) { + var multipleSingleLineComments = { + pos: start, + end: end, + kind: 2 /* SingleLineCommentTrivia */ + }; + addOutliningSpanComments(multipleSingleLineComments, /*autoCollapse*/ false); } - return undefined; } - function visit(node) { - switch (node.kind) { - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - var functionDeclaration = node; - var declarationName = getDeclarationName(functionDeclaration); - if (declarationName) { - var declarations = getDeclarations(declarationName); - var lastDeclaration = ts.lastOrUndefined(declarations); - // Check whether this declaration belongs to an "overload group". - if (lastDeclaration && functionDeclaration.parent === lastDeclaration.parent && functionDeclaration.symbol === lastDeclaration.symbol) { - // Overwrite the last declaration if it was an overload - // and this one is an implementation. - if (functionDeclaration.body && !lastDeclaration.body) { - declarations[declarations.length - 1] = functionDeclaration; - } + function autoCollapse(node) { + return ts.isFunctionBlock(node) && node.parent.kind !== 180 /* ArrowFunction */; + } + var depth = 0; + var maxDepth = 20; + function walk(n) { + if (depth > maxDepth) { + return; + } + if (ts.isDeclaration(n)) { + addOutliningForLeadingCommentsForNode(n); + } + switch (n.kind) { + case 199 /* Block */: + if (!ts.isFunctionBlock(n)) { + var parent_22 = n.parent; + var openBrace = ts.findChildOfKind(n, 15 /* OpenBraceToken */, sourceFile); + var closeBrace = ts.findChildOfKind(n, 16 /* CloseBraceToken */, sourceFile); + // Check if the block is standalone, or 'attached' to some parent statement. + // If the latter, we want to collapse the block, but consider its hint span + // to be the entire span of the parent. + if (parent_22.kind === 204 /* DoStatement */ || + parent_22.kind === 207 /* ForInStatement */ || + parent_22.kind === 208 /* ForOfStatement */ || + parent_22.kind === 206 /* ForStatement */ || + parent_22.kind === 203 /* IfStatement */ || + parent_22.kind === 205 /* WhileStatement */ || + parent_22.kind === 212 /* WithStatement */ || + parent_22.kind === 252 /* CatchClause */) { + addOutliningSpan(parent_22, openBrace, closeBrace, autoCollapse(n)); + break; } - else { - declarations.push(functionDeclaration); + if (parent_22.kind === 216 /* TryStatement */) { + // Could be the try-block, or the finally-block. + var tryStatement = parent_22; + if (tryStatement.tryBlock === n) { + addOutliningSpan(parent_22, openBrace, closeBrace, autoCollapse(n)); + break; + } + else if (tryStatement.finallyBlock === n) { + var finallyKeyword = ts.findChildOfKind(tryStatement, 85 /* FinallyKeyword */, sourceFile); + if (finallyKeyword) { + addOutliningSpan(finallyKeyword, openBrace, closeBrace, autoCollapse(n)); + break; + } + } } - ts.forEachChild(node, visit); + // Block was a standalone block. In this case we want to only collapse + // the span of the block, independent of any parent span. + var span_14 = ts.createTextSpanFromBounds(n.getStart(), n.end); + elements.push({ + textSpan: span_14, + hintSpan: span_14, + bannerText: collapseText, + autoCollapse: autoCollapse(n) + }); + break; } + // Fallthrough. + case 226 /* ModuleBlock */: { + var openBrace = ts.findChildOfKind(n, 15 /* OpenBraceToken */, sourceFile); + var closeBrace = ts.findChildOfKind(n, 16 /* CloseBraceToken */, sourceFile); + addOutliningSpan(n.parent, openBrace, closeBrace, autoCollapse(n)); break; + } case 221 /* ClassDeclaration */: - case 192 /* ClassExpression */: case 222 /* InterfaceDeclaration */: - case 223 /* TypeAliasDeclaration */: case 224 /* EnumDeclaration */: - case 225 /* ModuleDeclaration */: - case 229 /* ImportEqualsDeclaration */: - case 238 /* ExportSpecifier */: - case 234 /* ImportSpecifier */: - case 229 /* ImportEqualsDeclaration */: - case 231 /* ImportClause */: - case 232 /* NamespaceImport */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 159 /* TypeLiteral */: - addDeclaration(node); - ts.forEachChild(node, visit); + case 171 /* ObjectLiteralExpression */: + case 227 /* CaseBlock */: { + var openBrace = ts.findChildOfKind(n, 15 /* OpenBraceToken */, sourceFile); + var closeBrace = ts.findChildOfKind(n, 16 /* CloseBraceToken */, sourceFile); + addOutliningSpan(n, openBrace, closeBrace, autoCollapse(n)); break; - case 142 /* Parameter */: - // Only consider parameter properties - if (!(node.flags & 92 /* ParameterPropertyModifier */)) { - break; - } - // fall through - case 218 /* VariableDeclaration */: - case 169 /* BindingElement */: { - var decl = node; - if (ts.isBindingPattern(decl.name)) { - ts.forEachChild(decl.name, visit); - break; - } - if (decl.initializer) - visit(decl.initializer); } - case 255 /* EnumMember */: - case 145 /* PropertyDeclaration */: - case 144 /* PropertySignature */: - addDeclaration(node); - break; - case 236 /* ExportDeclaration */: - // Handle named exports case e.g.: - // export {a, b as B} from "mod"; - if (node.exportClause) { - ts.forEach(node.exportClause.elements, visit); - } - break; - case 230 /* ImportDeclaration */: - var importClause = node.importClause; - if (importClause) { - // Handle default import case e.g.: - // import d from "mod"; - if (importClause.name) { - addDeclaration(importClause); - } - // Handle named bindings in imports e.g.: - // import * as NS from "mod"; - // import {a, b as B} from "mod"; - if (importClause.namedBindings) { - if (importClause.namedBindings.kind === 232 /* NamespaceImport */) { - addDeclaration(importClause.namedBindings); - } - else { - ts.forEach(importClause.namedBindings.elements, visit); - } - } - } + case 170 /* ArrayLiteralExpression */: + var openBracket = ts.findChildOfKind(n, 19 /* OpenBracketToken */, sourceFile); + var closeBracket = ts.findChildOfKind(n, 20 /* CloseBracketToken */, sourceFile); + addOutliningSpan(n, openBracket, closeBracket, autoCollapse(n)); break; - default: - ts.forEachChild(node, visit); } + depth++; + ts.forEachChild(n, walk); + depth--; } - }; - return SourceFileObject; - }(NodeObject)); - function displayPartsToString(displayParts) { - if (displayParts) { - return ts.map(displayParts, function (displayPart) { return displayPart.text; }).join(""); - } - return ""; - } - ts.displayPartsToString = displayPartsToString; - function isLocalVariableOrFunction(symbol) { - if (symbol.parent) { - return false; // This is exported symbol + walk(sourceFile); + return elements; } - return ts.forEach(symbol.declarations, function (declaration) { - // Function expressions are local - if (declaration.kind === 179 /* FunctionExpression */) { - return true; - } - if (declaration.kind !== 218 /* VariableDeclaration */ && declaration.kind !== 220 /* FunctionDeclaration */) { - return false; - } - // If the parent is not sourceFile or module block it is local variable - for (var parent_17 = declaration.parent; !ts.isFunctionBlock(parent_17); parent_17 = parent_17.parent) { - // Reached source file or module block - if (parent_17.kind === 256 /* SourceFile */ || parent_17.kind === 226 /* ModuleBlock */) { - return false; - } - } - // parent is in function block - return true; - }); - } - function getDefaultCompilerOptions() { - // Always default to "ScriptTarget.ES5" for the language service + OutliningElementsCollector.collectElements = collectElements; + })(OutliningElementsCollector = ts.OutliningElementsCollector || (ts.OutliningElementsCollector = {})); +})(ts || (ts = {})); +/* @internal */ +var ts; +(function (ts) { + // Note(cyrusn): this enum is ordered from strongest match type to weakest match type. + (function (PatternMatchKind) { + PatternMatchKind[PatternMatchKind["exact"] = 0] = "exact"; + PatternMatchKind[PatternMatchKind["prefix"] = 1] = "prefix"; + PatternMatchKind[PatternMatchKind["substring"] = 2] = "substring"; + PatternMatchKind[PatternMatchKind["camelCase"] = 3] = "camelCase"; + })(ts.PatternMatchKind || (ts.PatternMatchKind = {})); + var PatternMatchKind = ts.PatternMatchKind; + function createPatternMatch(kind, punctuationStripped, isCaseSensitive, camelCaseWeight) { return { - target: 1 /* ES5 */, - jsx: 1 /* Preserve */ + kind: kind, + punctuationStripped: punctuationStripped, + isCaseSensitive: isCaseSensitive, + camelCaseWeight: camelCaseWeight }; } - ts.getDefaultCompilerOptions = getDefaultCompilerOptions; - // Cache host information about script should be refreshed - // at each language service public entry point, since we don't know when - // set of scripts handled by the host changes. - var HostCache = (function () { - function HostCache(host, getCanonicalFileName) { - this.host = host; - this.getCanonicalFileName = getCanonicalFileName; - // script id => script index - this.currentDirectory = host.getCurrentDirectory(); - this.fileNameToEntry = ts.createFileMap(); - // Initialize the list with the root file names - var rootFileNames = host.getScriptFileNames(); - for (var _i = 0, rootFileNames_1 = rootFileNames; _i < rootFileNames_1.length; _i++) { - var fileName = rootFileNames_1[_i]; - this.createEntry(fileName, ts.toPath(fileName, this.currentDirectory, getCanonicalFileName)); - } - // store the compilation settings - this._compilationSettings = host.getCompilationSettings() || getDefaultCompilerOptions(); - } - HostCache.prototype.compilationSettings = function () { - return this._compilationSettings; + function createPatternMatcher(pattern) { + // We'll often see the same candidate string many times when searching (For example, when + // we see the name of a module that is used everywhere, or the name of an overload). As + // such, we cache the information we compute about the candidate for the life of this + // pattern matcher so we don't have to compute it multiple times. + var stringToWordSpans = ts.createMap(); + pattern = pattern.trim(); + var dotSeparatedSegments = pattern.split(".").map(function (p) { return createSegment(p.trim()); }); + var invalidPattern = dotSeparatedSegments.length === 0 || ts.forEach(dotSeparatedSegments, segmentIsInvalid); + return { + getMatches: getMatches, + getMatchesForLastSegmentOfPattern: getMatchesForLastSegmentOfPattern, + patternContainsDots: dotSeparatedSegments.length > 1 }; - HostCache.prototype.createEntry = function (fileName, path) { - var entry; - var scriptSnapshot = this.host.getScriptSnapshot(fileName); - if (scriptSnapshot) { - entry = { - hostFileName: fileName, - version: this.host.getScriptVersion(fileName), - scriptSnapshot: scriptSnapshot, - scriptKind: ts.getScriptKind(fileName, this.host) - }; + // Quick checks so we can bail out when asked to match a candidate. + function skipMatch(candidate) { + return invalidPattern || !candidate; + } + function getMatchesForLastSegmentOfPattern(candidate) { + if (skipMatch(candidate)) { + return undefined; } - this.fileNameToEntry.set(path, entry); - return entry; - }; - HostCache.prototype.getEntry = function (path) { - return this.fileNameToEntry.get(path); - }; - HostCache.prototype.contains = function (path) { - return this.fileNameToEntry.contains(path); - }; - HostCache.prototype.getOrCreateEntry = function (fileName) { - var path = ts.toPath(fileName, this.currentDirectory, this.getCanonicalFileName); - return this.getOrCreateEntryByPath(fileName, path); - }; - HostCache.prototype.getOrCreateEntryByPath = function (fileName, path) { - return this.contains(path) - ? this.getEntry(path) - : this.createEntry(fileName, path); - }; - HostCache.prototype.getRootFileNames = function () { - var fileNames = []; - this.fileNameToEntry.forEachValue(function (path, value) { - if (value) { - fileNames.push(value.hostFileName); - } - }); - return fileNames; - }; - HostCache.prototype.getVersion = function (path) { - var file = this.getEntry(path); - return file && file.version; - }; - HostCache.prototype.getScriptSnapshot = function (path) { - var file = this.getEntry(path); - return file && file.scriptSnapshot; - }; - return HostCache; - }()); - var SyntaxTreeCache = (function () { - function SyntaxTreeCache(host) { - this.host = host; + return matchSegment(candidate, ts.lastOrUndefined(dotSeparatedSegments)); } - SyntaxTreeCache.prototype.getCurrentSourceFile = function (fileName) { - var scriptSnapshot = this.host.getScriptSnapshot(fileName); - if (!scriptSnapshot) { - // The host does not know about this file. - throw new Error("Could not find file: '" + fileName + "'."); + function getMatches(candidateContainers, candidate) { + if (skipMatch(candidate)) { + return undefined; } - var scriptKind = ts.getScriptKind(fileName, this.host); - var version = this.host.getScriptVersion(fileName); - var sourceFile; - if (this.currentFileName !== fileName) { - // This is a new file, just parse it - sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, 2 /* Latest */, version, /*setNodeParents*/ true, scriptKind); + // First, check that the last part of the dot separated pattern matches the name of the + // candidate. If not, then there's no point in proceeding and doing the more + // expensive work. + var candidateMatch = matchSegment(candidate, ts.lastOrUndefined(dotSeparatedSegments)); + if (!candidateMatch) { + return undefined; } - else if (this.currentFileVersion !== version) { - // This is the same file, just a newer version. Incrementally parse the file. - var editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot); - sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, editRange); + candidateContainers = candidateContainers || []; + // -1 because the last part was checked against the name, and only the rest + // of the parts are checked against the container. + if (dotSeparatedSegments.length - 1 > candidateContainers.length) { + // There weren't enough container parts to match against the pattern parts. + // So this definitely doesn't match. + return undefined; } - if (sourceFile) { - // All done, ensure state is up to date - this.currentFileVersion = version; - this.currentFileName = fileName; - this.currentFileScriptSnapshot = scriptSnapshot; - this.currentSourceFile = sourceFile; + // So far so good. Now break up the container for the candidate and check if all + // the dotted parts match up correctly. + var totalMatch = candidateMatch; + for (var i = dotSeparatedSegments.length - 2, j = candidateContainers.length - 1; i >= 0; i -= 1, j -= 1) { + var segment = dotSeparatedSegments[i]; + var containerName = candidateContainers[j]; + var containerMatch = matchSegment(containerName, segment); + if (!containerMatch) { + // This container didn't match the pattern piece. So there's no match at all. + return undefined; + } + ts.addRange(totalMatch, containerMatch); } - return this.currentSourceFile; - }; - return SyntaxTreeCache; - }()); - function setSourceFileFields(sourceFile, scriptSnapshot, version) { - sourceFile.version = version; - sourceFile.scriptSnapshot = scriptSnapshot; - } - var commandLineOptionsStringToEnum; - /** JS users may pass in string values for enum compiler options (such as ModuleKind), so convert. */ - function fixupCompilerOptions(options, diagnostics) { - // Lazily create this value to fix module loading errors. - commandLineOptionsStringToEnum = commandLineOptionsStringToEnum || ts.filter(ts.optionDeclarations, function (o) { - return typeof o.type === "object" && !ts.forEachProperty(o.type, function (v) { return typeof v !== "number"; }); - }); - options = ts.clone(options); - var _loop_3 = function(opt) { - if (!ts.hasProperty(options, opt.name)) { - return "continue"; + // Success, this symbol's full name matched against the dotted name the user was asking + // about. + return totalMatch; + } + function getWordSpans(word) { + if (!(word in stringToWordSpans)) { + stringToWordSpans[word] = breakIntoWordSpans(word); } - var value = options[opt.name]; - // Value should be a key of opt.type - if (typeof value === "string") { - // If value is not a string, this will fail - options[opt.name] = ts.parseCustomTypeOption(opt, value, diagnostics); + return stringToWordSpans[word]; + } + function matchTextChunk(candidate, chunk, punctuationStripped) { + var index = indexOfIgnoringCase(candidate, chunk.textLowerCase); + if (index === 0) { + if (chunk.text.length === candidate.length) { + // a) Check if the part matches the candidate entirely, in an case insensitive or + // sensitive manner. If it does, return that there was an exact match. + return createPatternMatch(PatternMatchKind.exact, punctuationStripped, /*isCaseSensitive:*/ candidate === chunk.text); + } + else { + // b) Check if the part is a prefix of the candidate, in a case insensitive or sensitive + // manner. If it does, return that there was a prefix match. + return createPatternMatch(PatternMatchKind.prefix, punctuationStripped, /*isCaseSensitive:*/ ts.startsWith(candidate, chunk.text)); + } + } + var isLowercase = chunk.isLowerCase; + if (isLowercase) { + if (index > 0) { + // c) If the part is entirely lowercase, then check if it is contained anywhere in the + // candidate in a case insensitive manner. If so, return that there was a substring + // match. + // + // Note: We only have a substring match if the lowercase part is prefix match of some + // word part. That way we don't match something like 'Class' when the user types 'a'. + // But we would match 'FooAttribute' (since 'Attribute' starts with 'a'). + var wordSpans = getWordSpans(candidate); + for (var _i = 0, wordSpans_1 = wordSpans; _i < wordSpans_1.length; _i++) { + var span_15 = wordSpans_1[_i]; + if (partStartsWith(candidate, span_15, chunk.text, /*ignoreCase:*/ true)) { + return createPatternMatch(PatternMatchKind.substring, punctuationStripped, + /*isCaseSensitive:*/ partStartsWith(candidate, span_15, chunk.text, /*ignoreCase:*/ false)); + } + } + } + } + else { + // d) If the part was not entirely lowercase, then check if it is contained in the + // candidate in a case *sensitive* manner. If so, return that there was a substring + // match. + if (candidate.indexOf(chunk.text) > 0) { + return createPatternMatch(PatternMatchKind.substring, punctuationStripped, /*isCaseSensitive:*/ true); + } } - else { - if (!ts.forEachProperty(opt.type, function (v) { return v === value; })) { - // Supplied value isn't a valid enum value. - diagnostics.push(ts.createCompilerDiagnosticForInvalidCustomType(opt)); + if (!isLowercase) { + // e) If the part was not entirely lowercase, then attempt a camel cased match as well. + if (chunk.characterSpans.length > 0) { + var candidateParts = getWordSpans(candidate); + var camelCaseWeight = tryCamelCaseMatch(candidate, candidateParts, chunk, /*ignoreCase:*/ false); + if (camelCaseWeight !== undefined) { + return createPatternMatch(PatternMatchKind.camelCase, punctuationStripped, /*isCaseSensitive:*/ true, /*camelCaseWeight:*/ camelCaseWeight); + } + camelCaseWeight = tryCamelCaseMatch(candidate, candidateParts, chunk, /*ignoreCase:*/ true); + if (camelCaseWeight !== undefined) { + return createPatternMatch(PatternMatchKind.camelCase, punctuationStripped, /*isCaseSensitive:*/ false, /*camelCaseWeight:*/ camelCaseWeight); + } } } - }; - for (var _i = 0, commandLineOptionsStringToEnum_1 = commandLineOptionsStringToEnum; _i < commandLineOptionsStringToEnum_1.length; _i++) { - var opt = commandLineOptionsStringToEnum_1[_i]; - _loop_3(opt); + if (isLowercase) { + // f) Is the pattern a substring of the candidate starting on one of the candidate's word boundaries? + // We could check every character boundary start of the candidate for the pattern. However, that's + // an m * n operation in the wost case. Instead, find the first instance of the pattern + // substring, and see if it starts on a capital letter. It seems unlikely that the user will try to + // filter the list based on a substring that starts on a capital letter and also with a lowercase one. + // (Pattern: fogbar, Candidate: quuxfogbarFogBar). + if (chunk.text.length < candidate.length) { + if (index > 0 && isUpperCaseLetter(candidate.charCodeAt(index))) { + return createPatternMatch(PatternMatchKind.substring, punctuationStripped, /*isCaseSensitive:*/ false); + } + } + } + return undefined; } - return options; - } - /* - * This function will compile source text from 'input' argument using specified compiler options. - * If not options are provided - it will use a set of default compiler options. - * Extra compiler options that will unconditionally be used by this function are: - * - isolatedModules = true - * - allowNonTsExtensions = true - * - noLib = true - * - noResolve = true - */ - function transpileModule(input, transpileOptions) { - var diagnostics = []; - var options = transpileOptions.compilerOptions ? fixupCompilerOptions(transpileOptions.compilerOptions, diagnostics) : getDefaultCompilerOptions(); - options.isolatedModules = true; - // transpileModule does not write anything to disk so there is no need to verify that there are no conflicts between input and output paths. - options.suppressOutputPathCheck = true; - // Filename can be non-ts file. - options.allowNonTsExtensions = true; - // We are not returning a sourceFile for lib file when asked by the program, - // so pass --noLib to avoid reporting a file not found error. - options.noLib = true; - // Clear out other settings that would not be used in transpiling this module - options.lib = undefined; - options.types = undefined; - options.noEmit = undefined; - options.noEmitOnError = undefined; - options.paths = undefined; - options.rootDirs = undefined; - options.declaration = undefined; - options.declarationDir = undefined; - options.out = undefined; - options.outFile = undefined; - // We are not doing a full typecheck, we are not resolving the whole context, - // so pass --noResolve to avoid reporting missing file errors. - options.noResolve = true; - // if jsx is specified then treat file as .tsx - var inputFileName = transpileOptions.fileName || (options.jsx ? "module.tsx" : "module.ts"); - var sourceFile = ts.createSourceFile(inputFileName, input, options.target); - if (transpileOptions.moduleName) { - sourceFile.moduleName = transpileOptions.moduleName; + function containsSpaceOrAsterisk(text) { + for (var i = 0; i < text.length; i++) { + var ch = text.charCodeAt(i); + if (ch === 32 /* space */ || ch === 42 /* asterisk */) { + return true; + } + } + return false; } - if (transpileOptions.renamedDependencies) { - sourceFile.renamedDependencies = ts.createMap(transpileOptions.renamedDependencies); + function matchSegment(candidate, segment) { + // First check if the segment matches as is. This is also useful if the segment contains + // characters we would normally strip when splitting into parts that we also may want to + // match in the candidate. For example if the segment is "@int" and the candidate is + // "@int", then that will show up as an exact match here. + // + // Note: if the segment contains a space or an asterisk then we must assume that it's a + // multi-word segment. + if (!containsSpaceOrAsterisk(segment.totalTextChunk.text)) { + var match = matchTextChunk(candidate, segment.totalTextChunk, /*punctuationStripped:*/ false); + if (match) { + return [match]; + } + } + // The logic for pattern matching is now as follows: + // + // 1) Break the segment passed in into words. Breaking is rather simple and a + // good way to think about it that if gives you all the individual alphanumeric words + // of the pattern. + // + // 2) For each word try to match the word against the candidate value. + // + // 3) Matching is as follows: + // + // a) Check if the word matches the candidate entirely, in an case insensitive or + // sensitive manner. If it does, return that there was an exact match. + // + // b) Check if the word is a prefix of the candidate, in a case insensitive or + // sensitive manner. If it does, return that there was a prefix match. + // + // c) If the word is entirely lowercase, then check if it is contained anywhere in the + // candidate in a case insensitive manner. If so, return that there was a substring + // match. + // + // Note: We only have a substring match if the lowercase part is prefix match of + // some word part. That way we don't match something like 'Class' when the user + // types 'a'. But we would match 'FooAttribute' (since 'Attribute' starts with + // 'a'). + // + // d) If the word was not entirely lowercase, then check if it is contained in the + // candidate in a case *sensitive* manner. If so, return that there was a substring + // match. + // + // e) If the word was not entirely lowercase, then attempt a camel cased match as + // well. + // + // f) The word is all lower case. Is it a case insensitive substring of the candidate starting + // on a part boundary of the candidate? + // + // Only if all words have some sort of match is the pattern considered matched. + var subWordTextChunks = segment.subWordTextChunks; + var matches = undefined; + for (var _i = 0, subWordTextChunks_1 = subWordTextChunks; _i < subWordTextChunks_1.length; _i++) { + var subWordTextChunk = subWordTextChunks_1[_i]; + // Try to match the candidate with this word + var result = matchTextChunk(candidate, subWordTextChunk, /*punctuationStripped:*/ true); + if (!result) { + return undefined; + } + matches = matches || []; + matches.push(result); + } + return matches; } - var newLine = ts.getNewLineCharacter(options); - // Output - var outputText; - var sourceMapText; - // Create a compilerHost object to allow the compiler to read and write files - var compilerHost = { - getSourceFile: function (fileName, target) { return fileName === ts.normalizePath(inputFileName) ? sourceFile : undefined; }, - writeFile: function (name, text, writeByteOrderMark) { - if (ts.fileExtensionIs(name, ".map")) { - ts.Debug.assert(sourceMapText === undefined, "Unexpected multiple source map outputs for the file '" + name + "'"); - sourceMapText = text; + function partStartsWith(candidate, candidateSpan, pattern, ignoreCase, patternSpan) { + var patternPartStart = patternSpan ? patternSpan.start : 0; + var patternPartLength = patternSpan ? patternSpan.length : pattern.length; + if (patternPartLength > candidateSpan.length) { + // Pattern part is longer than the candidate part. There can never be a match. + return false; + } + if (ignoreCase) { + for (var i = 0; i < patternPartLength; i++) { + var ch1 = pattern.charCodeAt(patternPartStart + i); + var ch2 = candidate.charCodeAt(candidateSpan.start + i); + if (toLowerCase(ch1) !== toLowerCase(ch2)) { + return false; + } } - else { - ts.Debug.assert(outputText === undefined, "Unexpected multiple outputs for the file: '" + name + "'"); - outputText = text; + } + else { + for (var i = 0; i < patternPartLength; i++) { + var ch1 = pattern.charCodeAt(patternPartStart + i); + var ch2 = candidate.charCodeAt(candidateSpan.start + i); + if (ch1 !== ch2) { + return false; + } } - }, - getDefaultLibFileName: function () { return "lib.d.ts"; }, - useCaseSensitiveFileNames: function () { return false; }, - getCanonicalFileName: function (fileName) { return fileName; }, - getCurrentDirectory: function () { return ""; }, - getNewLine: function () { return newLine; }, - fileExists: function (fileName) { return fileName === inputFileName; }, - readFile: function (fileName) { return ""; }, - directoryExists: function (directoryExists) { return true; }, - getDirectories: function (path) { return []; } - }; - var program = ts.createProgram([inputFileName], options, compilerHost); - if (transpileOptions.reportDiagnostics) { - ts.addRange(/*to*/ diagnostics, /*from*/ program.getSyntacticDiagnostics(sourceFile)); - ts.addRange(/*to*/ diagnostics, /*from*/ program.getOptionsDiagnostics()); + } + return true; } - // Emit - program.emit(); - ts.Debug.assert(outputText !== undefined, "Output generation failed"); - return { outputText: outputText, diagnostics: diagnostics, sourceMapText: sourceMapText }; - } - ts.transpileModule = transpileModule; - /* - * This is a shortcut function for transpileModule - it accepts transpileOptions as parameters and returns only outputText part of the result. - */ - function transpile(input, compilerOptions, fileName, diagnostics, moduleName) { - var output = transpileModule(input, { compilerOptions: compilerOptions, fileName: fileName, reportDiagnostics: !!diagnostics, moduleName: moduleName }); - // addRange correctly handles cases when wither 'from' or 'to' argument is missing - ts.addRange(diagnostics, output.diagnostics); - return output.outputText; - } - ts.transpile = transpile; - function createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget, version, setNodeParents, scriptKind) { - var text = scriptSnapshot.getText(0, scriptSnapshot.getLength()); - var sourceFile = ts.createSourceFile(fileName, text, scriptTarget, setNodeParents, scriptKind); - setSourceFileFields(sourceFile, scriptSnapshot, version); - return sourceFile; - } - ts.createLanguageServiceSourceFile = createLanguageServiceSourceFile; - ts.disableIncrementalParsing = false; - function updateLanguageServiceSourceFile(sourceFile, scriptSnapshot, version, textChangeRange, aggressiveChecks) { - // If we were given a text change range, and our version or open-ness changed, then - // incrementally parse this file. - if (textChangeRange) { - if (version !== sourceFile.version) { - // Once incremental parsing is ready, then just call into this function. - if (!ts.disableIncrementalParsing) { - var newText = void 0; - // grab the fragment from the beginning of the original text to the beginning of the span - var prefix = textChangeRange.span.start !== 0 - ? sourceFile.text.substr(0, textChangeRange.span.start) - : ""; - // grab the fragment from the end of the span till the end of the original text - var suffix = ts.textSpanEnd(textChangeRange.span) !== sourceFile.text.length - ? sourceFile.text.substr(ts.textSpanEnd(textChangeRange.span)) - : ""; - if (textChangeRange.newLength === 0) { - // edit was a deletion - just combine prefix and suffix - newText = prefix && suffix ? prefix + suffix : prefix || suffix; + function tryCamelCaseMatch(candidate, candidateParts, chunk, ignoreCase) { + var chunkCharacterSpans = chunk.characterSpans; + // Note: we may have more pattern parts than candidate parts. This is because multiple + // pattern parts may match a candidate part. For example "SiUI" against "SimpleUI". + // We'll have 3 pattern parts Si/U/I against two candidate parts Simple/UI. However, U + // and I will both match in UI. + var currentCandidate = 0; + var currentChunkSpan = 0; + var firstMatch = undefined; + var contiguous = undefined; + while (true) { + // Let's consider our termination cases + if (currentChunkSpan === chunkCharacterSpans.length) { + // We did match! We shall assign a weight to this + var weight = 0; + // Was this contiguous? + if (contiguous) { + weight += 1; } - else { - // it was actual edit, fetch the fragment of new text that correspond to new span - var changedText = scriptSnapshot.getText(textChangeRange.span.start, textChangeRange.span.start + textChangeRange.newLength); - // combine prefix, changed text and suffix - newText = prefix && suffix - ? prefix + changedText + suffix - : prefix - ? (prefix + changedText) - : (changedText + suffix); + // Did we start at the beginning of the candidate? + if (firstMatch === 0) { + weight += 2; } - var newSourceFile = ts.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); - setSourceFileFields(newSourceFile, scriptSnapshot, version); - // after incremental parsing nameTable might not be up-to-date - // drop it so it can be lazily recreated later - newSourceFile.nameTable = undefined; - // dispose all resources held by old script snapshot - if (sourceFile !== newSourceFile && sourceFile.scriptSnapshot) { - if (sourceFile.scriptSnapshot.dispose) { - sourceFile.scriptSnapshot.dispose(); + return weight; + } + else if (currentCandidate === candidateParts.length) { + // No match, since we still have more of the pattern to hit + return undefined; + } + var candidatePart = candidateParts[currentCandidate]; + var gotOneMatchThisCandidate = false; + // Consider the case of matching SiUI against SimpleUIElement. The candidate parts + // will be Simple/UI/Element, and the pattern parts will be Si/U/I. We'll match 'Si' + // against 'Simple' first. Then we'll match 'U' against 'UI'. However, we want to + // still keep matching pattern parts against that candidate part. + for (; currentChunkSpan < chunkCharacterSpans.length; currentChunkSpan++) { + var chunkCharacterSpan = chunkCharacterSpans[currentChunkSpan]; + if (gotOneMatchThisCandidate) { + // We've already gotten one pattern part match in this candidate. We will + // only continue trying to consumer pattern parts if the last part and this + // part are both upper case. + if (!isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan - 1].start)) || + !isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan].start))) { + break; } - sourceFile.scriptSnapshot = undefined; } - return newSourceFile; + if (!partStartsWith(candidate, candidatePart, chunk.text, ignoreCase, chunkCharacterSpan)) { + break; + } + gotOneMatchThisCandidate = true; + firstMatch = firstMatch === undefined ? currentCandidate : firstMatch; + // If we were contiguous, then keep that value. If we weren't, then keep that + // value. If we don't know, then set the value to 'true' as an initial match is + // obviously contiguous. + contiguous = contiguous === undefined ? true : contiguous; + candidatePart = ts.createTextSpan(candidatePart.start + chunkCharacterSpan.length, candidatePart.length - chunkCharacterSpan.length); + } + // Check if we matched anything at all. If we didn't, then we need to unset the + // contiguous bit if we currently had it set. + // If we haven't set the bit yet, then that means we haven't matched anything so + // far, and we don't want to change that. + if (!gotOneMatchThisCandidate && contiguous !== undefined) { + contiguous = false; } + // Move onto the next candidate. + currentCandidate++; } } - // Otherwise, just create a new source file. - return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents*/ true, sourceFile.scriptKind); } - ts.updateLanguageServiceSourceFile = updateLanguageServiceSourceFile; - function createDocumentRegistry(useCaseSensitiveFileNames, currentDirectory) { - if (currentDirectory === void 0) { currentDirectory = ""; } - // Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have - // for those settings. - var buckets = ts.createMap(); - var getCanonicalFileName = ts.createGetCanonicalFileName(!!useCaseSensitiveFileNames); - function getKeyForCompilationSettings(settings) { - return ("_" + settings.target + "|" + settings.module + "|" + settings.noResolve + "|" + settings.jsx + "|" + settings.allowJs + "|" + settings.baseUrl + "|" + JSON.stringify(settings.typeRoots) + "|" + JSON.stringify(settings.rootDirs) + "|" + JSON.stringify(settings.paths)); + ts.createPatternMatcher = createPatternMatcher; + function createSegment(text) { + return { + totalTextChunk: createTextChunk(text), + subWordTextChunks: breakPatternIntoTextChunks(text) + }; + } + // A segment is considered invalid if we couldn't find any words in it. + function segmentIsInvalid(segment) { + return segment.subWordTextChunks.length === 0; + } + function isUpperCaseLetter(ch) { + // Fast check for the ascii range. + if (ch >= 65 /* A */ && ch <= 90 /* Z */) { + return true; } - function getBucketForCompilationSettings(key, createIfMissing) { - var bucket = buckets[key]; - if (!bucket && createIfMissing) { - buckets[key] = bucket = ts.createFileMap(); - } - return bucket; + if (ch < 127 /* maxAsciiCharacter */ || !ts.isUnicodeIdentifierStart(ch, 2 /* Latest */)) { + return false; } - function reportStats() { - var bucketInfoArray = Object.keys(buckets).filter(function (name) { return name && name.charAt(0) === "_"; }).map(function (name) { - var entries = buckets[name]; - var sourceFiles = []; - entries.forEachValue(function (key, entry) { - sourceFiles.push({ - name: key, - refCount: entry.languageServiceRefCount, - references: entry.owners.slice(0) - }); - }); - sourceFiles.sort(function (x, y) { return y.refCount - x.refCount; }); - return { - bucket: name, - sourceFiles: sourceFiles - }; - }); - return JSON.stringify(bucketInfoArray, undefined, 2); + // TODO: find a way to determine this for any unicode characters in a + // non-allocating manner. + var str = String.fromCharCode(ch); + return str === str.toUpperCase(); + } + function isLowerCaseLetter(ch) { + // Fast check for the ascii range. + if (ch >= 97 /* a */ && ch <= 122 /* z */) { + return true; } - function acquireDocument(fileName, compilationSettings, scriptSnapshot, version, scriptKind) { - var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); - var key = getKeyForCompilationSettings(compilationSettings); - return acquireDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind); + if (ch < 127 /* maxAsciiCharacter */ || !ts.isUnicodeIdentifierStart(ch, 2 /* Latest */)) { + return false; } - function acquireDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind) { - return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, /*acquiring*/ true, scriptKind); + // TODO: find a way to determine this for any unicode characters in a + // non-allocating manner. + var str = String.fromCharCode(ch); + return str === str.toLowerCase(); + } + // Assumes 'value' is already lowercase. + function indexOfIgnoringCase(string, value) { + for (var i = 0, n = string.length - value.length; i <= n; i++) { + if (startsWithIgnoringCase(string, value, i)) { + return i; + } } - function updateDocument(fileName, compilationSettings, scriptSnapshot, version, scriptKind) { - var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); - var key = getKeyForCompilationSettings(compilationSettings); - return updateDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind); + return -1; + } + // Assumes 'value' is already lowercase. + function startsWithIgnoringCase(string, value, start) { + for (var i = 0, n = value.length; i < n; i++) { + var ch1 = toLowerCase(string.charCodeAt(i + start)); + var ch2 = value.charCodeAt(i); + if (ch1 !== ch2) { + return false; + } } - function updateDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind) { - return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, /*acquiring*/ false, scriptKind); + return true; + } + function toLowerCase(ch) { + // Fast convert for the ascii range. + if (ch >= 65 /* A */ && ch <= 90 /* Z */) { + return 97 /* a */ + (ch - 65 /* A */); } - function acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, acquiring, scriptKind) { - var bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ true); - var entry = bucket.get(path); - if (!entry) { - ts.Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?"); - // Have never seen this file with these settings. Create a new source file for it. - var sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false, scriptKind); - entry = { - sourceFile: sourceFile, - languageServiceRefCount: 0, - owners: [] - }; - bucket.set(path, entry); + if (ch < 127 /* maxAsciiCharacter */) { + return ch; + } + // TODO: find a way to compute this for any unicode characters in a + // non-allocating manner. + return String.fromCharCode(ch).toLowerCase().charCodeAt(0); + } + function isDigit(ch) { + // TODO(cyrusn): Find a way to support this for unicode digits. + return ch >= 48 /* _0 */ && ch <= 57 /* _9 */; + } + function isWordChar(ch) { + return isUpperCaseLetter(ch) || isLowerCaseLetter(ch) || isDigit(ch) || ch === 95 /* _ */ || ch === 36 /* $ */; + } + function breakPatternIntoTextChunks(pattern) { + var result = []; + var wordStart = 0; + var wordLength = 0; + for (var i = 0; i < pattern.length; i++) { + var ch = pattern.charCodeAt(i); + if (isWordChar(ch)) { + if (wordLength === 0) { + wordStart = i; + } + wordLength++; } else { - // We have an entry for this file. However, it may be for a different version of - // the script snapshot. If so, update it appropriately. Otherwise, we can just - // return it as is. - if (entry.sourceFile.version !== version) { - entry.sourceFile = updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version, scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot)); + if (wordLength > 0) { + result.push(createTextChunk(pattern.substr(wordStart, wordLength))); + wordLength = 0; } } - // If we're acquiring, then this is the first time this LS is asking for this document. - // Increase our ref count so we know there's another LS using the document. If we're - // not acquiring, then that means the LS is 'updating' the file instead, and that means - // it has already acquired the document previously. As such, we do not need to increase - // the ref count. - if (acquiring) { - entry.languageServiceRefCount++; + } + if (wordLength > 0) { + result.push(createTextChunk(pattern.substr(wordStart, wordLength))); + } + return result; + } + function createTextChunk(text) { + var textLowerCase = text.toLowerCase(); + return { + text: text, + textLowerCase: textLowerCase, + isLowerCase: text === textLowerCase, + characterSpans: breakIntoCharacterSpans(text) + }; + } + /* @internal */ function breakIntoCharacterSpans(identifier) { + return breakIntoSpans(identifier, /*word:*/ false); + } + ts.breakIntoCharacterSpans = breakIntoCharacterSpans; + /* @internal */ function breakIntoWordSpans(identifier) { + return breakIntoSpans(identifier, /*word:*/ true); + } + ts.breakIntoWordSpans = breakIntoWordSpans; + function breakIntoSpans(identifier, word) { + var result = []; + var wordStart = 0; + for (var i = 1, n = identifier.length; i < n; i++) { + var lastIsDigit = isDigit(identifier.charCodeAt(i - 1)); + var currentIsDigit = isDigit(identifier.charCodeAt(i)); + var hasTransitionFromLowerToUpper = transitionFromLowerToUpper(identifier, word, i); + var hasTransitionFromUpperToLower = transitionFromUpperToLower(identifier, word, i, wordStart); + if (charIsPunctuation(identifier.charCodeAt(i - 1)) || + charIsPunctuation(identifier.charCodeAt(i)) || + lastIsDigit !== currentIsDigit || + hasTransitionFromLowerToUpper || + hasTransitionFromUpperToLower) { + if (!isAllPunctuation(identifier, wordStart, i)) { + result.push(ts.createTextSpan(wordStart, i - wordStart)); + } + wordStart = i; } - return entry.sourceFile; } - function releaseDocument(fileName, compilationSettings) { - var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); - var key = getKeyForCompilationSettings(compilationSettings); - return releaseDocumentWithKey(path, key); + if (!isAllPunctuation(identifier, wordStart, identifier.length)) { + result.push(ts.createTextSpan(wordStart, identifier.length - wordStart)); } - function releaseDocumentWithKey(path, key) { - var bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ false); - ts.Debug.assert(bucket !== undefined); - var entry = bucket.get(path); - entry.languageServiceRefCount--; - ts.Debug.assert(entry.languageServiceRefCount >= 0); - if (entry.languageServiceRefCount === 0) { - bucket.remove(path); + return result; + } + function charIsPunctuation(ch) { + switch (ch) { + case 33 /* exclamation */: + case 34 /* doubleQuote */: + case 35 /* hash */: + case 37 /* percent */: + case 38 /* ampersand */: + case 39 /* singleQuote */: + case 40 /* openParen */: + case 41 /* closeParen */: + case 42 /* asterisk */: + case 44 /* comma */: + case 45 /* minus */: + case 46 /* dot */: + case 47 /* slash */: + case 58 /* colon */: + case 59 /* semicolon */: + case 63 /* question */: + case 64 /* at */: + case 91 /* openBracket */: + case 92 /* backslash */: + case 93 /* closeBracket */: + case 95 /* _ */: + case 123 /* openBrace */: + case 125 /* closeBrace */: + return true; + } + return false; + } + function isAllPunctuation(identifier, start, end) { + for (var i = start; i < end; i++) { + var ch = identifier.charCodeAt(i); + // We don't consider _ or $ as punctuation as there may be things with that name. + if (!charIsPunctuation(ch) || ch === 95 /* _ */ || ch === 36 /* $ */) { + return false; } } - return { - acquireDocument: acquireDocument, - acquireDocumentWithKey: acquireDocumentWithKey, - updateDocument: updateDocument, - updateDocumentWithKey: updateDocumentWithKey, - releaseDocument: releaseDocument, - releaseDocumentWithKey: releaseDocumentWithKey, - reportStats: reportStats, - getKeyForCompilationSettings: getKeyForCompilationSettings - }; + return true; } - ts.createDocumentRegistry = createDocumentRegistry; + function transitionFromUpperToLower(identifier, word, index, wordStart) { + if (word) { + // Cases this supports: + // 1) IDisposable -> I, Disposable + // 2) UIElement -> UI, Element + // 3) HTMLDocument -> HTML, Document + // + // etc. + if (index !== wordStart && + index + 1 < identifier.length) { + var currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index)); + var nextIsLower = isLowerCaseLetter(identifier.charCodeAt(index + 1)); + if (currentIsUpper && nextIsLower) { + // We have a transition from an upper to a lower letter here. But we only + // want to break if all the letters that preceded are uppercase. i.e. if we + // have "Foo" we don't want to break that into "F, oo". But if we have + // "IFoo" or "UIFoo", then we want to break that into "I, Foo" and "UI, + // Foo". i.e. the last uppercase letter belongs to the lowercase letters + // that follows. Note: this will make the following not split properly: + // "HELLOthere". However, these sorts of names do not show up in .Net + // programs. + for (var i = wordStart; i < index; i++) { + if (!isUpperCaseLetter(identifier.charCodeAt(i))) { + return false; + } + } + return true; + } + } + } + return false; + } + function transitionFromLowerToUpper(identifier, word, index) { + var lastIsUpper = isUpperCaseLetter(identifier.charCodeAt(index - 1)); + var currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index)); + // See if the casing indicates we're starting a new word. Note: if we're breaking on + // words, then just seeing an upper case character isn't enough. Instead, it has to + // be uppercase and the previous character can't be uppercase. + // + // For example, breaking "AddMetadata" on words would make: Add Metadata + // + // on characters would be: A dd M etadata + // + // Break "AM" on words would be: AM + // + // on characters would be: A M + // + // We break the search string on characters. But we break the symbol name on words. + var transition = word + ? (currentIsUpper && !lastIsUpper) + : currentIsUpper; + return transition; + } +})(ts || (ts = {})); +var ts; +(function (ts) { function preProcessFile(sourceText, readImportFiles, detectJavaScriptImports) { if (readImportFiles === void 0) { readImportFiles = true; } if (detectJavaScriptImports === void 0) { detectJavaScriptImports = false; } @@ -55284,7 +68918,7 @@ var ts; // ambient modules that are found inside external modules are interpreted as module augmentations var externalModule = false; function nextToken() { - var token = scanner.scan(); + var token = ts.scanner.scan(); if (token === 15 /* OpenBraceToken */) { braceNesting++; } @@ -55311,8 +68945,8 @@ var ts; }); } function getFileReference() { - var file = scanner.getTokenValue(); - var pos = scanner.getTokenPos(); + var file = ts.scanner.getTokenValue(); + var pos = ts.scanner.getTokenPos(); return { fileName: file, pos: pos, @@ -55338,7 +68972,7 @@ var ts; * Returns true if at least one token was consumed from the stream */ function tryConsumeDeclare() { - var token = scanner.getToken(); + var token = ts.scanner.getToken(); if (token === 122 /* DeclareKeyword */) { // declare module "mod" token = nextToken(); @@ -55356,7 +68990,7 @@ var ts; * Returns true if at least one token was consumed from the stream */ function tryConsumeImport() { - var token = scanner.getToken(); + var token = ts.scanner.getToken(); if (token === 89 /* ImportKeyword */) { token = nextToken(); if (token === 9 /* StringLiteral */) { @@ -55426,3988 +69060,5387 @@ var ts; } } } - return true; + return true; + } + return false; + } + function tryConsumeExport() { + var token = ts.scanner.getToken(); + if (token === 82 /* ExportKeyword */) { + markAsExternalModuleIfTopLevel(); + token = nextToken(); + if (token === 15 /* OpenBraceToken */) { + token = nextToken(); + // consume "{ a as B, c, d as D}" clauses + // make sure it stops on EOF + while (token !== 16 /* CloseBraceToken */ && token !== 1 /* EndOfFileToken */) { + token = nextToken(); + } + if (token === 16 /* CloseBraceToken */) { + token = nextToken(); + if (token === 136 /* FromKeyword */) { + token = nextToken(); + if (token === 9 /* StringLiteral */) { + // export {a as A} from "mod"; + // export {a, b as B} from "mod" + recordModuleName(); + } + } + } + } + else if (token === 37 /* AsteriskToken */) { + token = nextToken(); + if (token === 136 /* FromKeyword */) { + token = nextToken(); + if (token === 9 /* StringLiteral */) { + // export * from "mod" + recordModuleName(); + } + } + } + else if (token === 89 /* ImportKeyword */) { + token = nextToken(); + if (token === 69 /* Identifier */ || ts.isKeyword(token)) { + token = nextToken(); + if (token === 56 /* EqualsToken */) { + if (tryConsumeRequireCall(/*skipCurrentToken*/ true)) { + return true; + } + } + } + } + return true; + } + return false; + } + function tryConsumeRequireCall(skipCurrentToken) { + var token = skipCurrentToken ? nextToken() : ts.scanner.getToken(); + if (token === 129 /* RequireKeyword */) { + token = nextToken(); + if (token === 17 /* OpenParenToken */) { + token = nextToken(); + if (token === 9 /* StringLiteral */) { + // require("mod"); + recordModuleName(); + } + } + return true; + } + return false; + } + function tryConsumeDefine() { + var token = ts.scanner.getToken(); + if (token === 69 /* Identifier */ && ts.scanner.getTokenValue() === "define") { + token = nextToken(); + if (token !== 17 /* OpenParenToken */) { + return true; + } + token = nextToken(); + if (token === 9 /* StringLiteral */) { + // looks like define ("modname", ... - skip string literal and comma + token = nextToken(); + if (token === 24 /* CommaToken */) { + token = nextToken(); + } + else { + // unexpected token + return true; + } + } + // should be start of dependency list + if (token !== 19 /* OpenBracketToken */) { + return true; + } + // skip open bracket + token = nextToken(); + var i = 0; + // scan until ']' or EOF + while (token !== 20 /* CloseBracketToken */ && token !== 1 /* EndOfFileToken */) { + // record string literals as module names + if (token === 9 /* StringLiteral */) { + recordModuleName(); + i++; + } + token = nextToken(); + } + return true; + } + return false; + } + function processImports() { + ts.scanner.setText(sourceText); + nextToken(); + // Look for: + // import "mod"; + // import d from "mod" + // import {a as A } from "mod"; + // import * as NS from "mod" + // import d, {a, b as B} from "mod" + // import i = require("mod"); + // + // export * from "mod" + // export {a as b} from "mod" + // export import i = require("mod") + // (for JavaScript files) require("mod") + while (true) { + if (ts.scanner.getToken() === 1 /* EndOfFileToken */) { + break; + } + // check if at least one of alternative have moved scanner forward + if (tryConsumeDeclare() || + tryConsumeImport() || + tryConsumeExport() || + (detectJavaScriptImports && (tryConsumeRequireCall(/*skipCurrentToken*/ false) || tryConsumeDefine()))) { + continue; + } + else { + nextToken(); + } + } + ts.scanner.setText(undefined); + } + if (readImportFiles) { + processImports(); + } + processTripleSlashDirectives(); + if (externalModule) { + // for external modules module all nested ambient modules are augmentations + if (ambientExternalModules) { + // move all detected ambient modules to imported files since they need to be resolved + for (var _i = 0, ambientExternalModules_1 = ambientExternalModules; _i < ambientExternalModules_1.length; _i++) { + var decl = ambientExternalModules_1[_i]; + importedFiles.push(decl.ref); + } + } + return { referencedFiles: referencedFiles, typeReferenceDirectives: typeReferenceDirectives, importedFiles: importedFiles, isLibFile: isNoDefaultLib, ambientExternalModules: undefined }; + } + else { + // for global scripts ambient modules still can have augmentations - look for ambient modules with depth > 0 + var ambientModuleNames = void 0; + if (ambientExternalModules) { + for (var _a = 0, ambientExternalModules_2 = ambientExternalModules; _a < ambientExternalModules_2.length; _a++) { + var decl = ambientExternalModules_2[_a]; + if (decl.depth === 0) { + if (!ambientModuleNames) { + ambientModuleNames = []; + } + ambientModuleNames.push(decl.ref.fileName); + } + else { + importedFiles.push(decl.ref); + } + } + } + return { referencedFiles: referencedFiles, typeReferenceDirectives: typeReferenceDirectives, importedFiles: importedFiles, isLibFile: isNoDefaultLib, ambientExternalModules: ambientModuleNames }; + } + } + ts.preProcessFile = preProcessFile; +})(ts || (ts = {})); +/* @internal */ +var ts; +(function (ts) { + var Rename; + (function (Rename) { + function getRenameInfo(typeChecker, defaultLibFileName, getCanonicalFileName, sourceFile, position) { + var canonicalDefaultLibName = getCanonicalFileName(ts.normalizePath(defaultLibFileName)); + var node = ts.getTouchingWord(sourceFile, position, /*includeJsDocComment*/ true); + if (node) { + if (node.kind === 69 /* Identifier */ || + node.kind === 9 /* StringLiteral */ || + ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || + ts.isThis(node)) { + var symbol = typeChecker.getSymbolAtLocation(node); + // Only allow a symbol to be renamed if it actually has at least one declaration. + if (symbol) { + var declarations = symbol.getDeclarations(); + if (declarations && declarations.length > 0) { + // Disallow rename for elements that are defined in the standard TypeScript library. + if (ts.forEach(declarations, isDefinedInLibraryFile)) { + return getRenameInfoError(ts.getLocaleSpecificMessage(ts.Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library)); + } + var displayName = ts.stripQuotes(ts.getDeclaredName(typeChecker, symbol, node)); + var kind = ts.SymbolDisplay.getSymbolKind(typeChecker, symbol, node); + if (kind) { + return { + canRename: true, + kind: kind, + displayName: displayName, + localizedErrorMessage: undefined, + fullDisplayName: typeChecker.getFullyQualifiedName(symbol), + kindModifiers: ts.SymbolDisplay.getSymbolModifiers(symbol), + triggerSpan: createTriggerSpanForNode(node, sourceFile) + }; + } + } + } + else if (node.kind === 9 /* StringLiteral */) { + var type = ts.getStringLiteralTypeForNode(node, typeChecker); + if (type) { + if (isDefinedInLibraryFile(node)) { + return getRenameInfoError(ts.getLocaleSpecificMessage(ts.Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library)); + } + else { + var displayName = ts.stripQuotes(type.text); + return { + canRename: true, + kind: ts.ScriptElementKind.variableElement, + displayName: displayName, + localizedErrorMessage: undefined, + fullDisplayName: displayName, + kindModifiers: ts.ScriptElementKindModifier.none, + triggerSpan: createTriggerSpanForNode(node, sourceFile) + }; + } + } + } + } + } + return getRenameInfoError(ts.getLocaleSpecificMessage(ts.Diagnostics.You_cannot_rename_this_element)); + function getRenameInfoError(localizedErrorMessage) { + return { + canRename: false, + localizedErrorMessage: localizedErrorMessage, + displayName: undefined, + fullDisplayName: undefined, + kind: undefined, + kindModifiers: undefined, + triggerSpan: undefined + }; + } + function isDefinedInLibraryFile(declaration) { + if (defaultLibFileName) { + var sourceFile_2 = declaration.getSourceFile(); + var canonicalName = getCanonicalFileName(ts.normalizePath(sourceFile_2.fileName)); + if (canonicalName === canonicalDefaultLibName) { + return true; + } + } + return false; + } + function createTriggerSpanForNode(node, sourceFile) { + var start = node.getStart(sourceFile); + var width = node.getWidth(sourceFile); + if (node.kind === 9 /* StringLiteral */) { + // Exclude the quotes + start += 1; + width -= 2; + } + return ts.createTextSpan(start, width); + } + } + Rename.getRenameInfo = getRenameInfo; + })(Rename = ts.Rename || (ts.Rename = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var SignatureHelp; + (function (SignatureHelp) { + // A partially written generic type expression is not guaranteed to have the correct syntax tree. the expression could be parsed as less than/greater than expression or a comma expression + // or some other combination depending on what the user has typed so far. For the purposes of signature help we need to consider any location after "<" as a possible generic type reference. + // To do this, the method will back parse the expression starting at the position required. it will try to parse the current expression as a generic type expression, if it did succeed it + // will return the generic identifier that started the expression (e.g. "foo" in "foo(#a, b) -> The token introduces a list, and should begin a sig help session + // Case 2: + // fo#o#(a, b)# -> The token is either not associated with a list, or ends a list, so the session should end + // Case 3: + // foo(a#, #b#) -> The token is buried inside a list, and should give sig help + // Find out if 'node' is an argument, a type argument, or neither + if (node.kind === 25 /* LessThanToken */ || + node.kind === 17 /* OpenParenToken */) { + // Find the list that starts right *after* the < or ( token. + // If the user has just opened a list, consider this item 0. + var list = getChildListThatStartsWithOpenerToken(callExpression, node, sourceFile); + var isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos; + ts.Debug.assert(list !== undefined); + return { + kind: isTypeArgList ? 0 /* TypeArguments */ : 1 /* CallArguments */, + invocation: callExpression, + argumentsSpan: getApplicableSpanForArguments(list, sourceFile), + argumentIndex: 0, + argumentCount: getArgumentCount(list) + }; } - token = nextToken(); - if (token === 9 /* StringLiteral */) { - // looks like define ("modname", ... - skip string literal and comma - token = nextToken(); - if (token === 24 /* CommaToken */) { - token = nextToken(); - } - else { - // unexpected token - return true; - } + // findListItemInfo can return undefined if we are not in parent's argument list + // or type argument list. This includes cases where the cursor is: + // - To the right of the closing paren, non-substitution template, or template tail. + // - Between the type arguments and the arguments (greater than token) + // - On the target of the call (parent.func) + // - On the 'new' keyword in a 'new' expression + var listItemInfo = ts.findListItemInfo(node); + if (listItemInfo) { + var list = listItemInfo.list; + var isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos; + var argumentIndex = getArgumentIndex(list, node); + var argumentCount = getArgumentCount(list); + ts.Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, "argumentCount < argumentIndex, " + argumentCount + " < " + argumentIndex); + return { + kind: isTypeArgList ? 0 /* TypeArguments */ : 1 /* CallArguments */, + invocation: callExpression, + argumentsSpan: getApplicableSpanForArguments(list, sourceFile), + argumentIndex: argumentIndex, + argumentCount: argumentCount + }; } - // should be start of dependency list - if (token !== 19 /* OpenBracketToken */) { - return true; + return undefined; + } + else if (node.kind === 11 /* NoSubstitutionTemplateLiteral */ && node.parent.kind === 176 /* TaggedTemplateExpression */) { + // Check if we're actually inside the template; + // otherwise we'll fall out and return undefined. + if (ts.isInsideTemplateLiteral(node, position)) { + return getArgumentListInfoForTemplate(node.parent, /*argumentIndex*/ 0, sourceFile); } - // skip open bracket - token = nextToken(); - var i = 0; - // scan until ']' or EOF - while (token !== 20 /* CloseBracketToken */ && token !== 1 /* EndOfFileToken */) { - // record string literals as module names - if (token === 9 /* StringLiteral */) { - recordModuleName(); - i++; - } - token = nextToken(); + } + else if (node.kind === 12 /* TemplateHead */ && node.parent.parent.kind === 176 /* TaggedTemplateExpression */) { + var templateExpression = node.parent; + var tagExpression = templateExpression.parent; + ts.Debug.assert(templateExpression.kind === 189 /* TemplateExpression */); + var argumentIndex = ts.isInsideTemplateLiteral(node, position) ? 0 : 1; + return getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile); + } + else if (node.parent.kind === 197 /* TemplateSpan */ && node.parent.parent.parent.kind === 176 /* TaggedTemplateExpression */) { + var templateSpan = node.parent; + var templateExpression = templateSpan.parent; + var tagExpression = templateExpression.parent; + ts.Debug.assert(templateExpression.kind === 189 /* TemplateExpression */); + // If we're just after a template tail, don't show signature help. + if (node.kind === 14 /* TemplateTail */ && !ts.isInsideTemplateLiteral(node, position)) { + return undefined; } - return true; + var spanIndex = templateExpression.templateSpans.indexOf(templateSpan); + var argumentIndex = getArgumentIndexForTemplatePiece(spanIndex, node, position); + return getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile); } - return false; + return undefined; } - function processImports() { - scanner.setText(sourceText); - nextToken(); - // Look for: - // import "mod"; - // import d from "mod" - // import {a as A } from "mod"; - // import * as NS from "mod" - // import d, {a, b as B} from "mod" - // import i = require("mod"); + function getArgumentIndex(argumentsList, node) { + // The list we got back can include commas. In the presence of errors it may + // also just have nodes without commas. For example "Foo(a b c)" will have 3 + // args without commas. We want to find what index we're at. So we count + // forward until we hit ourselves, only incrementing the index if it isn't a + // comma. // - // export * from "mod" - // export {a as b} from "mod" - // export import i = require("mod") - // (for JavaScript files) require("mod") - while (true) { - if (scanner.getToken() === 1 /* EndOfFileToken */) { + // Note: the subtlety around trailing commas (in getArgumentCount) does not apply + // here. That's because we're only walking forward until we hit the node we're + // on. In that case, even if we're after the trailing comma, we'll still see + // that trailing comma in the list, and we'll have generated the appropriate + // arg index. + var argumentIndex = 0; + var listChildren = argumentsList.getChildren(); + for (var _i = 0, listChildren_1 = listChildren; _i < listChildren_1.length; _i++) { + var child = listChildren_1[_i]; + if (child === node) { break; } - // check if at least one of alternative have moved scanner forward - if (tryConsumeDeclare() || - tryConsumeImport() || - tryConsumeExport() || - (detectJavaScriptImports && (tryConsumeRequireCall(/*skipCurrentToken*/ false) || tryConsumeDefine()))) { - continue; - } - else { - nextToken(); + if (child.kind !== 24 /* CommaToken */) { + argumentIndex++; } } - scanner.setText(undefined); - } - if (readImportFiles) { - processImports(); + return argumentIndex; } - processTripleSlashDirectives(); - if (externalModule) { - // for external modules module all nested ambient modules are augmentations - if (ambientExternalModules) { - // move all detected ambient modules to imported files since they need to be resolved - for (var _i = 0, ambientExternalModules_1 = ambientExternalModules; _i < ambientExternalModules_1.length; _i++) { - var decl = ambientExternalModules_1[_i]; - importedFiles.push(decl.ref); - } + function getArgumentCount(argumentsList) { + // The argument count for a list is normally the number of non-comma children it has. + // For example, if you have "Foo(a,b)" then there will be three children of the arg + // list 'a' '' 'b'. So, in this case the arg count will be 2. However, there + // is a small subtlety. If you have "Foo(a,)", then the child list will just have + // 'a' ''. So, in the case where the last child is a comma, we increase the + // arg count by one to compensate. + // + // Note: this subtlety only applies to the last comma. If you had "Foo(a,," then + // we'll have: 'a' '' '' + // That will give us 2 non-commas. We then add one for the last comma, givin us an + // arg count of 3. + var listChildren = argumentsList.getChildren(); + var argumentCount = ts.countWhere(listChildren, function (arg) { return arg.kind !== 24 /* CommaToken */; }); + if (listChildren.length > 0 && ts.lastOrUndefined(listChildren).kind === 24 /* CommaToken */) { + argumentCount++; } - return { referencedFiles: referencedFiles, typeReferenceDirectives: typeReferenceDirectives, importedFiles: importedFiles, isLibFile: isNoDefaultLib, ambientExternalModules: undefined }; + return argumentCount; } - else { - // for global scripts ambient modules still can have augmentations - look for ambient modules with depth > 0 - var ambientModuleNames = void 0; - if (ambientExternalModules) { - for (var _a = 0, ambientExternalModules_2 = ambientExternalModules; _a < ambientExternalModules_2.length; _a++) { - var decl = ambientExternalModules_2[_a]; - if (decl.depth === 0) { - if (!ambientModuleNames) { - ambientModuleNames = []; - } - ambientModuleNames.push(decl.ref.fileName); - } - else { - importedFiles.push(decl.ref); - } + // spanIndex is either the index for a given template span. + // This does not give appropriate results for a NoSubstitutionTemplateLiteral + function getArgumentIndexForTemplatePiece(spanIndex, node, position) { + // Because the TemplateStringsArray is the first argument, we have to offset each substitution expression by 1. + // There are three cases we can encounter: + // 1. We are precisely in the template literal (argIndex = 0). + // 2. We are in or to the right of the substitution expression (argIndex = spanIndex + 1). + // 3. We are directly to the right of the template literal, but because we look for the token on the left, + // not enough to put us in the substitution expression; we should consider ourselves part of + // the *next* span's expression by offsetting the index (argIndex = (spanIndex + 1) + 1). + // + // Example: f `# abcd $#{# 1 + 1# }# efghi ${ #"#hello"# } # ` + // ^ ^ ^ ^ ^ ^ ^ ^ ^ + // Case: 1 1 3 2 1 3 2 2 1 + ts.Debug.assert(position >= node.getStart(), "Assumed 'position' could not occur before node."); + if (ts.isTemplateLiteralKind(node.kind)) { + if (ts.isInsideTemplateLiteral(node, position)) { + return 0; } + return spanIndex + 2; } - return { referencedFiles: referencedFiles, typeReferenceDirectives: typeReferenceDirectives, importedFiles: importedFiles, isLibFile: isNoDefaultLib, ambientExternalModules: ambientModuleNames }; + return spanIndex + 1; } - } - ts.preProcessFile = preProcessFile; - /// Helpers - function getTargetLabel(referenceNode, labelName) { - while (referenceNode) { - if (referenceNode.kind === 214 /* LabeledStatement */ && referenceNode.label.text === labelName) { - return referenceNode.label; - } - referenceNode = referenceNode.parent; + function getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile) { + // argumentCount is either 1 or (numSpans + 1) to account for the template strings array argument. + var argumentCount = tagExpression.template.kind === 11 /* NoSubstitutionTemplateLiteral */ + ? 1 + : tagExpression.template.templateSpans.length + 1; + ts.Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, "argumentCount < argumentIndex, " + argumentCount + " < " + argumentIndex); + return { + kind: 2 /* TaggedTemplateArguments */, + invocation: tagExpression, + argumentsSpan: getApplicableSpanForTaggedTemplate(tagExpression, sourceFile), + argumentIndex: argumentIndex, + argumentCount: argumentCount + }; } - return undefined; - } - function isJumpStatementTarget(node) { - return node.kind === 69 /* Identifier */ && - (node.parent.kind === 210 /* BreakStatement */ || node.parent.kind === 209 /* ContinueStatement */) && - node.parent.label === node; - } - function isLabelOfLabeledStatement(node) { - return node.kind === 69 /* Identifier */ && - node.parent.kind === 214 /* LabeledStatement */ && - node.parent.label === node; - } - /** - * Whether or not a 'node' is preceded by a label of the given string. - * Note: 'node' cannot be a SourceFile. - */ - function isLabeledBy(node, labelName) { - for (var owner = node.parent; owner.kind === 214 /* LabeledStatement */; owner = owner.parent) { - if (owner.label.text === labelName) { - return true; - } + function getApplicableSpanForArguments(argumentsList, sourceFile) { + // We use full start and skip trivia on the end because we want to include trivia on + // both sides. For example, + // + // foo( /*comment */ a, b, c /*comment*/ ) + // | | + // + // The applicable span is from the first bar to the second bar (inclusive, + // but not including parentheses) + var applicableSpanStart = argumentsList.getFullStart(); + var applicableSpanEnd = ts.skipTrivia(sourceFile.text, argumentsList.getEnd(), /*stopAfterLineBreak*/ false); + return ts.createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart); } - return false; - } - function isLabelName(node) { - return isLabelOfLabeledStatement(node) || isJumpStatementTarget(node); - } - function isRightSideOfQualifiedName(node) { - return node.parent.kind === 139 /* QualifiedName */ && node.parent.right === node; - } - function isRightSideOfPropertyAccess(node) { - return node && node.parent && node.parent.kind === 172 /* PropertyAccessExpression */ && node.parent.name === node; - } - function climbPastPropertyAccess(node) { - return isRightSideOfPropertyAccess(node) ? node.parent : node; - } - /** Get `C` given `N` if `N` is in the position `class C extends N` or `class C extends foo.N` where `N` is an identifier. */ - function tryGetClassByExtendingIdentifier(node) { - return ts.tryGetClassExtendingExpressionWithTypeArguments(climbPastPropertyAccess(node).parent); - } - function isCallExpressionTarget(node) { - return isCallOrNewExpressionTarget(node, 174 /* CallExpression */); - } - function isNewExpressionTarget(node) { - return isCallOrNewExpressionTarget(node, 175 /* NewExpression */); - } - function isCallOrNewExpressionTarget(node, kind) { - var target = climbPastPropertyAccess(node); - return target && target.parent && target.parent.kind === kind && target.parent.expression === target; - } - function climbPastManyPropertyAccesses(node) { - return isRightSideOfPropertyAccess(node) ? climbPastManyPropertyAccesses(node.parent) : node; - } - /** Returns a CallLikeExpression where `node` is the target being invoked. */ - function getAncestorCallLikeExpression(node) { - var target = climbPastManyPropertyAccesses(node); - var callLike = target.parent; - return callLike && ts.isCallLikeExpression(callLike) && ts.getInvokedExpression(callLike) === target && callLike; - } - function tryGetSignatureDeclaration(typeChecker, node) { - var callLike = getAncestorCallLikeExpression(node); - return callLike && typeChecker.getResolvedSignature(callLike).declaration; - } - function isNameOfModuleDeclaration(node) { - return node.parent.kind === 225 /* ModuleDeclaration */ && node.parent.name === node; - } - function isNameOfFunctionDeclaration(node) { - return node.kind === 69 /* Identifier */ && - ts.isFunctionLike(node.parent) && node.parent.name === node; - } - function isObjectLiteralPropertyDeclaration(node) { - switch (node.kind) { - case 253 /* PropertyAssignment */: - case 254 /* ShorthandPropertyAssignment */: - case 147 /* MethodDeclaration */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - return true; + function getApplicableSpanForTaggedTemplate(taggedTemplate, sourceFile) { + var template = taggedTemplate.template; + var applicableSpanStart = template.getStart(); + var applicableSpanEnd = template.getEnd(); + // We need to adjust the end position for the case where the template does not have a tail. + // Otherwise, we will not show signature help past the expression. + // For example, + // + // ` ${ 1 + 1 foo(10) + // | | + // + // This is because a Missing node has no width. However, what we actually want is to include trivia + // leading up to the next token in case the user is about to type in a TemplateMiddle or TemplateTail. + if (template.kind === 189 /* TemplateExpression */) { + var lastSpan = ts.lastOrUndefined(template.templateSpans); + if (lastSpan.literal.getFullWidth() === 0) { + applicableSpanEnd = ts.skipTrivia(sourceFile.text, applicableSpanEnd, /*stopAfterLineBreak*/ false); + } + } + return ts.createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart); } - return false; - } - /** - * Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 } - */ - function getContainingObjectLiteralElement(node) { - switch (node.kind) { - case 9 /* StringLiteral */: - case 8 /* NumericLiteral */: - if (node.parent.kind === 140 /* ComputedPropertyName */) { - return isObjectLiteralPropertyDeclaration(node.parent.parent) ? node.parent.parent : undefined; + function getContainingArgumentInfo(node, position, sourceFile) { + for (var n = node; n.kind !== 256 /* SourceFile */; n = n.parent) { + if (ts.isFunctionBlock(n)) { + return undefined; } - // intential fall through - case 69 /* Identifier */: - return isObjectLiteralPropertyDeclaration(node.parent) && node.parent.name === node ? node.parent : undefined; + // If the node is not a subspan of its parent, this is a big problem. + // There have been crashes that might be caused by this violation. + if (n.pos < n.parent.pos || n.end > n.parent.end) { + ts.Debug.fail("Node of kind " + n.kind + " is not a subspan of its parent of kind " + n.parent.kind); + } + var argumentInfo = getImmediatelyContainingArgumentInfo(n, position, sourceFile); + if (argumentInfo) { + return argumentInfo; + } + } + return undefined; } - return undefined; - } - function isLiteralNameOfPropertyDeclarationOrIndexAccess(node) { - if (node.kind === 9 /* StringLiteral */ || node.kind === 8 /* NumericLiteral */) { - switch (node.parent.kind) { - case 145 /* PropertyDeclaration */: - case 144 /* PropertySignature */: - case 253 /* PropertyAssignment */: - case 255 /* EnumMember */: - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 225 /* ModuleDeclaration */: - return node.parent.name === node; - case 173 /* ElementAccessExpression */: - return node.parent.argumentExpression === node; - case 140 /* ComputedPropertyName */: - return true; + SignatureHelp.getContainingArgumentInfo = getContainingArgumentInfo; + function getChildListThatStartsWithOpenerToken(parent, openerToken, sourceFile) { + var children = parent.getChildren(sourceFile); + var indexOfOpenerToken = children.indexOf(openerToken); + ts.Debug.assert(indexOfOpenerToken >= 0 && children.length > indexOfOpenerToken + 1); + return children[indexOfOpenerToken + 1]; + } + /** + * The selectedItemIndex could be negative for several reasons. + * 1. There are too many arguments for all of the overloads + * 2. None of the overloads were type compatible + * The solution here is to try to pick the best overload by picking + * either the first one that has an appropriate number of parameters, + * or the one with the most parameters. + */ + function selectBestInvalidOverloadIndex(candidates, argumentCount) { + var maxParamsSignatureIndex = -1; + var maxParams = -1; + for (var i = 0; i < candidates.length; i++) { + var candidate = candidates[i]; + if (candidate.hasRestParameter || candidate.parameters.length >= argumentCount) { + return i; + } + if (candidate.parameters.length > maxParams) { + maxParams = candidate.parameters.length; + maxParamsSignatureIndex = i; + } } + return maxParamsSignatureIndex; } - return false; - } - function isNameOfExternalModuleImportOrDeclaration(node) { - if (node.kind === 9 /* StringLiteral */) { - return isNameOfModuleDeclaration(node) || - (ts.isExternalModuleImportEqualsDeclaration(node.parent.parent) && ts.getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node); - } - return false; - } - /** Returns true if the position is within a comment */ - function isInsideComment(sourceFile, token, position) { - // The position has to be: 1. in the leading trivia (before token.getStart()), and 2. within a comment - return position <= token.getStart(sourceFile) && - (isInsideCommentRange(ts.getTrailingCommentRanges(sourceFile.text, token.getFullStart())) || - isInsideCommentRange(ts.getLeadingCommentRanges(sourceFile.text, token.getFullStart()))); - function isInsideCommentRange(comments) { - return ts.forEach(comments, function (comment) { - // either we are 1. completely inside the comment, or 2. at the end of the comment - if (comment.pos < position && position < comment.end) { - return true; + function createSignatureHelpItems(candidates, bestSignature, argumentListInfo, typeChecker) { + var applicableSpan = argumentListInfo.argumentsSpan; + var isTypeParameterList = argumentListInfo.kind === 0 /* TypeArguments */; + var invocation = argumentListInfo.invocation; + var callTarget = ts.getInvokedExpression(invocation); + var callTargetSymbol = typeChecker.getSymbolAtLocation(callTarget); + var callTargetDisplayParts = callTargetSymbol && ts.symbolToDisplayParts(typeChecker, callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined); + var items = ts.map(candidates, function (candidateSignature) { + var signatureHelpParameters; + var prefixDisplayParts = []; + var suffixDisplayParts = []; + if (callTargetDisplayParts) { + ts.addRange(prefixDisplayParts, callTargetDisplayParts); } - else if (position === comment.end) { - var text = sourceFile.text; - var width = comment.end - comment.pos; - // is single line comment or just /* - if (width <= 2 || text.charCodeAt(comment.pos + 1) === 47 /* slash */) { - return true; - } - else { - // is unterminated multi-line comment - return !(text.charCodeAt(comment.end - 1) === 47 /* slash */ && - text.charCodeAt(comment.end - 2) === 42 /* asterisk */); - } + if (isTypeParameterList) { + prefixDisplayParts.push(ts.punctuationPart(25 /* LessThanToken */)); + var typeParameters = candidateSignature.typeParameters; + signatureHelpParameters = typeParameters && typeParameters.length > 0 ? ts.map(typeParameters, createSignatureHelpParameterForTypeParameter) : emptyArray; + suffixDisplayParts.push(ts.punctuationPart(27 /* GreaterThanToken */)); + var parameterParts = ts.mapToDisplayParts(function (writer) { + return typeChecker.getSymbolDisplayBuilder().buildDisplayForParametersAndDelimiters(candidateSignature.thisParameter, candidateSignature.parameters, writer, invocation); + }); + ts.addRange(suffixDisplayParts, parameterParts); } - return false; + else { + var typeParameterParts = ts.mapToDisplayParts(function (writer) { + return typeChecker.getSymbolDisplayBuilder().buildDisplayForTypeParametersAndDelimiters(candidateSignature.typeParameters, writer, invocation); + }); + ts.addRange(prefixDisplayParts, typeParameterParts); + prefixDisplayParts.push(ts.punctuationPart(17 /* OpenParenToken */)); + var parameters = candidateSignature.parameters; + signatureHelpParameters = parameters.length > 0 ? ts.map(parameters, createSignatureHelpParameterForParameter) : emptyArray; + suffixDisplayParts.push(ts.punctuationPart(18 /* CloseParenToken */)); + } + var returnTypeParts = ts.mapToDisplayParts(function (writer) { + return typeChecker.getSymbolDisplayBuilder().buildReturnTypeDisplay(candidateSignature, writer, invocation); + }); + ts.addRange(suffixDisplayParts, returnTypeParts); + return { + isVariadic: candidateSignature.hasRestParameter, + prefixDisplayParts: prefixDisplayParts, + suffixDisplayParts: suffixDisplayParts, + separatorDisplayParts: [ts.punctuationPart(24 /* CommaToken */), ts.spacePart()], + parameters: signatureHelpParameters, + documentation: candidateSignature.getDocumentationComment() + }; }); - } - } - var SemanticMeaning; - (function (SemanticMeaning) { - SemanticMeaning[SemanticMeaning["None"] = 0] = "None"; - SemanticMeaning[SemanticMeaning["Value"] = 1] = "Value"; - SemanticMeaning[SemanticMeaning["Type"] = 2] = "Type"; - SemanticMeaning[SemanticMeaning["Namespace"] = 4] = "Namespace"; - SemanticMeaning[SemanticMeaning["All"] = 7] = "All"; - })(SemanticMeaning || (SemanticMeaning = {})); - var BreakContinueSearchType; - (function (BreakContinueSearchType) { - BreakContinueSearchType[BreakContinueSearchType["None"] = 0] = "None"; - BreakContinueSearchType[BreakContinueSearchType["Unlabeled"] = 1] = "Unlabeled"; - BreakContinueSearchType[BreakContinueSearchType["Labeled"] = 2] = "Labeled"; - BreakContinueSearchType[BreakContinueSearchType["All"] = 3] = "All"; - })(BreakContinueSearchType || (BreakContinueSearchType = {})); - // A cache of completion entries for keywords, these do not change between sessions - var keywordCompletions = []; - for (var i = 70 /* FirstKeyword */; i <= 138 /* LastKeyword */; i++) { - keywordCompletions.push({ - name: ts.tokenToString(i), - kind: ts.ScriptElementKind.keyword, - kindModifiers: ts.ScriptElementKindModifier.none, - sortText: "0" - }); - } - /* @internal */ function getContainerNode(node) { - while (true) { - node = node.parent; - if (!node) { - return undefined; + var argumentIndex = argumentListInfo.argumentIndex; + // argumentCount is the *apparent* number of arguments. + var argumentCount = argumentListInfo.argumentCount; + var selectedItemIndex = candidates.indexOf(bestSignature); + if (selectedItemIndex < 0) { + selectedItemIndex = selectBestInvalidOverloadIndex(candidates, argumentCount); } - switch (node.kind) { - case 256 /* SourceFile */: - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 221 /* ClassDeclaration */: - case 222 /* InterfaceDeclaration */: - case 224 /* EnumDeclaration */: - case 225 /* ModuleDeclaration */: - return node; + ts.Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, "argumentCount < argumentIndex, " + argumentCount + " < " + argumentIndex); + return { + items: items, + applicableSpan: applicableSpan, + selectedItemIndex: selectedItemIndex, + argumentIndex: argumentIndex, + argumentCount: argumentCount + }; + function createSignatureHelpParameterForParameter(parameter) { + var displayParts = ts.mapToDisplayParts(function (writer) { + return typeChecker.getSymbolDisplayBuilder().buildParameterDisplay(parameter, writer, invocation); + }); + return { + name: parameter.name, + documentation: parameter.getDocumentationComment(), + displayParts: displayParts, + isOptional: typeChecker.isOptionalParameter(parameter.valueDeclaration) + }; + } + function createSignatureHelpParameterForTypeParameter(typeParameter) { + var displayParts = ts.mapToDisplayParts(function (writer) { + return typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(typeParameter, writer, invocation); + }); + return { + name: typeParameter.symbol.name, + documentation: emptyArray, + displayParts: displayParts, + isOptional: false + }; } } - } - ts.getContainerNode = getContainerNode; - /* @internal */ function getNodeKind(node) { - switch (node.kind) { - case 256 /* SourceFile */: - return ts.isExternalModule(node) ? ts.ScriptElementKind.moduleElement : ts.ScriptElementKind.scriptElement; - case 225 /* ModuleDeclaration */: - return ts.ScriptElementKind.moduleElement; - case 221 /* ClassDeclaration */: - case 192 /* ClassExpression */: - return ts.ScriptElementKind.classElement; - case 222 /* InterfaceDeclaration */: return ts.ScriptElementKind.interfaceElement; - case 223 /* TypeAliasDeclaration */: return ts.ScriptElementKind.typeElement; - case 224 /* EnumDeclaration */: return ts.ScriptElementKind.enumElement; - case 218 /* VariableDeclaration */: - return getKindOfVariableDeclaration(node); - case 169 /* BindingElement */: - return getKindOfVariableDeclaration(ts.getRootDeclaration(node)); - case 180 /* ArrowFunction */: - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - return ts.ScriptElementKind.functionElement; - case 149 /* GetAccessor */: return ts.ScriptElementKind.memberGetAccessorElement; - case 150 /* SetAccessor */: return ts.ScriptElementKind.memberSetAccessorElement; - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - return ts.ScriptElementKind.memberFunctionElement; - case 145 /* PropertyDeclaration */: - case 144 /* PropertySignature */: - return ts.ScriptElementKind.memberVariableElement; - case 153 /* IndexSignature */: return ts.ScriptElementKind.indexSignatureElement; - case 152 /* ConstructSignature */: return ts.ScriptElementKind.constructSignatureElement; - case 151 /* CallSignature */: return ts.ScriptElementKind.callSignatureElement; - case 148 /* Constructor */: return ts.ScriptElementKind.constructorImplementationElement; - case 141 /* TypeParameter */: return ts.ScriptElementKind.typeParameterElement; - case 255 /* EnumMember */: return ts.ScriptElementKind.enumMemberElement; - case 142 /* Parameter */: return (node.flags & 92 /* ParameterPropertyModifier */) ? ts.ScriptElementKind.memberVariableElement : ts.ScriptElementKind.parameterElement; - case 229 /* ImportEqualsDeclaration */: - case 234 /* ImportSpecifier */: - case 231 /* ImportClause */: - case 238 /* ExportSpecifier */: - case 232 /* NamespaceImport */: - return ts.ScriptElementKind.alias; - case 279 /* JSDocTypedefTag */: + })(SignatureHelp = ts.SignatureHelp || (ts.SignatureHelp = {})); +})(ts || (ts = {})); +/* @internal */ +var ts; +(function (ts) { + var SymbolDisplay; + (function (SymbolDisplay) { + // TODO(drosen): use contextual SemanticMeaning. + function getSymbolKind(typeChecker, symbol, location) { + var flags = symbol.getFlags(); + if (flags & 32 /* Class */) + return ts.getDeclarationOfKind(symbol, 192 /* ClassExpression */) ? + ts.ScriptElementKind.localClassElement : ts.ScriptElementKind.classElement; + if (flags & 384 /* Enum */) + return ts.ScriptElementKind.enumElement; + if (flags & 524288 /* TypeAlias */) return ts.ScriptElementKind.typeElement; - default: - return ts.ScriptElementKind.unknown; - } - function getKindOfVariableDeclaration(v) { - return ts.isConst(v) - ? ts.ScriptElementKind.constElement - : ts.isLet(v) - ? ts.ScriptElementKind.letElement - : ts.ScriptElementKind.variableElement; - } - } - ts.getNodeKind = getNodeKind; - var CancellationTokenObject = (function () { - function CancellationTokenObject(cancellationToken) { - this.cancellationToken = cancellationToken; - } - CancellationTokenObject.prototype.isCancellationRequested = function () { - return this.cancellationToken && this.cancellationToken.isCancellationRequested(); - }; - CancellationTokenObject.prototype.throwIfCancellationRequested = function () { - if (this.isCancellationRequested()) { - throw new ts.OperationCanceledException(); + if (flags & 64 /* Interface */) + return ts.ScriptElementKind.interfaceElement; + if (flags & 262144 /* TypeParameter */) + return ts.ScriptElementKind.typeParameterElement; + var result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, flags, location); + if (result === ts.ScriptElementKind.unknown) { + if (flags & 262144 /* TypeParameter */) + return ts.ScriptElementKind.typeParameterElement; + if (flags & 8 /* EnumMember */) + return ts.ScriptElementKind.variableElement; + if (flags & 8388608 /* Alias */) + return ts.ScriptElementKind.alias; + if (flags & 1536 /* Module */) + return ts.ScriptElementKind.moduleElement; } - }; - return CancellationTokenObject; - }()); - function createLanguageService(host, documentRegistry) { - if (documentRegistry === void 0) { documentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory()); } - var syntaxTreeCache = new SyntaxTreeCache(host); - var ruleProvider; - var program; - var lastProjectVersion; - var useCaseSensitivefileNames = false; - var cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken()); - var currentDirectory = host.getCurrentDirectory(); - // Check if the localized messages json is set, otherwise query the host for it - if (!ts.localizedDiagnosticMessages && host.getLocalizedDiagnosticMessages) { - ts.localizedDiagnosticMessages = host.getLocalizedDiagnosticMessages(); + return result; } - function log(message) { - if (host.log) { - host.log(message); + SymbolDisplay.getSymbolKind = getSymbolKind; + function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, flags, location) { + if (typeChecker.isUndefinedSymbol(symbol)) { + return ts.ScriptElementKind.variableElement; } - } - var getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitivefileNames); - function getValidSourceFile(fileName) { - var sourceFile = program.getSourceFile(fileName); - if (!sourceFile) { - throw new Error("Could not find file: '" + fileName + "'."); + if (typeChecker.isArgumentsSymbol(symbol)) { + return ts.ScriptElementKind.localVariableElement; } - return sourceFile; - } - function getRuleProvider(options) { - // Ensure rules are initialized and up to date wrt to formatting options - if (!ruleProvider) { - ruleProvider = new ts.formatting.RulesProvider(); + if (location.kind === 97 /* ThisKeyword */ && ts.isExpression(location)) { + return ts.ScriptElementKind.parameterElement; } - ruleProvider.ensureUpToDate(options); - return ruleProvider; - } - function synchronizeHostData() { - // perform fast check if host supports it - if (host.getProjectVersion) { - var hostProjectVersion = host.getProjectVersion(); - if (hostProjectVersion) { - if (lastProjectVersion === hostProjectVersion) { - return; - } - lastProjectVersion = hostProjectVersion; + if (flags & 3 /* Variable */) { + if (ts.isFirstDeclarationOfSymbolParameter(symbol)) { + return ts.ScriptElementKind.parameterElement; } + else if (symbol.valueDeclaration && ts.isConst(symbol.valueDeclaration)) { + return ts.ScriptElementKind.constElement; + } + else if (ts.forEach(symbol.declarations, ts.isLet)) { + return ts.ScriptElementKind.letElement; + } + return isLocalVariableOrFunction(symbol) ? ts.ScriptElementKind.localVariableElement : ts.ScriptElementKind.variableElement; } - // Get a fresh cache of the host information - var hostCache = new HostCache(host, getCanonicalFileName); - // If the program is already up-to-date, we can reuse it - if (programUpToDate()) { - return; + if (flags & 16 /* Function */) + return isLocalVariableOrFunction(symbol) ? ts.ScriptElementKind.localFunctionElement : ts.ScriptElementKind.functionElement; + if (flags & 32768 /* GetAccessor */) + return ts.ScriptElementKind.memberGetAccessorElement; + if (flags & 65536 /* SetAccessor */) + return ts.ScriptElementKind.memberSetAccessorElement; + if (flags & 8192 /* Method */) + return ts.ScriptElementKind.memberFunctionElement; + if (flags & 16384 /* Constructor */) + return ts.ScriptElementKind.constructorImplementationElement; + if (flags & 4 /* Property */) { + if (flags & 268435456 /* SyntheticProperty */) { + // If union property is result of union of non method (property/accessors/variables), it is labeled as property + var unionPropertyKind = ts.forEach(typeChecker.getRootSymbols(symbol), function (rootSymbol) { + var rootSymbolFlags = rootSymbol.getFlags(); + if (rootSymbolFlags & (98308 /* PropertyOrAccessor */ | 3 /* Variable */)) { + return ts.ScriptElementKind.memberVariableElement; + } + ts.Debug.assert(!!(rootSymbolFlags & 8192 /* Method */)); + }); + if (!unionPropertyKind) { + // If this was union of all methods, + // make sure it has call signatures before we can label it as method + var typeOfUnionProperty = typeChecker.getTypeOfSymbolAtLocation(symbol, location); + if (typeOfUnionProperty.getCallSignatures().length) { + return ts.ScriptElementKind.memberFunctionElement; + } + return ts.ScriptElementKind.memberVariableElement; + } + return unionPropertyKind; + } + return ts.ScriptElementKind.memberVariableElement; } - // IMPORTANT - It is critical from this moment onward that we do not check - // cancellation tokens. We are about to mutate source files from a previous program - // instance. If we cancel midway through, we may end up in an inconsistent state where - // the program points to old source files that have been invalidated because of - // incremental parsing. - var oldSettings = program && program.getCompilerOptions(); - var newSettings = hostCache.compilationSettings(); - var shouldCreateNewSourceFiles = oldSettings && - (oldSettings.target !== newSettings.target || - oldSettings.module !== newSettings.module || - oldSettings.moduleResolution !== newSettings.moduleResolution || - oldSettings.noResolve !== newSettings.noResolve || - oldSettings.jsx !== newSettings.jsx || - oldSettings.allowJs !== newSettings.allowJs || - oldSettings.disableSizeLimit !== oldSettings.disableSizeLimit || - oldSettings.baseUrl !== newSettings.baseUrl || - !ts.equalOwnProperties(oldSettings.paths, newSettings.paths)); - // Now create a new compiler - var compilerHost = { - getSourceFile: getOrCreateSourceFile, - getSourceFileByPath: getOrCreateSourceFileByPath, - getCancellationToken: function () { return cancellationToken; }, - getCanonicalFileName: getCanonicalFileName, - useCaseSensitiveFileNames: function () { return useCaseSensitivefileNames; }, - getNewLine: function () { return ts.getNewLineOrDefaultFromHost(host); }, - getDefaultLibFileName: function (options) { return host.getDefaultLibFileName(options); }, - writeFile: function (fileName, data, writeByteOrderMark) { }, - getCurrentDirectory: function () { return currentDirectory; }, - fileExists: function (fileName) { - // stub missing host functionality - return hostCache.getOrCreateEntry(fileName) !== undefined; - }, - readFile: function (fileName) { - // stub missing host functionality - var entry = hostCache.getOrCreateEntry(fileName); - return entry && entry.scriptSnapshot.getText(0, entry.scriptSnapshot.getLength()); - }, - directoryExists: function (directoryName) { - return ts.directoryProbablyExists(directoryName, host); - }, - getDirectories: function (path) { - return host.getDirectories ? host.getDirectories(path) : []; + return ts.ScriptElementKind.unknown; + } + function getSymbolModifiers(symbol) { + return symbol && symbol.declarations && symbol.declarations.length > 0 + ? ts.getNodeModifiers(symbol.declarations[0]) + : ts.ScriptElementKindModifier.none; + } + SymbolDisplay.getSymbolModifiers = getSymbolModifiers; + // TODO(drosen): Currently completion entry details passes the SemanticMeaning.All instead of using semanticMeaning of location + function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, sourceFile, enclosingDeclaration, location, semanticMeaning) { + if (semanticMeaning === void 0) { semanticMeaning = ts.getMeaningFromLocation(location); } + var displayParts = []; + var documentation; + var symbolFlags = symbol.flags; + var symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, symbolFlags, location); + var hasAddedSymbolInfo; + var isThisExpression = location.kind === 97 /* ThisKeyword */ && ts.isExpression(location); + var type; + // Class at constructor site need to be shown as constructor apart from property,method, vars + if (symbolKind !== ts.ScriptElementKind.unknown || symbolFlags & 32 /* Class */ || symbolFlags & 8388608 /* Alias */) { + // If it is accessor they are allowed only if location is at name of the accessor + if (symbolKind === ts.ScriptElementKind.memberGetAccessorElement || symbolKind === ts.ScriptElementKind.memberSetAccessorElement) { + symbolKind = ts.ScriptElementKind.memberVariableElement; + } + var signature = void 0; + type = isThisExpression ? typeChecker.getTypeAtLocation(location) : typeChecker.getTypeOfSymbolAtLocation(symbol, location); + if (type) { + if (location.parent && location.parent.kind === 172 /* PropertyAccessExpression */) { + var right = location.parent.name; + // Either the location is on the right of a property access, or on the left and the right is missing + if (right === location || (right && right.getFullWidth() === 0)) { + location = location.parent; + } + } + // try get the call/construct signature from the type if it matches + var callExpression = void 0; + if (location.kind === 174 /* CallExpression */ || location.kind === 175 /* NewExpression */) { + callExpression = location; + } + else if (ts.isCallExpressionTarget(location) || ts.isNewExpressionTarget(location)) { + callExpression = location.parent; + } + if (callExpression) { + var candidateSignatures = []; + signature = typeChecker.getResolvedSignature(callExpression, candidateSignatures); + if (!signature && candidateSignatures.length) { + // Use the first candidate: + signature = candidateSignatures[0]; + } + var useConstructSignatures = callExpression.kind === 175 /* NewExpression */ || callExpression.expression.kind === 95 /* SuperKeyword */; + var allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures(); + if (!ts.contains(allSignatures, signature.target) && !ts.contains(allSignatures, signature)) { + // Get the first signature if there is one -- allSignatures may contain + // either the original signature or its target, so check for either + signature = allSignatures.length ? allSignatures[0] : undefined; + } + if (signature) { + if (useConstructSignatures && (symbolFlags & 32 /* Class */)) { + // Constructor + symbolKind = ts.ScriptElementKind.constructorImplementationElement; + addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); + } + else if (symbolFlags & 8388608 /* Alias */) { + symbolKind = ts.ScriptElementKind.alias; + pushTypePart(symbolKind); + displayParts.push(ts.spacePart()); + if (useConstructSignatures) { + displayParts.push(ts.keywordPart(92 /* NewKeyword */)); + displayParts.push(ts.spacePart()); + } + addFullSymbolName(symbol); + } + else { + addPrefixForAnyFunctionOrVar(symbol, symbolKind); + } + switch (symbolKind) { + case ts.ScriptElementKind.memberVariableElement: + case ts.ScriptElementKind.variableElement: + case ts.ScriptElementKind.constElement: + case ts.ScriptElementKind.letElement: + case ts.ScriptElementKind.parameterElement: + case ts.ScriptElementKind.localVariableElement: + // If it is call or construct signature of lambda's write type name + displayParts.push(ts.punctuationPart(54 /* ColonToken */)); + displayParts.push(ts.spacePart()); + if (useConstructSignatures) { + displayParts.push(ts.keywordPart(92 /* NewKeyword */)); + displayParts.push(ts.spacePart()); + } + if (!(type.flags & 2097152 /* Anonymous */) && type.symbol) { + ts.addRange(displayParts, ts.symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, 1 /* WriteTypeParametersOrArguments */)); + } + addSignatureDisplayParts(signature, allSignatures, 8 /* WriteArrowStyleSignature */); + break; + default: + // Just signature + addSignatureDisplayParts(signature, allSignatures); + } + hasAddedSymbolInfo = true; + } + } + else if ((ts.isNameOfFunctionDeclaration(location) && !(symbol.flags & 98304 /* Accessor */)) || + (location.kind === 121 /* ConstructorKeyword */ && location.parent.kind === 148 /* Constructor */)) { + // get the signature from the declaration and write it + var functionDeclaration = location.parent; + var allSignatures = functionDeclaration.kind === 148 /* Constructor */ ? type.getNonNullableType().getConstructSignatures() : type.getNonNullableType().getCallSignatures(); + if (!typeChecker.isImplementationOfOverload(functionDeclaration)) { + signature = typeChecker.getSignatureFromDeclaration(functionDeclaration); + } + else { + signature = allSignatures[0]; + } + if (functionDeclaration.kind === 148 /* Constructor */) { + // show (constructor) Type(...) signature + symbolKind = ts.ScriptElementKind.constructorImplementationElement; + addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); + } + else { + // (function/method) symbol(..signature) + addPrefixForAnyFunctionOrVar(functionDeclaration.kind === 151 /* CallSignature */ && + !(type.symbol.flags & 2048 /* TypeLiteral */ || type.symbol.flags & 4096 /* ObjectLiteral */) ? type.symbol : symbol, symbolKind); + } + addSignatureDisplayParts(signature, allSignatures); + hasAddedSymbolInfo = true; + } } - }; - if (host.trace) { - compilerHost.trace = function (message) { return host.trace(message); }; } - if (host.resolveModuleNames) { - compilerHost.resolveModuleNames = function (moduleNames, containingFile) { return host.resolveModuleNames(moduleNames, containingFile); }; + if (symbolFlags & 32 /* Class */ && !hasAddedSymbolInfo && !isThisExpression) { + if (ts.getDeclarationOfKind(symbol, 192 /* ClassExpression */)) { + // Special case for class expressions because we would like to indicate that + // the class name is local to the class body (similar to function expression) + // (local class) class + pushTypePart(ts.ScriptElementKind.localClassElement); + } + else { + // Class declaration has name which is not local. + displayParts.push(ts.keywordPart(73 /* ClassKeyword */)); + } + displayParts.push(ts.spacePart()); + addFullSymbolName(symbol); + writeTypeParametersOfSymbol(symbol, sourceFile); } - if (host.resolveTypeReferenceDirectives) { - compilerHost.resolveTypeReferenceDirectives = function (typeReferenceDirectiveNames, containingFile) { - return host.resolveTypeReferenceDirectives(typeReferenceDirectiveNames, containingFile); - }; + if ((symbolFlags & 64 /* Interface */) && (semanticMeaning & 2 /* Type */)) { + addNewLineIfDisplayPartsExist(); + displayParts.push(ts.keywordPart(107 /* InterfaceKeyword */)); + displayParts.push(ts.spacePart()); + addFullSymbolName(symbol); + writeTypeParametersOfSymbol(symbol, sourceFile); } - var documentRegistryBucketKey = documentRegistry.getKeyForCompilationSettings(newSettings); - var newProgram = ts.createProgram(hostCache.getRootFileNames(), newSettings, compilerHost, program); - // Release any files we have acquired in the old program but are - // not part of the new program. - if (program) { - var oldSourceFiles = program.getSourceFiles(); - var oldSettingsKey = documentRegistry.getKeyForCompilationSettings(oldSettings); - for (var _i = 0, oldSourceFiles_1 = oldSourceFiles; _i < oldSourceFiles_1.length; _i++) { - var oldSourceFile = oldSourceFiles_1[_i]; - if (!newProgram.getSourceFile(oldSourceFile.fileName) || shouldCreateNewSourceFiles) { - documentRegistry.releaseDocumentWithKey(oldSourceFile.path, oldSettingsKey); - } + if (symbolFlags & 524288 /* TypeAlias */) { + addNewLineIfDisplayPartsExist(); + displayParts.push(ts.keywordPart(134 /* TypeKeyword */)); + displayParts.push(ts.spacePart()); + addFullSymbolName(symbol); + writeTypeParametersOfSymbol(symbol, sourceFile); + displayParts.push(ts.spacePart()); + displayParts.push(ts.operatorPart(56 /* EqualsToken */)); + displayParts.push(ts.spacePart()); + ts.addRange(displayParts, ts.typeToDisplayParts(typeChecker, typeChecker.getDeclaredTypeOfSymbol(symbol), enclosingDeclaration, 512 /* InTypeAlias */)); + } + if (symbolFlags & 384 /* Enum */) { + addNewLineIfDisplayPartsExist(); + if (ts.forEach(symbol.declarations, ts.isConstEnumDeclaration)) { + displayParts.push(ts.keywordPart(74 /* ConstKeyword */)); + displayParts.push(ts.spacePart()); } + displayParts.push(ts.keywordPart(81 /* EnumKeyword */)); + displayParts.push(ts.spacePart()); + addFullSymbolName(symbol); } - // hostCache is captured in the closure for 'getOrCreateSourceFile' but it should not be used past this point. - // It needs to be cleared to allow all collected snapshots to be released - hostCache = undefined; - program = newProgram; - // Make sure all the nodes in the program are both bound, and have their parent - // pointers set property. - program.getTypeChecker(); - return; - function getOrCreateSourceFile(fileName) { - return getOrCreateSourceFileByPath(fileName, ts.toPath(fileName, currentDirectory, getCanonicalFileName)); + if (symbolFlags & 1536 /* Module */) { + addNewLineIfDisplayPartsExist(); + var declaration = ts.getDeclarationOfKind(symbol, 225 /* ModuleDeclaration */); + var isNamespace = declaration && declaration.name && declaration.name.kind === 69 /* Identifier */; + displayParts.push(ts.keywordPart(isNamespace ? 126 /* NamespaceKeyword */ : 125 /* ModuleKeyword */)); + displayParts.push(ts.spacePart()); + addFullSymbolName(symbol); } - function getOrCreateSourceFileByPath(fileName, path) { - ts.Debug.assert(hostCache !== undefined); - // The program is asking for this file, check first if the host can locate it. - // If the host can not locate the file, then it does not exist. return undefined - // to the program to allow reporting of errors for missing files. - var hostFileInformation = hostCache.getOrCreateEntryByPath(fileName, path); - if (!hostFileInformation) { - return undefined; + if ((symbolFlags & 262144 /* TypeParameter */) && (semanticMeaning & 2 /* Type */)) { + addNewLineIfDisplayPartsExist(); + displayParts.push(ts.punctuationPart(17 /* OpenParenToken */)); + displayParts.push(ts.textPart("type parameter")); + displayParts.push(ts.punctuationPart(18 /* CloseParenToken */)); + displayParts.push(ts.spacePart()); + addFullSymbolName(symbol); + displayParts.push(ts.spacePart()); + displayParts.push(ts.keywordPart(90 /* InKeyword */)); + displayParts.push(ts.spacePart()); + if (symbol.parent) { + // Class/Interface type parameter + addFullSymbolName(symbol.parent, enclosingDeclaration); + writeTypeParametersOfSymbol(symbol.parent, enclosingDeclaration); } - // Check if the language version has changed since we last created a program; if they are the same, - // it is safe to reuse the sourceFiles; if not, then the shape of the AST can change, and the oldSourceFile - // can not be reused. we have to dump all syntax trees and create new ones. - if (!shouldCreateNewSourceFiles) { - // Check if the old program had this file already - var oldSourceFile = program && program.getSourceFileByPath(path); - if (oldSourceFile) { - // We already had a source file for this file name. Go to the registry to - // ensure that we get the right up to date version of it. We need this to - // address the following race-condition. Specifically, say we have the following: - // - // LS1 - // \ - // DocumentRegistry - // / - // LS2 - // - // Each LS has a reference to file 'foo.ts' at version 1. LS2 then updates - // it's version of 'foo.ts' to version 2. This will cause LS2 and the - // DocumentRegistry to have version 2 of the document. HOwever, LS1 will - // have version 1. And *importantly* this source file will be *corrupt*. - // The act of creating version 2 of the file irrevocably damages the version - // 1 file. - // - // So, later when we call into LS1, we need to make sure that it doesn't use - // it's source file any more, and instead defers to DocumentRegistry to get - // either version 1, version 2 (or some other version) depending on what the - // host says should be used. - // We do not support the scenario where a host can modify a registered - // file's script kind, i.e. in one project some file is treated as ".ts" - // and in another as ".js" - ts.Debug.assert(hostFileInformation.scriptKind === oldSourceFile.scriptKind, "Registered script kind (" + oldSourceFile.scriptKind + ") should match new script kind (" + hostFileInformation.scriptKind + ") for file: " + path); - return documentRegistry.updateDocumentWithKey(fileName, path, newSettings, documentRegistryBucketKey, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind); + else { + // Method/function type parameter + var declaration = ts.getDeclarationOfKind(symbol, 141 /* TypeParameter */); + ts.Debug.assert(declaration !== undefined); + declaration = declaration.parent; + if (declaration) { + if (ts.isFunctionLikeKind(declaration.kind)) { + var signature = typeChecker.getSignatureFromDeclaration(declaration); + if (declaration.kind === 152 /* ConstructSignature */) { + displayParts.push(ts.keywordPart(92 /* NewKeyword */)); + displayParts.push(ts.spacePart()); + } + else if (declaration.kind !== 151 /* CallSignature */ && declaration.name) { + addFullSymbolName(declaration.symbol); + } + ts.addRange(displayParts, ts.signatureToDisplayParts(typeChecker, signature, sourceFile, 32 /* WriteTypeArgumentsOfSignature */)); + } + else { + // Type alias type parameter + // For example + // type list = T[]; // Both T will go through same code path + displayParts.push(ts.keywordPart(134 /* TypeKeyword */)); + displayParts.push(ts.spacePart()); + addFullSymbolName(declaration.symbol); + writeTypeParametersOfSymbol(declaration.symbol, sourceFile); + } } } - // Could not find this file in the old program, create a new SourceFile for it. - return documentRegistry.acquireDocumentWithKey(fileName, path, newSettings, documentRegistryBucketKey, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind); } - function sourceFileUpToDate(sourceFile) { - if (!sourceFile) { - return false; + if (symbolFlags & 8 /* EnumMember */) { + addPrefixForAnyFunctionOrVar(symbol, "enum member"); + var declaration = symbol.declarations[0]; + if (declaration.kind === 255 /* EnumMember */) { + var constantValue = typeChecker.getConstantValue(declaration); + if (constantValue !== undefined) { + displayParts.push(ts.spacePart()); + displayParts.push(ts.operatorPart(56 /* EqualsToken */)); + displayParts.push(ts.spacePart()); + displayParts.push(ts.displayPart(constantValue.toString(), ts.SymbolDisplayPartKind.numericLiteral)); + } } - var path = sourceFile.path || ts.toPath(sourceFile.fileName, currentDirectory, getCanonicalFileName); - return sourceFile.version === hostCache.getVersion(path); } - function programUpToDate() { - // If we haven't create a program yet, then it is not up-to-date - if (!program) { - return false; + if (symbolFlags & 8388608 /* Alias */) { + addNewLineIfDisplayPartsExist(); + if (symbol.declarations[0].kind === 228 /* NamespaceExportDeclaration */) { + displayParts.push(ts.keywordPart(82 /* ExportKeyword */)); + displayParts.push(ts.spacePart()); + displayParts.push(ts.keywordPart(126 /* NamespaceKeyword */)); } - // If number of files in the program do not match, it is not up-to-date - var rootFileNames = hostCache.getRootFileNames(); - if (program.getSourceFiles().length !== rootFileNames.length) { - return false; + else { + displayParts.push(ts.keywordPart(89 /* ImportKeyword */)); } - // If any file is not up-to-date, then the whole program is not up-to-date - for (var _i = 0, rootFileNames_2 = rootFileNames; _i < rootFileNames_2.length; _i++) { - var fileName = rootFileNames_2[_i]; - if (!sourceFileUpToDate(program.getSourceFile(fileName))) { - return false; + displayParts.push(ts.spacePart()); + addFullSymbolName(symbol); + ts.forEach(symbol.declarations, function (declaration) { + if (declaration.kind === 229 /* ImportEqualsDeclaration */) { + var importEqualsDeclaration = declaration; + if (ts.isExternalModuleImportEqualsDeclaration(importEqualsDeclaration)) { + displayParts.push(ts.spacePart()); + displayParts.push(ts.operatorPart(56 /* EqualsToken */)); + displayParts.push(ts.spacePart()); + displayParts.push(ts.keywordPart(129 /* RequireKeyword */)); + displayParts.push(ts.punctuationPart(17 /* OpenParenToken */)); + displayParts.push(ts.displayPart(ts.getTextOfNode(ts.getExternalModuleImportEqualsDeclarationExpression(importEqualsDeclaration)), ts.SymbolDisplayPartKind.stringLiteral)); + displayParts.push(ts.punctuationPart(18 /* CloseParenToken */)); + } + else { + var internalAliasSymbol = typeChecker.getSymbolAtLocation(importEqualsDeclaration.moduleReference); + if (internalAliasSymbol) { + displayParts.push(ts.spacePart()); + displayParts.push(ts.operatorPart(56 /* EqualsToken */)); + displayParts.push(ts.spacePart()); + addFullSymbolName(internalAliasSymbol, enclosingDeclaration); + } + } + return true; } - } - // If the compilation settings do no match, then the program is not up-to-date - return ts.compareDataObjects(program.getCompilerOptions(), hostCache.compilationSettings()); - } - } - function getProgram() { - synchronizeHostData(); - return program; - } - function cleanupSemanticCache() { - // TODO: Should we jettison the program (or it's type checker) here? - } - function dispose() { - if (program) { - ts.forEach(program.getSourceFiles(), function (f) { - return documentRegistry.releaseDocument(f.fileName, program.getCompilerOptions()); }); } - } - /// Diagnostics - function getSyntacticDiagnostics(fileName) { - synchronizeHostData(); - return program.getSyntacticDiagnostics(getValidSourceFile(fileName), cancellationToken); - } - /** - * getSemanticDiagnostics return array of Diagnostics. If '-d' is not enabled, only report semantic errors - * If '-d' enabled, report both semantic and emitter errors - */ - function getSemanticDiagnostics(fileName) { - synchronizeHostData(); - var targetSourceFile = getValidSourceFile(fileName); - // Only perform the action per file regardless of '-out' flag as LanguageServiceHost is expected to call this function per file. - // Therefore only get diagnostics for given file. - var semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken); - if (!program.getCompilerOptions().declaration) { - return semanticDiagnostics; + if (!hasAddedSymbolInfo) { + if (symbolKind !== ts.ScriptElementKind.unknown) { + if (type) { + if (isThisExpression) { + addNewLineIfDisplayPartsExist(); + displayParts.push(ts.keywordPart(97 /* ThisKeyword */)); + } + else { + addPrefixForAnyFunctionOrVar(symbol, symbolKind); + } + // For properties, variables and local vars: show the type + if (symbolKind === ts.ScriptElementKind.memberVariableElement || + symbolFlags & 3 /* Variable */ || + symbolKind === ts.ScriptElementKind.localVariableElement || + isThisExpression) { + displayParts.push(ts.punctuationPart(54 /* ColonToken */)); + displayParts.push(ts.spacePart()); + // If the type is type parameter, format it specially + if (type.symbol && type.symbol.flags & 262144 /* TypeParameter */) { + var typeParameterParts = ts.mapToDisplayParts(function (writer) { + typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(type, writer, enclosingDeclaration); + }); + ts.addRange(displayParts, typeParameterParts); + } + else { + ts.addRange(displayParts, ts.typeToDisplayParts(typeChecker, type, enclosingDeclaration)); + } + } + else if (symbolFlags & 16 /* Function */ || + symbolFlags & 8192 /* Method */ || + symbolFlags & 16384 /* Constructor */ || + symbolFlags & 131072 /* Signature */ || + symbolFlags & 98304 /* Accessor */ || + symbolKind === ts.ScriptElementKind.memberFunctionElement) { + var allSignatures = type.getNonNullableType().getCallSignatures(); + addSignatureDisplayParts(allSignatures[0], allSignatures); + } + } + } + else { + symbolKind = getSymbolKind(typeChecker, symbol, location); + } } - // If '-d' is enabled, check for emitter error. One example of emitter error is export class implements non-export interface - var declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile, cancellationToken); - return ts.concatenate(semanticDiagnostics, declarationDiagnostics); - } - function getCompilerOptionsDiagnostics() { - synchronizeHostData(); - return program.getOptionsDiagnostics(cancellationToken).concat(program.getGlobalDiagnostics(cancellationToken)); - } - /** - * Get the name to be display in completion from a given symbol. - * - * @return undefined if the name is of external module otherwise a name with striped of any quote - */ - function getCompletionEntryDisplayNameForSymbol(symbol, target, performCharacterChecks, location) { - var displayName = ts.getDeclaredName(program.getTypeChecker(), symbol, location); - if (displayName) { - var firstCharCode = displayName.charCodeAt(0); - // First check of the displayName is not external module; if it is an external module, it is not valid entry - if ((symbol.flags & 1920 /* Namespace */) && (firstCharCode === 39 /* singleQuote */ || firstCharCode === 34 /* doubleQuote */)) { - // If the symbol is external module, don't show it in the completion list - // (i.e declare module "http" { const x; } | // <= request completion here, "http" should not be there) - return undefined; + if (!documentation) { + documentation = symbol.getDocumentationComment(); + if (documentation.length === 0 && symbol.flags & 4 /* Property */) { + // For some special property access expressions like `experts.foo = foo` or `module.exports.foo = foo` + // there documentation comments might be attached to the right hand side symbol of their declarations. + // The pattern of such special property access is that the parent symbol is the symbol of the file. + if (symbol.parent && ts.forEach(symbol.parent.declarations, function (declaration) { return declaration.kind === 256 /* SourceFile */; })) { + for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { + var declaration = _a[_i]; + if (!declaration.parent || declaration.parent.kind !== 187 /* BinaryExpression */) { + continue; + } + var rhsSymbol = typeChecker.getSymbolAtLocation(declaration.parent.right); + if (!rhsSymbol) { + continue; + } + documentation = rhsSymbol.getDocumentationComment(); + if (documentation.length > 0) { + break; + } + } + } } } - return getCompletionEntryDisplayName(displayName, target, performCharacterChecks); - } - /** - * Get a displayName from a given for completion list, performing any necessary quotes stripping - * and checking whether the name is valid identifier name. - */ - function getCompletionEntryDisplayName(name, target, performCharacterChecks) { - if (!name) { - return undefined; + return { displayParts: displayParts, documentation: documentation, symbolKind: symbolKind }; + function addNewLineIfDisplayPartsExist() { + if (displayParts.length) { + displayParts.push(ts.lineBreakPart()); + } } - name = ts.stripQuotes(name); - if (!name) { - return undefined; + function addFullSymbolName(symbol, enclosingDeclaration) { + var fullSymbolDisplayParts = ts.symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration || sourceFile, /*meaning*/ undefined, 1 /* WriteTypeParametersOrArguments */ | 2 /* UseOnlyExternalAliasing */); + ts.addRange(displayParts, fullSymbolDisplayParts); } - // If the user entered name for the symbol was quoted, removing the quotes is not enough, as the name could be an - // invalid identifier name. We need to check if whatever was inside the quotes is actually a valid identifier name. - // e.g "b a" is valid quoted name but when we strip off the quotes, it is invalid. - // We, thus, need to check if whatever was inside the quotes is actually a valid identifier name. - if (performCharacterChecks) { - if (!ts.isIdentifier(name, target)) { - return undefined; + function addPrefixForAnyFunctionOrVar(symbol, symbolKind) { + addNewLineIfDisplayPartsExist(); + if (symbolKind) { + pushTypePart(symbolKind); + displayParts.push(ts.spacePart()); + addFullSymbolName(symbol); } } - return name; + function pushTypePart(symbolKind) { + switch (symbolKind) { + case ts.ScriptElementKind.variableElement: + case ts.ScriptElementKind.functionElement: + case ts.ScriptElementKind.letElement: + case ts.ScriptElementKind.constElement: + case ts.ScriptElementKind.constructorImplementationElement: + displayParts.push(ts.textOrKeywordPart(symbolKind)); + return; + default: + displayParts.push(ts.punctuationPart(17 /* OpenParenToken */)); + displayParts.push(ts.textOrKeywordPart(symbolKind)); + displayParts.push(ts.punctuationPart(18 /* CloseParenToken */)); + return; + } + } + function addSignatureDisplayParts(signature, allSignatures, flags) { + ts.addRange(displayParts, ts.signatureToDisplayParts(typeChecker, signature, enclosingDeclaration, flags | 32 /* WriteTypeArgumentsOfSignature */)); + if (allSignatures.length > 1) { + displayParts.push(ts.spacePart()); + displayParts.push(ts.punctuationPart(17 /* OpenParenToken */)); + displayParts.push(ts.operatorPart(35 /* PlusToken */)); + displayParts.push(ts.displayPart((allSignatures.length - 1).toString(), ts.SymbolDisplayPartKind.numericLiteral)); + displayParts.push(ts.spacePart()); + displayParts.push(ts.textPart(allSignatures.length === 2 ? "overload" : "overloads")); + displayParts.push(ts.punctuationPart(18 /* CloseParenToken */)); + } + documentation = signature.getDocumentationComment(); + } + function writeTypeParametersOfSymbol(symbol, enclosingDeclaration) { + var typeParameterParts = ts.mapToDisplayParts(function (writer) { + typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplayFromSymbol(symbol, writer, enclosingDeclaration); + }); + ts.addRange(displayParts, typeParameterParts); + } } - function getCompletionData(fileName, position) { - var typeChecker = program.getTypeChecker(); - var sourceFile = getValidSourceFile(fileName); - var isJavaScriptFile = ts.isSourceFileJavaScript(sourceFile); - var isJsDocTagName = false; - var start = ts.timestamp(); - var currentToken = ts.getTokenAtPosition(sourceFile, position); - log("getCompletionData: Get current token: " + (ts.timestamp() - start)); - start = ts.timestamp(); - // Completion not allowed inside comments, bail out if this is the case - var insideComment = isInsideComment(sourceFile, currentToken, position); - log("getCompletionData: Is inside comment: " + (ts.timestamp() - start)); - if (insideComment) { - // The current position is next to the '@' sign, when no tag name being provided yet. - // Provide a full list of tag names - if (ts.hasDocComment(sourceFile, position) && sourceFile.text.charCodeAt(position - 1) === 64 /* at */) { - isJsDocTagName = true; + SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind; + function isLocalVariableOrFunction(symbol) { + if (symbol.parent) { + return false; // This is exported symbol + } + return ts.forEach(symbol.declarations, function (declaration) { + // Function expressions are local + if (declaration.kind === 179 /* FunctionExpression */) { + return true; } - // Completion should work inside certain JsDoc tags. For example: - // /** @type {number | string} */ - // Completion should work in the brackets - var insideJsDocTagExpression = false; - var tag = ts.getJsDocTagAtPosition(sourceFile, position); - if (tag) { - if (tag.tagName.pos <= position && position <= tag.tagName.end) { - isJsDocTagName = true; - } - switch (tag.kind) { - case 277 /* JSDocTypeTag */: - case 275 /* JSDocParameterTag */: - case 276 /* JSDocReturnTag */: - var tagWithExpression = tag; - if (tagWithExpression.typeExpression) { - insideJsDocTagExpression = tagWithExpression.typeExpression.pos < position && position < tagWithExpression.typeExpression.end; - } - break; + if (declaration.kind !== 218 /* VariableDeclaration */ && declaration.kind !== 220 /* FunctionDeclaration */) { + return false; + } + // If the parent is not sourceFile or module block it is local variable + for (var parent_23 = declaration.parent; !ts.isFunctionBlock(parent_23); parent_23 = parent_23.parent) { + // Reached source file or module block + if (parent_23.kind === 256 /* SourceFile */ || parent_23.kind === 226 /* ModuleBlock */) { + return false; } } - if (isJsDocTagName) { - return { symbols: undefined, isMemberCompletion: false, isNewIdentifierLocation: false, location: undefined, isRightOfDot: false, isJsDocTagName: isJsDocTagName }; + // parent is in function block + return true; + }); + } + })(SymbolDisplay = ts.SymbolDisplay || (ts.SymbolDisplay = {})); +})(ts || (ts = {})); +var ts; +(function (ts) { + /* + * This function will compile source text from 'input' argument using specified compiler options. + * If not options are provided - it will use a set of default compiler options. + * Extra compiler options that will unconditionally be used by this function are: + * - isolatedModules = true + * - allowNonTsExtensions = true + * - noLib = true + * - noResolve = true + */ + function transpileModule(input, transpileOptions) { + var diagnostics = []; + var options = transpileOptions.compilerOptions ? fixupCompilerOptions(transpileOptions.compilerOptions, diagnostics) : ts.getDefaultCompilerOptions(); + options.isolatedModules = true; + // transpileModule does not write anything to disk so there is no need to verify that there are no conflicts between input and output paths. + options.suppressOutputPathCheck = true; + // Filename can be non-ts file. + options.allowNonTsExtensions = true; + // We are not returning a sourceFile for lib file when asked by the program, + // so pass --noLib to avoid reporting a file not found error. + options.noLib = true; + // Clear out other settings that would not be used in transpiling this module + options.lib = undefined; + options.types = undefined; + options.noEmit = undefined; + options.noEmitOnError = undefined; + options.paths = undefined; + options.rootDirs = undefined; + options.declaration = undefined; + options.declarationDir = undefined; + options.out = undefined; + options.outFile = undefined; + // We are not doing a full typecheck, we are not resolving the whole context, + // so pass --noResolve to avoid reporting missing file errors. + options.noResolve = true; + // if jsx is specified then treat file as .tsx + var inputFileName = transpileOptions.fileName || (options.jsx ? "module.tsx" : "module.ts"); + var sourceFile = ts.createSourceFile(inputFileName, input, options.target); + if (transpileOptions.moduleName) { + sourceFile.moduleName = transpileOptions.moduleName; + } + if (transpileOptions.renamedDependencies) { + sourceFile.renamedDependencies = ts.createMap(transpileOptions.renamedDependencies); + } + var newLine = ts.getNewLineCharacter(options); + // Output + var outputText; + var sourceMapText; + // Create a compilerHost object to allow the compiler to read and write files + var compilerHost = { + getSourceFile: function (fileName, target) { return fileName === ts.normalizePath(inputFileName) ? sourceFile : undefined; }, + writeFile: function (name, text, writeByteOrderMark) { + if (ts.fileExtensionIs(name, ".map")) { + ts.Debug.assert(sourceMapText === undefined, "Unexpected multiple source map outputs for the file '" + name + "'"); + sourceMapText = text; } - if (!insideJsDocTagExpression) { - // Proceed if the current position is in jsDoc tag expression; otherwise it is a normal - // comment or the plain text part of a jsDoc comment, so no completion should be available - log("Returning an empty list because completion was inside a regular comment or plain text part of a JsDoc comment."); - return undefined; + else { + ts.Debug.assert(outputText === undefined, "Unexpected multiple outputs for the file: '" + name + "'"); + outputText = text; } + }, + getDefaultLibFileName: function () { return "lib.d.ts"; }, + useCaseSensitiveFileNames: function () { return false; }, + getCanonicalFileName: function (fileName) { return fileName; }, + getCurrentDirectory: function () { return ""; }, + getNewLine: function () { return newLine; }, + fileExists: function (fileName) { return fileName === inputFileName; }, + readFile: function (fileName) { return ""; }, + directoryExists: function (directoryExists) { return true; }, + getDirectories: function (path) { return []; } + }; + var program = ts.createProgram([inputFileName], options, compilerHost); + if (transpileOptions.reportDiagnostics) { + ts.addRange(/*to*/ diagnostics, /*from*/ program.getSyntacticDiagnostics(sourceFile)); + ts.addRange(/*to*/ diagnostics, /*from*/ program.getOptionsDiagnostics()); + } + // Emit + program.emit(); + ts.Debug.assert(outputText !== undefined, "Output generation failed"); + return { outputText: outputText, diagnostics: diagnostics, sourceMapText: sourceMapText }; + } + ts.transpileModule = transpileModule; + /* + * This is a shortcut function for transpileModule - it accepts transpileOptions as parameters and returns only outputText part of the result. + */ + function transpile(input, compilerOptions, fileName, diagnostics, moduleName) { + var output = transpileModule(input, { compilerOptions: compilerOptions, fileName: fileName, reportDiagnostics: !!diagnostics, moduleName: moduleName }); + // addRange correctly handles cases when wither 'from' or 'to' argument is missing + ts.addRange(diagnostics, output.diagnostics); + return output.outputText; + } + ts.transpile = transpile; + var commandLineOptionsStringToEnum; + /** JS users may pass in string values for enum compiler options (such as ModuleKind), so convert. */ + function fixupCompilerOptions(options, diagnostics) { + // Lazily create this value to fix module loading errors. + commandLineOptionsStringToEnum = commandLineOptionsStringToEnum || ts.filter(ts.optionDeclarations, function (o) { + return typeof o.type === "object" && !ts.forEachProperty(o.type, function (v) { return typeof v !== "number"; }); + }); + options = ts.clone(options); + var _loop_2 = function (opt) { + if (!ts.hasProperty(options, opt.name)) { + return "continue"; } - start = ts.timestamp(); - var previousToken = ts.findPrecedingToken(position, sourceFile); - log("getCompletionData: Get previous token 1: " + (ts.timestamp() - start)); - // The decision to provide completion depends on the contextToken, which is determined through the previousToken. - // Note: 'previousToken' (and thus 'contextToken') can be undefined if we are the beginning of the file - var contextToken = previousToken; - // Check if the caret is at the end of an identifier; this is a partial identifier that we want to complete: e.g. a.toS| - // Skip this partial identifier and adjust the contextToken to the token that precedes it. - if (contextToken && position <= contextToken.end && ts.isWord(contextToken.kind)) { - var start_2 = ts.timestamp(); - contextToken = ts.findPrecedingToken(contextToken.getFullStart(), sourceFile); - log("getCompletionData: Get previous token 2: " + (ts.timestamp() - start_2)); + var value = options[opt.name]; + // Value should be a key of opt.type + if (typeof value === "string") { + // If value is not a string, this will fail + options[opt.name] = ts.parseCustomTypeOption(opt, value, diagnostics); } - // Find the node where completion is requested on. - // Also determine whether we are trying to complete with members of that node - // or attributes of a JSX tag. - var node = currentToken; - var isRightOfDot = false; - var isRightOfOpenTag = false; - var isStartingCloseTag = false; - var location = ts.getTouchingPropertyName(sourceFile, position); - if (contextToken) { - // Bail out if this is a known invalid completion location - if (isCompletionListBlocker(contextToken)) { - log("Returning an empty list because completion was requested in an invalid position."); - return undefined; + else { + if (!ts.forEachProperty(opt.type, function (v) { return v === value; })) { + // Supplied value isn't a valid enum value. + diagnostics.push(ts.createCompilerDiagnosticForInvalidCustomType(opt)); } - var parent_18 = contextToken.parent, kind = contextToken.kind; - if (kind === 21 /* DotToken */) { - if (parent_18.kind === 172 /* PropertyAccessExpression */) { - node = contextToken.parent.expression; - isRightOfDot = true; - } - else if (parent_18.kind === 139 /* QualifiedName */) { - node = contextToken.parent.left; - isRightOfDot = true; + } + }; + for (var _i = 0, commandLineOptionsStringToEnum_1 = commandLineOptionsStringToEnum; _i < commandLineOptionsStringToEnum_1.length; _i++) { + var opt = commandLineOptionsStringToEnum_1[_i]; + _loop_2(opt); + } + return options; + } +})(ts || (ts = {})); +/// +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + var standardScanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ false, 0 /* Standard */); + var jsxScanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ false, 1 /* JSX */); + /** + * Scanner that is currently used for formatting + */ + var scanner; + var ScanAction; + (function (ScanAction) { + ScanAction[ScanAction["Scan"] = 0] = "Scan"; + ScanAction[ScanAction["RescanGreaterThanToken"] = 1] = "RescanGreaterThanToken"; + ScanAction[ScanAction["RescanSlashToken"] = 2] = "RescanSlashToken"; + ScanAction[ScanAction["RescanTemplateToken"] = 3] = "RescanTemplateToken"; + ScanAction[ScanAction["RescanJsxIdentifier"] = 4] = "RescanJsxIdentifier"; + ScanAction[ScanAction["RescanJsxText"] = 5] = "RescanJsxText"; + })(ScanAction || (ScanAction = {})); + function getFormattingScanner(sourceFile, startPos, endPos) { + ts.Debug.assert(scanner === undefined); + scanner = sourceFile.languageVariant === 1 /* JSX */ ? jsxScanner : standardScanner; + scanner.setText(sourceFile.text); + scanner.setTextPos(startPos); + var wasNewLine = true; + var leadingTrivia; + var trailingTrivia; + var savedPos; + var lastScanAction; + var lastTokenInfo; + return { + advance: advance, + readTokenInfo: readTokenInfo, + isOnToken: isOnToken, + getCurrentLeadingTrivia: function () { return leadingTrivia; }, + lastTrailingTriviaWasNewLine: function () { return wasNewLine; }, + skipToEndOf: skipToEndOf, + close: function () { + ts.Debug.assert(scanner !== undefined); + lastTokenInfo = undefined; + scanner.setText(undefined); + scanner = undefined; + } + }; + function advance() { + ts.Debug.assert(scanner !== undefined); + lastTokenInfo = undefined; + var isStarted = scanner.getStartPos() !== startPos; + if (isStarted) { + if (trailingTrivia) { + ts.Debug.assert(trailingTrivia.length !== 0); + wasNewLine = ts.lastOrUndefined(trailingTrivia).kind === 4 /* NewLineTrivia */; } else { - // There is nothing that precedes the dot, so this likely just a stray character - // or leading into a '...' token. Just bail out instead. - return undefined; + wasNewLine = false; } } - else if (sourceFile.languageVariant === 1 /* JSX */) { - if (kind === 25 /* LessThanToken */) { - isRightOfOpenTag = true; - location = contextToken; + leadingTrivia = undefined; + trailingTrivia = undefined; + if (!isStarted) { + scanner.scan(); + } + var pos = scanner.getStartPos(); + // Read leading trivia and token + while (pos < endPos) { + var t = scanner.getToken(); + if (!ts.isTrivia(t)) { + break; } - else if (kind === 39 /* SlashToken */ && contextToken.parent.kind === 245 /* JsxClosingElement */) { - isStartingCloseTag = true; - location = contextToken; + // consume leading trivia + scanner.scan(); + var item = { + pos: pos, + end: scanner.getStartPos(), + kind: t + }; + pos = scanner.getStartPos(); + if (!leadingTrivia) { + leadingTrivia = []; } + leadingTrivia.push(item); } + savedPos = scanner.getStartPos(); } - var semanticStart = ts.timestamp(); - var isMemberCompletion; - var isNewIdentifierLocation; - var symbols = []; - if (isRightOfDot) { - getTypeScriptMemberSymbols(); - } - else if (isRightOfOpenTag) { - var tagSymbols = typeChecker.getJsxIntrinsicTagNames(); - if (tryGetGlobalSymbols()) { - symbols = tagSymbols.concat(symbols.filter(function (s) { return !!(s.flags & (107455 /* Value */ | 8388608 /* Alias */)); })); - } - else { - symbols = tagSymbols; + function shouldRescanGreaterThanToken(node) { + if (node) { + switch (node.kind) { + case 29 /* GreaterThanEqualsToken */: + case 64 /* GreaterThanGreaterThanEqualsToken */: + case 65 /* GreaterThanGreaterThanGreaterThanEqualsToken */: + case 45 /* GreaterThanGreaterThanGreaterThanToken */: + case 44 /* GreaterThanGreaterThanToken */: + return true; + } } - isMemberCompletion = true; - isNewIdentifierLocation = false; + return false; } - else if (isStartingCloseTag) { - var tagName = contextToken.parent.parent.openingElement.tagName; - var tagSymbol = typeChecker.getSymbolAtLocation(tagName); - if (!typeChecker.isUnknownSymbol(tagSymbol)) { - symbols = [tagSymbol]; + function shouldRescanJsxIdentifier(node) { + if (node.parent) { + switch (node.parent.kind) { + case 246 /* JsxAttribute */: + case 243 /* JsxOpeningElement */: + case 245 /* JsxClosingElement */: + case 242 /* JsxSelfClosingElement */: + return node.kind === 69 /* Identifier */; + } } - isMemberCompletion = true; - isNewIdentifierLocation = false; + return false; } - else { - // For JavaScript or TypeScript, if we're not after a dot, then just try to get the - // global symbols in scope. These results should be valid for either language as - // the set of symbols that can be referenced from this location. - if (!tryGetGlobalSymbols()) { - return undefined; - } + function shouldRescanJsxText(node) { + return node && node.kind === 244 /* JsxText */; } - log("getCompletionData: Semantic work: " + (ts.timestamp() - semanticStart)); - return { symbols: symbols, isMemberCompletion: isMemberCompletion, isNewIdentifierLocation: isNewIdentifierLocation, location: location, isRightOfDot: (isRightOfDot || isRightOfOpenTag), isJsDocTagName: isJsDocTagName }; - function getTypeScriptMemberSymbols() { - // Right of dot member completion list - isMemberCompletion = true; - isNewIdentifierLocation = false; - if (node.kind === 69 /* Identifier */ || node.kind === 139 /* QualifiedName */ || node.kind === 172 /* PropertyAccessExpression */) { - var symbol = typeChecker.getSymbolAtLocation(node); - // This is an alias, follow what it aliases - if (symbol && symbol.flags & 8388608 /* Alias */) { - symbol = typeChecker.getAliasedSymbol(symbol); - } - if (symbol && symbol.flags & 1952 /* HasExports */) { - // Extract module or enum members - var exportedSymbols = typeChecker.getExportsOfModule(symbol); - ts.forEach(exportedSymbols, function (symbol) { - if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) { - symbols.push(symbol); - } - }); - } - } - var type = typeChecker.getTypeAtLocation(node); - addTypeProperties(type); + function shouldRescanSlashToken(container) { + return container.kind === 10 /* RegularExpressionLiteral */; } - function addTypeProperties(type) { - if (type) { - // Filter private properties - for (var _i = 0, _a = type.getApparentProperties(); _i < _a.length; _i++) { - var symbol = _a[_i]; - if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) { - symbols.push(symbol); - } - } - if (isJavaScriptFile && type.flags & 524288 /* Union */) { - // In javascript files, for union types, we don't just get the members that - // the individual types have in common, we also include all the members that - // each individual type has. This is because we're going to add all identifiers - // anyways. So we might as well elevate the members that were at least part - // of the individual types to a higher status since we know what they are. - var unionType = type; - for (var _b = 0, _c = unionType.types; _b < _c.length; _b++) { - var elementType = _c[_b]; - addTypeProperties(elementType); - } - } - } + function shouldRescanTemplateToken(container) { + return container.kind === 13 /* TemplateMiddle */ || + container.kind === 14 /* TemplateTail */; } - function tryGetGlobalSymbols() { - var objectLikeContainer; - var namedImportsOrExports; - var jsxContainer; - if (objectLikeContainer = tryGetObjectLikeCompletionContainer(contextToken)) { - return tryGetObjectLikeCompletionSymbols(objectLikeContainer); + function startsWithSlashToken(t) { + return t === 39 /* SlashToken */ || t === 61 /* SlashEqualsToken */; + } + function readTokenInfo(n) { + ts.Debug.assert(scanner !== undefined); + if (!isOnToken()) { + // scanner is not on the token (either advance was not called yet or scanner is already past the end position) + return { + leadingTrivia: leadingTrivia, + trailingTrivia: undefined, + token: undefined + }; } - if (namedImportsOrExports = tryGetNamedImportsOrExportsForCompletion(contextToken)) { - // cursor is in an import clause - // try to show exported member for imported module - return tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports); + // normally scanner returns the smallest available token + // check the kind of context node to determine if scanner should have more greedy behavior and consume more text. + var expectedScanAction = shouldRescanGreaterThanToken(n) + ? 1 /* RescanGreaterThanToken */ + : shouldRescanSlashToken(n) + ? 2 /* RescanSlashToken */ + : shouldRescanTemplateToken(n) + ? 3 /* RescanTemplateToken */ + : shouldRescanJsxIdentifier(n) + ? 4 /* RescanJsxIdentifier */ + : shouldRescanJsxText(n) + ? 5 /* RescanJsxText */ + : 0 /* Scan */; + if (lastTokenInfo && expectedScanAction === lastScanAction) { + // readTokenInfo was called before with the same expected scan action. + // No need to re-scan text, return existing 'lastTokenInfo' + // it is ok to call fixTokenKind here since it does not affect + // what portion of text is consumed. In contrast rescanning can change it, + // i.e. for '>=' when originally scanner eats just one character + // and rescanning forces it to consume more. + return fixTokenKind(lastTokenInfo, n); } - if (jsxContainer = tryGetContainingJsxElement(contextToken)) { - var attrsType = void 0; - if ((jsxContainer.kind === 242 /* JsxSelfClosingElement */) || (jsxContainer.kind === 243 /* JsxOpeningElement */)) { - // Cursor is inside a JSX self-closing element or opening element - attrsType = typeChecker.getJsxElementAttributesType(jsxContainer); - if (attrsType) { - symbols = filterJsxAttributes(typeChecker.getPropertiesOfType(attrsType), jsxContainer.attributes); - isMemberCompletion = true; - isNewIdentifierLocation = false; - return true; - } - } + if (scanner.getStartPos() !== savedPos) { + ts.Debug.assert(lastTokenInfo !== undefined); + // readTokenInfo was called before but scan action differs - rescan text + scanner.setTextPos(savedPos); + scanner.scan(); } - // Get all entities in the current scope. - isMemberCompletion = false; - isNewIdentifierLocation = isNewIdentifierDefinitionLocation(contextToken); - if (previousToken !== contextToken) { - ts.Debug.assert(!!previousToken, "Expected 'contextToken' to be defined when different from 'previousToken'."); + var currentToken = scanner.getToken(); + if (expectedScanAction === 1 /* RescanGreaterThanToken */ && currentToken === 27 /* GreaterThanToken */) { + currentToken = scanner.reScanGreaterToken(); + ts.Debug.assert(n.kind === currentToken); + lastScanAction = 1 /* RescanGreaterThanToken */; } - // We need to find the node that will give us an appropriate scope to begin - // aggregating completion candidates. This is achieved in 'getScopeNode' - // by finding the first node that encompasses a position, accounting for whether a node - // is "complete" to decide whether a position belongs to the node. - // - // However, at the end of an identifier, we are interested in the scope of the identifier - // itself, but fall outside of the identifier. For instance: - // - // xyz => x$ - // - // the cursor is outside of both the 'x' and the arrow function 'xyz => x', - // so 'xyz' is not returned in our results. - // - // We define 'adjustedPosition' so that we may appropriately account for - // being at the end of an identifier. The intention is that if requesting completion - // at the end of an identifier, it should be effectively equivalent to requesting completion - // anywhere inside/at the beginning of the identifier. So in the previous case, the - // 'adjustedPosition' will work as if requesting completion in the following: - // - // xyz => $x - // - // If previousToken !== contextToken, then - // - 'contextToken' was adjusted to the token prior to 'previousToken' - // because we were at the end of an identifier. - // - 'previousToken' is defined. - var adjustedPosition = previousToken !== contextToken ? - previousToken.getStart() : - position; - var scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile; - /// TODO filter meaning based on the current context - var symbolMeanings = 793064 /* Type */ | 107455 /* Value */ | 1920 /* Namespace */ | 8388608 /* Alias */; - symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings); - return true; - } - /** - * Finds the first node that "embraces" the position, so that one may - * accurately aggregate locals from the closest containing scope. - */ - function getScopeNode(initialToken, position, sourceFile) { - var scope = initialToken; - while (scope && !ts.positionBelongsToNode(scope, position, sourceFile)) { - scope = scope.parent; + else if (expectedScanAction === 2 /* RescanSlashToken */ && startsWithSlashToken(currentToken)) { + currentToken = scanner.reScanSlashToken(); + ts.Debug.assert(n.kind === currentToken); + lastScanAction = 2 /* RescanSlashToken */; } - return scope; - } - function isCompletionListBlocker(contextToken) { - var start = ts.timestamp(); - var result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) || - isSolelyIdentifierDefinitionLocation(contextToken) || - isDotOfNumericLiteral(contextToken) || - isInJsxText(contextToken); - log("getCompletionsAtPosition: isCompletionListBlocker: " + (ts.timestamp() - start)); - return result; - } - function isInJsxText(contextToken) { - if (contextToken.kind === 244 /* JsxText */) { - return true; + else if (expectedScanAction === 3 /* RescanTemplateToken */ && currentToken === 16 /* CloseBraceToken */) { + currentToken = scanner.reScanTemplateToken(); + lastScanAction = 3 /* RescanTemplateToken */; } - if (contextToken.kind === 27 /* GreaterThanToken */ && contextToken.parent) { - if (contextToken.parent.kind === 243 /* JsxOpeningElement */) { - return true; - } - if (contextToken.parent.kind === 245 /* JsxClosingElement */ || contextToken.parent.kind === 242 /* JsxSelfClosingElement */) { - return contextToken.parent.parent && contextToken.parent.parent.kind === 241 /* JsxElement */; - } + else if (expectedScanAction === 4 /* RescanJsxIdentifier */ && currentToken === 69 /* Identifier */) { + currentToken = scanner.scanJsxIdentifier(); + lastScanAction = 4 /* RescanJsxIdentifier */; } - return false; - } - function isNewIdentifierDefinitionLocation(previousToken) { - if (previousToken) { - var containingNodeKind = previousToken.parent.kind; - switch (previousToken.kind) { - case 24 /* CommaToken */: - return containingNodeKind === 174 /* CallExpression */ // func( a, | - || containingNodeKind === 148 /* Constructor */ // constructor( a, | /* public, protected, private keywords are allowed here, so show completion */ - || containingNodeKind === 175 /* NewExpression */ // new C(a, | - || containingNodeKind === 170 /* ArrayLiteralExpression */ // [a, | - || containingNodeKind === 187 /* BinaryExpression */ // const x = (a, | - || containingNodeKind === 156 /* FunctionType */; // var x: (s: string, list| - case 17 /* OpenParenToken */: - return containingNodeKind === 174 /* CallExpression */ // func( | - || containingNodeKind === 148 /* Constructor */ // constructor( | - || containingNodeKind === 175 /* NewExpression */ // new C(a| - || containingNodeKind === 178 /* ParenthesizedExpression */ // const x = (a| - || containingNodeKind === 164 /* ParenthesizedType */; // function F(pred: (a| /* this can become an arrow function, where 'a' is the argument */ - case 19 /* OpenBracketToken */: - return containingNodeKind === 170 /* ArrayLiteralExpression */ // [ | - || containingNodeKind === 153 /* IndexSignature */ // [ | : string ] - || containingNodeKind === 140 /* ComputedPropertyName */; // [ | /* this can become an index signature */ - case 125 /* ModuleKeyword */: // module | - case 126 /* NamespaceKeyword */: - return true; - case 21 /* DotToken */: - return containingNodeKind === 225 /* ModuleDeclaration */; // module A.| - case 15 /* OpenBraceToken */: - return containingNodeKind === 221 /* ClassDeclaration */; // class A{ | - case 56 /* EqualsToken */: - return containingNodeKind === 218 /* VariableDeclaration */ // const x = a| - || containingNodeKind === 187 /* BinaryExpression */; // x = a| - case 12 /* TemplateHead */: - return containingNodeKind === 189 /* TemplateExpression */; // `aa ${| - case 13 /* TemplateMiddle */: - return containingNodeKind === 197 /* TemplateSpan */; // `aa ${10} dd ${| - case 112 /* PublicKeyword */: - case 110 /* PrivateKeyword */: - case 111 /* ProtectedKeyword */: - return containingNodeKind === 145 /* PropertyDeclaration */; // class A{ public | - } - // Previous token may have been a keyword that was converted to an identifier. - switch (previousToken.getText()) { - case "public": - case "protected": - case "private": - return true; - } + else if (expectedScanAction === 5 /* RescanJsxText */) { + currentToken = scanner.reScanJsxToken(); + lastScanAction = 5 /* RescanJsxText */; } - return false; - } - function isInStringOrRegularExpressionOrTemplateLiteral(contextToken) { - if (contextToken.kind === 9 /* StringLiteral */ - || contextToken.kind === 10 /* RegularExpressionLiteral */ - || ts.isTemplateLiteralKind(contextToken.kind)) { - var start_3 = contextToken.getStart(); - var end = contextToken.getEnd(); - // To be "in" one of these literals, the position has to be: - // 1. entirely within the token text. - // 2. at the end position of an unterminated token. - // 3. at the end of a regular expression (due to trailing flags like '/foo/g'). - if (start_3 < position && position < end) { - return true; + else { + lastScanAction = 0 /* Scan */; + } + var token = { + pos: scanner.getStartPos(), + end: scanner.getTextPos(), + kind: currentToken + }; + // consume trailing trivia + if (trailingTrivia) { + trailingTrivia = undefined; + } + while (scanner.getStartPos() < endPos) { + currentToken = scanner.scan(); + if (!ts.isTrivia(currentToken)) { + break; } - if (position === end) { - return !!contextToken.isUnterminated - || contextToken.kind === 10 /* RegularExpressionLiteral */; + var trivia = { + pos: scanner.getStartPos(), + end: scanner.getTextPos(), + kind: currentToken + }; + if (!trailingTrivia) { + trailingTrivia = []; + } + trailingTrivia.push(trivia); + if (currentToken === 4 /* NewLineTrivia */) { + // move past new line + scanner.scan(); + break; } } - return false; + lastTokenInfo = { + leadingTrivia: leadingTrivia, + trailingTrivia: trailingTrivia, + token: token + }; + return fixTokenKind(lastTokenInfo, n); + } + function isOnToken() { + ts.Debug.assert(scanner !== undefined); + var current = (lastTokenInfo && lastTokenInfo.token.kind) || scanner.getToken(); + var startPos = (lastTokenInfo && lastTokenInfo.token.pos) || scanner.getStartPos(); + return startPos < endPos && current !== 1 /* EndOfFileToken */ && !ts.isTrivia(current); + } + // when containing node in the tree is token + // but its kind differs from the kind that was returned by the scanner, + // then kind needs to be fixed. This might happen in cases + // when parser interprets token differently, i.e keyword treated as identifier + function fixTokenKind(tokenInfo, container) { + if (ts.isToken(container) && tokenInfo.token.kind !== container.kind) { + tokenInfo.token.kind = container.kind; + } + return tokenInfo; } - /** - * Aggregates relevant symbols for completion in object literals and object binding patterns. - * Relevant symbols are stored in the captured 'symbols' variable. - * - * @returns true if 'symbols' was successfully populated; false otherwise. - */ - function tryGetObjectLikeCompletionSymbols(objectLikeContainer) { - // We're looking up possible property names from contextual/inferred/declared type. - isMemberCompletion = true; - var typeForObject; - var existingMembers; - if (objectLikeContainer.kind === 171 /* ObjectLiteralExpression */) { - // We are completing on contextual types, but may also include properties - // other than those within the declared type. - isNewIdentifierLocation = true; - // If the object literal is being assigned to something of type 'null | { hello: string }', - // it clearly isn't trying to satisfy the 'null' type. So we grab the non-nullable type if possible. - typeForObject = typeChecker.getContextualType(objectLikeContainer); - typeForObject = typeForObject && typeForObject.getNonNullableType(); - existingMembers = objectLikeContainer.properties; + function skipToEndOf(node) { + scanner.setTextPos(node.end); + savedPos = scanner.getStartPos(); + lastScanAction = undefined; + lastTokenInfo = undefined; + wasNewLine = false; + leadingTrivia = undefined; + trailingTrivia = undefined; + } + } + formatting.getFormattingScanner = getFormattingScanner; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + var FormattingContext = (function () { + function FormattingContext(sourceFile, formattingRequestKind) { + this.sourceFile = sourceFile; + this.formattingRequestKind = formattingRequestKind; + } + FormattingContext.prototype.updateContext = function (currentRange, currentTokenParent, nextRange, nextTokenParent, commonParent) { + ts.Debug.assert(currentRange !== undefined, "currentTokenSpan is null"); + ts.Debug.assert(currentTokenParent !== undefined, "currentTokenParent is null"); + ts.Debug.assert(nextRange !== undefined, "nextTokenSpan is null"); + ts.Debug.assert(nextTokenParent !== undefined, "nextTokenParent is null"); + ts.Debug.assert(commonParent !== undefined, "commonParent is null"); + this.currentTokenSpan = currentRange; + this.currentTokenParent = currentTokenParent; + this.nextTokenSpan = nextRange; + this.nextTokenParent = nextTokenParent; + this.contextNode = commonParent; + // drop cached results + this.contextNodeAllOnSameLine = undefined; + this.nextNodeAllOnSameLine = undefined; + this.tokensAreOnSameLine = undefined; + this.contextNodeBlockIsOnOneLine = undefined; + this.nextNodeBlockIsOnOneLine = undefined; + }; + FormattingContext.prototype.ContextNodeAllOnSameLine = function () { + if (this.contextNodeAllOnSameLine === undefined) { + this.contextNodeAllOnSameLine = this.NodeIsOnOneLine(this.contextNode); } - else if (objectLikeContainer.kind === 167 /* ObjectBindingPattern */) { - // We are *only* completing on properties from the type being destructured. - isNewIdentifierLocation = false; - var rootDeclaration = ts.getRootDeclaration(objectLikeContainer.parent); - if (ts.isVariableLike(rootDeclaration)) { - // We don't want to complete using the type acquired by the shape - // of the binding pattern; we are only interested in types acquired - // through type declaration or inference. - // Also proceed if rootDeclaration is a parameter and if its containing function expression/arrow function is contextually typed - - // type of parameter will flow in from the contextual type of the function - var canGetType = !!(rootDeclaration.initializer || rootDeclaration.type); - if (!canGetType && rootDeclaration.kind === 142 /* Parameter */) { - if (ts.isExpression(rootDeclaration.parent)) { - canGetType = !!typeChecker.getContextualType(rootDeclaration.parent); - } - else if (rootDeclaration.parent.kind === 147 /* MethodDeclaration */ || rootDeclaration.parent.kind === 150 /* SetAccessor */) { - canGetType = ts.isExpression(rootDeclaration.parent.parent) && !!typeChecker.getContextualType(rootDeclaration.parent.parent); - } - } - if (canGetType) { - typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer); - existingMembers = objectLikeContainer.elements; - } - } - else { - ts.Debug.fail("Root declaration is not variable-like."); - } + return this.contextNodeAllOnSameLine; + }; + FormattingContext.prototype.NextNodeAllOnSameLine = function () { + if (this.nextNodeAllOnSameLine === undefined) { + this.nextNodeAllOnSameLine = this.NodeIsOnOneLine(this.nextTokenParent); } - else { - ts.Debug.fail("Expected object literal or binding pattern, got " + objectLikeContainer.kind); + return this.nextNodeAllOnSameLine; + }; + FormattingContext.prototype.TokensAreOnSameLine = function () { + if (this.tokensAreOnSameLine === undefined) { + var startLine = this.sourceFile.getLineAndCharacterOfPosition(this.currentTokenSpan.pos).line; + var endLine = this.sourceFile.getLineAndCharacterOfPosition(this.nextTokenSpan.pos).line; + this.tokensAreOnSameLine = (startLine === endLine); } - if (!typeForObject) { - return false; + return this.tokensAreOnSameLine; + }; + FormattingContext.prototype.ContextNodeBlockIsOnOneLine = function () { + if (this.contextNodeBlockIsOnOneLine === undefined) { + this.contextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.contextNode); } - var typeMembers = typeChecker.getPropertiesOfType(typeForObject); - if (typeMembers && typeMembers.length > 0) { - // Add filtered items to the completion list - symbols = filterObjectMembersList(typeMembers, existingMembers); + return this.contextNodeBlockIsOnOneLine; + }; + FormattingContext.prototype.NextNodeBlockIsOnOneLine = function () { + if (this.nextNodeBlockIsOnOneLine === undefined) { + this.nextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.nextTokenParent); } - return true; + return this.nextNodeBlockIsOnOneLine; + }; + FormattingContext.prototype.NodeIsOnOneLine = function (node) { + var startLine = this.sourceFile.getLineAndCharacterOfPosition(node.getStart(this.sourceFile)).line; + var endLine = this.sourceFile.getLineAndCharacterOfPosition(node.getEnd()).line; + return startLine === endLine; + }; + FormattingContext.prototype.BlockIsOnOneLine = function (node) { + var openBrace = ts.findChildOfKind(node, 15 /* OpenBraceToken */, this.sourceFile); + var closeBrace = ts.findChildOfKind(node, 16 /* CloseBraceToken */, this.sourceFile); + if (openBrace && closeBrace) { + var startLine = this.sourceFile.getLineAndCharacterOfPosition(openBrace.getEnd()).line; + var endLine = this.sourceFile.getLineAndCharacterOfPosition(closeBrace.getStart(this.sourceFile)).line; + return startLine === endLine; + } + return false; + }; + return FormattingContext; + }()); + formatting.FormattingContext = FormattingContext; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + (function (FormattingRequestKind) { + FormattingRequestKind[FormattingRequestKind["FormatDocument"] = 0] = "FormatDocument"; + FormattingRequestKind[FormattingRequestKind["FormatSelection"] = 1] = "FormatSelection"; + FormattingRequestKind[FormattingRequestKind["FormatOnEnter"] = 2] = "FormatOnEnter"; + FormattingRequestKind[FormattingRequestKind["FormatOnSemicolon"] = 3] = "FormatOnSemicolon"; + FormattingRequestKind[FormattingRequestKind["FormatOnClosingCurlyBrace"] = 4] = "FormatOnClosingCurlyBrace"; + })(formatting.FormattingRequestKind || (formatting.FormattingRequestKind = {})); + var FormattingRequestKind = formatting.FormattingRequestKind; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + var Rule = (function () { + function Rule(Descriptor, Operation, Flag) { + if (Flag === void 0) { Flag = 0 /* None */; } + this.Descriptor = Descriptor; + this.Operation = Operation; + this.Flag = Flag; } - /** - * Aggregates relevant symbols for completion in import clauses and export clauses - * whose declarations have a module specifier; for instance, symbols will be aggregated for - * - * import { | } from "moduleName"; - * export { a as foo, | } from "moduleName"; - * - * but not for - * - * export { | }; - * - * Relevant symbols are stored in the captured 'symbols' variable. - * - * @returns true if 'symbols' was successfully populated; false otherwise. - */ - function tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports) { - var declarationKind = namedImportsOrExports.kind === 233 /* NamedImports */ ? - 230 /* ImportDeclaration */ : - 236 /* ExportDeclaration */; - var importOrExportDeclaration = ts.getAncestor(namedImportsOrExports, declarationKind); - var moduleSpecifier = importOrExportDeclaration.moduleSpecifier; - if (!moduleSpecifier) { - return false; + Rule.prototype.toString = function () { + return "[desc=" + this.Descriptor + "," + + "operation=" + this.Operation + "," + + "flag=" + this.Flag + "]"; + }; + return Rule; + }()); + formatting.Rule = Rule; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + (function (RuleAction) { + RuleAction[RuleAction["Ignore"] = 1] = "Ignore"; + RuleAction[RuleAction["Space"] = 2] = "Space"; + RuleAction[RuleAction["NewLine"] = 4] = "NewLine"; + RuleAction[RuleAction["Delete"] = 8] = "Delete"; + })(formatting.RuleAction || (formatting.RuleAction = {})); + var RuleAction = formatting.RuleAction; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + var RuleDescriptor = (function () { + function RuleDescriptor(LeftTokenRange, RightTokenRange) { + this.LeftTokenRange = LeftTokenRange; + this.RightTokenRange = RightTokenRange; + } + RuleDescriptor.prototype.toString = function () { + return "[leftRange=" + this.LeftTokenRange + "," + + "rightRange=" + this.RightTokenRange + "]"; + }; + RuleDescriptor.create1 = function (left, right) { + return RuleDescriptor.create4(formatting.Shared.TokenRange.FromToken(left), formatting.Shared.TokenRange.FromToken(right)); + }; + RuleDescriptor.create2 = function (left, right) { + return RuleDescriptor.create4(left, formatting.Shared.TokenRange.FromToken(right)); + }; + RuleDescriptor.create3 = function (left, right) { + return RuleDescriptor.create4(formatting.Shared.TokenRange.FromToken(left), right); + }; + RuleDescriptor.create4 = function (left, right) { + return new RuleDescriptor(left, right); + }; + return RuleDescriptor; + }()); + formatting.RuleDescriptor = RuleDescriptor; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + (function (RuleFlags) { + RuleFlags[RuleFlags["None"] = 0] = "None"; + RuleFlags[RuleFlags["CanDeleteNewLines"] = 1] = "CanDeleteNewLines"; + })(formatting.RuleFlags || (formatting.RuleFlags = {})); + var RuleFlags = formatting.RuleFlags; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + var RuleOperation = (function () { + function RuleOperation(Context, Action) { + this.Context = Context; + this.Action = Action; + } + RuleOperation.prototype.toString = function () { + return "[context=" + this.Context + "," + + "action=" + this.Action + "]"; + }; + RuleOperation.create1 = function (action) { + return RuleOperation.create2(formatting.RuleOperationContext.Any, action); + }; + RuleOperation.create2 = function (context, action) { + return new RuleOperation(context, action); + }; + return RuleOperation; + }()); + formatting.RuleOperation = RuleOperation; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + var RuleOperationContext = (function () { + function RuleOperationContext() { + var funcs = []; + for (var _i = 0; _i < arguments.length; _i++) { + funcs[_i - 0] = arguments[_i]; } - isMemberCompletion = true; - isNewIdentifierLocation = false; - var exports; - var moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importOrExportDeclaration.moduleSpecifier); - if (moduleSpecifierSymbol) { - exports = typeChecker.getExportsOfModule(moduleSpecifierSymbol); + this.customContextChecks = funcs; + } + RuleOperationContext.prototype.IsAny = function () { + return this === RuleOperationContext.Any; + }; + RuleOperationContext.prototype.InContext = function (context) { + if (this.IsAny()) { + return true; + } + for (var _i = 0, _a = this.customContextChecks; _i < _a.length; _i++) { + var check = _a[_i]; + if (!check(context)) { + return false; + } } - symbols = exports ? filterNamedImportOrExportCompletionItems(exports, namedImportsOrExports.elements) : emptyArray; return true; + }; + return RuleOperationContext; + }()); + RuleOperationContext.Any = new RuleOperationContext(); + formatting.RuleOperationContext = RuleOperationContext; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + var Rules = (function () { + function Rules() { + /// + /// Common Rules + /// + // Leave comments alone + this.IgnoreBeforeComment = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.Comments), formatting.RuleOperation.create1(1 /* Ignore */)); + this.IgnoreAfterLineComment = new formatting.Rule(formatting.RuleDescriptor.create3(2 /* SingleLineCommentTrivia */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create1(1 /* Ignore */)); + // Space after keyword but not before ; or : or ? + this.NoSpaceBeforeSemicolon = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 23 /* SemicolonToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceBeforeColon = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 54 /* ColonToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), 8 /* Delete */)); + this.NoSpaceBeforeQuestionMark = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 53 /* QuestionToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), 8 /* Delete */)); + this.SpaceAfterColon = new formatting.Rule(formatting.RuleDescriptor.create3(54 /* ColonToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), 2 /* Space */)); + this.SpaceAfterQuestionMarkInConditionalOperator = new formatting.Rule(formatting.RuleDescriptor.create3(53 /* QuestionToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsConditionalOperatorContext), 2 /* Space */)); + this.NoSpaceAfterQuestionMark = new formatting.Rule(formatting.RuleDescriptor.create3(53 /* QuestionToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.SpaceAfterSemicolon = new formatting.Rule(formatting.RuleDescriptor.create3(23 /* SemicolonToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + // Space after }. + this.SpaceAfterCloseBrace = new formatting.Rule(formatting.RuleDescriptor.create3(16 /* CloseBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsAfterCodeBlockContext), 2 /* Space */)); + // Special case for (}, else) and (}, while) since else & while tokens are not part of the tree which makes SpaceAfterCloseBrace rule not applied + this.SpaceBetweenCloseBraceAndElse = new formatting.Rule(formatting.RuleDescriptor.create1(16 /* CloseBraceToken */, 80 /* ElseKeyword */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.SpaceBetweenCloseBraceAndWhile = new formatting.Rule(formatting.RuleDescriptor.create1(16 /* CloseBraceToken */, 104 /* WhileKeyword */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.NoSpaceAfterCloseBrace = new formatting.Rule(formatting.RuleDescriptor.create3(16 /* CloseBraceToken */, formatting.Shared.TokenRange.FromTokens([18 /* CloseParenToken */, 20 /* CloseBracketToken */, 24 /* CommaToken */, 23 /* SemicolonToken */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + // No space for dot + this.NoSpaceBeforeDot = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 21 /* DotToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceAfterDot = new formatting.Rule(formatting.RuleDescriptor.create3(21 /* DotToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + // No space before and after indexer + this.NoSpaceBeforeOpenBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 19 /* OpenBracketToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceAfterCloseBracket = new formatting.Rule(formatting.RuleDescriptor.create3(20 /* CloseBracketToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBeforeBlockInFunctionDeclarationContext), 8 /* Delete */)); + // Place a space before open brace in a function declaration + this.FunctionOpenBraceLeftTokenRange = formatting.Shared.TokenRange.AnyIncludingMultilineComments; + this.SpaceBeforeOpenBraceInFunction = new formatting.Rule(formatting.RuleDescriptor.create2(this.FunctionOpenBraceLeftTokenRange, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext, Rules.IsBeforeBlockContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), 2 /* Space */), 1 /* CanDeleteNewLines */); + // Place a space before open brace in a TypeScript declaration that has braces as children (class, module, enum, etc) + this.TypeScriptOpenBraceLeftTokenRange = formatting.Shared.TokenRange.FromTokens([69 /* Identifier */, 3 /* MultiLineCommentTrivia */, 73 /* ClassKeyword */, 82 /* ExportKeyword */, 89 /* ImportKeyword */]); + this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock = new formatting.Rule(formatting.RuleDescriptor.create2(this.TypeScriptOpenBraceLeftTokenRange, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsTypeScriptDeclWithBlockContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), 2 /* Space */), 1 /* CanDeleteNewLines */); + // Place a space before open brace in a control flow construct + this.ControlOpenBraceLeftTokenRange = formatting.Shared.TokenRange.FromTokens([18 /* CloseParenToken */, 3 /* MultiLineCommentTrivia */, 79 /* DoKeyword */, 100 /* TryKeyword */, 85 /* FinallyKeyword */, 80 /* ElseKeyword */]); + this.SpaceBeforeOpenBraceInControl = new formatting.Rule(formatting.RuleDescriptor.create2(this.ControlOpenBraceLeftTokenRange, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), 2 /* Space */), 1 /* CanDeleteNewLines */); + // Insert a space after { and before } in single-line contexts, but remove space from empty object literals {}. + this.SpaceAfterOpenBrace = new formatting.Rule(formatting.RuleDescriptor.create3(15 /* OpenBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSingleLineBlockContext), 2 /* Space */)); + this.SpaceBeforeCloseBrace = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSingleLineBlockContext), 2 /* Space */)); + this.NoSpaceAfterOpenBrace = new formatting.Rule(formatting.RuleDescriptor.create3(15 /* OpenBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSingleLineBlockContext), 8 /* Delete */)); + this.NoSpaceBeforeCloseBrace = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSingleLineBlockContext), 8 /* Delete */)); + this.NoSpaceBetweenEmptyBraceBrackets = new formatting.Rule(formatting.RuleDescriptor.create1(15 /* OpenBraceToken */, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsObjectContext), 8 /* Delete */)); + // Insert new line after { and before } in multi-line contexts. + this.NewLineAfterOpenBraceInBlockContext = new formatting.Rule(formatting.RuleDescriptor.create3(15 /* OpenBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsMultilineBlockContext), 4 /* NewLine */)); + // For functions and control block place } on a new line [multi-line rule] + this.NewLineBeforeCloseBraceInBlockContext = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.AnyIncludingMultilineComments, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsMultilineBlockContext), 4 /* NewLine */)); + // Special handling of unary operators. + // Prefix operators generally shouldn't have a space between + // them and their target unary expression. + this.NoSpaceAfterUnaryPrefixOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.UnaryPrefixOperators, formatting.Shared.TokenRange.UnaryPrefixExpressions), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), 8 /* Delete */)); + this.NoSpaceAfterUnaryPreincrementOperator = new formatting.Rule(formatting.RuleDescriptor.create3(41 /* PlusPlusToken */, formatting.Shared.TokenRange.UnaryPreincrementExpressions), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceAfterUnaryPredecrementOperator = new formatting.Rule(formatting.RuleDescriptor.create3(42 /* MinusMinusToken */, formatting.Shared.TokenRange.UnaryPredecrementExpressions), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceBeforeUnaryPostincrementOperator = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.UnaryPostincrementExpressions, 41 /* PlusPlusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceBeforeUnaryPostdecrementOperator = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.UnaryPostdecrementExpressions, 42 /* MinusMinusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + // More unary operator special-casing. + // DevDiv 181814: Be careful when removing leading whitespace + // around unary operators. Examples: + // 1 - -2 --X--> 1--2 + // a + ++b --X--> a+++b + this.SpaceAfterPostincrementWhenFollowedByAdd = new formatting.Rule(formatting.RuleDescriptor.create1(41 /* PlusPlusToken */, 35 /* PlusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); + this.SpaceAfterAddWhenFollowedByUnaryPlus = new formatting.Rule(formatting.RuleDescriptor.create1(35 /* PlusToken */, 35 /* PlusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); + this.SpaceAfterAddWhenFollowedByPreincrement = new formatting.Rule(formatting.RuleDescriptor.create1(35 /* PlusToken */, 41 /* PlusPlusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); + this.SpaceAfterPostdecrementWhenFollowedBySubtract = new formatting.Rule(formatting.RuleDescriptor.create1(42 /* MinusMinusToken */, 36 /* MinusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); + this.SpaceAfterSubtractWhenFollowedByUnaryMinus = new formatting.Rule(formatting.RuleDescriptor.create1(36 /* MinusToken */, 36 /* MinusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); + this.SpaceAfterSubtractWhenFollowedByPredecrement = new formatting.Rule(formatting.RuleDescriptor.create1(36 /* MinusToken */, 42 /* MinusMinusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); + this.NoSpaceBeforeComma = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 24 /* CommaToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.SpaceAfterCertainKeywords = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([102 /* VarKeyword */, 98 /* ThrowKeyword */, 92 /* NewKeyword */, 78 /* DeleteKeyword */, 94 /* ReturnKeyword */, 101 /* TypeOfKeyword */, 119 /* AwaitKeyword */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.SpaceAfterLetConstInVariableDeclaration = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([108 /* LetKeyword */, 74 /* ConstKeyword */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsStartOfVariableDeclarationList), 2 /* Space */)); + this.NoSpaceBeforeOpenParenInFuncCall = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsFunctionCallOrNewContext, Rules.IsPreviousTokenNotComma), 8 /* Delete */)); + this.SpaceAfterFunctionInFuncDecl = new formatting.Rule(formatting.RuleDescriptor.create3(87 /* FunctionKeyword */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 2 /* Space */)); + this.NoSpaceBeforeOpenParenInFuncDecl = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsFunctionDeclContext), 8 /* Delete */)); + this.SpaceAfterVoidOperator = new formatting.Rule(formatting.RuleDescriptor.create3(103 /* VoidKeyword */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsVoidOpContext), 2 /* Space */)); + this.NoSpaceBetweenReturnAndSemicolon = new formatting.Rule(formatting.RuleDescriptor.create1(94 /* ReturnKeyword */, 23 /* SemicolonToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + // Add a space between statements. All keywords except (do,else,case) has open/close parens after them. + // So, we have a rule to add a space for [),Any], [do,Any], [else,Any], and [case,Any] + this.SpaceBetweenStatements = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([18 /* CloseParenToken */, 79 /* DoKeyword */, 80 /* ElseKeyword */, 71 /* CaseKeyword */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNonJsxElementContext, Rules.IsNotForContext), 2 /* Space */)); + // This low-pri rule takes care of "try {" and "finally {" in case the rule SpaceBeforeOpenBraceInControl didn't execute on FormatOnEnter. + this.SpaceAfterTryFinally = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.FromTokens([100 /* TryKeyword */, 85 /* FinallyKeyword */]), 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + // get x() {} + // set x(val) {} + this.SpaceAfterGetSetInMember = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.FromTokens([123 /* GetKeyword */, 131 /* SetKeyword */]), 69 /* Identifier */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 2 /* Space */)); + // Special case for binary operators (that are keywords). For these we have to add a space and shouldn't follow any user options. + this.SpaceBeforeBinaryKeywordOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.BinaryKeywordOperators), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); + this.SpaceAfterBinaryKeywordOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.BinaryKeywordOperators, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); + // TypeScript-specific higher priority rules + // Treat constructor as an identifier in a function declaration, and remove spaces between constructor and following left parentheses + this.NoSpaceAfterConstructor = new formatting.Rule(formatting.RuleDescriptor.create1(121 /* ConstructorKeyword */, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + // Use of module as a function call. e.g.: import m2 = module("m2"); + this.NoSpaceAfterModuleImport = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.FromTokens([125 /* ModuleKeyword */, 129 /* RequireKeyword */]), 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + // Add a space around certain TypeScript keywords + this.SpaceAfterCertainTypeScriptKeywords = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([115 /* AbstractKeyword */, 73 /* ClassKeyword */, 122 /* DeclareKeyword */, 77 /* DefaultKeyword */, 81 /* EnumKeyword */, 82 /* ExportKeyword */, 83 /* ExtendsKeyword */, 123 /* GetKeyword */, 106 /* ImplementsKeyword */, 89 /* ImportKeyword */, 107 /* InterfaceKeyword */, 125 /* ModuleKeyword */, 126 /* NamespaceKeyword */, 110 /* PrivateKeyword */, 112 /* PublicKeyword */, 111 /* ProtectedKeyword */, 131 /* SetKeyword */, 113 /* StaticKeyword */, 134 /* TypeKeyword */, 136 /* FromKeyword */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.SpaceBeforeCertainTypeScriptKeywords = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.FromTokens([83 /* ExtendsKeyword */, 106 /* ImplementsKeyword */, 136 /* FromKeyword */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + // Treat string literals in module names as identifiers, and add a space between the literal and the opening Brace braces, e.g.: module "m2" { + this.SpaceAfterModuleName = new formatting.Rule(formatting.RuleDescriptor.create1(9 /* StringLiteral */, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsModuleDeclContext), 2 /* Space */)); + // Lambda expressions + this.SpaceBeforeArrow = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 34 /* EqualsGreaterThanToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.SpaceAfterArrow = new formatting.Rule(formatting.RuleDescriptor.create3(34 /* EqualsGreaterThanToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + // Optional parameters and let args + this.NoSpaceAfterEllipsis = new formatting.Rule(formatting.RuleDescriptor.create1(22 /* DotDotDotToken */, 69 /* Identifier */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceAfterOptionalParameters = new formatting.Rule(formatting.RuleDescriptor.create3(53 /* QuestionToken */, formatting.Shared.TokenRange.FromTokens([18 /* CloseParenToken */, 24 /* CommaToken */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), 8 /* Delete */)); + // generics and type assertions + this.NoSpaceBeforeOpenAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.TypeNames, 25 /* LessThanToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), 8 /* Delete */)); + this.NoSpaceBetweenCloseParenAndAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create1(18 /* CloseParenToken */, 25 /* LessThanToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), 8 /* Delete */)); + this.NoSpaceAfterOpenAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create3(25 /* LessThanToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), 8 /* Delete */)); + this.NoSpaceBeforeCloseAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 27 /* GreaterThanToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), 8 /* Delete */)); + this.NoSpaceAfterCloseAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create3(27 /* GreaterThanToken */, formatting.Shared.TokenRange.FromTokens([17 /* OpenParenToken */, 19 /* OpenBracketToken */, 27 /* GreaterThanToken */, 24 /* CommaToken */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), 8 /* Delete */)); + // Remove spaces in empty interface literals. e.g.: x: {} + this.NoSpaceBetweenEmptyInterfaceBraceBrackets = new formatting.Rule(formatting.RuleDescriptor.create1(15 /* OpenBraceToken */, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsObjectTypeContext), 8 /* Delete */)); + // decorators + this.SpaceBeforeAt = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 55 /* AtToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.NoSpaceAfterAt = new formatting.Rule(formatting.RuleDescriptor.create3(55 /* AtToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.SpaceAfterDecorator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.FromTokens([115 /* AbstractKeyword */, 69 /* Identifier */, 82 /* ExportKeyword */, 77 /* DefaultKeyword */, 73 /* ClassKeyword */, 113 /* StaticKeyword */, 112 /* PublicKeyword */, 110 /* PrivateKeyword */, 111 /* ProtectedKeyword */, 123 /* GetKeyword */, 131 /* SetKeyword */, 19 /* OpenBracketToken */, 37 /* AsteriskToken */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsEndOfDecoratorContextOnSameLine), 2 /* Space */)); + this.NoSpaceBetweenFunctionKeywordAndStar = new formatting.Rule(formatting.RuleDescriptor.create1(87 /* FunctionKeyword */, 37 /* AsteriskToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclarationOrFunctionExpressionContext), 8 /* Delete */)); + this.SpaceAfterStarInGeneratorDeclaration = new formatting.Rule(formatting.RuleDescriptor.create3(37 /* AsteriskToken */, formatting.Shared.TokenRange.FromTokens([69 /* Identifier */, 17 /* OpenParenToken */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclarationOrFunctionExpressionContext), 2 /* Space */)); + this.NoSpaceBetweenYieldKeywordAndStar = new formatting.Rule(formatting.RuleDescriptor.create1(114 /* YieldKeyword */, 37 /* AsteriskToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsYieldOrYieldStarWithOperand), 8 /* Delete */)); + this.SpaceBetweenYieldOrYieldStarAndOperand = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([114 /* YieldKeyword */, 37 /* AsteriskToken */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsYieldOrYieldStarWithOperand), 2 /* Space */)); + // Async-await + this.SpaceBetweenAsyncAndOpenParen = new formatting.Rule(formatting.RuleDescriptor.create1(118 /* AsyncKeyword */, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsArrowFunctionContext, Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.SpaceBetweenAsyncAndFunctionKeyword = new formatting.Rule(formatting.RuleDescriptor.create1(118 /* AsyncKeyword */, 87 /* FunctionKeyword */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + // template string + this.NoSpaceBetweenTagAndTemplateString = new formatting.Rule(formatting.RuleDescriptor.create3(69 /* Identifier */, formatting.Shared.TokenRange.FromTokens([11 /* NoSubstitutionTemplateLiteral */, 12 /* TemplateHead */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + // jsx opening element + this.SpaceBeforeJsxAttribute = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 69 /* Identifier */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNextTokenParentJsxAttribute, Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.SpaceBeforeSlashInJsxOpeningElement = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 39 /* SlashToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsJsxSelfClosingElementContext, Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.NoSpaceBeforeGreaterThanTokenInJsxOpeningElement = new formatting.Rule(formatting.RuleDescriptor.create1(39 /* SlashToken */, 27 /* GreaterThanToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsJsxSelfClosingElementContext, Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceBeforeEqualInJsxAttribute = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 56 /* EqualsToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsJsxAttributeContext, Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceAfterEqualInJsxAttribute = new formatting.Rule(formatting.RuleDescriptor.create3(56 /* EqualsToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsJsxAttributeContext, Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + // These rules are higher in priority than user-configurable rules. + this.HighPriorityCommonRules = [ + this.IgnoreBeforeComment, this.IgnoreAfterLineComment, + this.NoSpaceBeforeColon, this.SpaceAfterColon, this.NoSpaceBeforeQuestionMark, this.SpaceAfterQuestionMarkInConditionalOperator, + this.NoSpaceAfterQuestionMark, + this.NoSpaceBeforeDot, this.NoSpaceAfterDot, + this.NoSpaceAfterUnaryPrefixOperator, + this.NoSpaceAfterUnaryPreincrementOperator, this.NoSpaceAfterUnaryPredecrementOperator, + this.NoSpaceBeforeUnaryPostincrementOperator, this.NoSpaceBeforeUnaryPostdecrementOperator, + this.SpaceAfterPostincrementWhenFollowedByAdd, + this.SpaceAfterAddWhenFollowedByUnaryPlus, this.SpaceAfterAddWhenFollowedByPreincrement, + this.SpaceAfterPostdecrementWhenFollowedBySubtract, + this.SpaceAfterSubtractWhenFollowedByUnaryMinus, this.SpaceAfterSubtractWhenFollowedByPredecrement, + this.NoSpaceAfterCloseBrace, + this.NewLineBeforeCloseBraceInBlockContext, + this.SpaceAfterCloseBrace, this.SpaceBetweenCloseBraceAndElse, this.SpaceBetweenCloseBraceAndWhile, this.NoSpaceBetweenEmptyBraceBrackets, + this.NoSpaceBetweenFunctionKeywordAndStar, this.SpaceAfterStarInGeneratorDeclaration, + this.SpaceAfterFunctionInFuncDecl, this.NewLineAfterOpenBraceInBlockContext, this.SpaceAfterGetSetInMember, + this.NoSpaceBetweenYieldKeywordAndStar, this.SpaceBetweenYieldOrYieldStarAndOperand, + this.NoSpaceBetweenReturnAndSemicolon, + this.SpaceAfterCertainKeywords, + this.SpaceAfterLetConstInVariableDeclaration, + this.NoSpaceBeforeOpenParenInFuncCall, + this.SpaceBeforeBinaryKeywordOperator, this.SpaceAfterBinaryKeywordOperator, + this.SpaceAfterVoidOperator, + this.SpaceBetweenAsyncAndOpenParen, this.SpaceBetweenAsyncAndFunctionKeyword, + this.NoSpaceBetweenTagAndTemplateString, + this.SpaceBeforeJsxAttribute, this.SpaceBeforeSlashInJsxOpeningElement, this.NoSpaceBeforeGreaterThanTokenInJsxOpeningElement, + this.NoSpaceBeforeEqualInJsxAttribute, this.NoSpaceAfterEqualInJsxAttribute, + // TypeScript-specific rules + this.NoSpaceAfterConstructor, this.NoSpaceAfterModuleImport, + this.SpaceAfterCertainTypeScriptKeywords, this.SpaceBeforeCertainTypeScriptKeywords, + this.SpaceAfterModuleName, + this.SpaceBeforeArrow, this.SpaceAfterArrow, + this.NoSpaceAfterEllipsis, + this.NoSpaceAfterOptionalParameters, + this.NoSpaceBetweenEmptyInterfaceBraceBrackets, + this.NoSpaceBeforeOpenAngularBracket, + this.NoSpaceBetweenCloseParenAndAngularBracket, + this.NoSpaceAfterOpenAngularBracket, + this.NoSpaceBeforeCloseAngularBracket, + this.NoSpaceAfterCloseAngularBracket, + this.SpaceBeforeAt, + this.NoSpaceAfterAt, + this.SpaceAfterDecorator, + ]; + // These rules are lower in priority than user-configurable rules. + this.LowPriorityCommonRules = [ + this.NoSpaceBeforeSemicolon, + this.SpaceBeforeOpenBraceInControl, this.SpaceBeforeOpenBraceInFunction, this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock, + this.NoSpaceBeforeComma, + this.NoSpaceBeforeOpenBracket, + this.NoSpaceAfterCloseBracket, + this.SpaceAfterSemicolon, + this.NoSpaceBeforeOpenParenInFuncDecl, + this.SpaceBetweenStatements, this.SpaceAfterTryFinally + ]; + /// + /// Rules controlled by user options + /// + // Insert space after comma delimiter + this.SpaceAfterComma = new formatting.Rule(formatting.RuleDescriptor.create3(24 /* CommaToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNonJsxElementContext, Rules.IsNextTokenNotCloseBracket), 2 /* Space */)); + this.NoSpaceAfterComma = new formatting.Rule(formatting.RuleDescriptor.create3(24 /* CommaToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNonJsxElementContext), 8 /* Delete */)); + // Insert space before and after binary operators + this.SpaceBeforeBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.BinaryOperators), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); + this.SpaceAfterBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.BinaryOperators, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); + this.NoSpaceBeforeBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.BinaryOperators), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 8 /* Delete */)); + this.NoSpaceAfterBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.BinaryOperators, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 8 /* Delete */)); + // Insert space after keywords in control flow statements + this.SpaceAfterKeywordInControl = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Keywords, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext), 2 /* Space */)); + this.NoSpaceAfterKeywordInControl = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Keywords, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext), 8 /* Delete */)); + // Open Brace braces after function + // TypeScript: Function can have return types, which can be made of tons of different token kinds + this.NewLineBeforeOpenBraceInFunction = new formatting.Rule(formatting.RuleDescriptor.create2(this.FunctionOpenBraceLeftTokenRange, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext, Rules.IsBeforeMultilineBlockContext), 4 /* NewLine */), 1 /* CanDeleteNewLines */); + // Open Brace braces after TypeScript module/class/interface + this.NewLineBeforeOpenBraceInTypeScriptDeclWithBlock = new formatting.Rule(formatting.RuleDescriptor.create2(this.TypeScriptOpenBraceLeftTokenRange, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsTypeScriptDeclWithBlockContext, Rules.IsBeforeMultilineBlockContext), 4 /* NewLine */), 1 /* CanDeleteNewLines */); + // Open Brace braces after control block + this.NewLineBeforeOpenBraceInControl = new formatting.Rule(formatting.RuleDescriptor.create2(this.ControlOpenBraceLeftTokenRange, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext, Rules.IsBeforeMultilineBlockContext), 4 /* NewLine */), 1 /* CanDeleteNewLines */); + // Insert space after semicolon in for statement + this.SpaceAfterSemicolonInFor = new formatting.Rule(formatting.RuleDescriptor.create3(23 /* SemicolonToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsForContext), 2 /* Space */)); + this.NoSpaceAfterSemicolonInFor = new formatting.Rule(formatting.RuleDescriptor.create3(23 /* SemicolonToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsForContext), 8 /* Delete */)); + // Insert space after opening and before closing nonempty parenthesis + this.SpaceAfterOpenParen = new formatting.Rule(formatting.RuleDescriptor.create3(17 /* OpenParenToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.SpaceBeforeCloseParen = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 18 /* CloseParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.NoSpaceBetweenParens = new formatting.Rule(formatting.RuleDescriptor.create1(17 /* OpenParenToken */, 18 /* CloseParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceAfterOpenParen = new formatting.Rule(formatting.RuleDescriptor.create3(17 /* OpenParenToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceBeforeCloseParen = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 18 /* CloseParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + // Insert space after opening and before closing nonempty brackets + this.SpaceAfterOpenBracket = new formatting.Rule(formatting.RuleDescriptor.create3(19 /* OpenBracketToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.SpaceBeforeCloseBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 20 /* CloseBracketToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.NoSpaceBetweenBrackets = new formatting.Rule(formatting.RuleDescriptor.create1(19 /* OpenBracketToken */, 20 /* CloseBracketToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceAfterOpenBracket = new formatting.Rule(formatting.RuleDescriptor.create3(19 /* OpenBracketToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceBeforeCloseBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 20 /* CloseBracketToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + // Insert space after opening and before closing template string braces + this.NoSpaceAfterTemplateHeadAndMiddle = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([12 /* TemplateHead */, 13 /* TemplateMiddle */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.SpaceAfterTemplateHeadAndMiddle = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([12 /* TemplateHead */, 13 /* TemplateMiddle */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.NoSpaceBeforeTemplateMiddleAndTail = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.FromTokens([13 /* TemplateMiddle */, 14 /* TemplateTail */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.SpaceBeforeTemplateMiddleAndTail = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.FromTokens([13 /* TemplateMiddle */, 14 /* TemplateTail */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + // No space after { and before } in JSX expression + this.NoSpaceAfterOpenBraceInJsxExpression = new formatting.Rule(formatting.RuleDescriptor.create3(15 /* OpenBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsJsxExpressionContext), 8 /* Delete */)); + this.SpaceAfterOpenBraceInJsxExpression = new formatting.Rule(formatting.RuleDescriptor.create3(15 /* OpenBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsJsxExpressionContext), 2 /* Space */)); + this.NoSpaceBeforeCloseBraceInJsxExpression = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsJsxExpressionContext), 8 /* Delete */)); + this.SpaceBeforeCloseBraceInJsxExpression = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsJsxExpressionContext), 2 /* Space */)); + // Insert space after function keyword for anonymous functions + this.SpaceAfterAnonymousFunctionKeyword = new formatting.Rule(formatting.RuleDescriptor.create1(87 /* FunctionKeyword */, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 2 /* Space */)); + this.NoSpaceAfterAnonymousFunctionKeyword = new formatting.Rule(formatting.RuleDescriptor.create1(87 /* FunctionKeyword */, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 8 /* Delete */)); + // No space after type assertion + this.NoSpaceAfterTypeAssertion = new formatting.Rule(formatting.RuleDescriptor.create3(27 /* GreaterThanToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeAssertionContext), 8 /* Delete */)); + this.SpaceAfterTypeAssertion = new formatting.Rule(formatting.RuleDescriptor.create3(27 /* GreaterThanToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeAssertionContext), 2 /* Space */)); } - /** - * Returns the immediate owning object literal or binding pattern of a context token, - * on the condition that one exists and that the context implies completion should be given. - */ - function tryGetObjectLikeCompletionContainer(contextToken) { - if (contextToken) { - switch (contextToken.kind) { - case 15 /* OpenBraceToken */: // const x = { | - case 24 /* CommaToken */: - var parent_19 = contextToken.parent; - if (parent_19 && (parent_19.kind === 171 /* ObjectLiteralExpression */ || parent_19.kind === 167 /* ObjectBindingPattern */)) { - return parent_19; - } - break; + Rules.prototype.getRuleName = function (rule) { + var o = this; + for (var name_54 in o) { + if (o[name_54] === rule) { + return name_54; } } - return undefined; - } - /** - * Returns the containing list of named imports or exports of a context token, - * on the condition that one exists and that the context implies completion should be given. - */ - function tryGetNamedImportsOrExportsForCompletion(contextToken) { - if (contextToken) { - switch (contextToken.kind) { - case 15 /* OpenBraceToken */: // import { | - case 24 /* CommaToken */: - switch (contextToken.parent.kind) { - case 233 /* NamedImports */: - case 237 /* NamedExports */: - return contextToken.parent; - } - } + throw new Error("Unknown rule"); + }; + /// + /// Contexts + /// + Rules.IsForContext = function (context) { + return context.contextNode.kind === 206 /* ForStatement */; + }; + Rules.IsNotForContext = function (context) { + return !Rules.IsForContext(context); + }; + Rules.IsBinaryOpContext = function (context) { + switch (context.contextNode.kind) { + case 187 /* BinaryExpression */: + case 188 /* ConditionalExpression */: + case 195 /* AsExpression */: + case 238 /* ExportSpecifier */: + case 234 /* ImportSpecifier */: + case 154 /* TypePredicate */: + case 162 /* UnionType */: + case 163 /* IntersectionType */: + return true; + // equals in binding elements: function foo([[x, y] = [1, 2]]) + case 169 /* BindingElement */: + // equals in type X = ... + case 223 /* TypeAliasDeclaration */: + // equal in import a = module('a'); + case 229 /* ImportEqualsDeclaration */: + // equal in let a = 0; + case 218 /* VariableDeclaration */: + // equal in p = 0; + case 142 /* Parameter */: + case 255 /* EnumMember */: + case 145 /* PropertyDeclaration */: + case 144 /* PropertySignature */: + return context.currentTokenSpan.kind === 56 /* EqualsToken */ || context.nextTokenSpan.kind === 56 /* EqualsToken */; + // "in" keyword in for (let x in []) { } + case 207 /* ForInStatement */: + return context.currentTokenSpan.kind === 90 /* InKeyword */ || context.nextTokenSpan.kind === 90 /* InKeyword */; + // Technically, "of" is not a binary operator, but format it the same way as "in" + case 208 /* ForOfStatement */: + return context.currentTokenSpan.kind === 138 /* OfKeyword */ || context.nextTokenSpan.kind === 138 /* OfKeyword */; } - return undefined; - } - function tryGetContainingJsxElement(contextToken) { - if (contextToken) { - var parent_20 = contextToken.parent; - switch (contextToken.kind) { - case 26 /* LessThanSlashToken */: - case 39 /* SlashToken */: - case 69 /* Identifier */: - case 246 /* JsxAttribute */: - case 247 /* JsxSpreadAttribute */: - if (parent_20 && (parent_20.kind === 242 /* JsxSelfClosingElement */ || parent_20.kind === 243 /* JsxOpeningElement */)) { - return parent_20; - } - else if (parent_20.kind === 246 /* JsxAttribute */) { - return parent_20.parent; - } - break; - // The context token is the closing } or " of an attribute, which means - // its parent is a JsxExpression, whose parent is a JsxAttribute, - // whose parent is a JsxOpeningLikeElement - case 9 /* StringLiteral */: - if (parent_20 && ((parent_20.kind === 246 /* JsxAttribute */) || (parent_20.kind === 247 /* JsxSpreadAttribute */))) { - return parent_20.parent; - } - break; - case 16 /* CloseBraceToken */: - if (parent_20 && - parent_20.kind === 248 /* JsxExpression */ && - parent_20.parent && - (parent_20.parent.kind === 246 /* JsxAttribute */)) { - return parent_20.parent.parent; - } - if (parent_20 && parent_20.kind === 247 /* JsxSpreadAttribute */) { - return parent_20.parent; - } - break; - } + return false; + }; + Rules.IsNotBinaryOpContext = function (context) { + return !Rules.IsBinaryOpContext(context); + }; + Rules.IsConditionalOperatorContext = function (context) { + return context.contextNode.kind === 188 /* ConditionalExpression */; + }; + Rules.IsSameLineTokenOrBeforeMultilineBlockContext = function (context) { + //// This check is mainly used inside SpaceBeforeOpenBraceInControl and SpaceBeforeOpenBraceInFunction. + //// + //// Ex: + //// if (1) { .... + //// * ) and { are on the same line so apply the rule. Here we don't care whether it's same or multi block context + //// + //// Ex: + //// if (1) + //// { ... } + //// * ) and { are on different lines. We only need to format if the block is multiline context. So in this case we don't format. + //// + //// Ex: + //// if (1) + //// { ... + //// } + //// * ) and { are on different lines. We only need to format if the block is multiline context. So in this case we format. + return context.TokensAreOnSameLine() || Rules.IsBeforeMultilineBlockContext(context); + }; + // This check is done before an open brace in a control construct, a function, or a typescript block declaration + Rules.IsBeforeMultilineBlockContext = function (context) { + return Rules.IsBeforeBlockContext(context) && !(context.NextNodeAllOnSameLine() || context.NextNodeBlockIsOnOneLine()); + }; + Rules.IsMultilineBlockContext = function (context) { + return Rules.IsBlockContext(context) && !(context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine()); + }; + Rules.IsSingleLineBlockContext = function (context) { + return Rules.IsBlockContext(context) && (context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine()); + }; + Rules.IsBlockContext = function (context) { + return Rules.NodeIsBlockContext(context.contextNode); + }; + Rules.IsBeforeBlockContext = function (context) { + return Rules.NodeIsBlockContext(context.nextTokenParent); + }; + // IMPORTANT!!! This method must return true ONLY for nodes with open and close braces as immediate children + Rules.NodeIsBlockContext = function (node) { + if (Rules.NodeIsTypeScriptDeclWithBlockContext(node)) { + // This means we are in a context that looks like a block to the user, but in the grammar is actually not a node (it's a class, module, enum, object type literal, etc). + return true; } - return undefined; - } - function isFunction(kind) { - switch (kind) { - case 179 /* FunctionExpression */: - case 180 /* ArrowFunction */: + switch (node.kind) { + case 199 /* Block */: + case 227 /* CaseBlock */: + case 171 /* ObjectLiteralExpression */: + case 226 /* ModuleBlock */: + return true; + } + return false; + }; + Rules.IsFunctionDeclContext = function (context) { + switch (context.contextNode.kind) { case 220 /* FunctionDeclaration */: case 147 /* MethodDeclaration */: case 146 /* MethodSignature */: + // case SyntaxKind.MemberFunctionDeclaration: case 149 /* GetAccessor */: case 150 /* SetAccessor */: + // case SyntaxKind.MethodSignature: case 151 /* CallSignature */: - case 152 /* ConstructSignature */: - case 153 /* IndexSignature */: + case 179 /* FunctionExpression */: + case 148 /* Constructor */: + case 180 /* ArrowFunction */: + // case SyntaxKind.ConstructorDeclaration: + // case SyntaxKind.SimpleArrowFunctionExpression: + // case SyntaxKind.ParenthesizedArrowFunctionExpression: + case 222 /* InterfaceDeclaration */: return true; } return false; - } - /** - * @returns true if we are certain that the currently edited location must define a new location; false otherwise. - */ - function isSolelyIdentifierDefinitionLocation(contextToken) { - var containingNodeKind = contextToken.parent.kind; - switch (contextToken.kind) { - case 24 /* CommaToken */: - return containingNodeKind === 218 /* VariableDeclaration */ || - containingNodeKind === 219 /* VariableDeclarationList */ || - containingNodeKind === 200 /* VariableStatement */ || - containingNodeKind === 224 /* EnumDeclaration */ || - isFunction(containingNodeKind) || - containingNodeKind === 221 /* ClassDeclaration */ || - containingNodeKind === 192 /* ClassExpression */ || - containingNodeKind === 222 /* InterfaceDeclaration */ || - containingNodeKind === 168 /* ArrayBindingPattern */ || - containingNodeKind === 223 /* TypeAliasDeclaration */; // type Map, K, | - case 21 /* DotToken */: - return containingNodeKind === 168 /* ArrayBindingPattern */; // var [.| - case 54 /* ColonToken */: - return containingNodeKind === 169 /* BindingElement */; // var {x :html| - case 19 /* OpenBracketToken */: - return containingNodeKind === 168 /* ArrayBindingPattern */; // var [x| - case 17 /* OpenParenToken */: - return containingNodeKind === 252 /* CatchClause */ || - isFunction(containingNodeKind); - case 15 /* OpenBraceToken */: - return containingNodeKind === 224 /* EnumDeclaration */ || - containingNodeKind === 222 /* InterfaceDeclaration */ || - containingNodeKind === 159 /* TypeLiteral */; // const x : { | - case 23 /* SemicolonToken */: - return containingNodeKind === 144 /* PropertySignature */ && - contextToken.parent && contextToken.parent.parent && - (contextToken.parent.parent.kind === 222 /* InterfaceDeclaration */ || - contextToken.parent.parent.kind === 159 /* TypeLiteral */); // const x : { a; | - case 25 /* LessThanToken */: - return containingNodeKind === 221 /* ClassDeclaration */ || - containingNodeKind === 192 /* ClassExpression */ || - containingNodeKind === 222 /* InterfaceDeclaration */ || - containingNodeKind === 223 /* TypeAliasDeclaration */ || - isFunction(containingNodeKind); - case 113 /* StaticKeyword */: - return containingNodeKind === 145 /* PropertyDeclaration */; - case 22 /* DotDotDotToken */: - return containingNodeKind === 142 /* Parameter */ || - (contextToken.parent && contextToken.parent.parent && - contextToken.parent.parent.kind === 168 /* ArrayBindingPattern */); // var [...z| - case 112 /* PublicKeyword */: - case 110 /* PrivateKeyword */: - case 111 /* ProtectedKeyword */: - return containingNodeKind === 142 /* Parameter */; - case 116 /* AsKeyword */: - return containingNodeKind === 234 /* ImportSpecifier */ || - containingNodeKind === 238 /* ExportSpecifier */ || - containingNodeKind === 232 /* NamespaceImport */; - case 73 /* ClassKeyword */: - case 81 /* EnumKeyword */: - case 107 /* InterfaceKeyword */: - case 87 /* FunctionKeyword */: - case 102 /* VarKeyword */: - case 123 /* GetKeyword */: - case 131 /* SetKeyword */: - case 89 /* ImportKeyword */: - case 108 /* LetKeyword */: - case 74 /* ConstKeyword */: - case 114 /* YieldKeyword */: - case 134 /* TypeKeyword */: - return true; - } - // Previous token may have been a keyword that was converted to an identifier. - switch (contextToken.getText()) { - case "abstract": - case "async": - case "class": - case "const": - case "declare": - case "enum": - case "function": - case "interface": - case "let": - case "private": - case "protected": - case "public": - case "static": - case "var": - case "yield": + }; + Rules.IsFunctionDeclarationOrFunctionExpressionContext = function (context) { + return context.contextNode.kind === 220 /* FunctionDeclaration */ || context.contextNode.kind === 179 /* FunctionExpression */; + }; + Rules.IsTypeScriptDeclWithBlockContext = function (context) { + return Rules.NodeIsTypeScriptDeclWithBlockContext(context.contextNode); + }; + Rules.NodeIsTypeScriptDeclWithBlockContext = function (node) { + switch (node.kind) { + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + case 222 /* InterfaceDeclaration */: + case 224 /* EnumDeclaration */: + case 159 /* TypeLiteral */: + case 225 /* ModuleDeclaration */: + case 236 /* ExportDeclaration */: + case 237 /* NamedExports */: + case 230 /* ImportDeclaration */: + case 233 /* NamedImports */: return true; } return false; - } - function isDotOfNumericLiteral(contextToken) { - if (contextToken.kind === 8 /* NumericLiteral */) { - var text = contextToken.getFullText(); - return text.charAt(text.length - 1) === "."; + }; + Rules.IsAfterCodeBlockContext = function (context) { + switch (context.currentTokenParent.kind) { + case 221 /* ClassDeclaration */: + case 225 /* ModuleDeclaration */: + case 224 /* EnumDeclaration */: + case 199 /* Block */: + case 252 /* CatchClause */: + case 226 /* ModuleBlock */: + case 213 /* SwitchStatement */: + return true; } return false; - } - /** - * Filters out completion suggestions for named imports or exports. - * - * @param exportsOfModule The list of symbols which a module exposes. - * @param namedImportsOrExports The list of existing import/export specifiers in the import/export clause. - * - * @returns Symbols to be suggested at an import/export clause, barring those whose named imports/exports - * do not occur at the current position and have not otherwise been typed. - */ - function filterNamedImportOrExportCompletionItems(exportsOfModule, namedImportsOrExports) { - var existingImportsOrExports = ts.createMap(); - for (var _i = 0, namedImportsOrExports_1 = namedImportsOrExports; _i < namedImportsOrExports_1.length; _i++) { - var element = namedImportsOrExports_1[_i]; - // If this is the current item we are editing right now, do not filter it out - if (element.getStart() <= position && position <= element.getEnd()) { - continue; - } - var name_41 = element.propertyName || element.name; - existingImportsOrExports[name_41.text] = true; - } - if (!ts.someProperties(existingImportsOrExports)) { - return ts.filter(exportsOfModule, function (e) { return e.name !== "default"; }); - } - return ts.filter(exportsOfModule, function (e) { return e.name !== "default" && !existingImportsOrExports[e.name]; }); - } - /** - * Filters out completion suggestions for named imports or exports. - * - * @returns Symbols to be suggested in an object binding pattern or object literal expression, barring those whose declarations - * do not occur at the current position and have not otherwise been typed. - */ - function filterObjectMembersList(contextualMemberSymbols, existingMembers) { - if (!existingMembers || existingMembers.length === 0) { - return contextualMemberSymbols; - } - var existingMemberNames = ts.createMap(); - for (var _i = 0, existingMembers_1 = existingMembers; _i < existingMembers_1.length; _i++) { - var m = existingMembers_1[_i]; - // Ignore omitted expressions for missing members - if (m.kind !== 253 /* PropertyAssignment */ && - m.kind !== 254 /* ShorthandPropertyAssignment */ && - m.kind !== 169 /* BindingElement */ && - m.kind !== 147 /* MethodDeclaration */) { - continue; - } - // If this is the current item we are editing right now, do not filter it out - if (m.getStart() <= position && position <= m.getEnd()) { - continue; - } - var existingName = void 0; - if (m.kind === 169 /* BindingElement */ && m.propertyName) { - // include only identifiers in completion list - if (m.propertyName.kind === 69 /* Identifier */) { - existingName = m.propertyName.text; - } - } - else { - // TODO(jfreeman): Account for computed property name - // NOTE: if one only performs this step when m.name is an identifier, - // things like '__proto__' are not filtered out. - existingName = m.name.text; - } - existingMemberNames[existingName] = true; - } - return ts.filter(contextualMemberSymbols, function (m) { return !existingMemberNames[m.name]; }); - } - /** - * Filters out completion suggestions from 'symbols' according to existing JSX attributes. - * - * @returns Symbols to be suggested in a JSX element, barring those whose attributes - * do not occur at the current position and have not otherwise been typed. - */ - function filterJsxAttributes(symbols, attributes) { - var seenNames = ts.createMap(); - for (var _i = 0, attributes_1 = attributes; _i < attributes_1.length; _i++) { - var attr = attributes_1[_i]; - // If this is the current item we are editing right now, do not filter it out - if (attr.getStart() <= position && position <= attr.getEnd()) { - continue; - } - if (attr.kind === 246 /* JsxAttribute */) { - seenNames[attr.name.text] = true; - } + }; + Rules.IsControlDeclContext = function (context) { + switch (context.contextNode.kind) { + case 203 /* IfStatement */: + case 213 /* SwitchStatement */: + case 206 /* ForStatement */: + case 207 /* ForInStatement */: + case 208 /* ForOfStatement */: + case 205 /* WhileStatement */: + case 216 /* TryStatement */: + case 204 /* DoStatement */: + case 212 /* WithStatement */: + // TODO + // case SyntaxKind.ElseClause: + case 252 /* CatchClause */: + return true; + default: + return false; } - return ts.filter(symbols, function (a) { return !seenNames[a.name]; }); - } - } - function getCompletionsAtPosition(fileName, position) { - synchronizeHostData(); - var sourceFile = getValidSourceFile(fileName); - if (ts.isInString(sourceFile, position)) { - return getStringLiteralCompletionEntries(sourceFile, position); - } - var completionData = getCompletionData(fileName, position); - if (!completionData) { - return undefined; - } - var symbols = completionData.symbols, isMemberCompletion = completionData.isMemberCompletion, isNewIdentifierLocation = completionData.isNewIdentifierLocation, location = completionData.location, isJsDocTagName = completionData.isJsDocTagName; - if (isJsDocTagName) { - // If the current position is a jsDoc tag name, only tag names should be provided for completion - return { isMemberCompletion: false, isNewIdentifierLocation: false, entries: getAllJsDocCompletionEntries() }; - } - var entries = []; - if (ts.isSourceFileJavaScript(sourceFile)) { - var uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, /*performCharacterChecks*/ false); - ts.addRange(entries, getJavaScriptCompletionEntries(sourceFile, location.pos, uniqueNames)); - } - else { - if (!symbols || symbols.length === 0) { - if (sourceFile.languageVariant === 1 /* JSX */ && - location.parent && location.parent.kind === 245 /* JsxClosingElement */) { - // In the TypeScript JSX element, if such element is not defined. When users query for completion at closing tag, - // instead of simply giving unknown value, the completion will return the tag-name of an associated opening-element. - // For example: - // var x =
completion list at "1" will contain "div" with type any - var tagName = location.parent.parent.openingElement.tagName; - entries.push({ - name: tagName.text, - kind: undefined, - kindModifiers: undefined, - sortText: "0", - }); - } - else { - return undefined; - } + }; + Rules.IsObjectContext = function (context) { + return context.contextNode.kind === 171 /* ObjectLiteralExpression */; + }; + Rules.IsFunctionCallContext = function (context) { + return context.contextNode.kind === 174 /* CallExpression */; + }; + Rules.IsNewContext = function (context) { + return context.contextNode.kind === 175 /* NewExpression */; + }; + Rules.IsFunctionCallOrNewContext = function (context) { + return Rules.IsFunctionCallContext(context) || Rules.IsNewContext(context); + }; + Rules.IsPreviousTokenNotComma = function (context) { + return context.currentTokenSpan.kind !== 24 /* CommaToken */; + }; + Rules.IsNextTokenNotCloseBracket = function (context) { + return context.nextTokenSpan.kind !== 20 /* CloseBracketToken */; + }; + Rules.IsArrowFunctionContext = function (context) { + return context.contextNode.kind === 180 /* ArrowFunction */; + }; + Rules.IsNonJsxSameLineTokenContext = function (context) { + return context.TokensAreOnSameLine() && context.contextNode.kind !== 244 /* JsxText */; + }; + Rules.IsNonJsxElementContext = function (context) { + return context.contextNode.kind !== 241 /* JsxElement */; + }; + Rules.IsJsxExpressionContext = function (context) { + return context.contextNode.kind === 248 /* JsxExpression */; + }; + Rules.IsNextTokenParentJsxAttribute = function (context) { + return context.nextTokenParent.kind === 246 /* JsxAttribute */; + }; + Rules.IsJsxAttributeContext = function (context) { + return context.contextNode.kind === 246 /* JsxAttribute */; + }; + Rules.IsJsxSelfClosingElementContext = function (context) { + return context.contextNode.kind === 242 /* JsxSelfClosingElement */; + }; + Rules.IsNotBeforeBlockInFunctionDeclarationContext = function (context) { + return !Rules.IsFunctionDeclContext(context) && !Rules.IsBeforeBlockContext(context); + }; + Rules.IsEndOfDecoratorContextOnSameLine = function (context) { + return context.TokensAreOnSameLine() && + context.contextNode.decorators && + Rules.NodeIsInDecoratorContext(context.currentTokenParent) && + !Rules.NodeIsInDecoratorContext(context.nextTokenParent); + }; + Rules.NodeIsInDecoratorContext = function (node) { + while (ts.isPartOfExpression(node)) { + node = node.parent; } - getCompletionEntriesFromSymbols(symbols, entries, location, /*performCharacterChecks*/ true); - } - // Add keywords if this is not a member completion list - if (!isMemberCompletion && !isJsDocTagName) { - ts.addRange(entries, keywordCompletions); - } - return { isMemberCompletion: isMemberCompletion, isNewIdentifierLocation: isNewIdentifierLocation || ts.isSourceFileJavaScript(sourceFile), entries: entries }; - function getJavaScriptCompletionEntries(sourceFile, position, uniqueNames) { - var entries = []; - var target = program.getCompilerOptions().target; - var nameTable = getNameTable(sourceFile); - for (var name_42 in nameTable) { - // Skip identifiers produced only from the current location - if (nameTable[name_42] === position) { - continue; - } - if (!uniqueNames[name_42]) { - uniqueNames[name_42] = name_42; - var displayName = getCompletionEntryDisplayName(ts.unescapeIdentifier(name_42), target, /*performCharacterChecks*/ true); - if (displayName) { - var entry = { - name: displayName, - kind: ts.ScriptElementKind.warning, - kindModifiers: "", - sortText: "1" - }; - entries.push(entry); - } - } + return node.kind === 143 /* Decorator */; + }; + Rules.IsStartOfVariableDeclarationList = function (context) { + return context.currentTokenParent.kind === 219 /* VariableDeclarationList */ && + context.currentTokenParent.getStart(context.sourceFile) === context.currentTokenSpan.pos; + }; + Rules.IsNotFormatOnEnter = function (context) { + return context.formattingRequestKind !== 2 /* FormatOnEnter */; + }; + Rules.IsModuleDeclContext = function (context) { + return context.contextNode.kind === 225 /* ModuleDeclaration */; + }; + Rules.IsObjectTypeContext = function (context) { + return context.contextNode.kind === 159 /* TypeLiteral */; // && context.contextNode.parent.kind !== SyntaxKind.InterfaceDeclaration; + }; + Rules.IsTypeArgumentOrParameterOrAssertion = function (token, parent) { + if (token.kind !== 25 /* LessThanToken */ && token.kind !== 27 /* GreaterThanToken */) { + return false; } - return entries; - } - function getAllJsDocCompletionEntries() { - return jsDocCompletionEntries || (jsDocCompletionEntries = ts.map(jsDocTagNames, function (tagName) { - return { - name: tagName, - kind: ts.ScriptElementKind.keyword, - kindModifiers: "", - sortText: "0", - }; - })); - } - function createCompletionEntry(symbol, location, performCharacterChecks) { - // Try to get a valid display name for this symbol, if we could not find one, then ignore it. - // We would like to only show things that can be added after a dot, so for instance numeric properties can - // not be accessed with a dot (a.1 <- invalid) - var displayName = getCompletionEntryDisplayNameForSymbol(symbol, program.getCompilerOptions().target, performCharacterChecks, location); - if (!displayName) { - return undefined; + switch (parent.kind) { + case 155 /* TypeReference */: + case 177 /* TypeAssertionExpression */: + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + case 222 /* InterfaceDeclaration */: + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + case 180 /* ArrowFunction */: + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + case 151 /* CallSignature */: + case 152 /* ConstructSignature */: + case 174 /* CallExpression */: + case 175 /* NewExpression */: + case 194 /* ExpressionWithTypeArguments */: + return true; + default: + return false; } - // TODO(drosen): Right now we just permit *all* semantic meanings when calling - // 'getSymbolKind' which is permissible given that it is backwards compatible; but - // really we should consider passing the meaning for the node so that we don't report - // that a suggestion for a value is an interface. We COULD also just do what - // 'getSymbolModifiers' does, which is to use the first declaration. - // Use a 'sortText' of 0' so that all symbol completion entries come before any other - // entries (like JavaScript identifier entries). - return { - name: displayName, - kind: getSymbolKind(symbol, location), - kindModifiers: getSymbolModifiers(symbol), - sortText: "0", - }; + }; + Rules.IsTypeArgumentOrParameterOrAssertionContext = function (context) { + return Rules.IsTypeArgumentOrParameterOrAssertion(context.currentTokenSpan, context.currentTokenParent) || + Rules.IsTypeArgumentOrParameterOrAssertion(context.nextTokenSpan, context.nextTokenParent); + }; + Rules.IsTypeAssertionContext = function (context) { + return context.contextNode.kind === 177 /* TypeAssertionExpression */; + }; + Rules.IsVoidOpContext = function (context) { + return context.currentTokenSpan.kind === 103 /* VoidKeyword */ && context.currentTokenParent.kind === 183 /* VoidExpression */; + }; + Rules.IsYieldOrYieldStarWithOperand = function (context) { + return context.contextNode.kind === 190 /* YieldExpression */ && context.contextNode.expression !== undefined; + }; + return Rules; + }()); + formatting.Rules = Rules; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + var RulesMap = (function () { + function RulesMap() { + this.map = []; + this.mapRowLength = 0; } - function getCompletionEntriesFromSymbols(symbols, entries, location, performCharacterChecks) { - var start = ts.timestamp(); - var uniqueNames = ts.createMap(); - if (symbols) { - for (var _i = 0, symbols_4 = symbols; _i < symbols_4.length; _i++) { - var symbol = symbols_4[_i]; - var entry = createCompletionEntry(symbol, location, performCharacterChecks); - if (entry) { - var id = ts.escapeIdentifier(entry.name); - if (!uniqueNames[id]) { - entries.push(entry); - uniqueNames[id] = id; - } + RulesMap.create = function (rules) { + var result = new RulesMap(); + result.Initialize(rules); + return result; + }; + RulesMap.prototype.Initialize = function (rules) { + this.mapRowLength = 138 /* LastToken */ + 1; + this.map = new Array(this.mapRowLength * this.mapRowLength); // new Array(this.mapRowLength * this.mapRowLength); + // This array is used only during construction of the rulesbucket in the map + var rulesBucketConstructionStateList = new Array(this.map.length); // new Array(this.map.length); + this.FillRules(rules, rulesBucketConstructionStateList); + return this.map; + }; + RulesMap.prototype.FillRules = function (rules, rulesBucketConstructionStateList) { + var _this = this; + rules.forEach(function (rule) { + _this.FillRule(rule, rulesBucketConstructionStateList); + }); + }; + RulesMap.prototype.GetRuleBucketIndex = function (row, column) { + var rulesBucketIndex = (row * this.mapRowLength) + column; + // Debug.Assert(rulesBucketIndex < this.map.Length, "Trying to access an index outside the array."); + return rulesBucketIndex; + }; + RulesMap.prototype.FillRule = function (rule, rulesBucketConstructionStateList) { + var _this = this; + var specificRule = rule.Descriptor.LeftTokenRange !== formatting.Shared.TokenRange.Any && + rule.Descriptor.RightTokenRange !== formatting.Shared.TokenRange.Any; + rule.Descriptor.LeftTokenRange.GetTokens().forEach(function (left) { + rule.Descriptor.RightTokenRange.GetTokens().forEach(function (right) { + var rulesBucketIndex = _this.GetRuleBucketIndex(left, right); + var rulesBucket = _this.map[rulesBucketIndex]; + if (rulesBucket === undefined) { + rulesBucket = _this.map[rulesBucketIndex] = new RulesBucket(); + } + rulesBucket.AddRule(rule, specificRule, rulesBucketConstructionStateList, rulesBucketIndex); + }); + }); + }; + RulesMap.prototype.GetRule = function (context) { + var bucketIndex = this.GetRuleBucketIndex(context.currentTokenSpan.kind, context.nextTokenSpan.kind); + var bucket = this.map[bucketIndex]; + if (bucket) { + for (var _i = 0, _a = bucket.Rules(); _i < _a.length; _i++) { + var rule = _a[_i]; + if (rule.Operation.Context.InContext(context)) { + return rule; } } } - log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (ts.timestamp() - start)); - return uniqueNames; + return undefined; + }; + return RulesMap; + }()); + formatting.RulesMap = RulesMap; + var MaskBitSize = 5; + var Mask = 0x1f; + (function (RulesPosition) { + RulesPosition[RulesPosition["IgnoreRulesSpecific"] = 0] = "IgnoreRulesSpecific"; + RulesPosition[RulesPosition["IgnoreRulesAny"] = MaskBitSize * 1] = "IgnoreRulesAny"; + RulesPosition[RulesPosition["ContextRulesSpecific"] = MaskBitSize * 2] = "ContextRulesSpecific"; + RulesPosition[RulesPosition["ContextRulesAny"] = MaskBitSize * 3] = "ContextRulesAny"; + RulesPosition[RulesPosition["NoContextRulesSpecific"] = MaskBitSize * 4] = "NoContextRulesSpecific"; + RulesPosition[RulesPosition["NoContextRulesAny"] = MaskBitSize * 5] = "NoContextRulesAny"; + })(formatting.RulesPosition || (formatting.RulesPosition = {})); + var RulesPosition = formatting.RulesPosition; + var RulesBucketConstructionState = (function () { + function RulesBucketConstructionState() { + //// The Rules list contains all the inserted rules into a rulebucket in the following order: + //// 1- Ignore rules with specific token combination + //// 2- Ignore rules with any token combination + //// 3- Context rules with specific token combination + //// 4- Context rules with any token combination + //// 5- Non-context rules with specific token combination + //// 6- Non-context rules with any token combination + //// + //// The member rulesInsertionIndexBitmap is used to describe the number of rules + //// in each sub-bucket (above) hence can be used to know the index of where to insert + //// the next rule. It's a bitmap which contains 6 different sections each is given 5 bits. + //// + //// Example: + //// In order to insert a rule to the end of sub-bucket (3), we get the index by adding + //// the values in the bitmap segments 3rd, 2nd, and 1st. + this.rulesInsertionIndexBitmap = 0; } - function getStringLiteralCompletionEntries(sourceFile, position) { - var node = ts.findPrecedingToken(position, sourceFile); - if (!node || node.kind !== 9 /* StringLiteral */) { - return undefined; + RulesBucketConstructionState.prototype.GetInsertionIndex = function (maskPosition) { + var index = 0; + var pos = 0; + var indexBitmap = this.rulesInsertionIndexBitmap; + while (pos <= maskPosition) { + index += (indexBitmap & Mask); + indexBitmap >>= MaskBitSize; + pos += MaskBitSize; } - if (node.parent.kind === 253 /* PropertyAssignment */ && node.parent.parent.kind === 171 /* ObjectLiteralExpression */) { - // Get quoted name of properties of the object literal expression - // i.e. interface ConfigFiles { - // 'jspm:dev': string - // } - // let files: ConfigFiles = { - // '/*completion position*/' - // } - // - // function foo(c: ConfigFiles) {} - // foo({ - // '/*completion position*/' - // }); - return getStringLiteralCompletionEntriesFromPropertyAssignment(node.parent); + return index; + }; + RulesBucketConstructionState.prototype.IncreaseInsertionIndex = function (maskPosition) { + var value = (this.rulesInsertionIndexBitmap >> maskPosition) & Mask; + value++; + ts.Debug.assert((value & Mask) === value, "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules."); + var temp = this.rulesInsertionIndexBitmap & ~(Mask << maskPosition); + temp |= value << maskPosition; + this.rulesInsertionIndexBitmap = temp; + }; + return RulesBucketConstructionState; + }()); + formatting.RulesBucketConstructionState = RulesBucketConstructionState; + var RulesBucket = (function () { + function RulesBucket() { + this.rules = []; + } + RulesBucket.prototype.Rules = function () { + return this.rules; + }; + RulesBucket.prototype.AddRule = function (rule, specificTokens, constructionState, rulesBucketIndex) { + var position; + if (rule.Operation.Action === 1 /* Ignore */) { + position = specificTokens ? + RulesPosition.IgnoreRulesSpecific : + RulesPosition.IgnoreRulesAny; } - else if (ts.isElementAccessExpression(node.parent) && node.parent.argumentExpression === node) { - // Get all names of properties on the expression - // i.e. interface A { - // 'prop1': string - // } - // let a: A; - // a['/*completion position*/'] - return getStringLiteralCompletionEntriesFromElementAccess(node.parent); + else if (!rule.Operation.Context.IsAny()) { + position = specificTokens ? + RulesPosition.ContextRulesSpecific : + RulesPosition.ContextRulesAny; } else { - var argumentInfo = ts.SignatureHelp.getContainingArgumentInfo(node, position, sourceFile); - if (argumentInfo) { - // Get string literal completions from specialized signatures of the target - // i.e. declare function f(a: 'A'); - // f("/*completion position*/") - return getStringLiteralCompletionEntriesFromCallExpression(argumentInfo, node); - } - // Get completion for string literal from string literal type - // i.e. var x: "hi" | "hello" = "/*completion position*/" - return getStringLiteralCompletionEntriesFromContextualType(node); + position = specificTokens ? + RulesPosition.NoContextRulesSpecific : + RulesPosition.NoContextRulesAny; } - } - function getStringLiteralCompletionEntriesFromPropertyAssignment(element) { - var typeChecker = program.getTypeChecker(); - var type = typeChecker.getContextualType(element.parent); - var entries = []; - if (type) { - getCompletionEntriesFromSymbols(type.getApparentProperties(), entries, element, /*performCharacterChecks*/ false); - if (entries.length) { - return { isMemberCompletion: true, isNewIdentifierLocation: true, entries: entries }; - } + var state = constructionState[rulesBucketIndex]; + if (state === undefined) { + state = constructionState[rulesBucketIndex] = new RulesBucketConstructionState(); } - } - function getStringLiteralCompletionEntriesFromCallExpression(argumentInfo, location) { - var typeChecker = program.getTypeChecker(); - var candidates = []; - var entries = []; - typeChecker.getResolvedSignature(argumentInfo.invocation, candidates); - for (var _i = 0, candidates_3 = candidates; _i < candidates_3.length; _i++) { - var candidate = candidates_3[_i]; - if (candidate.parameters.length > argumentInfo.argumentIndex) { - var parameter = candidate.parameters[argumentInfo.argumentIndex]; - addStringLiteralCompletionsFromType(typeChecker.getTypeAtLocation(parameter.valueDeclaration), entries); + var index = state.GetInsertionIndex(position); + this.rules.splice(index, 0, rule); + state.IncreaseInsertionIndex(position); + }; + return RulesBucket; + }()); + formatting.RulesBucket = RulesBucket; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + var Shared; + (function (Shared) { + var TokenRangeAccess = (function () { + function TokenRangeAccess(from, to, except) { + this.tokens = []; + for (var token = from; token <= to; token++) { + if (ts.indexOf(except, token) < 0) { + this.tokens.push(token); + } } } - if (entries.length) { - return { isMemberCompletion: false, isNewIdentifierLocation: true, entries: entries }; + TokenRangeAccess.prototype.GetTokens = function () { + return this.tokens; + }; + TokenRangeAccess.prototype.Contains = function (token) { + return this.tokens.indexOf(token) >= 0; + }; + return TokenRangeAccess; + }()); + Shared.TokenRangeAccess = TokenRangeAccess; + var TokenValuesAccess = (function () { + function TokenValuesAccess(tks) { + this.tokens = tks && tks.length ? tks : []; } - return undefined; - } - function getStringLiteralCompletionEntriesFromElementAccess(node) { - var typeChecker = program.getTypeChecker(); - var type = typeChecker.getTypeAtLocation(node.expression); - var entries = []; - if (type) { - getCompletionEntriesFromSymbols(type.getApparentProperties(), entries, node, /*performCharacterChecks*/ false); - if (entries.length) { - return { isMemberCompletion: true, isNewIdentifierLocation: true, entries: entries }; - } + TokenValuesAccess.prototype.GetTokens = function () { + return this.tokens; + }; + TokenValuesAccess.prototype.Contains = function (token) { + return this.tokens.indexOf(token) >= 0; + }; + return TokenValuesAccess; + }()); + Shared.TokenValuesAccess = TokenValuesAccess; + var TokenSingleValueAccess = (function () { + function TokenSingleValueAccess(token) { + this.token = token; } - return undefined; - } - function getStringLiteralCompletionEntriesFromContextualType(node) { - var typeChecker = program.getTypeChecker(); - var type = typeChecker.getContextualType(node); - if (type) { - var entries_2 = []; - addStringLiteralCompletionsFromType(type, entries_2); - if (entries_2.length) { - return { isMemberCompletion: false, isNewIdentifierLocation: false, entries: entries_2 }; + TokenSingleValueAccess.prototype.GetTokens = function () { + return [this.token]; + }; + TokenSingleValueAccess.prototype.Contains = function (tokenValue) { + return tokenValue === this.token; + }; + return TokenSingleValueAccess; + }()); + Shared.TokenSingleValueAccess = TokenSingleValueAccess; + var TokenAllAccess = (function () { + function TokenAllAccess() { + } + TokenAllAccess.prototype.GetTokens = function () { + var result = []; + for (var token = 0 /* FirstToken */; token <= 138 /* LastToken */; token++) { + result.push(token); } + return result; + }; + TokenAllAccess.prototype.Contains = function (tokenValue) { + return true; + }; + TokenAllAccess.prototype.toString = function () { + return "[allTokens]"; + }; + return TokenAllAccess; + }()); + Shared.TokenAllAccess = TokenAllAccess; + var TokenRange = (function () { + function TokenRange(tokenAccess) { + this.tokenAccess = tokenAccess; } - return undefined; + TokenRange.FromToken = function (token) { + return new TokenRange(new TokenSingleValueAccess(token)); + }; + TokenRange.FromTokens = function (tokens) { + return new TokenRange(new TokenValuesAccess(tokens)); + }; + TokenRange.FromRange = function (f, to, except) { + if (except === void 0) { except = []; } + return new TokenRange(new TokenRangeAccess(f, to, except)); + }; + TokenRange.AllTokens = function () { + return new TokenRange(new TokenAllAccess()); + }; + TokenRange.prototype.GetTokens = function () { + return this.tokenAccess.GetTokens(); + }; + TokenRange.prototype.Contains = function (token) { + return this.tokenAccess.Contains(token); + }; + TokenRange.prototype.toString = function () { + return this.tokenAccess.toString(); + }; + return TokenRange; + }()); + TokenRange.Any = TokenRange.AllTokens(); + TokenRange.AnyIncludingMultilineComments = TokenRange.FromTokens(TokenRange.Any.GetTokens().concat([3 /* MultiLineCommentTrivia */])); + TokenRange.Keywords = TokenRange.FromRange(70 /* FirstKeyword */, 138 /* LastKeyword */); + TokenRange.BinaryOperators = TokenRange.FromRange(25 /* FirstBinaryOperator */, 68 /* LastBinaryOperator */); + TokenRange.BinaryKeywordOperators = TokenRange.FromTokens([90 /* InKeyword */, 91 /* InstanceOfKeyword */, 138 /* OfKeyword */, 116 /* AsKeyword */, 124 /* IsKeyword */]); + TokenRange.UnaryPrefixOperators = TokenRange.FromTokens([41 /* PlusPlusToken */, 42 /* MinusMinusToken */, 50 /* TildeToken */, 49 /* ExclamationToken */]); + TokenRange.UnaryPrefixExpressions = TokenRange.FromTokens([8 /* NumericLiteral */, 69 /* Identifier */, 17 /* OpenParenToken */, 19 /* OpenBracketToken */, 15 /* OpenBraceToken */, 97 /* ThisKeyword */, 92 /* NewKeyword */]); + TokenRange.UnaryPreincrementExpressions = TokenRange.FromTokens([69 /* Identifier */, 17 /* OpenParenToken */, 97 /* ThisKeyword */, 92 /* NewKeyword */]); + TokenRange.UnaryPostincrementExpressions = TokenRange.FromTokens([69 /* Identifier */, 18 /* CloseParenToken */, 20 /* CloseBracketToken */, 92 /* NewKeyword */]); + TokenRange.UnaryPredecrementExpressions = TokenRange.FromTokens([69 /* Identifier */, 17 /* OpenParenToken */, 97 /* ThisKeyword */, 92 /* NewKeyword */]); + TokenRange.UnaryPostdecrementExpressions = TokenRange.FromTokens([69 /* Identifier */, 18 /* CloseParenToken */, 20 /* CloseBracketToken */, 92 /* NewKeyword */]); + TokenRange.Comments = TokenRange.FromTokens([2 /* SingleLineCommentTrivia */, 3 /* MultiLineCommentTrivia */]); + TokenRange.TypeNames = TokenRange.FromTokens([69 /* Identifier */, 130 /* NumberKeyword */, 132 /* StringKeyword */, 120 /* BooleanKeyword */, 133 /* SymbolKeyword */, 103 /* VoidKeyword */, 117 /* AnyKeyword */]); + Shared.TokenRange = TokenRange; + })(Shared = formatting.Shared || (formatting.Shared = {})); + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + var RulesProvider = (function () { + function RulesProvider() { + this.globalRules = new formatting.Rules(); } - function addStringLiteralCompletionsFromType(type, result) { - if (!type) { - return; + RulesProvider.prototype.getRuleName = function (rule) { + return this.globalRules.getRuleName(rule); + }; + RulesProvider.prototype.getRuleByName = function (name) { + return this.globalRules[name]; + }; + RulesProvider.prototype.getRulesMap = function () { + return this.rulesMap; + }; + RulesProvider.prototype.ensureUpToDate = function (options) { + if (!this.options || !ts.compareDataObjects(this.options, options)) { + var activeRules = this.createActiveRules(options); + var rulesMap = formatting.RulesMap.create(activeRules); + this.activeRules = activeRules; + this.rulesMap = rulesMap; + this.options = ts.clone(options); } - if (type.flags & 524288 /* Union */) { - ts.forEach(type.types, function (t) { return addStringLiteralCompletionsFromType(t, result); }); + }; + RulesProvider.prototype.createActiveRules = function (options) { + var rules = this.globalRules.HighPriorityCommonRules.slice(0); + if (options.insertSpaceAfterCommaDelimiter) { + rules.push(this.globalRules.SpaceAfterComma); } else { - if (type.flags & 32 /* StringLiteral */) { - result.push({ - name: type.text, - kindModifiers: ts.ScriptElementKindModifier.none, - kind: ts.ScriptElementKind.variableElement, - sortText: "0" - }); - } - } - } - } - function getCompletionEntryDetails(fileName, position, entryName) { - synchronizeHostData(); - // Compute all the completion symbols again. - var completionData = getCompletionData(fileName, position); - if (completionData) { - var symbols = completionData.symbols, location_2 = completionData.location; - // Find the symbol with the matching entry name. - var target_2 = program.getCompilerOptions().target; - // We don't need to perform character checks here because we're only comparing the - // name against 'entryName' (which is known to be good), not building a new - // completion entry. - var symbol = ts.forEach(symbols, function (s) { return getCompletionEntryDisplayNameForSymbol(s, target_2, /*performCharacterChecks*/ false, location_2) === entryName ? s : undefined; }); - if (symbol) { - var _a = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getValidSourceFile(fileName), location_2, location_2, 7 /* All */), displayParts = _a.displayParts, documentation = _a.documentation, symbolKind = _a.symbolKind; - return { - name: entryName, - kindModifiers: getSymbolModifiers(symbol), - kind: symbolKind, - displayParts: displayParts, - documentation: documentation - }; + rules.push(this.globalRules.NoSpaceAfterComma); } - } - // Didn't find a symbol with this name. See if we can find a keyword instead. - var keywordCompletion = ts.forEach(keywordCompletions, function (c) { return c.name === entryName; }); - if (keywordCompletion) { - return { - name: entryName, - kind: ts.ScriptElementKind.keyword, - kindModifiers: ts.ScriptElementKindModifier.none, - displayParts: [ts.displayPart(entryName, ts.SymbolDisplayPartKind.keyword)], - documentation: undefined - }; - } - return undefined; - } - // TODO(drosen): use contextual SemanticMeaning. - function getSymbolKind(symbol, location) { - var flags = symbol.getFlags(); - if (flags & 32 /* Class */) - return ts.getDeclarationOfKind(symbol, 192 /* ClassExpression */) ? - ts.ScriptElementKind.localClassElement : ts.ScriptElementKind.classElement; - if (flags & 384 /* Enum */) - return ts.ScriptElementKind.enumElement; - if (flags & 524288 /* TypeAlias */) - return ts.ScriptElementKind.typeElement; - if (flags & 64 /* Interface */) - return ts.ScriptElementKind.interfaceElement; - if (flags & 262144 /* TypeParameter */) - return ts.ScriptElementKind.typeParameterElement; - var result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, location); - if (result === ts.ScriptElementKind.unknown) { - if (flags & 262144 /* TypeParameter */) - return ts.ScriptElementKind.typeParameterElement; - if (flags & 8 /* EnumMember */) - return ts.ScriptElementKind.variableElement; - if (flags & 8388608 /* Alias */) - return ts.ScriptElementKind.alias; - if (flags & 1536 /* Module */) - return ts.ScriptElementKind.moduleElement; - } - return result; - } - function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, location) { - var typeChecker = program.getTypeChecker(); - if (typeChecker.isUndefinedSymbol(symbol)) { - return ts.ScriptElementKind.variableElement; - } - if (typeChecker.isArgumentsSymbol(symbol)) { - return ts.ScriptElementKind.localVariableElement; - } - if (location.kind === 97 /* ThisKeyword */ && ts.isExpression(location)) { - return ts.ScriptElementKind.parameterElement; - } - if (flags & 3 /* Variable */) { - if (ts.isFirstDeclarationOfSymbolParameter(symbol)) { - return ts.ScriptElementKind.parameterElement; + if (options.insertSpaceAfterFunctionKeywordForAnonymousFunctions) { + rules.push(this.globalRules.SpaceAfterAnonymousFunctionKeyword); } - else if (symbol.valueDeclaration && ts.isConst(symbol.valueDeclaration)) { - return ts.ScriptElementKind.constElement; + else { + rules.push(this.globalRules.NoSpaceAfterAnonymousFunctionKeyword); } - else if (ts.forEach(symbol.declarations, ts.isLet)) { - return ts.ScriptElementKind.letElement; + if (options.insertSpaceAfterKeywordsInControlFlowStatements) { + rules.push(this.globalRules.SpaceAfterKeywordInControl); } - return isLocalVariableOrFunction(symbol) ? ts.ScriptElementKind.localVariableElement : ts.ScriptElementKind.variableElement; - } - if (flags & 16 /* Function */) - return isLocalVariableOrFunction(symbol) ? ts.ScriptElementKind.localFunctionElement : ts.ScriptElementKind.functionElement; - if (flags & 32768 /* GetAccessor */) - return ts.ScriptElementKind.memberGetAccessorElement; - if (flags & 65536 /* SetAccessor */) - return ts.ScriptElementKind.memberSetAccessorElement; - if (flags & 8192 /* Method */) - return ts.ScriptElementKind.memberFunctionElement; - if (flags & 16384 /* Constructor */) - return ts.ScriptElementKind.constructorImplementationElement; - if (flags & 4 /* Property */) { - if (flags & 268435456 /* SyntheticProperty */) { - // If union property is result of union of non method (property/accessors/variables), it is labeled as property - var unionPropertyKind = ts.forEach(typeChecker.getRootSymbols(symbol), function (rootSymbol) { - var rootSymbolFlags = rootSymbol.getFlags(); - if (rootSymbolFlags & (98308 /* PropertyOrAccessor */ | 3 /* Variable */)) { - return ts.ScriptElementKind.memberVariableElement; - } - ts.Debug.assert(!!(rootSymbolFlags & 8192 /* Method */)); - }); - if (!unionPropertyKind) { - // If this was union of all methods, - // make sure it has call signatures before we can label it as method - var typeOfUnionProperty = typeChecker.getTypeOfSymbolAtLocation(symbol, location); - if (typeOfUnionProperty.getCallSignatures().length) { - return ts.ScriptElementKind.memberFunctionElement; - } - return ts.ScriptElementKind.memberVariableElement; - } - return unionPropertyKind; + else { + rules.push(this.globalRules.NoSpaceAfterKeywordInControl); } - return ts.ScriptElementKind.memberVariableElement; - } - return ts.ScriptElementKind.unknown; - } - function getSymbolModifiers(symbol) { - return symbol && symbol.declarations && symbol.declarations.length > 0 - ? ts.getNodeModifiers(symbol.declarations[0]) - : ts.ScriptElementKindModifier.none; - } - // TODO(drosen): Currently completion entry details passes the SemanticMeaning.All instead of using semanticMeaning of location - function getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, sourceFile, enclosingDeclaration, location, semanticMeaning) { - if (semanticMeaning === void 0) { semanticMeaning = getMeaningFromLocation(location); } - var typeChecker = program.getTypeChecker(); - var displayParts = []; - var documentation; - var symbolFlags = symbol.flags; - var symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags, location); - var hasAddedSymbolInfo; - var isThisExpression = location.kind === 97 /* ThisKeyword */ && ts.isExpression(location); - var type; - // Class at constructor site need to be shown as constructor apart from property,method, vars - if (symbolKind !== ts.ScriptElementKind.unknown || symbolFlags & 32 /* Class */ || symbolFlags & 8388608 /* Alias */) { - // If it is accessor they are allowed only if location is at name of the accessor - if (symbolKind === ts.ScriptElementKind.memberGetAccessorElement || symbolKind === ts.ScriptElementKind.memberSetAccessorElement) { - symbolKind = ts.ScriptElementKind.memberVariableElement; + if (options.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis) { + rules.push(this.globalRules.SpaceAfterOpenParen); + rules.push(this.globalRules.SpaceBeforeCloseParen); + rules.push(this.globalRules.NoSpaceBetweenParens); } - var signature = void 0; - type = isThisExpression ? typeChecker.getTypeAtLocation(location) : typeChecker.getTypeOfSymbolAtLocation(symbol, location); - if (type) { - if (location.parent && location.parent.kind === 172 /* PropertyAccessExpression */) { - var right = location.parent.name; - // Either the location is on the right of a property access, or on the left and the right is missing - if (right === location || (right && right.getFullWidth() === 0)) { - location = location.parent; - } - } - // try get the call/construct signature from the type if it matches - var callExpression = void 0; - if (location.kind === 174 /* CallExpression */ || location.kind === 175 /* NewExpression */) { - callExpression = location; - } - else if (isCallExpressionTarget(location) || isNewExpressionTarget(location)) { - callExpression = location.parent; - } - if (callExpression) { - var candidateSignatures = []; - signature = typeChecker.getResolvedSignature(callExpression, candidateSignatures); - if (!signature && candidateSignatures.length) { - // Use the first candidate: - signature = candidateSignatures[0]; - } - var useConstructSignatures = callExpression.kind === 175 /* NewExpression */ || callExpression.expression.kind === 95 /* SuperKeyword */; - var allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures(); - if (!ts.contains(allSignatures, signature.target) && !ts.contains(allSignatures, signature)) { - // Get the first signature if there is one -- allSignatures may contain - // either the original signature or its target, so check for either - signature = allSignatures.length ? allSignatures[0] : undefined; - } - if (signature) { - if (useConstructSignatures && (symbolFlags & 32 /* Class */)) { - // Constructor - symbolKind = ts.ScriptElementKind.constructorImplementationElement; - addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); - } - else if (symbolFlags & 8388608 /* Alias */) { - symbolKind = ts.ScriptElementKind.alias; - pushTypePart(symbolKind); - displayParts.push(ts.spacePart()); - if (useConstructSignatures) { - displayParts.push(ts.keywordPart(92 /* NewKeyword */)); - displayParts.push(ts.spacePart()); - } - addFullSymbolName(symbol); - } - else { - addPrefixForAnyFunctionOrVar(symbol, symbolKind); - } - switch (symbolKind) { - case ts.ScriptElementKind.memberVariableElement: - case ts.ScriptElementKind.variableElement: - case ts.ScriptElementKind.constElement: - case ts.ScriptElementKind.letElement: - case ts.ScriptElementKind.parameterElement: - case ts.ScriptElementKind.localVariableElement: - // If it is call or construct signature of lambda's write type name - displayParts.push(ts.punctuationPart(54 /* ColonToken */)); - displayParts.push(ts.spacePart()); - if (useConstructSignatures) { - displayParts.push(ts.keywordPart(92 /* NewKeyword */)); - displayParts.push(ts.spacePart()); - } - if (!(type.flags & 2097152 /* Anonymous */) && type.symbol) { - ts.addRange(displayParts, ts.symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, 1 /* WriteTypeParametersOrArguments */)); - } - addSignatureDisplayParts(signature, allSignatures, 8 /* WriteArrowStyleSignature */); - break; - default: - // Just signature - addSignatureDisplayParts(signature, allSignatures); - } - hasAddedSymbolInfo = true; - } - } - else if ((isNameOfFunctionDeclaration(location) && !(symbol.flags & 98304 /* Accessor */)) || - (location.kind === 121 /* ConstructorKeyword */ && location.parent.kind === 148 /* Constructor */)) { - // get the signature from the declaration and write it - var functionDeclaration = location.parent; - var allSignatures = functionDeclaration.kind === 148 /* Constructor */ ? type.getNonNullableType().getConstructSignatures() : type.getNonNullableType().getCallSignatures(); - if (!typeChecker.isImplementationOfOverload(functionDeclaration)) { - signature = typeChecker.getSignatureFromDeclaration(functionDeclaration); - } - else { - signature = allSignatures[0]; - } - if (functionDeclaration.kind === 148 /* Constructor */) { - // show (constructor) Type(...) signature - symbolKind = ts.ScriptElementKind.constructorImplementationElement; - addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); - } - else { - // (function/method) symbol(..signature) - addPrefixForAnyFunctionOrVar(functionDeclaration.kind === 151 /* CallSignature */ && - !(type.symbol.flags & 2048 /* TypeLiteral */ || type.symbol.flags & 4096 /* ObjectLiteral */) ? type.symbol : symbol, symbolKind); - } - addSignatureDisplayParts(signature, allSignatures); - hasAddedSymbolInfo = true; - } + else { + rules.push(this.globalRules.NoSpaceAfterOpenParen); + rules.push(this.globalRules.NoSpaceBeforeCloseParen); + rules.push(this.globalRules.NoSpaceBetweenParens); } - } - if (symbolFlags & 32 /* Class */ && !hasAddedSymbolInfo && !isThisExpression) { - if (ts.getDeclarationOfKind(symbol, 192 /* ClassExpression */)) { - // Special case for class expressions because we would like to indicate that - // the class name is local to the class body (similar to function expression) - // (local class) class - pushTypePart(ts.ScriptElementKind.localClassElement); + if (options.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets) { + rules.push(this.globalRules.SpaceAfterOpenBracket); + rules.push(this.globalRules.SpaceBeforeCloseBracket); + rules.push(this.globalRules.NoSpaceBetweenBrackets); } else { - // Class declaration has name which is not local. - displayParts.push(ts.keywordPart(73 /* ClassKeyword */)); - } - displayParts.push(ts.spacePart()); - addFullSymbolName(symbol); - writeTypeParametersOfSymbol(symbol, sourceFile); - } - if ((symbolFlags & 64 /* Interface */) && (semanticMeaning & 2 /* Type */)) { - addNewLineIfDisplayPartsExist(); - displayParts.push(ts.keywordPart(107 /* InterfaceKeyword */)); - displayParts.push(ts.spacePart()); - addFullSymbolName(symbol); - writeTypeParametersOfSymbol(symbol, sourceFile); - } - if (symbolFlags & 524288 /* TypeAlias */) { - addNewLineIfDisplayPartsExist(); - displayParts.push(ts.keywordPart(134 /* TypeKeyword */)); - displayParts.push(ts.spacePart()); - addFullSymbolName(symbol); - writeTypeParametersOfSymbol(symbol, sourceFile); - displayParts.push(ts.spacePart()); - displayParts.push(ts.operatorPart(56 /* EqualsToken */)); - displayParts.push(ts.spacePart()); - ts.addRange(displayParts, ts.typeToDisplayParts(typeChecker, typeChecker.getDeclaredTypeOfSymbol(symbol), enclosingDeclaration, 512 /* InTypeAlias */)); - } - if (symbolFlags & 384 /* Enum */) { - addNewLineIfDisplayPartsExist(); - if (ts.forEach(symbol.declarations, ts.isConstEnumDeclaration)) { - displayParts.push(ts.keywordPart(74 /* ConstKeyword */)); - displayParts.push(ts.spacePart()); + rules.push(this.globalRules.NoSpaceAfterOpenBracket); + rules.push(this.globalRules.NoSpaceBeforeCloseBracket); + rules.push(this.globalRules.NoSpaceBetweenBrackets); } - displayParts.push(ts.keywordPart(81 /* EnumKeyword */)); - displayParts.push(ts.spacePart()); - addFullSymbolName(symbol); - } - if (symbolFlags & 1536 /* Module */) { - addNewLineIfDisplayPartsExist(); - var declaration = ts.getDeclarationOfKind(symbol, 225 /* ModuleDeclaration */); - var isNamespace = declaration && declaration.name && declaration.name.kind === 69 /* Identifier */; - displayParts.push(ts.keywordPart(isNamespace ? 126 /* NamespaceKeyword */ : 125 /* ModuleKeyword */)); - displayParts.push(ts.spacePart()); - addFullSymbolName(symbol); - } - if ((symbolFlags & 262144 /* TypeParameter */) && (semanticMeaning & 2 /* Type */)) { - addNewLineIfDisplayPartsExist(); - displayParts.push(ts.punctuationPart(17 /* OpenParenToken */)); - displayParts.push(ts.textPart("type parameter")); - displayParts.push(ts.punctuationPart(18 /* CloseParenToken */)); - displayParts.push(ts.spacePart()); - addFullSymbolName(symbol); - displayParts.push(ts.spacePart()); - displayParts.push(ts.keywordPart(90 /* InKeyword */)); - displayParts.push(ts.spacePart()); - if (symbol.parent) { - // Class/Interface type parameter - addFullSymbolName(symbol.parent, enclosingDeclaration); - writeTypeParametersOfSymbol(symbol.parent, enclosingDeclaration); + // The default value of InsertSpaceAfterOpeningAndBeforeClosingNonemptyBraces is true + // so if the option is undefined, we should treat it as true as well + if (options.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces !== false) { + rules.push(this.globalRules.SpaceAfterOpenBrace); + rules.push(this.globalRules.SpaceBeforeCloseBrace); + rules.push(this.globalRules.NoSpaceBetweenEmptyBraceBrackets); } else { - // Method/function type parameter - var declaration = ts.getDeclarationOfKind(symbol, 141 /* TypeParameter */); - ts.Debug.assert(declaration !== undefined); - declaration = declaration.parent; - if (declaration) { - if (ts.isFunctionLikeKind(declaration.kind)) { - var signature = typeChecker.getSignatureFromDeclaration(declaration); - if (declaration.kind === 152 /* ConstructSignature */) { - displayParts.push(ts.keywordPart(92 /* NewKeyword */)); - displayParts.push(ts.spacePart()); - } - else if (declaration.kind !== 151 /* CallSignature */ && declaration.name) { - addFullSymbolName(declaration.symbol); - } - ts.addRange(displayParts, ts.signatureToDisplayParts(typeChecker, signature, sourceFile, 32 /* WriteTypeArgumentsOfSignature */)); - } - else { - // Type alias type parameter - // For example - // type list = T[]; // Both T will go through same code path - displayParts.push(ts.keywordPart(134 /* TypeKeyword */)); - displayParts.push(ts.spacePart()); - addFullSymbolName(declaration.symbol); - writeTypeParametersOfSymbol(declaration.symbol, sourceFile); - } - } + rules.push(this.globalRules.NoSpaceAfterOpenBrace); + rules.push(this.globalRules.NoSpaceBeforeCloseBrace); + rules.push(this.globalRules.NoSpaceBetweenEmptyBraceBrackets); } - } - if (symbolFlags & 8 /* EnumMember */) { - addPrefixForAnyFunctionOrVar(symbol, "enum member"); - var declaration = symbol.declarations[0]; - if (declaration.kind === 255 /* EnumMember */) { - var constantValue = typeChecker.getConstantValue(declaration); - if (constantValue !== undefined) { - displayParts.push(ts.spacePart()); - displayParts.push(ts.operatorPart(56 /* EqualsToken */)); - displayParts.push(ts.spacePart()); - displayParts.push(ts.displayPart(constantValue.toString(), ts.SymbolDisplayPartKind.numericLiteral)); - } + if (options.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces) { + rules.push(this.globalRules.SpaceAfterTemplateHeadAndMiddle); + rules.push(this.globalRules.SpaceBeforeTemplateMiddleAndTail); } - } - if (symbolFlags & 8388608 /* Alias */) { - addNewLineIfDisplayPartsExist(); - if (symbol.declarations[0].kind === 228 /* NamespaceExportDeclaration */) { - displayParts.push(ts.keywordPart(82 /* ExportKeyword */)); - displayParts.push(ts.spacePart()); - displayParts.push(ts.keywordPart(126 /* NamespaceKeyword */)); + else { + rules.push(this.globalRules.NoSpaceAfterTemplateHeadAndMiddle); + rules.push(this.globalRules.NoSpaceBeforeTemplateMiddleAndTail); + } + if (options.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces) { + rules.push(this.globalRules.SpaceAfterOpenBraceInJsxExpression); + rules.push(this.globalRules.SpaceBeforeCloseBraceInJsxExpression); } else { - displayParts.push(ts.keywordPart(89 /* ImportKeyword */)); + rules.push(this.globalRules.NoSpaceAfterOpenBraceInJsxExpression); + rules.push(this.globalRules.NoSpaceBeforeCloseBraceInJsxExpression); } - displayParts.push(ts.spacePart()); - addFullSymbolName(symbol); - ts.forEach(symbol.declarations, function (declaration) { - if (declaration.kind === 229 /* ImportEqualsDeclaration */) { - var importEqualsDeclaration = declaration; - if (ts.isExternalModuleImportEqualsDeclaration(importEqualsDeclaration)) { - displayParts.push(ts.spacePart()); - displayParts.push(ts.operatorPart(56 /* EqualsToken */)); - displayParts.push(ts.spacePart()); - displayParts.push(ts.keywordPart(129 /* RequireKeyword */)); - displayParts.push(ts.punctuationPart(17 /* OpenParenToken */)); - displayParts.push(ts.displayPart(ts.getTextOfNode(ts.getExternalModuleImportEqualsDeclarationExpression(importEqualsDeclaration)), ts.SymbolDisplayPartKind.stringLiteral)); - displayParts.push(ts.punctuationPart(18 /* CloseParenToken */)); - } - else { - var internalAliasSymbol = typeChecker.getSymbolAtLocation(importEqualsDeclaration.moduleReference); - if (internalAliasSymbol) { - displayParts.push(ts.spacePart()); - displayParts.push(ts.operatorPart(56 /* EqualsToken */)); - displayParts.push(ts.spacePart()); - addFullSymbolName(internalAliasSymbol, enclosingDeclaration); - } - } - return true; - } - }); - } - if (!hasAddedSymbolInfo) { - if (symbolKind !== ts.ScriptElementKind.unknown) { - if (type) { - if (isThisExpression) { - addNewLineIfDisplayPartsExist(); - displayParts.push(ts.keywordPart(97 /* ThisKeyword */)); - } - else { - addPrefixForAnyFunctionOrVar(symbol, symbolKind); - } - // For properties, variables and local vars: show the type - if (symbolKind === ts.ScriptElementKind.memberVariableElement || - symbolFlags & 3 /* Variable */ || - symbolKind === ts.ScriptElementKind.localVariableElement || - isThisExpression) { - displayParts.push(ts.punctuationPart(54 /* ColonToken */)); - displayParts.push(ts.spacePart()); - // If the type is type parameter, format it specially - if (type.symbol && type.symbol.flags & 262144 /* TypeParameter */) { - var typeParameterParts = ts.mapToDisplayParts(function (writer) { - typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(type, writer, enclosingDeclaration); - }); - ts.addRange(displayParts, typeParameterParts); - } - else { - ts.addRange(displayParts, ts.typeToDisplayParts(typeChecker, type, enclosingDeclaration)); - } - } - else if (symbolFlags & 16 /* Function */ || - symbolFlags & 8192 /* Method */ || - symbolFlags & 16384 /* Constructor */ || - symbolFlags & 131072 /* Signature */ || - symbolFlags & 98304 /* Accessor */ || - symbolKind === ts.ScriptElementKind.memberFunctionElement) { - var allSignatures = type.getNonNullableType().getCallSignatures(); - addSignatureDisplayParts(allSignatures[0], allSignatures); - } - } + if (options.insertSpaceAfterSemicolonInForStatements) { + rules.push(this.globalRules.SpaceAfterSemicolonInFor); } else { - symbolKind = getSymbolKind(symbol, location); + rules.push(this.globalRules.NoSpaceAfterSemicolonInFor); } - } - if (!documentation) { - documentation = symbol.getDocumentationComment(); - if (documentation.length === 0 && symbol.flags & 4 /* Property */) { - // For some special property access expressions like `experts.foo = foo` or `module.exports.foo = foo` - // there documentation comments might be attached to the right hand side symbol of their declarations. - // The pattern of such special property access is that the parent symbol is the symbol of the file. - if (symbol.parent && ts.forEach(symbol.parent.declarations, function (declaration) { return declaration.kind === 256 /* SourceFile */; })) { - for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { - var declaration = _a[_i]; - if (!declaration.parent || declaration.parent.kind !== 187 /* BinaryExpression */) { - continue; - } - var rhsSymbol = program.getTypeChecker().getSymbolAtLocation(declaration.parent.right); - if (!rhsSymbol) { - continue; - } - documentation = rhsSymbol.getDocumentationComment(); - if (documentation.length > 0) { - break; - } - } - } + if (options.insertSpaceBeforeAndAfterBinaryOperators) { + rules.push(this.globalRules.SpaceBeforeBinaryOperator); + rules.push(this.globalRules.SpaceAfterBinaryOperator); } - } - return { displayParts: displayParts, documentation: documentation, symbolKind: symbolKind }; - function addNewLineIfDisplayPartsExist() { - if (displayParts.length) { - displayParts.push(ts.lineBreakPart()); + else { + rules.push(this.globalRules.NoSpaceBeforeBinaryOperator); + rules.push(this.globalRules.NoSpaceAfterBinaryOperator); } - } - function addFullSymbolName(symbol, enclosingDeclaration) { - var fullSymbolDisplayParts = ts.symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration || sourceFile, /*meaning*/ undefined, 1 /* WriteTypeParametersOrArguments */ | 2 /* UseOnlyExternalAliasing */); - ts.addRange(displayParts, fullSymbolDisplayParts); - } - function addPrefixForAnyFunctionOrVar(symbol, symbolKind) { - addNewLineIfDisplayPartsExist(); - if (symbolKind) { - pushTypePart(symbolKind); - displayParts.push(ts.spacePart()); - addFullSymbolName(symbol); + if (options.placeOpenBraceOnNewLineForControlBlocks) { + rules.push(this.globalRules.NewLineBeforeOpenBraceInControl); } - } - function pushTypePart(symbolKind) { - switch (symbolKind) { - case ts.ScriptElementKind.variableElement: - case ts.ScriptElementKind.functionElement: - case ts.ScriptElementKind.letElement: - case ts.ScriptElementKind.constElement: - case ts.ScriptElementKind.constructorImplementationElement: - displayParts.push(ts.textOrKeywordPart(symbolKind)); - return; - default: - displayParts.push(ts.punctuationPart(17 /* OpenParenToken */)); - displayParts.push(ts.textOrKeywordPart(symbolKind)); - displayParts.push(ts.punctuationPart(18 /* CloseParenToken */)); - return; + if (options.placeOpenBraceOnNewLineForFunctions) { + rules.push(this.globalRules.NewLineBeforeOpenBraceInFunction); + rules.push(this.globalRules.NewLineBeforeOpenBraceInTypeScriptDeclWithBlock); } - } - function addSignatureDisplayParts(signature, allSignatures, flags) { - ts.addRange(displayParts, ts.signatureToDisplayParts(typeChecker, signature, enclosingDeclaration, flags | 32 /* WriteTypeArgumentsOfSignature */)); - if (allSignatures.length > 1) { - displayParts.push(ts.spacePart()); - displayParts.push(ts.punctuationPart(17 /* OpenParenToken */)); - displayParts.push(ts.operatorPart(35 /* PlusToken */)); - displayParts.push(ts.displayPart((allSignatures.length - 1).toString(), ts.SymbolDisplayPartKind.numericLiteral)); - displayParts.push(ts.spacePart()); - displayParts.push(ts.textPart(allSignatures.length === 2 ? "overload" : "overloads")); - displayParts.push(ts.punctuationPart(18 /* CloseParenToken */)); + if (options.insertSpaceAfterTypeAssertion) { + rules.push(this.globalRules.SpaceAfterTypeAssertion); } - documentation = signature.getDocumentationComment(); - } - function writeTypeParametersOfSymbol(symbol, enclosingDeclaration) { - var typeParameterParts = ts.mapToDisplayParts(function (writer) { - typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplayFromSymbol(symbol, writer, enclosingDeclaration); - }); - ts.addRange(displayParts, typeParameterParts); - } - } - function getQuickInfoAtPosition(fileName, position) { - synchronizeHostData(); - var sourceFile = getValidSourceFile(fileName); - var node = ts.getTouchingPropertyName(sourceFile, position); - if (node === sourceFile) { - return undefined; + else { + rules.push(this.globalRules.NoSpaceAfterTypeAssertion); + } + rules = rules.concat(this.globalRules.LowPriorityCommonRules); + return rules; + }; + return RulesProvider; + }()); + formatting.RulesProvider = RulesProvider; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/// +/// +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + var Constants; + (function (Constants) { + Constants[Constants["Unknown"] = -1] = "Unknown"; + })(Constants || (Constants = {})); + function formatOnEnter(position, sourceFile, rulesProvider, options) { + var line = sourceFile.getLineAndCharacterOfPosition(position).line; + if (line === 0) { + return []; } - if (isLabelName(node)) { - return undefined; + // After the enter key, the cursor is now at a new line. The new line may or may not contain non-whitespace characters. + // If the new line has only whitespaces, we won't want to format this line, because that would remove the indentation as + // trailing whitespaces. So the end of the formatting span should be the later one between: + // 1. the end of the previous line + // 2. the last non-whitespace character in the current line + var endOfFormatSpan = ts.getEndLinePosition(line, sourceFile); + while (ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(endOfFormatSpan))) { + endOfFormatSpan--; } - var typeChecker = program.getTypeChecker(); - var symbol = typeChecker.getSymbolAtLocation(node); - if (!symbol || typeChecker.isUnknownSymbol(symbol)) { - // Try getting just type at this position and show - switch (node.kind) { - case 69 /* Identifier */: - case 172 /* PropertyAccessExpression */: - case 139 /* QualifiedName */: - case 97 /* ThisKeyword */: - case 165 /* ThisType */: - case 95 /* SuperKeyword */: - // For the identifiers/this/super etc get the type at position - var type = typeChecker.getTypeAtLocation(node); - if (type) { - return { - kind: ts.ScriptElementKind.unknown, - kindModifiers: ts.ScriptElementKindModifier.none, - textSpan: ts.createTextSpan(node.getStart(), node.getWidth()), - displayParts: ts.typeToDisplayParts(typeChecker, type, getContainerNode(node)), - documentation: type.symbol ? type.symbol.getDocumentationComment() : undefined - }; - } - } - return undefined; + // if the character at the end of the span is a line break, we shouldn't include it, because it indicates we don't want to + // touch the current line at all. Also, on some OSes the line break consists of two characters (\r\n), we should test if the + // previous character before the end of format span is line break character as well. + if (ts.isLineBreak(sourceFile.text.charCodeAt(endOfFormatSpan))) { + endOfFormatSpan--; } - var displayPartsDocumentationsAndKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, sourceFile, getContainerNode(node), node); - return { - kind: displayPartsDocumentationsAndKind.symbolKind, - kindModifiers: getSymbolModifiers(symbol), - textSpan: ts.createTextSpan(node.getStart(), node.getWidth()), - displayParts: displayPartsDocumentationsAndKind.displayParts, - documentation: displayPartsDocumentationsAndKind.documentation + var span = { + // get start position for the previous line + pos: ts.getStartPositionOfLine(line - 1, sourceFile), + // end value is exclusive so add 1 to the result + end: endOfFormatSpan + 1 }; + return formatSpan(span, sourceFile, options, rulesProvider, 2 /* FormatOnEnter */); } - function createDefinitionInfo(node, symbolKind, symbolName, containerName) { - return { - fileName: node.getSourceFile().fileName, - textSpan: ts.createTextSpanFromBounds(node.getStart(), node.getEnd()), - kind: symbolKind, - name: symbolName, - containerKind: undefined, - containerName: containerName + formatting.formatOnEnter = formatOnEnter; + function formatOnSemicolon(position, sourceFile, rulesProvider, options) { + return formatOutermostParent(position, 23 /* SemicolonToken */, sourceFile, options, rulesProvider, 3 /* FormatOnSemicolon */); + } + formatting.formatOnSemicolon = formatOnSemicolon; + function formatOnClosingCurly(position, sourceFile, rulesProvider, options) { + return formatOutermostParent(position, 16 /* CloseBraceToken */, sourceFile, options, rulesProvider, 4 /* FormatOnClosingCurlyBrace */); + } + formatting.formatOnClosingCurly = formatOnClosingCurly; + function formatDocument(sourceFile, rulesProvider, options) { + var span = { + pos: 0, + end: sourceFile.text.length }; + return formatSpan(span, sourceFile, options, rulesProvider, 0 /* FormatDocument */); } - function getSymbolInfo(typeChecker, symbol, node) { - return { - symbolName: typeChecker.symbolToString(symbol), - symbolKind: getSymbolKind(symbol, node), - containerName: symbol.parent ? typeChecker.symbolToString(symbol.parent, node) : "" + formatting.formatDocument = formatDocument; + function formatSelection(start, end, sourceFile, rulesProvider, options) { + // format from the beginning of the line + var span = { + pos: ts.getLineStartPositionForPosition(start, sourceFile), + end: end }; + return formatSpan(span, sourceFile, options, rulesProvider, 1 /* FormatSelection */); } - function createDefinitionFromSignatureDeclaration(decl) { - var typeChecker = program.getTypeChecker(); - var _a = getSymbolInfo(typeChecker, decl.symbol, decl), symbolName = _a.symbolName, symbolKind = _a.symbolKind, containerName = _a.containerName; - return createDefinitionInfo(decl, symbolKind, symbolName, containerName); + formatting.formatSelection = formatSelection; + function formatOutermostParent(position, expectedLastToken, sourceFile, options, rulesProvider, requestKind) { + var parent = findOutermostParent(position, expectedLastToken, sourceFile); + if (!parent) { + return []; + } + var span = { + pos: ts.getLineStartPositionForPosition(parent.getStart(sourceFile), sourceFile), + end: parent.end + }; + return formatSpan(span, sourceFile, options, rulesProvider, requestKind); } - function getDefinitionFromSymbol(symbol, node) { - var typeChecker = program.getTypeChecker(); - var result = []; - var declarations = symbol.getDeclarations(); - var _a = getSymbolInfo(typeChecker, symbol, node), symbolName = _a.symbolName, symbolKind = _a.symbolKind, containerName = _a.containerName; - if (!tryAddConstructSignature(symbol, node, symbolKind, symbolName, containerName, result) && - !tryAddCallSignature(symbol, node, symbolKind, symbolName, containerName, result)) { - // Just add all the declarations. - ts.forEach(declarations, function (declaration) { - result.push(createDefinitionInfo(declaration, symbolKind, symbolName, containerName)); - }); + function findOutermostParent(position, expectedTokenKind, sourceFile) { + var precedingToken = ts.findPrecedingToken(position, sourceFile); + // when it is claimed that trigger character was typed at given position + // we verify that there is a token with a matching kind whose end is equal to position (because the character was just typed). + // If this condition is not hold - then trigger character was typed in some other context, + // i.e.in comment and thus should not trigger autoformatting + if (!precedingToken || + precedingToken.kind !== expectedTokenKind || + position !== precedingToken.getEnd()) { + return undefined; } - return result; - function tryAddConstructSignature(symbol, location, symbolKind, symbolName, containerName, result) { - // Applicable only if we are in a new expression, or we are on a constructor declaration - // and in either case the symbol has a construct signature definition, i.e. class - if (isNewExpressionTarget(location) || location.kind === 121 /* ConstructorKeyword */) { - if (symbol.flags & 32 /* Class */) { - // Find the first class-like declaration and try to get the construct signature. - for (var _i = 0, _a = symbol.getDeclarations(); _i < _a.length; _i++) { - var declaration = _a[_i]; - if (ts.isClassLike(declaration)) { - return tryAddSignature(declaration.members, - /*selectConstructors*/ true, symbolKind, symbolName, containerName, result); - } - } - ts.Debug.fail("Expected declaration to have at least one class-like declaration"); - } - } - return false; + // walk up and search for the parent node that ends at the same position with precedingToken. + // for cases like this + // + // let x = 1; + // while (true) { + // } + // after typing close curly in while statement we want to reformat just the while statement. + // However if we just walk upwards searching for the parent that has the same end value - + // we'll end up with the whole source file. isListElement allows to stop on the list element level + var current = precedingToken; + while (current && + current.parent && + current.parent.end === precedingToken.end && + !isListElement(current.parent, current)) { + current = current.parent; } - function tryAddCallSignature(symbol, location, symbolKind, symbolName, containerName, result) { - if (isCallExpressionTarget(location) || isNewExpressionTarget(location) || isNameOfFunctionDeclaration(location)) { - return tryAddSignature(symbol.declarations, /*selectConstructors*/ false, symbolKind, symbolName, containerName, result); - } - return false; + return current; + } + // Returns true if node is a element in some list in parent + // i.e. parent is class declaration with the list of members and node is one of members. + function isListElement(parent, node) { + switch (parent.kind) { + case 221 /* ClassDeclaration */: + case 222 /* InterfaceDeclaration */: + return ts.rangeContainsRange(parent.members, node); + case 225 /* ModuleDeclaration */: + var body = parent.body; + return body && body.kind === 199 /* Block */ && ts.rangeContainsRange(body.statements, node); + case 256 /* SourceFile */: + case 199 /* Block */: + case 226 /* ModuleBlock */: + return ts.rangeContainsRange(parent.statements, node); + case 252 /* CatchClause */: + return ts.rangeContainsRange(parent.block.statements, node); } - function tryAddSignature(signatureDeclarations, selectConstructors, symbolKind, symbolName, containerName, result) { - var declarations = []; - var definition; - ts.forEach(signatureDeclarations, function (d) { - if ((selectConstructors && d.kind === 148 /* Constructor */) || - (!selectConstructors && (d.kind === 220 /* FunctionDeclaration */ || d.kind === 147 /* MethodDeclaration */ || d.kind === 146 /* MethodSignature */))) { - declarations.push(d); - if (d.body) - definition = d; + return false; + } + /** find node that fully contains given text range */ + function findEnclosingNode(range, sourceFile) { + return find(sourceFile); + function find(n) { + var candidate = ts.forEachChild(n, function (c) { return ts.startEndContainsRange(c.getStart(sourceFile), c.end, range) && c; }); + if (candidate) { + var result = find(candidate); + if (result) { + return result; } - }); - if (definition) { - result.push(createDefinitionInfo(definition, symbolKind, symbolName, containerName)); - return true; } - else if (declarations.length) { - result.push(createDefinitionInfo(ts.lastOrUndefined(declarations), symbolKind, symbolName, containerName)); - return true; - } - return false; + return n; } } - function findReferenceInPosition(refs, pos) { - for (var _i = 0, refs_1 = refs; _i < refs_1.length; _i++) { - var ref = refs_1[_i]; - if (ref.pos <= pos && pos < ref.end) { - return ref; - } + /** formatting is not applied to ranges that contain parse errors. + * This function will return a predicate that for a given text range will tell + * if there are any parse errors that overlap with the range. + */ + function prepareRangeContainsErrorFunction(errors, originalRange) { + if (!errors.length) { + return rangeHasNoErrors; } - return undefined; - } - function getDefinitionInfoForFileReference(name, targetFileName) { - return { - fileName: targetFileName, - textSpan: ts.createTextSpanFromBounds(0, 0), - kind: ts.ScriptElementKind.scriptElement, - name: name, - containerName: undefined, - containerKind: undefined - }; - } - /// Goto definition - function getDefinitionAtPosition(fileName, position) { - synchronizeHostData(); - var sourceFile = getValidSourceFile(fileName); - /// Triple slash reference comments - var comment = findReferenceInPosition(sourceFile.referencedFiles, position); - if (comment) { - var referenceFile = ts.tryResolveScriptReference(program, sourceFile, comment); - if (referenceFile) { - return [getDefinitionInfoForFileReference(comment.fileName, referenceFile.fileName)]; - } - return undefined; + // pick only errors that fall in range + var sorted = errors + .filter(function (d) { return ts.rangeOverlapsWithStartEnd(originalRange, d.start, d.start + d.length); }) + .sort(function (e1, e2) { return e1.start - e2.start; }); + if (!sorted.length) { + return rangeHasNoErrors; } - // Type reference directives - var typeReferenceDirective = findReferenceInPosition(sourceFile.typeReferenceDirectives, position); - if (typeReferenceDirective) { - var referenceFile = program.getResolvedTypeReferenceDirectives()[typeReferenceDirective.fileName]; - if (referenceFile && referenceFile.resolvedFileName) { - return [getDefinitionInfoForFileReference(typeReferenceDirective.fileName, referenceFile.resolvedFileName)]; + var index = 0; + return function (r) { + // in current implementation sequence of arguments [r1, r2...] is monotonically increasing. + // 'index' tracks the index of the most recent error that was checked. + while (true) { + if (index >= sorted.length) { + // all errors in the range were already checked -> no error in specified range + return false; + } + var error = sorted[index]; + if (r.end <= error.start) { + // specified range ends before the error refered by 'index' - no error in range + return false; + } + if (ts.startEndOverlapsWithStartEnd(r.pos, r.end, error.start, error.start + error.length)) { + // specified range overlaps with error range + return true; + } + index++; } - return undefined; - } - var node = ts.getTouchingPropertyName(sourceFile, position); - if (node === sourceFile) { - return undefined; + }; + function rangeHasNoErrors(r) { + return false; } - // Labels - if (isJumpStatementTarget(node)) { - var labelName = node.text; - var label = getTargetLabel(node.parent, node.text); - return label ? [createDefinitionInfo(label, ts.ScriptElementKind.label, labelName, /*containerName*/ undefined)] : undefined; + } + /** + * Start of the original range might fall inside the comment - scanner will not yield appropriate results + * This function will look for token that is located before the start of target range + * and return its end as start position for the scanner. + */ + function getScanStartPosition(enclosingNode, originalRange, sourceFile) { + var start = enclosingNode.getStart(sourceFile); + if (start === originalRange.pos && enclosingNode.end === originalRange.end) { + return start; } - var typeChecker = program.getTypeChecker(); - var calledDeclaration = tryGetSignatureDeclaration(typeChecker, node); - if (calledDeclaration) { - return [createDefinitionFromSignatureDeclaration(calledDeclaration)]; + var precedingToken = ts.findPrecedingToken(originalRange.pos, sourceFile); + if (!precedingToken) { + // no preceding token found - start from the beginning of enclosing node + return enclosingNode.pos; } - var symbol = typeChecker.getSymbolAtLocation(node); - // Could not find a symbol e.g. node is string or number keyword, - // or the symbol was an internal symbol and does not have a declaration e.g. undefined symbol - if (!symbol) { - return undefined; + // preceding token ends after the start of original range (i.e when originalRange.pos falls in the middle of literal) + // start from the beginning of enclosingNode to handle the entire 'originalRange' + if (precedingToken.end >= originalRange.pos) { + return enclosingNode.pos; } - // If this is an alias, and the request came at the declaration location - // get the aliased symbol instead. This allows for goto def on an import e.g. - // import {A, B} from "mod"; - // to jump to the implementation directly. - if (symbol.flags & 8388608 /* Alias */) { - var declaration = symbol.declarations[0]; - // Go to the original declaration for cases: - // - // (1) when the aliased symbol was declared in the location(parent). - // (2) when the aliased symbol is originating from a named import. - // - if (node.kind === 69 /* Identifier */ && - (node.parent === declaration || - (declaration.kind === 234 /* ImportSpecifier */ && declaration.parent && declaration.parent.kind === 233 /* NamedImports */))) { - symbol = typeChecker.getAliasedSymbol(symbol); + return precedingToken.end; + } + /* + * For cases like + * if (a || + * b ||$ + * c) {...} + * If we hit Enter at $ we want line ' b ||' to be indented. + * Formatting will be applied to the last two lines. + * Node that fully encloses these lines is binary expression 'a ||...'. + * Initial indentation for this node will be 0. + * Binary expressions don't introduce new indentation scopes, however it is possible + * that some parent node on the same line does - like if statement in this case. + * Note that we are considering parents only from the same line with initial node - + * if parent is on the different line - its delta was already contributed + * to the initial indentation. + */ + function getOwnOrInheritedDelta(n, options, sourceFile) { + var previousLine = -1 /* Unknown */; + var child; + while (n) { + var line = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)).line; + if (previousLine !== -1 /* Unknown */ && line !== previousLine) { + break; } - } - // Because name in short-hand property assignment has two different meanings: property name and property value, - // using go-to-definition at such position should go to the variable declaration of the property value rather than - // go to the declaration of the property name (in this case stay at the same position). However, if go-to-definition - // is performed at the location of property access, we would like to go to definition of the property in the short-hand - // assignment. This case and others are handled by the following code. - if (node.parent.kind === 254 /* ShorthandPropertyAssignment */) { - var shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration); - if (!shorthandSymbol) { - return []; + if (formatting.SmartIndenter.shouldIndentChildNode(n, child)) { + return options.indentSize; } - var shorthandDeclarations = shorthandSymbol.getDeclarations(); - var shorthandSymbolKind_1 = getSymbolKind(shorthandSymbol, node); - var shorthandSymbolName_1 = typeChecker.symbolToString(shorthandSymbol); - var shorthandContainerName_1 = typeChecker.symbolToString(symbol.parent, node); - return ts.map(shorthandDeclarations, function (declaration) { return createDefinitionInfo(declaration, shorthandSymbolKind_1, shorthandSymbolName_1, shorthandContainerName_1); }); + previousLine = line; + child = n; + n = n.parent; } - return getDefinitionFromSymbol(symbol, node); + return 0; } - /// Goto type - function getTypeDefinitionAtPosition(fileName, position) { - synchronizeHostData(); - var sourceFile = getValidSourceFile(fileName); - var node = ts.getTouchingPropertyName(sourceFile, position); - if (node === sourceFile) { - return undefined; - } - var typeChecker = program.getTypeChecker(); - var symbol = typeChecker.getSymbolAtLocation(node); - if (!symbol) { - return undefined; + function formatSpan(originalRange, sourceFile, options, rulesProvider, requestKind) { + var rangeContainsError = prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange); + // formatting context is used by rules provider + var formattingContext = new formatting.FormattingContext(sourceFile, requestKind); + // find the smallest node that fully wraps the range and compute the initial indentation for the node + var enclosingNode = findEnclosingNode(originalRange, sourceFile); + var formattingScanner = formatting.getFormattingScanner(sourceFile, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end); + var initialIndentation = formatting.SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, options); + var previousRangeHasError; + var previousRange; + var previousParent; + var previousRangeStartLine; + var lastIndentedLine; + var indentationOnLastIndentedLine; + var edits = []; + formattingScanner.advance(); + if (formattingScanner.isOnToken()) { + var startLine = sourceFile.getLineAndCharacterOfPosition(enclosingNode.getStart(sourceFile)).line; + var undecoratedStartLine = startLine; + if (enclosingNode.decorators) { + undecoratedStartLine = sourceFile.getLineAndCharacterOfPosition(ts.getNonDecoratorTokenPosOfNode(enclosingNode, sourceFile)).line; + } + var delta = getOwnOrInheritedDelta(enclosingNode, options, sourceFile); + processNode(enclosingNode, enclosingNode, startLine, undecoratedStartLine, initialIndentation, delta); } - var type = typeChecker.getTypeOfSymbolAtLocation(symbol, node); - if (!type) { - return undefined; + if (!formattingScanner.isOnToken()) { + var leadingTrivia = formattingScanner.getCurrentLeadingTrivia(); + if (leadingTrivia) { + processTrivia(leadingTrivia, enclosingNode, enclosingNode, undefined); + trimTrailingWhitespacesForRemainingRange(); + } } - if (type.flags & 524288 /* Union */ && !(type.flags & 16 /* Enum */)) { - var result_4 = []; - ts.forEach(type.types, function (t) { - if (t.symbol) { - ts.addRange(/*to*/ result_4, /*from*/ getDefinitionFromSymbol(t.symbol, node)); + formattingScanner.close(); + return edits; + // local functions + /** Tries to compute the indentation for a list element. + * If list element is not in range then + * function will pick its actual indentation + * so it can be pushed downstream as inherited indentation. + * If list element is in the range - its indentation will be equal + * to inherited indentation from its predecessors. + */ + function tryComputeIndentationForListItem(startPos, endPos, parentStartLine, range, inheritedIndentation) { + if (ts.rangeOverlapsWithStartEnd(range, startPos, endPos) || + ts.rangeContainsStartEnd(range, startPos, endPos) /* Not to miss zero-range nodes e.g. JsxText */) { + if (inheritedIndentation !== -1 /* Unknown */) { + return inheritedIndentation; } - }); - return result_4; - } - if (!type.symbol) { - return undefined; - } - return getDefinitionFromSymbol(type.symbol, node); - } - function getOccurrencesAtPosition(fileName, position) { - var results = getOccurrencesAtPositionCore(fileName, position); - if (results) { - var sourceFile_2 = getCanonicalFileName(ts.normalizeSlashes(fileName)); - // Get occurrences only supports reporting occurrences for the file queried. So - // filter down to that list. - results = ts.filter(results, function (r) { return getCanonicalFileName(ts.normalizeSlashes(r.fileName)) === sourceFile_2; }); - } - return results; - } - function getDocumentHighlights(fileName, position, filesToSearch) { - synchronizeHostData(); - var sourceFilesToSearch = ts.map(filesToSearch, function (f) { return program.getSourceFile(f); }); - var sourceFile = getValidSourceFile(fileName); - var node = ts.getTouchingWord(sourceFile, position); - if (!node) { - return undefined; - } - return getSemanticDocumentHighlights(node) || getSyntacticDocumentHighlights(node); - function getHighlightSpanForNode(node) { - var start = node.getStart(); - var end = node.getEnd(); - return { - fileName: sourceFile.fileName, - textSpan: ts.createTextSpanFromBounds(start, end), - kind: ts.HighlightSpanKind.none - }; + } + else { + var startLine = sourceFile.getLineAndCharacterOfPosition(startPos).line; + var startLinePosition = ts.getLineStartPositionForPosition(startPos, sourceFile); + var column = formatting.SmartIndenter.findFirstNonWhitespaceColumn(startLinePosition, startPos, sourceFile, options); + if (startLine !== parentStartLine || startPos === column) { + // Use the base indent size if it is greater than + // the indentation of the inherited predecessor. + var baseIndentSize = formatting.SmartIndenter.getBaseIndentation(options); + return baseIndentSize > column ? baseIndentSize : column; + } + } + return -1 /* Unknown */; } - function getSemanticDocumentHighlights(node) { - if (node.kind === 69 /* Identifier */ || - node.kind === 97 /* ThisKeyword */ || - node.kind === 165 /* ThisType */ || - node.kind === 95 /* SuperKeyword */ || - node.kind === 9 /* StringLiteral */ || - isLiteralNameOfPropertyDeclarationOrIndexAccess(node)) { - var referencedSymbols = getReferencedSymbolsForNode(node, sourceFilesToSearch, /*findInStrings*/ false, /*findInComments*/ false); - return convertReferencedSymbols(referencedSymbols); + function computeIndentation(node, startLine, inheritedIndentation, parent, parentDynamicIndentation, effectiveParentStartLine) { + var indentation = inheritedIndentation; + var delta = formatting.SmartIndenter.shouldIndentChildNode(node) ? options.indentSize : 0; + if (effectiveParentStartLine === startLine) { + // if node is located on the same line with the parent + // - inherit indentation from the parent + // - push children if either parent of node itself has non-zero delta + indentation = startLine === lastIndentedLine + ? indentationOnLastIndentedLine + : parentDynamicIndentation.getIndentation(); + delta = Math.min(options.indentSize, parentDynamicIndentation.getDelta(node) + delta); } - return undefined; - function convertReferencedSymbols(referencedSymbols) { - if (!referencedSymbols) { - return undefined; + else if (indentation === -1 /* Unknown */) { + if (formatting.SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement(parent, node, startLine, sourceFile)) { + indentation = parentDynamicIndentation.getIndentation(); } - var fileNameToDocumentHighlights = ts.createMap(); - var result = []; - for (var _i = 0, referencedSymbols_1 = referencedSymbols; _i < referencedSymbols_1.length; _i++) { - var referencedSymbol = referencedSymbols_1[_i]; - for (var _a = 0, _b = referencedSymbol.references; _a < _b.length; _a++) { - var referenceEntry = _b[_a]; - var fileName_1 = referenceEntry.fileName; - var documentHighlights = fileNameToDocumentHighlights[fileName_1]; - if (!documentHighlights) { - documentHighlights = { fileName: fileName_1, highlightSpans: [] }; - fileNameToDocumentHighlights[fileName_1] = documentHighlights; - result.push(documentHighlights); - } - documentHighlights.highlightSpans.push({ - textSpan: referenceEntry.textSpan, - kind: referenceEntry.isWriteAccess ? ts.HighlightSpanKind.writtenReference : ts.HighlightSpanKind.reference - }); - } + else { + indentation = parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta(node); } - return result; } + return { + indentation: indentation, + delta: delta + }; } - function getSyntacticDocumentHighlights(node) { - var fileName = sourceFile.fileName; - var highlightSpans = getHighlightSpans(node); - if (!highlightSpans || highlightSpans.length === 0) { - return undefined; - } - return [{ fileName: fileName, highlightSpans: highlightSpans }]; - // returns true if 'node' is defined and has a matching 'kind'. - function hasKind(node, kind) { - return node !== undefined && node.kind === kind; + function getFirstNonDecoratorTokenOfNode(node) { + if (node.modifiers && node.modifiers.length) { + return node.modifiers[0].kind; } - // Null-propagating 'parent' function. - function parent(node) { - return node && node.parent; + switch (node.kind) { + case 221 /* ClassDeclaration */: return 73 /* ClassKeyword */; + case 222 /* InterfaceDeclaration */: return 107 /* InterfaceKeyword */; + case 220 /* FunctionDeclaration */: return 87 /* FunctionKeyword */; + case 224 /* EnumDeclaration */: return 224 /* EnumDeclaration */; + case 149 /* GetAccessor */: return 123 /* GetKeyword */; + case 150 /* SetAccessor */: return 131 /* SetKeyword */; + case 147 /* MethodDeclaration */: + if (node.asteriskToken) { + return 37 /* AsteriskToken */; + } /* + fall-through + */ + case 145 /* PropertyDeclaration */: + case 142 /* Parameter */: + return node.name.kind; } - function getHighlightSpans(node) { - if (node) { - switch (node.kind) { - case 88 /* IfKeyword */: + } + function getDynamicIndentation(node, nodeStartLine, indentation, delta) { + return { + getIndentationForComment: function (kind, tokenIndentation, container) { + switch (kind) { + // preceding comment to the token that closes the indentation scope inherits the indentation from the scope + // .. { + // // comment + // } + case 16 /* CloseBraceToken */: + case 20 /* CloseBracketToken */: + case 18 /* CloseParenToken */: + return indentation + getEffectiveDelta(delta, container); + } + return tokenIndentation !== -1 /* Unknown */ ? tokenIndentation : indentation; + }, + getIndentationForToken: function (line, kind, container) { + if (nodeStartLine !== line && node.decorators) { + if (kind === getFirstNonDecoratorTokenOfNode(node)) { + // if this token is the first token following the list of decorators, we do not need to indent + return indentation; + } + } + switch (kind) { + // open and close brace, 'else' and 'while' (in do statement) tokens has indentation of the parent + case 15 /* OpenBraceToken */: + case 16 /* CloseBraceToken */: + case 19 /* OpenBracketToken */: + case 20 /* CloseBracketToken */: + case 17 /* OpenParenToken */: + case 18 /* CloseParenToken */: case 80 /* ElseKeyword */: - if (hasKind(node.parent, 203 /* IfStatement */)) { - return getIfElseOccurrences(node.parent); - } - break; - case 94 /* ReturnKeyword */: - if (hasKind(node.parent, 211 /* ReturnStatement */)) { - return getReturnOccurrences(node.parent); - } - break; - case 98 /* ThrowKeyword */: - if (hasKind(node.parent, 215 /* ThrowStatement */)) { - return getThrowOccurrences(node.parent); - } - break; - case 72 /* CatchKeyword */: - if (hasKind(parent(parent(node)), 216 /* TryStatement */)) { - return getTryCatchFinallyOccurrences(node.parent.parent); - } - break; - case 100 /* TryKeyword */: - case 85 /* FinallyKeyword */: - if (hasKind(parent(node), 216 /* TryStatement */)) { - return getTryCatchFinallyOccurrences(node.parent); - } - break; - case 96 /* SwitchKeyword */: - if (hasKind(node.parent, 213 /* SwitchStatement */)) { - return getSwitchCaseDefaultOccurrences(node.parent); - } - break; - case 71 /* CaseKeyword */: - case 77 /* DefaultKeyword */: - if (hasKind(parent(parent(parent(node))), 213 /* SwitchStatement */)) { - return getSwitchCaseDefaultOccurrences(node.parent.parent.parent); - } - break; - case 70 /* BreakKeyword */: - case 75 /* ContinueKeyword */: - if (hasKind(node.parent, 210 /* BreakStatement */) || hasKind(node.parent, 209 /* ContinueStatement */)) { - return getBreakOrContinueStatementOccurrences(node.parent); - } - break; - case 86 /* ForKeyword */: - if (hasKind(node.parent, 206 /* ForStatement */) || - hasKind(node.parent, 207 /* ForInStatement */) || - hasKind(node.parent, 208 /* ForOfStatement */)) { - return getLoopBreakContinueOccurrences(node.parent); - } - break; case 104 /* WhileKeyword */: - case 79 /* DoKeyword */: - if (hasKind(node.parent, 205 /* WhileStatement */) || hasKind(node.parent, 204 /* DoStatement */)) { - return getLoopBreakContinueOccurrences(node.parent); - } - break; - case 121 /* ConstructorKeyword */: - if (hasKind(node.parent, 148 /* Constructor */)) { - return getConstructorOccurrences(node.parent); - } - break; - case 123 /* GetKeyword */: - case 131 /* SetKeyword */: - if (hasKind(node.parent, 149 /* GetAccessor */) || hasKind(node.parent, 150 /* SetAccessor */)) { - return getGetAndSetOccurrences(node.parent); - } - break; + case 55 /* AtToken */: + return indentation; default: - if (ts.isModifierKind(node.kind) && node.parent && - (ts.isDeclaration(node.parent) || node.parent.kind === 200 /* VariableStatement */)) { - return getModifierOccurrences(node.kind, node.parent); - } - } - } - return undefined; - } - /** - * Aggregates all throw-statements within this node *without* crossing - * into function boundaries and try-blocks with catch-clauses. - */ - function aggregateOwnedThrowStatements(node) { - var statementAccumulator = []; - aggregate(node); - return statementAccumulator; - function aggregate(node) { - if (node.kind === 215 /* ThrowStatement */) { - statementAccumulator.push(node); + // if token line equals to the line of containing node (this is a first token in the node) - use node indentation + return nodeStartLine !== line ? indentation + getEffectiveDelta(delta, container) : indentation; } - else if (node.kind === 216 /* TryStatement */) { - var tryStatement = node; - if (tryStatement.catchClause) { - aggregate(tryStatement.catchClause); + }, + getIndentation: function () { return indentation; }, + getDelta: function (child) { return getEffectiveDelta(delta, child); }, + recomputeIndentation: function (lineAdded) { + if (node.parent && formatting.SmartIndenter.shouldIndentChildNode(node.parent, node)) { + if (lineAdded) { + indentation += options.indentSize; } else { - // Exceptions thrown within a try block lacking a catch clause - // are "owned" in the current context. - aggregate(tryStatement.tryBlock); + indentation -= options.indentSize; } - if (tryStatement.finallyBlock) { - aggregate(tryStatement.finallyBlock); + if (formatting.SmartIndenter.shouldIndentChildNode(node)) { + delta = options.indentSize; } - } - else if (!ts.isFunctionLike(node)) { - ts.forEachChild(node, aggregate); - } - } - } - /** - * For lack of a better name, this function takes a throw statement and returns the - * nearest ancestor that is a try-block (whose try statement has a catch clause), - * function-block, or source file. - */ - function getThrowStatementOwner(throwStatement) { - var child = throwStatement; - while (child.parent) { - var parent_21 = child.parent; - if (ts.isFunctionBlock(parent_21) || parent_21.kind === 256 /* SourceFile */) { - return parent_21; - } - // A throw-statement is only owned by a try-statement if the try-statement has - // a catch clause, and if the throw-statement occurs within the try block. - if (parent_21.kind === 216 /* TryStatement */) { - var tryStatement = parent_21; - if (tryStatement.tryBlock === child && tryStatement.catchClause) { - return child; + else { + delta = 0; } } - child = parent_21; } - return undefined; + }; + function getEffectiveDelta(delta, child) { + // Delta value should be zero when the node explicitly prevents indentation of the child node + return formatting.SmartIndenter.nodeWillIndentChild(node, child, true) ? delta : 0; } - function aggregateAllBreakAndContinueStatements(node) { - var statementAccumulator = []; - aggregate(node); - return statementAccumulator; - function aggregate(node) { - if (node.kind === 210 /* BreakStatement */ || node.kind === 209 /* ContinueStatement */) { - statementAccumulator.push(node); - } - else if (!ts.isFunctionLike(node)) { - ts.forEachChild(node, aggregate); - } - } + } + function processNode(node, contextNode, nodeStartLine, undecoratedNodeStartLine, indentation, delta) { + if (!ts.rangeOverlapsWithStartEnd(originalRange, node.getStart(sourceFile), node.getEnd())) { + return; } - function ownsBreakOrContinueStatement(owner, statement) { - var actualOwner = getBreakOrContinueOwner(statement); - return actualOwner && actualOwner === owner; + var nodeDynamicIndentation = getDynamicIndentation(node, nodeStartLine, indentation, delta); + // a useful observations when tracking context node + // / + // [a] + // / | \ + // [b] [c] [d] + // node 'a' is a context node for nodes 'b', 'c', 'd' + // except for the leftmost leaf token in [b] - in this case context node ('e') is located somewhere above 'a' + // this rule can be applied recursively to child nodes of 'a'. + // + // context node is set to parent node value after processing every child node + // context node is set to parent of the token after processing every token + var childContextNode = contextNode; + // if there are any tokens that logically belong to node and interleave child nodes + // such tokens will be consumed in processChildNode for for the child that follows them + ts.forEachChild(node, function (child) { + processChildNode(child, /*inheritedIndentation*/ -1 /* Unknown */, node, nodeDynamicIndentation, nodeStartLine, undecoratedNodeStartLine, /*isListItem*/ false); + }, function (nodes) { + processChildNodes(nodes, node, nodeStartLine, nodeDynamicIndentation); + }); + // proceed any tokens in the node that are located after child nodes + while (formattingScanner.isOnToken()) { + var tokenInfo = formattingScanner.readTokenInfo(node); + if (tokenInfo.token.end > node.end) { + break; + } + consumeTokenAndAdvanceScanner(tokenInfo, node, nodeDynamicIndentation); } - function getBreakOrContinueOwner(statement) { - for (var node_1 = statement.parent; node_1; node_1 = node_1.parent) { - switch (node_1.kind) { - case 213 /* SwitchStatement */: - if (statement.kind === 209 /* ContinueStatement */) { - continue; - } - // Fall through. - case 206 /* ForStatement */: - case 207 /* ForInStatement */: - case 208 /* ForOfStatement */: - case 205 /* WhileStatement */: - case 204 /* DoStatement */: - if (!statement.label || isLabeledBy(node_1, statement.label.text)) { - return node_1; - } - break; - default: - // Don't cross function boundaries. - if (ts.isFunctionLike(node_1)) { - return undefined; - } - break; + function processChildNode(child, inheritedIndentation, parent, parentDynamicIndentation, parentStartLine, undecoratedParentStartLine, isListItem, isFirstListItem) { + var childStartPos = child.getStart(sourceFile); + var childStartLine = sourceFile.getLineAndCharacterOfPosition(childStartPos).line; + var undecoratedChildStartLine = childStartLine; + if (child.decorators) { + undecoratedChildStartLine = sourceFile.getLineAndCharacterOfPosition(ts.getNonDecoratorTokenPosOfNode(child, sourceFile)).line; + } + // if child is a list item - try to get its indentation + var childIndentationAmount = -1 /* Unknown */; + if (isListItem) { + childIndentationAmount = tryComputeIndentationForListItem(childStartPos, child.end, parentStartLine, originalRange, inheritedIndentation); + if (childIndentationAmount !== -1 /* Unknown */) { + inheritedIndentation = childIndentationAmount; } } - return undefined; - } - function getModifierOccurrences(modifier, declaration) { - var container = declaration.parent; - // Make sure we only highlight the keyword when it makes sense to do so. - if (ts.isAccessibilityModifier(modifier)) { - if (!(container.kind === 221 /* ClassDeclaration */ || - container.kind === 192 /* ClassExpression */ || - (declaration.kind === 142 /* Parameter */ && hasKind(container, 148 /* Constructor */)))) { - return undefined; + // child node is outside the target range - do not dive inside + if (!ts.rangeOverlapsWithStartEnd(originalRange, child.pos, child.end)) { + if (child.end < originalRange.pos) { + formattingScanner.skipToEndOf(child); } + return inheritedIndentation; } - else if (modifier === 113 /* StaticKeyword */) { - if (!(container.kind === 221 /* ClassDeclaration */ || container.kind === 192 /* ClassExpression */)) { - return undefined; + if (child.getFullWidth() === 0) { + return inheritedIndentation; + } + while (formattingScanner.isOnToken()) { + // proceed any parent tokens that are located prior to child.getStart() + var tokenInfo = formattingScanner.readTokenInfo(node); + if (tokenInfo.token.end > childStartPos) { + // stop when formatting scanner advances past the beginning of the child + break; } + consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation); } - else if (modifier === 82 /* ExportKeyword */ || modifier === 122 /* DeclareKeyword */) { - if (!(container.kind === 226 /* ModuleBlock */ || container.kind === 256 /* SourceFile */)) { - return undefined; + if (!formattingScanner.isOnToken()) { + return inheritedIndentation; + } + if (ts.isToken(child)) { + // if child node is a token, it does not impact indentation, proceed it using parent indentation scope rules + var tokenInfo = formattingScanner.readTokenInfo(child); + ts.Debug.assert(tokenInfo.token.end === child.end); + consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation, child); + return inheritedIndentation; + } + var effectiveParentStartLine = child.kind === 143 /* Decorator */ ? childStartLine : undecoratedParentStartLine; + var childIndentation = computeIndentation(child, childStartLine, childIndentationAmount, node, parentDynamicIndentation, effectiveParentStartLine); + processNode(child, childContextNode, childStartLine, undecoratedChildStartLine, childIndentation.indentation, childIndentation.delta); + childContextNode = node; + if (isFirstListItem && parent.kind === 170 /* ArrayLiteralExpression */ && inheritedIndentation === -1 /* Unknown */) { + inheritedIndentation = childIndentation.indentation; + } + return inheritedIndentation; + } + function processChildNodes(nodes, parent, parentStartLine, parentDynamicIndentation) { + var listStartToken = getOpenTokenForList(parent, nodes); + var listEndToken = getCloseTokenForOpenToken(listStartToken); + var listDynamicIndentation = parentDynamicIndentation; + var startLine = parentStartLine; + if (listStartToken !== 0 /* Unknown */) { + // introduce a new indentation scope for lists (including list start and end tokens) + while (formattingScanner.isOnToken()) { + var tokenInfo = formattingScanner.readTokenInfo(parent); + if (tokenInfo.token.end > nodes.pos) { + // stop when formatting scanner moves past the beginning of node list + break; + } + else if (tokenInfo.token.kind === listStartToken) { + // consume list start token + startLine = sourceFile.getLineAndCharacterOfPosition(tokenInfo.token.pos).line; + var indentation_1 = computeIndentation(tokenInfo.token, startLine, -1 /* Unknown */, parent, parentDynamicIndentation, parentStartLine); + listDynamicIndentation = getDynamicIndentation(parent, parentStartLine, indentation_1.indentation, indentation_1.delta); + consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation); + } + else { + // consume any tokens that precede the list as child elements of 'node' using its indentation scope + consumeTokenAndAdvanceScanner(tokenInfo, parent, parentDynamicIndentation); + } } } - else if (modifier === 115 /* AbstractKeyword */) { - if (!(container.kind === 221 /* ClassDeclaration */ || declaration.kind === 221 /* ClassDeclaration */)) { - return undefined; + var inheritedIndentation = -1 /* Unknown */; + for (var i = 0; i < nodes.length; i++) { + var child = nodes[i]; + inheritedIndentation = processChildNode(child, inheritedIndentation, node, listDynamicIndentation, startLine, startLine, /*isListItem*/ true, /*isFirstListItem*/ i === 0); + } + if (listEndToken !== 0 /* Unknown */) { + if (formattingScanner.isOnToken()) { + var tokenInfo = formattingScanner.readTokenInfo(parent); + // consume the list end token only if it is still belong to the parent + // there might be the case when current token matches end token but does not considered as one + // function (x: function) <-- + // without this check close paren will be interpreted as list end token for function expression which is wrong + if (tokenInfo.token.kind === listEndToken && ts.rangeContainsRange(parent, tokenInfo.token)) { + // consume list end token + consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation); + } } } - else { - // unsupported modifier - return undefined; + } + function consumeTokenAndAdvanceScanner(currentTokenInfo, parent, dynamicIndentation, container) { + ts.Debug.assert(ts.rangeContainsRange(parent, currentTokenInfo.token)); + var lastTriviaWasNewLine = formattingScanner.lastTrailingTriviaWasNewLine(); + var indentToken = false; + if (currentTokenInfo.leadingTrivia) { + processTrivia(currentTokenInfo.leadingTrivia, parent, childContextNode, dynamicIndentation); } - var keywords = []; - var modifierFlag = getFlagFromModifier(modifier); - var nodes; - switch (container.kind) { - case 226 /* ModuleBlock */: - case 256 /* SourceFile */: - // Container is either a class declaration or the declaration is a classDeclaration - if (modifierFlag & 128 /* Abstract */) { - nodes = declaration.members.concat(declaration); + var lineAdded; + var isTokenInRange = ts.rangeContainsRange(originalRange, currentTokenInfo.token); + var tokenStart = sourceFile.getLineAndCharacterOfPosition(currentTokenInfo.token.pos); + if (isTokenInRange) { + var rangeHasError = rangeContainsError(currentTokenInfo.token); + // save previousRange since processRange will overwrite this value with current one + var savePreviousRange = previousRange; + lineAdded = processRange(currentTokenInfo.token, tokenStart, parent, childContextNode, dynamicIndentation); + if (rangeHasError) { + // do not indent comments\token if token range overlaps with some error + indentToken = false; + } + else { + if (lineAdded !== undefined) { + indentToken = lineAdded; } else { - nodes = container.statements; + // indent token only if end line of previous range does not match start line of the token + var prevEndLine = savePreviousRange && sourceFile.getLineAndCharacterOfPosition(savePreviousRange.end).line; + indentToken = lastTriviaWasNewLine && tokenStart.line !== prevEndLine; } - break; - case 148 /* Constructor */: - nodes = container.parameters.concat(container.parent.members); - break; - case 221 /* ClassDeclaration */: - case 192 /* ClassExpression */: - nodes = container.members; - // If we're an accessibility modifier, we're in an instance member and should search - // the constructor's parameter list for instance members as well. - if (modifierFlag & 28 /* AccessibilityModifier */) { - var constructor = ts.forEach(container.members, function (member) { - return member.kind === 148 /* Constructor */ && member; - }); - if (constructor) { - nodes = nodes.concat(constructor.parameters); + } + } + if (currentTokenInfo.trailingTrivia) { + processTrivia(currentTokenInfo.trailingTrivia, parent, childContextNode, dynamicIndentation); + } + if (indentToken) { + var tokenIndentation = (isTokenInRange && !rangeContainsError(currentTokenInfo.token)) ? + dynamicIndentation.getIndentationForToken(tokenStart.line, currentTokenInfo.token.kind, container) : + -1 /* Unknown */; + var indentNextTokenOrTrivia = true; + if (currentTokenInfo.leadingTrivia) { + var commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind, tokenIndentation, container); + for (var _i = 0, _a = currentTokenInfo.leadingTrivia; _i < _a.length; _i++) { + var triviaItem = _a[_i]; + var triviaInRange = ts.rangeContainsRange(originalRange, triviaItem); + switch (triviaItem.kind) { + case 3 /* MultiLineCommentTrivia */: + if (triviaInRange) { + indentMultilineComment(triviaItem, commentIndentation, /*firstLineIsIndented*/ !indentNextTokenOrTrivia); + } + indentNextTokenOrTrivia = false; + break; + case 2 /* SingleLineCommentTrivia */: + if (indentNextTokenOrTrivia && triviaInRange) { + insertIndentation(triviaItem.pos, commentIndentation, /*lineAdded*/ false); + } + indentNextTokenOrTrivia = false; + break; + case 4 /* NewLineTrivia */: + indentNextTokenOrTrivia = true; + break; } } - else if (modifierFlag & 128 /* Abstract */) { - nodes = nodes.concat(container); - } - break; - default: - ts.Debug.fail("Invalid container kind."); - } - ts.forEach(nodes, function (node) { - if (node.modifiers && node.flags & modifierFlag) { - ts.forEach(node.modifiers, function (child) { return pushKeywordIf(keywords, child, modifier); }); } - }); - return ts.map(keywords, getHighlightSpanForNode); - function getFlagFromModifier(modifier) { - switch (modifier) { - case 112 /* PublicKeyword */: - return 4 /* Public */; - case 110 /* PrivateKeyword */: - return 8 /* Private */; - case 111 /* ProtectedKeyword */: - return 16 /* Protected */; - case 113 /* StaticKeyword */: - return 32 /* Static */; - case 82 /* ExportKeyword */: - return 1 /* Export */; - case 122 /* DeclareKeyword */: - return 2 /* Ambient */; - case 115 /* AbstractKeyword */: - return 128 /* Abstract */; - default: - ts.Debug.fail(); + // indent token only if is it is in target range and does not overlap with any error ranges + if (tokenIndentation !== -1 /* Unknown */ && indentNextTokenOrTrivia) { + insertIndentation(currentTokenInfo.token.pos, tokenIndentation, lineAdded); + lastIndentedLine = tokenStart.line; + indentationOnLastIndentedLine = tokenIndentation; } } + formattingScanner.advance(); + childContextNode = parent; } - function pushKeywordIf(keywordList, token) { - var expected = []; - for (var _i = 2; _i < arguments.length; _i++) { - expected[_i - 2] = arguments[_i]; + } + function processTrivia(trivia, parent, contextNode, dynamicIndentation) { + for (var _i = 0, trivia_1 = trivia; _i < trivia_1.length; _i++) { + var triviaItem = trivia_1[_i]; + if (ts.isComment(triviaItem.kind) && ts.rangeContainsRange(originalRange, triviaItem)) { + var triviaItemStart = sourceFile.getLineAndCharacterOfPosition(triviaItem.pos); + processRange(triviaItem, triviaItemStart, parent, contextNode, dynamicIndentation); } - if (token && ts.contains(expected, token.kind)) { - keywordList.push(token); - return true; + } + } + function processRange(range, rangeStart, parent, contextNode, dynamicIndentation) { + var rangeHasError = rangeContainsError(range); + var lineAdded; + if (!rangeHasError && !previousRangeHasError) { + if (!previousRange) { + // trim whitespaces starting from the beginning of the span up to the current line + var originalStart = sourceFile.getLineAndCharacterOfPosition(originalRange.pos); + trimTrailingWhitespacesForLines(originalStart.line, rangeStart.line); + } + else { + lineAdded = + processPair(range, rangeStart.line, parent, previousRange, previousRangeStartLine, previousParent, contextNode, dynamicIndentation); } - return false; } - function getGetAndSetOccurrences(accessorDeclaration) { - var keywords = []; - tryPushAccessorKeyword(accessorDeclaration.symbol, 149 /* GetAccessor */); - tryPushAccessorKeyword(accessorDeclaration.symbol, 150 /* SetAccessor */); - return ts.map(keywords, getHighlightSpanForNode); - function tryPushAccessorKeyword(accessorSymbol, accessorKind) { - var accessor = ts.getDeclarationOfKind(accessorSymbol, accessorKind); - if (accessor) { - ts.forEach(accessor.getChildren(), function (child) { return pushKeywordIf(keywords, child, 123 /* GetKeyword */, 131 /* SetKeyword */); }); + previousRange = range; + previousParent = parent; + previousRangeStartLine = rangeStart.line; + previousRangeHasError = rangeHasError; + return lineAdded; + } + function processPair(currentItem, currentStartLine, currentParent, previousItem, previousStartLine, previousParent, contextNode, dynamicIndentation) { + formattingContext.updateContext(previousItem, previousParent, currentItem, currentParent, contextNode); + var rule = rulesProvider.getRulesMap().GetRule(formattingContext); + var trimTrailingWhitespaces; + var lineAdded; + if (rule) { + applyRuleEdits(rule, previousItem, previousStartLine, currentItem, currentStartLine); + if (rule.Operation.Action & (2 /* Space */ | 8 /* Delete */) && currentStartLine !== previousStartLine) { + lineAdded = false; + // Handle the case where the next line is moved to be the end of this line. + // In this case we don't indent the next line in the next pass. + if (currentParent.getStart(sourceFile) === currentItem.pos) { + dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ false); + } + } + else if (rule.Operation.Action & 4 /* NewLine */ && currentStartLine === previousStartLine) { + lineAdded = true; + // Handle the case where token2 is moved to the new line. + // In this case we indent token2 in the next pass but we set + // sameLineIndent flag to notify the indenter that the indentation is within the line. + if (currentParent.getStart(sourceFile) === currentItem.pos) { + dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ true); } } + // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line + trimTrailingWhitespaces = !(rule.Operation.Action & 8 /* Delete */) && rule.Flag !== 1 /* CanDeleteNewLines */; } - function getConstructorOccurrences(constructorDeclaration) { - var declarations = constructorDeclaration.symbol.getDeclarations(); - var keywords = []; - ts.forEach(declarations, function (declaration) { - ts.forEach(declaration.getChildren(), function (token) { - return pushKeywordIf(keywords, token, 121 /* ConstructorKeyword */); - }); - }); - return ts.map(keywords, getHighlightSpanForNode); + else { + trimTrailingWhitespaces = true; } - function getLoopBreakContinueOccurrences(loopNode) { - var keywords = []; - if (pushKeywordIf(keywords, loopNode.getFirstToken(), 86 /* ForKeyword */, 104 /* WhileKeyword */, 79 /* DoKeyword */)) { - // If we succeeded and got a do-while loop, then start looking for a 'while' keyword. - if (loopNode.kind === 204 /* DoStatement */) { - var loopTokens = loopNode.getChildren(); - for (var i = loopTokens.length - 1; i >= 0; i--) { - if (pushKeywordIf(keywords, loopTokens[i], 104 /* WhileKeyword */)) { - break; - } - } - } + if (currentStartLine !== previousStartLine && trimTrailingWhitespaces) { + // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line + trimTrailingWhitespacesForLines(previousStartLine, currentStartLine, previousItem); + } + return lineAdded; + } + function insertIndentation(pos, indentation, lineAdded) { + var indentationString = getIndentationString(indentation, options); + if (lineAdded) { + // new line is added before the token by the formatting rules + // insert indentation string at the very beginning of the token + recordReplace(pos, 0, indentationString); + } + else { + var tokenStart = sourceFile.getLineAndCharacterOfPosition(pos); + var startLinePosition = ts.getStartPositionOfLine(tokenStart.line, sourceFile); + if (indentation !== tokenStart.character || indentationIsDifferent(indentationString, startLinePosition)) { + recordReplace(startLinePosition, tokenStart.character, indentationString); } - var breaksAndContinues = aggregateAllBreakAndContinueStatements(loopNode.statement); - ts.forEach(breaksAndContinues, function (statement) { - if (ownsBreakOrContinueStatement(loopNode, statement)) { - pushKeywordIf(keywords, statement.getFirstToken(), 70 /* BreakKeyword */, 75 /* ContinueKeyword */); - } - }); - return ts.map(keywords, getHighlightSpanForNode); } - function getBreakOrContinueStatementOccurrences(breakOrContinueStatement) { - var owner = getBreakOrContinueOwner(breakOrContinueStatement); - if (owner) { - switch (owner.kind) { - case 206 /* ForStatement */: - case 207 /* ForInStatement */: - case 208 /* ForOfStatement */: - case 204 /* DoStatement */: - case 205 /* WhileStatement */: - return getLoopBreakContinueOccurrences(owner); - case 213 /* SwitchStatement */: - return getSwitchCaseDefaultOccurrences(owner); - } + } + function indentationIsDifferent(indentationString, startLinePosition) { + return indentationString !== sourceFile.text.substr(startLinePosition, indentationString.length); + } + function indentMultilineComment(commentRange, indentation, firstLineIsIndented) { + // split comment in lines + var startLine = sourceFile.getLineAndCharacterOfPosition(commentRange.pos).line; + var endLine = sourceFile.getLineAndCharacterOfPosition(commentRange.end).line; + var parts; + if (startLine === endLine) { + if (!firstLineIsIndented) { + // treat as single line comment + insertIndentation(commentRange.pos, indentation, /*lineAdded*/ false); } - return undefined; + return; } - function getSwitchCaseDefaultOccurrences(switchStatement) { - var keywords = []; - pushKeywordIf(keywords, switchStatement.getFirstToken(), 96 /* SwitchKeyword */); - // Go through each clause in the switch statement, collecting the 'case'/'default' keywords. - ts.forEach(switchStatement.caseBlock.clauses, function (clause) { - pushKeywordIf(keywords, clause.getFirstToken(), 71 /* CaseKeyword */, 77 /* DefaultKeyword */); - var breaksAndContinues = aggregateAllBreakAndContinueStatements(clause); - ts.forEach(breaksAndContinues, function (statement) { - if (ownsBreakOrContinueStatement(switchStatement, statement)) { - pushKeywordIf(keywords, statement.getFirstToken(), 70 /* BreakKeyword */); - } - }); - }); - return ts.map(keywords, getHighlightSpanForNode); + else { + parts = []; + var startPos = commentRange.pos; + for (var line = startLine; line < endLine; line++) { + var endOfLine = ts.getEndLinePosition(line, sourceFile); + parts.push({ pos: startPos, end: endOfLine }); + startPos = ts.getStartPositionOfLine(line + 1, sourceFile); + } + parts.push({ pos: startPos, end: commentRange.end }); } - function getTryCatchFinallyOccurrences(tryStatement) { - var keywords = []; - pushKeywordIf(keywords, tryStatement.getFirstToken(), 100 /* TryKeyword */); - if (tryStatement.catchClause) { - pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken(), 72 /* CatchKeyword */); + var startLinePos = ts.getStartPositionOfLine(startLine, sourceFile); + var nonWhitespaceColumnInFirstPart = formatting.SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(startLinePos, parts[0].pos, sourceFile, options); + if (indentation === nonWhitespaceColumnInFirstPart.column) { + return; + } + var startIndex = 0; + if (firstLineIsIndented) { + startIndex = 1; + startLine++; + } + // shift all parts on the delta size + var delta = indentation - nonWhitespaceColumnInFirstPart.column; + for (var i = startIndex, len = parts.length; i < len; i++, startLine++) { + var startLinePos_1 = ts.getStartPositionOfLine(startLine, sourceFile); + var nonWhitespaceCharacterAndColumn = i === 0 + ? nonWhitespaceColumnInFirstPart + : formatting.SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(parts[i].pos, parts[i].end, sourceFile, options); + var newIndentation = nonWhitespaceCharacterAndColumn.column + delta; + if (newIndentation > 0) { + var indentationString = getIndentationString(newIndentation, options); + recordReplace(startLinePos_1, nonWhitespaceCharacterAndColumn.character, indentationString); } - if (tryStatement.finallyBlock) { - var finallyKeyword = ts.findChildOfKind(tryStatement, 85 /* FinallyKeyword */, sourceFile); - pushKeywordIf(keywords, finallyKeyword, 85 /* FinallyKeyword */); + else { + recordDelete(startLinePos_1, nonWhitespaceCharacterAndColumn.character); } - return ts.map(keywords, getHighlightSpanForNode); } - function getThrowOccurrences(throwStatement) { - var owner = getThrowStatementOwner(throwStatement); - if (!owner) { - return undefined; + } + function trimTrailingWhitespacesForLines(line1, line2, range) { + for (var line = line1; line < line2; line++) { + var lineStartPosition = ts.getStartPositionOfLine(line, sourceFile); + var lineEndPosition = ts.getEndLinePosition(line, sourceFile); + // do not trim whitespaces in comments or template expression + if (range && (ts.isComment(range.kind) || ts.isStringOrRegularExpressionOrTemplateLiteral(range.kind)) && range.pos <= lineEndPosition && range.end > lineEndPosition) { + continue; } - var keywords = []; - ts.forEach(aggregateOwnedThrowStatements(owner), function (throwStatement) { - pushKeywordIf(keywords, throwStatement.getFirstToken(), 98 /* ThrowKeyword */); - }); - // If the "owner" is a function, then we equate 'return' and 'throw' statements in their - // ability to "jump out" of the function, and include occurrences for both. - if (ts.isFunctionBlock(owner)) { - ts.forEachReturnStatement(owner, function (returnStatement) { - pushKeywordIf(keywords, returnStatement.getFirstToken(), 94 /* ReturnKeyword */); - }); + var whitespaceStart = getTrailingWhitespaceStartPosition(lineStartPosition, lineEndPosition); + if (whitespaceStart !== -1) { + ts.Debug.assert(whitespaceStart === lineStartPosition || !ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(whitespaceStart - 1))); + recordDelete(whitespaceStart, lineEndPosition + 1 - whitespaceStart); } - return ts.map(keywords, getHighlightSpanForNode); } - function getReturnOccurrences(returnStatement) { - var func = ts.getContainingFunction(returnStatement); - // If we didn't find a containing function with a block body, bail out. - if (!(func && hasKind(func.body, 199 /* Block */))) { - return undefined; - } - var keywords = []; - ts.forEachReturnStatement(func.body, function (returnStatement) { - pushKeywordIf(keywords, returnStatement.getFirstToken(), 94 /* ReturnKeyword */); - }); - // Include 'throw' statements that do not occur within a try block. - ts.forEach(aggregateOwnedThrowStatements(func.body), function (throwStatement) { - pushKeywordIf(keywords, throwStatement.getFirstToken(), 98 /* ThrowKeyword */); - }); - return ts.map(keywords, getHighlightSpanForNode); + } + /** + * @param start The position of the first character in range + * @param end The position of the last character in range + */ + function getTrailingWhitespaceStartPosition(start, end) { + var pos = end; + while (pos >= start && ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(pos))) { + pos--; } - function getIfElseOccurrences(ifStatement) { - var keywords = []; - // Traverse upwards through all parent if-statements linked by their else-branches. - while (hasKind(ifStatement.parent, 203 /* IfStatement */) && ifStatement.parent.elseStatement === ifStatement) { - ifStatement = ifStatement.parent; - } - // Now traverse back down through the else branches, aggregating if/else keywords of if-statements. - while (ifStatement) { - var children = ifStatement.getChildren(); - pushKeywordIf(keywords, children[0], 88 /* IfKeyword */); - // Generally the 'else' keyword is second-to-last, so we traverse backwards. - for (var i = children.length - 1; i >= 0; i--) { - if (pushKeywordIf(keywords, children[i], 80 /* ElseKeyword */)) { - break; - } + if (pos !== end) { + return pos + 1; + } + return -1; + } + /** + * Trimming will be done for lines after the previous range + */ + function trimTrailingWhitespacesForRemainingRange() { + var startPosition = previousRange ? previousRange.end : originalRange.pos; + var startLine = sourceFile.getLineAndCharacterOfPosition(startPosition).line; + var endLine = sourceFile.getLineAndCharacterOfPosition(originalRange.end).line; + trimTrailingWhitespacesForLines(startLine, endLine + 1, previousRange); + } + function newTextChange(start, len, newText) { + return { span: ts.createTextSpan(start, len), newText: newText }; + } + function recordDelete(start, len) { + if (len) { + edits.push(newTextChange(start, len, "")); + } + } + function recordReplace(start, len, newText) { + if (len || newText) { + edits.push(newTextChange(start, len, newText)); + } + } + function applyRuleEdits(rule, previousRange, previousStartLine, currentRange, currentStartLine) { + switch (rule.Operation.Action) { + case 1 /* Ignore */: + // no action required + return; + case 8 /* Delete */: + if (previousRange.end !== currentRange.pos) { + // delete characters starting from t1.end up to t2.pos exclusive + recordDelete(previousRange.end, currentRange.pos - previousRange.end); } - if (!hasKind(ifStatement.elseStatement, 203 /* IfStatement */)) { - break; + break; + case 4 /* NewLine */: + // exit early if we on different lines and rule cannot change number of newlines + // if line1 and line2 are on subsequent lines then no edits are required - ok to exit + // if line1 and line2 are separated with more than one newline - ok to exit since we cannot delete extra new lines + if (rule.Flag !== 1 /* CanDeleteNewLines */ && previousStartLine !== currentStartLine) { + return; } - ifStatement = ifStatement.elseStatement; + // edit should not be applied only if we have one line feed between elements + var lineDelta = currentStartLine - previousStartLine; + if (lineDelta !== 1) { + recordReplace(previousRange.end, currentRange.pos - previousRange.end, options.newLineCharacter); + } + break; + case 2 /* Space */: + // exit early if we on different lines and rule cannot change number of newlines + if (rule.Flag !== 1 /* CanDeleteNewLines */ && previousStartLine !== currentStartLine) { + return; + } + var posDelta = currentRange.pos - previousRange.end; + if (posDelta !== 1 || sourceFile.text.charCodeAt(previousRange.end) !== 32 /* space */) { + recordReplace(previousRange.end, currentRange.pos - previousRange.end, " "); + } + break; + } + } + } + function getOpenTokenForList(node, list) { + switch (node.kind) { + case 148 /* Constructor */: + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + case 180 /* ArrowFunction */: + if (node.typeParameters === list) { + return 25 /* LessThanToken */; } - var result = []; - // We'd like to highlight else/ifs together if they are only separated by whitespace - // (i.e. the keywords are separated by no comments, no newlines). - for (var i = 0; i < keywords.length; i++) { - if (keywords[i].kind === 80 /* ElseKeyword */ && i < keywords.length - 1) { - var elseKeyword = keywords[i]; - var ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword. - var shouldCombindElseAndIf = true; - // Avoid recalculating getStart() by iterating backwards. - for (var j = ifKeyword.getStart() - 1; j >= elseKeyword.end; j--) { - if (!ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(j))) { - shouldCombindElseAndIf = false; - break; - } - } - if (shouldCombindElseAndIf) { - result.push({ - fileName: fileName, - textSpan: ts.createTextSpanFromBounds(elseKeyword.getStart(), ifKeyword.end), - kind: ts.HighlightSpanKind.reference - }); - i++; // skip the next keyword - continue; - } + else if (node.parameters === list) { + return 17 /* OpenParenToken */; + } + break; + case 174 /* CallExpression */: + case 175 /* NewExpression */: + if (node.typeArguments === list) { + return 25 /* LessThanToken */; + } + else if (node.arguments === list) { + return 17 /* OpenParenToken */; + } + break; + case 155 /* TypeReference */: + if (node.typeArguments === list) { + return 25 /* LessThanToken */; + } + } + return 0 /* Unknown */; + } + function getCloseTokenForOpenToken(kind) { + switch (kind) { + case 17 /* OpenParenToken */: + return 18 /* CloseParenToken */; + case 25 /* LessThanToken */: + return 27 /* GreaterThanToken */; + } + return 0 /* Unknown */; + } + var internedSizes; + var internedTabsIndentation; + var internedSpacesIndentation; + function getIndentationString(indentation, options) { + // reset interned strings if FormatCodeOptions were changed + var resetInternedStrings = !internedSizes || (internedSizes.tabSize !== options.tabSize || internedSizes.indentSize !== options.indentSize); + if (resetInternedStrings) { + internedSizes = { tabSize: options.tabSize, indentSize: options.indentSize }; + internedTabsIndentation = internedSpacesIndentation = undefined; + } + if (!options.convertTabsToSpaces) { + var tabs = Math.floor(indentation / options.tabSize); + var spaces = indentation - tabs * options.tabSize; + var tabString = void 0; + if (!internedTabsIndentation) { + internedTabsIndentation = []; + } + if (internedTabsIndentation[tabs] === undefined) { + internedTabsIndentation[tabs] = tabString = repeat("\t", tabs); + } + else { + tabString = internedTabsIndentation[tabs]; + } + return spaces ? tabString + repeat(" ", spaces) : tabString; + } + else { + var spacesString = void 0; + var quotient = Math.floor(indentation / options.indentSize); + var remainder = indentation % options.indentSize; + if (!internedSpacesIndentation) { + internedSpacesIndentation = []; + } + if (internedSpacesIndentation[quotient] === undefined) { + spacesString = repeat(" ", options.indentSize * quotient); + internedSpacesIndentation[quotient] = spacesString; + } + else { + spacesString = internedSpacesIndentation[quotient]; + } + return remainder ? spacesString + repeat(" ", remainder) : spacesString; + } + function repeat(value, count) { + var s = ""; + for (var i = 0; i < count; i++) { + s += value; + } + return s; + } + } + formatting.getIndentationString = getIndentationString; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + var SmartIndenter; + (function (SmartIndenter) { + var Value; + (function (Value) { + Value[Value["Unknown"] = -1] = "Unknown"; + })(Value || (Value = {})); + function getIndentation(position, sourceFile, options) { + if (position > sourceFile.text.length) { + return getBaseIndentation(options); // past EOF + } + // no indentation when the indent style is set to none, + // so we can return fast + if (options.indentStyle === ts.IndentStyle.None) { + return 0; + } + var precedingToken = ts.findPrecedingToken(position, sourceFile); + if (!precedingToken) { + return getBaseIndentation(options); + } + // no indentation in string \regex\template literals + var precedingTokenIsLiteral = ts.isStringOrRegularExpressionOrTemplateLiteral(precedingToken.kind); + if (precedingTokenIsLiteral && precedingToken.getStart(sourceFile) <= position && precedingToken.end > position) { + return 0; + } + var lineAtPosition = sourceFile.getLineAndCharacterOfPosition(position).line; + // indentation is first non-whitespace character in a previous line + // for block indentation, we should look for a line which contains something that's not + // whitespace. + if (options.indentStyle === ts.IndentStyle.Block) { + // move backwards until we find a line with a non-whitespace character, + // then find the first non-whitespace character for that line. + var current_1 = position; + while (current_1 > 0) { + var char = sourceFile.text.charCodeAt(current_1); + if (!ts.isWhiteSpace(char)) { + break; } - // Ordinary case: just highlight the keyword. - result.push(getHighlightSpanForNode(keywords[i])); + current_1--; } - return result; + var lineStart = ts.getLineStartPositionForPosition(current_1, sourceFile); + return SmartIndenter.findFirstNonWhitespaceColumn(lineStart, current_1, sourceFile, options); } - } - } - /// References and Occurrences - function getOccurrencesAtPositionCore(fileName, position) { - synchronizeHostData(); - return convertDocumentHighlights(getDocumentHighlights(fileName, position, [fileName])); - function convertDocumentHighlights(documentHighlights) { - if (!documentHighlights) { - return undefined; + if (precedingToken.kind === 24 /* CommaToken */ && precedingToken.parent.kind !== 187 /* BinaryExpression */) { + // previous token is comma that separates items in list - find the previous item and try to derive indentation from it + var actualIndentation = getActualIndentationForListItemBeforeComma(precedingToken, sourceFile, options); + if (actualIndentation !== -1 /* Unknown */) { + return actualIndentation; + } } - var result = []; - for (var _i = 0, documentHighlights_1 = documentHighlights; _i < documentHighlights_1.length; _i++) { - var entry = documentHighlights_1[_i]; - for (var _a = 0, _b = entry.highlightSpans; _a < _b.length; _a++) { - var highlightSpan = _b[_a]; - result.push({ - fileName: entry.fileName, - textSpan: highlightSpan.textSpan, - isWriteAccess: highlightSpan.kind === ts.HighlightSpanKind.writtenReference, - isDefinition: false - }); + // try to find node that can contribute to indentation and includes 'position' starting from 'precedingToken' + // if such node is found - compute initial indentation for 'position' inside this node + var previous; + var current = precedingToken; + var currentStart; + var indentationDelta; + while (current) { + if (ts.positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(current, previous)) { + currentStart = getStartLineAndCharacterForNode(current, sourceFile); + if (nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile)) { + indentationDelta = 0; + } + else { + indentationDelta = lineAtPosition !== currentStart.line ? options.indentSize : 0; + } + break; + } + // check if current node is a list item - if yes, take indentation from it + var actualIndentation = getActualIndentationForListItem(current, sourceFile, options); + if (actualIndentation !== -1 /* Unknown */) { + return actualIndentation; } + actualIndentation = getLineIndentationWhenExpressionIsInMultiLine(current, sourceFile, options); + if (actualIndentation !== -1 /* Unknown */) { + return actualIndentation + options.indentSize; + } + previous = current; + current = current.parent; } - return result; - } - } - function convertReferences(referenceSymbols) { - if (!referenceSymbols) { - return undefined; + if (!current) { + // no parent was found - return the base indentation of the SourceFile + return getBaseIndentation(options); + } + return getIndentationForNodeWorker(current, currentStart, /*ignoreActualIndentationRange*/ undefined, indentationDelta, sourceFile, options); } - var referenceEntries = []; - for (var _i = 0, referenceSymbols_1 = referenceSymbols; _i < referenceSymbols_1.length; _i++) { - var referenceSymbol = referenceSymbols_1[_i]; - ts.addRange(referenceEntries, referenceSymbol.references); + SmartIndenter.getIndentation = getIndentation; + function getIndentationForNode(n, ignoreActualIndentationRange, sourceFile, options) { + var start = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)); + return getIndentationForNodeWorker(n, start, ignoreActualIndentationRange, /*indentationDelta*/ 0, sourceFile, options); } - return referenceEntries; - } - function findRenameLocations(fileName, position, findInStrings, findInComments) { - var referencedSymbols = findReferencedSymbols(fileName, position, findInStrings, findInComments); - return convertReferences(referencedSymbols); - } - function getReferencesAtPosition(fileName, position) { - var referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings*/ false, /*findInComments*/ false); - return convertReferences(referencedSymbols); - } - function findReferences(fileName, position) { - var referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings*/ false, /*findInComments*/ false); - // Only include referenced symbols that have a valid definition. - return ts.filter(referencedSymbols, function (rs) { return !!rs.definition; }); - } - function findReferencedSymbols(fileName, position, findInStrings, findInComments) { - synchronizeHostData(); - var sourceFile = getValidSourceFile(fileName); - var node = ts.getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true); - if (node === sourceFile) { - return undefined; + SmartIndenter.getIndentationForNode = getIndentationForNode; + function getBaseIndentation(options) { + return options.baseIndentSize || 0; } - switch (node.kind) { - case 8 /* NumericLiteral */: - if (!isLiteralNameOfPropertyDeclarationOrIndexAccess(node)) { - break; + SmartIndenter.getBaseIndentation = getBaseIndentation; + function getIndentationForNodeWorker(current, currentStart, ignoreActualIndentationRange, indentationDelta, sourceFile, options) { + var parent = current.parent; + var parentStart; + // walk upwards and collect indentations for pairs of parent-child nodes + // indentation is not added if parent and child nodes start on the same line or if parent is IfStatement and child starts on the same line with 'else clause' + while (parent) { + var useActualIndentation = true; + if (ignoreActualIndentationRange) { + var start = current.getStart(sourceFile); + useActualIndentation = start < ignoreActualIndentationRange.pos || start > ignoreActualIndentationRange.end; } - // Fallthrough - case 69 /* Identifier */: - case 97 /* ThisKeyword */: - // case SyntaxKind.SuperKeyword: TODO:GH#9268 - case 121 /* ConstructorKeyword */: - case 9 /* StringLiteral */: - return getReferencedSymbolsForNode(node, program.getSourceFiles(), findInStrings, findInComments); + if (useActualIndentation) { + // check if current node is a list item - if yes, take indentation from it + var actualIndentation = getActualIndentationForListItem(current, sourceFile, options); + if (actualIndentation !== -1 /* Unknown */) { + return actualIndentation + indentationDelta; + } + } + parentStart = getParentStart(parent, current, sourceFile); + var parentAndChildShareLine = parentStart.line === currentStart.line || + childStartsOnTheSameLineWithElseInIfStatement(parent, current, currentStart.line, sourceFile); + if (useActualIndentation) { + // try to fetch actual indentation for current node from source text + var actualIndentation = getActualIndentationForNode(current, parent, currentStart, parentAndChildShareLine, sourceFile, options); + if (actualIndentation !== -1 /* Unknown */) { + return actualIndentation + indentationDelta; + } + actualIndentation = getLineIndentationWhenExpressionIsInMultiLine(current, sourceFile, options); + if (actualIndentation !== -1 /* Unknown */) { + return actualIndentation + indentationDelta; + } + } + // increase indentation if parent node wants its content to be indented and parent and child nodes don't start on the same line + if (shouldIndentChildNode(parent, current) && !parentAndChildShareLine) { + indentationDelta += options.indentSize; + } + current = parent; + currentStart = parentStart; + parent = current.parent; + } + return indentationDelta + getBaseIndentation(options); } - return undefined; - } - function isThis(node) { - switch (node.kind) { - case 97 /* ThisKeyword */: - // case SyntaxKind.ThisType: TODO: GH#9267 - return true; - case 69 /* Identifier */: - // 'this' as a parameter - return node.originalKeywordKind === 97 /* ThisKeyword */ && node.parent.kind === 142 /* Parameter */; - default: - return false; + function getParentStart(parent, child, sourceFile) { + var containingList = getContainingList(child, sourceFile); + if (containingList) { + return sourceFile.getLineAndCharacterOfPosition(containingList.pos); + } + return sourceFile.getLineAndCharacterOfPosition(parent.getStart(sourceFile)); } - } - function getReferencedSymbolsForNode(node, sourceFiles, findInStrings, findInComments) { - var typeChecker = program.getTypeChecker(); - // Labels - if (isLabelName(node)) { - if (isJumpStatementTarget(node)) { - var labelDefinition = getTargetLabel(node.parent, node.text); - // if we have a label definition, look within its statement for references, if not, then - // the label is undefined and we have no results.. - return labelDefinition ? getLabelReferencesInNode(labelDefinition.parent, labelDefinition) : undefined; + /* + * Function returns Value.Unknown if indentation cannot be determined + */ + function getActualIndentationForListItemBeforeComma(commaToken, sourceFile, options) { + // previous token is comma that separates items in list - find the previous item and try to derive indentation from it + var commaItemInfo = ts.findListItemInfo(commaToken); + if (commaItemInfo && commaItemInfo.listItemIndex > 0) { + return deriveActualIndentationFromList(commaItemInfo.list.getChildren(), commaItemInfo.listItemIndex - 1, sourceFile, options); } else { - // it is a label definition and not a target, search within the parent labeledStatement - return getLabelReferencesInNode(node.parent, node); + // handle broken code gracefully + return -1 /* Unknown */; } } - if (isThis(node)) { - return getReferencesForThisKeyword(node, sourceFiles); + /* + * Function returns Value.Unknown if actual indentation for node should not be used (i.e because node is nested expression) + */ + function getActualIndentationForNode(current, parent, currentLineAndChar, parentAndChildShareLine, sourceFile, options) { + // actual indentation is used for statements\declarations if one of cases below is true: + // - parent is SourceFile - by default immediate children of SourceFile are not indented except when user indents them manually + // - parent and child are not on the same line + var useActualIndentation = (ts.isDeclaration(current) || ts.isStatementButNotDeclaration(current)) && + (parent.kind === 256 /* SourceFile */ || !parentAndChildShareLine); + if (!useActualIndentation) { + return -1 /* Unknown */; + } + return findColumnForFirstNonWhitespaceCharacterInLine(currentLineAndChar, sourceFile, options); } - if (node.kind === 95 /* SuperKeyword */) { - return getReferencesForSuperKeyword(node); + function nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile) { + var nextToken = ts.findNextToken(precedingToken, current); + if (!nextToken) { + return false; + } + if (nextToken.kind === 15 /* OpenBraceToken */) { + // open braces are always indented at the parent level + return true; + } + else if (nextToken.kind === 16 /* CloseBraceToken */) { + // close braces are indented at the parent level if they are located on the same line with cursor + // this means that if new line will be added at $ position, this case will be indented + // class A { + // $ + // } + /// and this one - not + // class A { + // $} + var nextTokenStartLine = getStartLineAndCharacterForNode(nextToken, sourceFile).line; + return lineAtPosition === nextTokenStartLine; + } + return false; } - // `getSymbolAtLocation` normally returns the symbol of the class when given the constructor keyword, - // so we have to specify that we want the constructor symbol. - var symbol = typeChecker.getSymbolAtLocation(node); - if (!symbol && node.kind === 9 /* StringLiteral */) { - return getReferencesForStringLiteral(node, sourceFiles); + function getStartLineAndCharacterForNode(n, sourceFile) { + return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)); } - // Could not find a symbol e.g. unknown identifier - if (!symbol) { - // Can't have references to something that we have no symbol for. - return undefined; + function childStartsOnTheSameLineWithElseInIfStatement(parent, child, childStartLine, sourceFile) { + if (parent.kind === 203 /* IfStatement */ && parent.elseStatement === child) { + var elseKeyword = ts.findChildOfKind(parent, 80 /* ElseKeyword */, sourceFile); + ts.Debug.assert(elseKeyword !== undefined); + var elseKeywordStartLine = getStartLineAndCharacterForNode(elseKeyword, sourceFile).line; + return elseKeywordStartLine === childStartLine; + } + return false; } - var declarations = symbol.declarations; - // The symbol was an internal symbol and does not have a declaration e.g. undefined symbol - if (!declarations || !declarations.length) { + SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement = childStartsOnTheSameLineWithElseInIfStatement; + function getContainingList(node, sourceFile) { + if (node.parent) { + switch (node.parent.kind) { + case 155 /* TypeReference */: + if (node.parent.typeArguments && + ts.rangeContainsStartEnd(node.parent.typeArguments, node.getStart(sourceFile), node.getEnd())) { + return node.parent.typeArguments; + } + break; + case 171 /* ObjectLiteralExpression */: + return node.parent.properties; + case 170 /* ArrayLiteralExpression */: + return node.parent.elements; + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + case 180 /* ArrowFunction */: + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + case 151 /* CallSignature */: + case 152 /* ConstructSignature */: { + var start = node.getStart(sourceFile); + if (node.parent.typeParameters && + ts.rangeContainsStartEnd(node.parent.typeParameters, start, node.getEnd())) { + return node.parent.typeParameters; + } + if (ts.rangeContainsStartEnd(node.parent.parameters, start, node.getEnd())) { + return node.parent.parameters; + } + break; + } + case 175 /* NewExpression */: + case 174 /* CallExpression */: { + var start = node.getStart(sourceFile); + if (node.parent.typeArguments && + ts.rangeContainsStartEnd(node.parent.typeArguments, start, node.getEnd())) { + return node.parent.typeArguments; + } + if (node.parent.arguments && + ts.rangeContainsStartEnd(node.parent.arguments, start, node.getEnd())) { + return node.parent.arguments; + } + break; + } + } + } return undefined; } - var result; - // Compute the meaning from the location and the symbol it references - var searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations); - // Get the text to search for. - // Note: if this is an external module symbol, the name doesn't include quotes. - var declaredName = ts.stripQuotes(ts.getDeclaredName(typeChecker, symbol, node)); - // Try to get the smallest valid scope that we can limit our search to; - // otherwise we'll need to search globally (i.e. include each file). - var scope = getSymbolScope(symbol); - // Maps from a symbol ID to the ReferencedSymbol entry in 'result'. - var symbolToIndex = []; - if (scope) { - result = []; - getReferencesInNode(scope, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex); + function getActualIndentationForListItem(node, sourceFile, options) { + var containingList = getContainingList(node, sourceFile); + return containingList ? getActualIndentationFromList(containingList) : -1 /* Unknown */; + function getActualIndentationFromList(list) { + var index = ts.indexOf(list, node); + return index !== -1 ? deriveActualIndentationFromList(list, index, sourceFile, options) : -1 /* Unknown */; + } } - else { - var internedName = getInternedName(symbol, node, declarations); - for (var _i = 0, sourceFiles_4 = sourceFiles; _i < sourceFiles_4.length; _i++) { - var sourceFile = sourceFiles_4[_i]; - cancellationToken.throwIfCancellationRequested(); - var nameTable = getNameTable(sourceFile); - if (nameTable[internedName] !== undefined) { - result = result || []; - getReferencesInNode(sourceFile, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex); + function getLineIndentationWhenExpressionIsInMultiLine(node, sourceFile, options) { + // actual indentation should not be used when: + // - node is close parenthesis - this is the end of the expression + if (node.kind === 18 /* CloseParenToken */) { + return -1 /* Unknown */; + } + if (node.parent && (node.parent.kind === 174 /* CallExpression */ || + node.parent.kind === 175 /* NewExpression */) && + node.parent.expression !== node) { + var fullCallOrNewExpression = node.parent.expression; + var startingExpression = getStartingExpression(fullCallOrNewExpression); + if (fullCallOrNewExpression === startingExpression) { + return -1 /* Unknown */; + } + var fullCallOrNewExpressionEnd = sourceFile.getLineAndCharacterOfPosition(fullCallOrNewExpression.end); + var startingExpressionEnd = sourceFile.getLineAndCharacterOfPosition(startingExpression.end); + if (fullCallOrNewExpressionEnd.line === startingExpressionEnd.line) { + return -1 /* Unknown */; } + return findColumnForFirstNonWhitespaceCharacterInLine(fullCallOrNewExpressionEnd, sourceFile, options); } - } - return result; - function getDefinition(symbol) { - var info = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, node.getSourceFile(), getContainerNode(node), node); - var name = ts.map(info.displayParts, function (p) { return p.text; }).join(""); - var declarations = symbol.declarations; - if (!declarations || declarations.length === 0) { - return undefined; + return -1 /* Unknown */; + function getStartingExpression(node) { + while (true) { + switch (node.kind) { + case 174 /* CallExpression */: + case 175 /* NewExpression */: + case 172 /* PropertyAccessExpression */: + case 173 /* ElementAccessExpression */: + node = node.expression; + break; + default: + return node; + } + } } - return { - containerKind: "", - containerName: "", - name: name, - kind: info.symbolKind, - fileName: declarations[0].getSourceFile().fileName, - textSpan: ts.createTextSpan(declarations[0].getStart(), 0), - displayParts: info.displayParts - }; } - function getAliasSymbolForPropertyNameSymbol(symbol, location) { - if (symbol.flags & 8388608 /* Alias */) { - // Default import get alias - var defaultImport = ts.getDeclarationOfKind(symbol, 231 /* ImportClause */); - if (defaultImport) { - return typeChecker.getAliasedSymbol(symbol); + function deriveActualIndentationFromList(list, index, sourceFile, options) { + ts.Debug.assert(index >= 0 && index < list.length); + var node = list[index]; + // walk toward the start of the list starting from current node and check if the line is the same for all items. + // if end line for item [i - 1] differs from the start line for item [i] - find column of the first non-whitespace character on the line of item [i] + var lineAndCharacter = getStartLineAndCharacterForNode(node, sourceFile); + for (var i = index - 1; i >= 0; i--) { + if (list[i].kind === 24 /* CommaToken */) { + continue; } - var importOrExportSpecifier = ts.forEach(symbol.declarations, function (declaration) { return (declaration.kind === 234 /* ImportSpecifier */ || - declaration.kind === 238 /* ExportSpecifier */) ? declaration : undefined; }); - if (importOrExportSpecifier && - // export { a } - (!importOrExportSpecifier.propertyName || - // export {a as class } where a is location - importOrExportSpecifier.propertyName === location)) { - // If Import specifier -> get alias - // else Export specifier -> get local target - return importOrExportSpecifier.kind === 234 /* ImportSpecifier */ ? - typeChecker.getAliasedSymbol(symbol) : - typeChecker.getExportSpecifierLocalTargetSymbol(importOrExportSpecifier); + // skip list items that ends on the same line with the current list element + var prevEndLine = sourceFile.getLineAndCharacterOfPosition(list[i].end).line; + if (prevEndLine !== lineAndCharacter.line) { + return findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options); } + lineAndCharacter = getStartLineAndCharacterForNode(list[i], sourceFile); } - return undefined; - } - function followAliasIfNecessary(symbol, location) { - return getAliasSymbolForPropertyNameSymbol(symbol, location) || symbol; - } - function getPropertySymbolOfDestructuringAssignment(location) { - return ts.isArrayLiteralOrObjectLiteralDestructuringPattern(location.parent.parent) && - typeChecker.getPropertySymbolOfDestructuringAssignment(location); + return -1 /* Unknown */; } - function isObjectBindingPatternElementWithoutPropertyName(symbol) { - var bindingElement = ts.getDeclarationOfKind(symbol, 169 /* BindingElement */); - return bindingElement && - bindingElement.parent.kind === 167 /* ObjectBindingPattern */ && - !bindingElement.propertyName; + function findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options) { + var lineStart = sourceFile.getPositionOfLineAndCharacter(lineAndCharacter.line, 0); + return findFirstNonWhitespaceColumn(lineStart, lineStart + lineAndCharacter.character, sourceFile, options); } - function getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol) { - if (isObjectBindingPatternElementWithoutPropertyName(symbol)) { - var bindingElement = ts.getDeclarationOfKind(symbol, 169 /* BindingElement */); - var typeOfPattern = typeChecker.getTypeAtLocation(bindingElement.parent); - return typeOfPattern && typeChecker.getPropertyOfType(typeOfPattern, bindingElement.name.text); + /* + Character is the actual index of the character since the beginning of the line. + Column - position of the character after expanding tabs to spaces + "0\t2$" + value of 'character' for '$' is 3 + value of 'column' for '$' is 6 (assuming that tab size is 4) + */ + function findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options) { + var character = 0; + var column = 0; + for (var pos = startPos; pos < endPos; pos++) { + var ch = sourceFile.text.charCodeAt(pos); + if (!ts.isWhiteSpaceSingleLine(ch)) { + break; + } + if (ch === 9 /* tab */) { + column += options.tabSize + (column % options.tabSize); + } + else { + column++; + } + character++; } - return undefined; + return { column: column, character: character }; } - function getInternedName(symbol, location, declarations) { - // If this is an export or import specifier it could have been renamed using the 'as' syntax. - // If so we want to search for whatever under the cursor. - if (ts.isImportOrExportSpecifierName(location)) { - return location.getText(); - } - // Try to get the local symbol if we're dealing with an 'export default' - // since that symbol has the "true" name. - var localExportDefaultSymbol = ts.getLocalSymbolForExportDefault(symbol); - symbol = localExportDefaultSymbol || symbol; - return ts.stripQuotes(symbol.name); + SmartIndenter.findFirstNonWhitespaceCharacterAndColumn = findFirstNonWhitespaceCharacterAndColumn; + function findFirstNonWhitespaceColumn(startPos, endPos, sourceFile, options) { + return findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options).column; } - /** - * Determines the smallest scope in which a symbol may have named references. - * Note that not every construct has been accounted for. This function can - * probably be improved. - * - * @returns undefined if the scope cannot be determined, implying that - * a reference to a symbol can occur anywhere. - */ - function getSymbolScope(symbol) { - // If this is the symbol of a named function expression or named class expression, - // then named references are limited to its own scope. - var valueDeclaration = symbol.valueDeclaration; - if (valueDeclaration && (valueDeclaration.kind === 179 /* FunctionExpression */ || valueDeclaration.kind === 192 /* ClassExpression */)) { - return valueDeclaration; - } - // If this is private property or method, the scope is the containing class - if (symbol.flags & (4 /* Property */ | 8192 /* Method */)) { - var privateDeclaration = ts.forEach(symbol.getDeclarations(), function (d) { return (d.flags & 8 /* Private */) ? d : undefined; }); - if (privateDeclaration) { - return ts.getAncestor(privateDeclaration, 221 /* ClassDeclaration */); - } - } - // If the symbol is an import we would like to find it if we are looking for what it imports. - // So consider it visible outside its declaration scope. - if (symbol.flags & 8388608 /* Alias */) { - return undefined; - } - // If symbol is of object binding pattern element without property name we would want to - // look for property too and that could be anywhere - if (isObjectBindingPatternElementWithoutPropertyName(symbol)) { - return undefined; - } - // if this symbol is visible from its parent container, e.g. exported, then bail out - // if symbol correspond to the union property - bail out - if (symbol.parent || (symbol.flags & 268435456 /* SyntheticProperty */)) { - return undefined; + SmartIndenter.findFirstNonWhitespaceColumn = findFirstNonWhitespaceColumn; + function nodeContentIsAlwaysIndented(kind) { + switch (kind) { + case 202 /* ExpressionStatement */: + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + case 222 /* InterfaceDeclaration */: + case 224 /* EnumDeclaration */: + case 223 /* TypeAliasDeclaration */: + case 170 /* ArrayLiteralExpression */: + case 199 /* Block */: + case 226 /* ModuleBlock */: + case 171 /* ObjectLiteralExpression */: + case 159 /* TypeLiteral */: + case 161 /* TupleType */: + case 227 /* CaseBlock */: + case 250 /* DefaultClause */: + case 249 /* CaseClause */: + case 178 /* ParenthesizedExpression */: + case 172 /* PropertyAccessExpression */: + case 174 /* CallExpression */: + case 175 /* NewExpression */: + case 200 /* VariableStatement */: + case 218 /* VariableDeclaration */: + case 235 /* ExportAssignment */: + case 211 /* ReturnStatement */: + case 188 /* ConditionalExpression */: + case 168 /* ArrayBindingPattern */: + case 167 /* ObjectBindingPattern */: + case 243 /* JsxOpeningElement */: + case 242 /* JsxSelfClosingElement */: + case 248 /* JsxExpression */: + case 146 /* MethodSignature */: + case 151 /* CallSignature */: + case 152 /* ConstructSignature */: + case 142 /* Parameter */: + case 156 /* FunctionType */: + case 157 /* ConstructorType */: + case 164 /* ParenthesizedType */: + case 176 /* TaggedTemplateExpression */: + case 184 /* AwaitExpression */: + case 237 /* NamedExports */: + case 233 /* NamedImports */: + case 238 /* ExportSpecifier */: + case 234 /* ImportSpecifier */: + return true; } - var scope; - var declarations = symbol.getDeclarations(); - if (declarations) { - for (var _i = 0, declarations_9 = declarations; _i < declarations_9.length; _i++) { - var declaration = declarations_9[_i]; - var container = getContainerNode(declaration); - if (!container) { - return undefined; - } - if (scope && scope !== container) { - // Different declarations have different containers, bail out - return undefined; - } - if (container.kind === 256 /* SourceFile */ && !ts.isExternalModule(container)) { - // This is a global variable and not an external module, any declaration defined - // within this scope is visible outside the file - return undefined; - } - // The search scope is the container node - scope = container; - } + return false; + } + /* @internal */ + function nodeWillIndentChild(parent, child, indentByDefault) { + var childKind = child ? child.kind : 0 /* Unknown */; + switch (parent.kind) { + case 204 /* DoStatement */: + case 205 /* WhileStatement */: + case 207 /* ForInStatement */: + case 208 /* ForOfStatement */: + case 206 /* ForStatement */: + case 203 /* IfStatement */: + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + case 147 /* MethodDeclaration */: + case 180 /* ArrowFunction */: + case 148 /* Constructor */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + return childKind !== 199 /* Block */; + case 236 /* ExportDeclaration */: + return childKind !== 237 /* NamedExports */; + case 230 /* ImportDeclaration */: + return childKind !== 231 /* ImportClause */ || + (child.namedBindings && child.namedBindings.kind !== 233 /* NamedImports */); + case 241 /* JsxElement */: + return childKind !== 245 /* JsxClosingElement */; } - return scope; + // No explicit rule for given nodes so the result will follow the default value argument + return indentByDefault; } - function getPossibleSymbolReferencePositions(sourceFile, symbolName, start, end) { - var positions = []; - /// TODO: Cache symbol existence for files to save text search - // Also, need to make this work for unicode escapes. - // Be resilient in the face of a symbol with no name or zero length name - if (!symbolName || !symbolName.length) { - return positions; + SmartIndenter.nodeWillIndentChild = nodeWillIndentChild; + /* + Function returns true when the parent node should indent the given child by an explicit rule + */ + function shouldIndentChildNode(parent, child) { + return nodeContentIsAlwaysIndented(parent.kind) || nodeWillIndentChild(parent, child, /*indentByDefault*/ false); + } + SmartIndenter.shouldIndentChildNode = shouldIndentChildNode; + })(SmartIndenter = formatting.SmartIndenter || (formatting.SmartIndenter = {})); + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +var ts; +(function (ts) { + /** The version of the language service API */ + ts.servicesVersion = "0.5"; + function createNode(kind, pos, end, parent) { + var node = kind >= 139 /* FirstNode */ ? new NodeObject(kind, pos, end) : + kind === 69 /* Identifier */ ? new IdentifierObject(kind, pos, end) : + new TokenObject(kind, pos, end); + node.parent = parent; + return node; + } + var NodeObject = (function () { + function NodeObject(kind, pos, end) { + this.pos = pos; + this.end = end; + this.flags = 0 /* None */; + this.transformFlags = undefined; + this.excludeTransformFlags = undefined; + this.parent = undefined; + this.kind = kind; + } + NodeObject.prototype.getSourceFile = function () { + return ts.getSourceFileOfNode(this); + }; + NodeObject.prototype.getStart = function (sourceFile, includeJsDocComment) { + return ts.getTokenPosOfNode(this, sourceFile, includeJsDocComment); + }; + NodeObject.prototype.getFullStart = function () { + return this.pos; + }; + NodeObject.prototype.getEnd = function () { + return this.end; + }; + NodeObject.prototype.getWidth = function (sourceFile) { + return this.getEnd() - this.getStart(sourceFile); + }; + NodeObject.prototype.getFullWidth = function () { + return this.end - this.pos; + }; + NodeObject.prototype.getLeadingTriviaWidth = function (sourceFile) { + return this.getStart(sourceFile) - this.pos; + }; + NodeObject.prototype.getFullText = function (sourceFile) { + return (sourceFile || this.getSourceFile()).text.substring(this.pos, this.end); + }; + NodeObject.prototype.getText = function (sourceFile) { + if (!sourceFile) { + sourceFile = this.getSourceFile(); + } + return sourceFile.text.substring(this.getStart(sourceFile), this.getEnd()); + }; + NodeObject.prototype.addSyntheticNodes = function (nodes, pos, end, useJSDocScanner) { + ts.scanner.setTextPos(pos); + while (pos < end) { + var token = useJSDocScanner ? ts.scanner.scanJSDocToken() : ts.scanner.scan(); + var textPos = ts.scanner.getTextPos(); + if (textPos <= end) { + nodes.push(createNode(token, pos, textPos, this)); } - var text = sourceFile.text; - var sourceLength = text.length; - var symbolNameLength = symbolName.length; - var position = text.indexOf(symbolName, start); - while (position >= 0) { - cancellationToken.throwIfCancellationRequested(); - // If we are past the end, stop looking - if (position > end) - break; - // We found a match. Make sure it's not part of a larger word (i.e. the char - // before and after it have to be a non-identifier char). - var endPosition = position + symbolNameLength; - if ((position === 0 || !ts.isIdentifierPart(text.charCodeAt(position - 1), 2 /* Latest */)) && - (endPosition === sourceLength || !ts.isIdentifierPart(text.charCodeAt(endPosition), 2 /* Latest */))) { - // Found a real match. Keep searching. - positions.push(position); - } - position = text.indexOf(symbolName, position + symbolNameLength + 1); + pos = textPos; + } + return pos; + }; + NodeObject.prototype.createSyntaxList = function (nodes) { + var list = createNode(286 /* SyntaxList */, nodes.pos, nodes.end, this); + list._children = []; + var pos = nodes.pos; + for (var _i = 0, nodes_4 = nodes; _i < nodes_4.length; _i++) { + var node = nodes_4[_i]; + if (pos < node.pos) { + pos = this.addSyntheticNodes(list._children, pos, node.pos); } - return positions; + list._children.push(node); + pos = node.end; } - function getLabelReferencesInNode(container, targetLabel) { - var references = []; - var sourceFile = container.getSourceFile(); - var labelName = targetLabel.text; - var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container.getStart(), container.getEnd()); - ts.forEach(possiblePositions, function (position) { - cancellationToken.throwIfCancellationRequested(); - var node = ts.getTouchingWord(sourceFile, position); - if (!node || node.getWidth() !== labelName.length) { - return; + if (pos < nodes.end) { + this.addSyntheticNodes(list._children, pos, nodes.end); + } + return list; + }; + NodeObject.prototype.createChildren = function (sourceFile) { + var _this = this; + var children; + if (this.kind >= 139 /* FirstNode */) { + ts.scanner.setText((sourceFile || this.getSourceFile()).text); + children = []; + var pos_3 = this.pos; + var useJSDocScanner_1 = this.kind >= 273 /* FirstJSDocTagNode */ && this.kind <= 285 /* LastJSDocTagNode */; + var processNode = function (node) { + var isJSDocTagNode = ts.isJSDocTag(node); + if (!isJSDocTagNode && pos_3 < node.pos) { + pos_3 = _this.addSyntheticNodes(children, pos_3, node.pos, useJSDocScanner_1); } - // Only pick labels that are either the target label, or have a target that is the target label - if (node === targetLabel || - (isJumpStatementTarget(node) && getTargetLabel(node, labelName) === targetLabel)) { - references.push(getReferenceEntryFromNode(node)); + children.push(node); + if (!isJSDocTagNode) { + pos_3 = node.end; } - }); - var definition = { - containerKind: "", - containerName: "", - fileName: targetLabel.getSourceFile().fileName, - kind: ts.ScriptElementKind.label, - name: labelName, - textSpan: ts.createTextSpanFromBounds(targetLabel.getStart(), targetLabel.getEnd()), - displayParts: [ts.displayPart(labelName, ts.SymbolDisplayPartKind.text)] }; - return [{ definition: definition, references: references }]; - } - function isValidReferencePosition(node, searchSymbolName) { - if (node) { - // Compare the length so we filter out strict superstrings of the symbol we are looking for - switch (node.kind) { - case 69 /* Identifier */: - return node.getWidth() === searchSymbolName.length; - case 9 /* StringLiteral */: - if (isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || - isNameOfExternalModuleImportOrDeclaration(node)) { - // For string literals we have two additional chars for the quotes - return node.getWidth() === searchSymbolName.length + 2; - } - break; - case 8 /* NumericLiteral */: - if (isLiteralNameOfPropertyDeclarationOrIndexAccess(node)) { - return node.getWidth() === searchSymbolName.length; - } - break; - } - } - return false; - } - /** Search within node "container" for references for a search value, where the search value is defined as a - * tuple of(searchSymbol, searchText, searchLocation, and searchMeaning). - * searchLocation: a node where the search value - */ - function getReferencesInNode(container, searchSymbol, searchText, searchLocation, searchMeaning, findInStrings, findInComments, result, symbolToIndex) { - var sourceFile = container.getSourceFile(); - var tripleSlashDirectivePrefixRegex = /^\/\/\/\s*= 0) { - var referencedSymbol = getReferencedSymbol(shorthandValueSymbol); - referencedSymbol.references.push(getReferenceEntryFromNode(referenceSymbolDeclaration.name)); - } - else if (searchLocation.kind === 121 /* ConstructorKeyword */) { - findAdditionalConstructorReferences(referenceSymbol, referenceLocation); - } - } - }); - } - return; - /** Adds references when a constructor is used with `new this()` in its own class and `super()` calls in subclasses. */ - function findAdditionalConstructorReferences(referenceSymbol, referenceLocation) { - ts.Debug.assert(ts.isClassLike(searchSymbol.valueDeclaration)); - var referenceClass = referenceLocation.parent; - if (referenceSymbol === searchSymbol && ts.isClassLike(referenceClass)) { - ts.Debug.assert(referenceClass.name === referenceLocation); - // This is the class declaration containing the constructor. - addReferences(findOwnConstructorCalls(searchSymbol)); + var processNodes = function (nodes) { + if (pos_3 < nodes.pos) { + pos_3 = _this.addSyntheticNodes(children, pos_3, nodes.pos, useJSDocScanner_1); } - else { - // If this class appears in `extends C`, then the extending class' "super" calls are references. - var classExtending = tryGetClassByExtendingIdentifier(referenceLocation); - if (classExtending && ts.isClassLike(classExtending) && followAliasIfNecessary(referenceSymbol, referenceLocation) === searchSymbol) { - addReferences(superConstructorAccesses(classExtending)); - } + children.push(_this.createSyntaxList(nodes)); + pos_3 = nodes.end; + }; + // jsDocComments need to be the first children + if (this.jsDocComments) { + for (var _i = 0, _a = this.jsDocComments; _i < _a.length; _i++) { + var jsDocComment = _a[_i]; + processNode(jsDocComment); } } - function addReferences(references) { - if (references.length) { - var referencedSymbol = getReferencedSymbol(searchSymbol); - ts.addRange(referencedSymbol.references, ts.map(references, getReferenceEntryFromNode)); - } + // For syntactic classifications, all trivia are classcified together, including jsdoc comments. + // For that to work, the jsdoc comments should still be the leading trivia of the first child. + // Restoring the scanner position ensures that. + pos_3 = this.pos; + ts.forEachChild(this, processNode, processNodes); + if (pos_3 < this.end) { + this.addSyntheticNodes(children, pos_3, this.end); } - /** `classSymbol` is the class where the constructor was defined. - * Reference the constructor and all calls to `new this()`. - */ - function findOwnConstructorCalls(classSymbol) { - var result = []; - for (var _i = 0, _a = classSymbol.members["__constructor"].declarations; _i < _a.length; _i++) { - var decl = _a[_i]; - ts.Debug.assert(decl.kind === 148 /* Constructor */); - var ctrKeyword = decl.getChildAt(0); - ts.Debug.assert(ctrKeyword.kind === 121 /* ConstructorKeyword */); - result.push(ctrKeyword); - } - ts.forEachProperty(classSymbol.exports, function (member) { - var decl = member.valueDeclaration; - if (decl && decl.kind === 147 /* MethodDeclaration */) { - var body = decl.body; - if (body) { - forEachDescendantOfKind(body, 97 /* ThisKeyword */, function (thisKeyword) { - if (isNewExpressionTarget(thisKeyword)) { - result.push(thisKeyword); - } - }); - } - } - }); - return result; + ts.scanner.setText(undefined); + } + this._children = children || ts.emptyArray; + }; + NodeObject.prototype.getChildCount = function (sourceFile) { + if (!this._children) + this.createChildren(sourceFile); + return this._children.length; + }; + NodeObject.prototype.getChildAt = function (index, sourceFile) { + if (!this._children) + this.createChildren(sourceFile); + return this._children[index]; + }; + NodeObject.prototype.getChildren = function (sourceFile) { + if (!this._children) + this.createChildren(sourceFile); + return this._children; + }; + NodeObject.prototype.getFirstToken = function (sourceFile) { + var children = this.getChildren(sourceFile); + if (!children.length) { + return undefined; + } + var child = children[0]; + return child.kind < 139 /* FirstNode */ ? child : child.getFirstToken(sourceFile); + }; + NodeObject.prototype.getLastToken = function (sourceFile) { + var children = this.getChildren(sourceFile); + var child = ts.lastOrUndefined(children); + if (!child) { + return undefined; + } + return child.kind < 139 /* FirstNode */ ? child : child.getLastToken(sourceFile); + }; + return NodeObject; + }()); + var TokenOrIdentifierObject = (function () { + function TokenOrIdentifierObject(pos, end) { + // Set properties in same order as NodeObject + this.pos = pos; + this.end = end; + this.flags = 0 /* None */; + this.parent = undefined; + } + TokenOrIdentifierObject.prototype.getSourceFile = function () { + return ts.getSourceFileOfNode(this); + }; + TokenOrIdentifierObject.prototype.getStart = function (sourceFile, includeJsDocComment) { + return ts.getTokenPosOfNode(this, sourceFile, includeJsDocComment); + }; + TokenOrIdentifierObject.prototype.getFullStart = function () { + return this.pos; + }; + TokenOrIdentifierObject.prototype.getEnd = function () { + return this.end; + }; + TokenOrIdentifierObject.prototype.getWidth = function (sourceFile) { + return this.getEnd() - this.getStart(sourceFile); + }; + TokenOrIdentifierObject.prototype.getFullWidth = function () { + return this.end - this.pos; + }; + TokenOrIdentifierObject.prototype.getLeadingTriviaWidth = function (sourceFile) { + return this.getStart(sourceFile) - this.pos; + }; + TokenOrIdentifierObject.prototype.getFullText = function (sourceFile) { + return (sourceFile || this.getSourceFile()).text.substring(this.pos, this.end); + }; + TokenOrIdentifierObject.prototype.getText = function (sourceFile) { + return (sourceFile || this.getSourceFile()).text.substring(this.getStart(), this.getEnd()); + }; + TokenOrIdentifierObject.prototype.getChildCount = function (sourceFile) { + return 0; + }; + TokenOrIdentifierObject.prototype.getChildAt = function (index, sourceFile) { + return undefined; + }; + TokenOrIdentifierObject.prototype.getChildren = function (sourceFile) { + return ts.emptyArray; + }; + TokenOrIdentifierObject.prototype.getFirstToken = function (sourceFile) { + return undefined; + }; + TokenOrIdentifierObject.prototype.getLastToken = function (sourceFile) { + return undefined; + }; + return TokenOrIdentifierObject; + }()); + var SymbolObject = (function () { + function SymbolObject(flags, name) { + this.flags = flags; + this.name = name; + } + SymbolObject.prototype.getFlags = function () { + return this.flags; + }; + SymbolObject.prototype.getName = function () { + return this.name; + }; + SymbolObject.prototype.getDeclarations = function () { + return this.declarations; + }; + SymbolObject.prototype.getDocumentationComment = function () { + if (this.documentationComment === undefined) { + this.documentationComment = ts.JsDoc.getJsDocCommentsFromDeclarations(this.declarations, this.name, !(this.flags & 4 /* Property */)); + } + return this.documentationComment; + }; + return SymbolObject; + }()); + var TokenObject = (function (_super) { + __extends(TokenObject, _super); + function TokenObject(kind, pos, end) { + _super.call(this, pos, end); + this.kind = kind; + } + return TokenObject; + }(TokenOrIdentifierObject)); + var IdentifierObject = (function (_super) { + __extends(IdentifierObject, _super); + function IdentifierObject(kind, pos, end) { + _super.call(this, pos, end); + } + return IdentifierObject; + }(TokenOrIdentifierObject)); + IdentifierObject.prototype.kind = 69 /* Identifier */; + var TypeObject = (function () { + function TypeObject(checker, flags) { + this.checker = checker; + this.flags = flags; + } + TypeObject.prototype.getFlags = function () { + return this.flags; + }; + TypeObject.prototype.getSymbol = function () { + return this.symbol; + }; + TypeObject.prototype.getProperties = function () { + return this.checker.getPropertiesOfType(this); + }; + TypeObject.prototype.getProperty = function (propertyName) { + return this.checker.getPropertyOfType(this, propertyName); + }; + TypeObject.prototype.getApparentProperties = function () { + return this.checker.getAugmentedPropertiesOfType(this); + }; + TypeObject.prototype.getCallSignatures = function () { + return this.checker.getSignaturesOfType(this, 0 /* Call */); + }; + TypeObject.prototype.getConstructSignatures = function () { + return this.checker.getSignaturesOfType(this, 1 /* Construct */); + }; + TypeObject.prototype.getStringIndexType = function () { + return this.checker.getIndexTypeOfType(this, 0 /* String */); + }; + TypeObject.prototype.getNumberIndexType = function () { + return this.checker.getIndexTypeOfType(this, 1 /* Number */); + }; + TypeObject.prototype.getBaseTypes = function () { + return this.flags & (32768 /* Class */ | 65536 /* Interface */) + ? this.checker.getBaseTypes(this) + : undefined; + }; + TypeObject.prototype.getNonNullableType = function () { + return this.checker.getNonNullableType(this); + }; + return TypeObject; + }()); + var SignatureObject = (function () { + function SignatureObject(checker) { + this.checker = checker; + } + SignatureObject.prototype.getDeclaration = function () { + return this.declaration; + }; + SignatureObject.prototype.getTypeParameters = function () { + return this.typeParameters; + }; + SignatureObject.prototype.getParameters = function () { + return this.parameters; + }; + SignatureObject.prototype.getReturnType = function () { + return this.checker.getReturnTypeOfSignature(this); + }; + SignatureObject.prototype.getDocumentationComment = function () { + if (this.documentationComment === undefined) { + this.documentationComment = this.declaration ? ts.JsDoc.getJsDocCommentsFromDeclarations([this.declaration], + /*name*/ undefined, + /*canUseParsedParamTagComments*/ false) : []; + } + return this.documentationComment; + }; + return SignatureObject; + }()); + var SourceFileObject = (function (_super) { + __extends(SourceFileObject, _super); + function SourceFileObject(kind, pos, end) { + _super.call(this, kind, pos, end); + } + SourceFileObject.prototype.update = function (newText, textChangeRange) { + return ts.updateSourceFile(this, newText, textChangeRange); + }; + SourceFileObject.prototype.getLineAndCharacterOfPosition = function (position) { + return ts.getLineAndCharacterOfPosition(this, position); + }; + SourceFileObject.prototype.getLineStarts = function () { + return ts.getLineStarts(this); + }; + SourceFileObject.prototype.getPositionOfLineAndCharacter = function (line, character) { + return ts.getPositionOfLineAndCharacter(this, line, character); + }; + SourceFileObject.prototype.getNamedDeclarations = function () { + if (!this.namedDeclarations) { + this.namedDeclarations = this.computeNamedDeclarations(); + } + return this.namedDeclarations; + }; + SourceFileObject.prototype.computeNamedDeclarations = function () { + var result = ts.createMap(); + ts.forEachChild(this, visit); + return result; + function addDeclaration(declaration) { + var name = getDeclarationName(declaration); + if (name) { + ts.multiMapAdd(result, name, declaration); } - /** Find references to `super` in the constructor of an extending class. */ - function superConstructorAccesses(cls) { - var symbol = cls.symbol; - var ctr = symbol.members["__constructor"]; - if (!ctr) { - return []; + } + function getDeclarations(name) { + return result[name] || (result[name] = []); + } + function getDeclarationName(declaration) { + if (declaration.name) { + var result_6 = getTextOfIdentifierOrLiteral(declaration.name); + if (result_6 !== undefined) { + return result_6; } - var result = []; - for (var _i = 0, _a = ctr.declarations; _i < _a.length; _i++) { - var decl = _a[_i]; - ts.Debug.assert(decl.kind === 148 /* Constructor */); - var body = decl.body; - if (body) { - forEachDescendantOfKind(body, 95 /* SuperKeyword */, function (node) { - if (isCallExpressionTarget(node)) { - result.push(node); - } - }); + if (declaration.name.kind === 140 /* ComputedPropertyName */) { + var expr = declaration.name.expression; + if (expr.kind === 172 /* PropertyAccessExpression */) { + return expr.name.text; } + return getTextOfIdentifierOrLiteral(expr); } - ; - return result; - } - function getReferencedSymbol(symbol) { - var symbolId = ts.getSymbolId(symbol); - var index = symbolToIndex[symbolId]; - if (index === undefined) { - index = result.length; - symbolToIndex[symbolId] = index; - result.push({ - definition: getDefinition(symbol), - references: [] - }); - } - return result[index]; } - function isInNonReferenceComment(sourceFile, position) { - return ts.isInCommentHelper(sourceFile, position, isNonReferenceComment); - function isNonReferenceComment(c) { - var commentText = sourceFile.text.substring(c.pos, c.end); - return !tripleSlashDirectivePrefixRegex.test(commentText); + return undefined; + } + function getTextOfIdentifierOrLiteral(node) { + if (node) { + if (node.kind === 69 /* Identifier */ || + node.kind === 9 /* StringLiteral */ || + node.kind === 8 /* NumericLiteral */) { + return node.text; } } + return undefined; } - function getReferencesForSuperKeyword(superKeyword) { - var searchSpaceNode = ts.getSuperContainer(superKeyword, /*stopOnFunctions*/ false); - if (!searchSpaceNode) { - return undefined; - } - // Whether 'super' occurs in a static context within a class. - var staticFlag = 32 /* Static */; - switch (searchSpaceNode.kind) { - case 145 /* PropertyDeclaration */: - case 144 /* PropertySignature */: + function visit(node) { + switch (node.kind) { + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: case 147 /* MethodDeclaration */: case 146 /* MethodSignature */: - case 148 /* Constructor */: + var functionDeclaration = node; + var declarationName = getDeclarationName(functionDeclaration); + if (declarationName) { + var declarations = getDeclarations(declarationName); + var lastDeclaration = ts.lastOrUndefined(declarations); + // Check whether this declaration belongs to an "overload group". + if (lastDeclaration && functionDeclaration.parent === lastDeclaration.parent && functionDeclaration.symbol === lastDeclaration.symbol) { + // Overwrite the last declaration if it was an overload + // and this one is an implementation. + if (functionDeclaration.body && !lastDeclaration.body) { + declarations[declarations.length - 1] = functionDeclaration; + } + } + else { + declarations.push(functionDeclaration); + } + ts.forEachChild(node, visit); + } + break; + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + case 222 /* InterfaceDeclaration */: + case 223 /* TypeAliasDeclaration */: + case 224 /* EnumDeclaration */: + case 225 /* ModuleDeclaration */: + case 229 /* ImportEqualsDeclaration */: + case 238 /* ExportSpecifier */: + case 234 /* ImportSpecifier */: + case 229 /* ImportEqualsDeclaration */: + case 231 /* ImportClause */: + case 232 /* NamespaceImport */: case 149 /* GetAccessor */: case 150 /* SetAccessor */: - staticFlag &= searchSpaceNode.flags; - searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class + case 159 /* TypeLiteral */: + addDeclaration(node); + ts.forEachChild(node, visit); break; - default: - return undefined; - } - var references = []; - var sourceFile = searchSpaceNode.getSourceFile(); - var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); - ts.forEach(possiblePositions, function (position) { - cancellationToken.throwIfCancellationRequested(); - var node = ts.getTouchingWord(sourceFile, position); - if (!node || node.kind !== 95 /* SuperKeyword */) { - return; - } - var container = ts.getSuperContainer(node, /*stopOnFunctions*/ false); - // If we have a 'super' container, we must have an enclosing class. - // Now make sure the owning class is the same as the search-space - // and has the same static qualifier as the original 'super's owner. - if (container && (32 /* Static */ & container.flags) === staticFlag && container.parent.symbol === searchSpaceNode.symbol) { - references.push(getReferenceEntryFromNode(node)); - } - }); - var definition = getDefinition(searchSpaceNode.symbol); - return [{ definition: definition, references: references }]; - } - function getReferencesForThisKeyword(thisOrSuperKeyword, sourceFiles) { - var searchSpaceNode = ts.getThisContainer(thisOrSuperKeyword, /* includeArrowFunctions */ false); - // Whether 'this' occurs in a static context within a class. - var staticFlag = 32 /* Static */; - switch (searchSpaceNode.kind) { - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - if (ts.isObjectLiteralMethod(searchSpaceNode)) { + case 142 /* Parameter */: + // Only consider parameter properties + if (!ts.hasModifier(node, 92 /* ParameterPropertyModifier */)) { break; } // fall through + case 218 /* VariableDeclaration */: + case 169 /* BindingElement */: { + var decl = node; + if (ts.isBindingPattern(decl.name)) { + ts.forEachChild(decl.name, visit); + break; + } + if (decl.initializer) + visit(decl.initializer); + } + case 255 /* EnumMember */: case 145 /* PropertyDeclaration */: case 144 /* PropertySignature */: - case 148 /* Constructor */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - staticFlag &= searchSpaceNode.flags; - searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class + addDeclaration(node); break; - case 256 /* SourceFile */: - if (ts.isExternalModule(searchSpaceNode)) { - return undefined; + case 236 /* ExportDeclaration */: + // Handle named exports case e.g.: + // export {a, b as B} from "mod"; + if (node.exportClause) { + ts.forEach(node.exportClause.elements, visit); } - // Fall through - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: break; - // Computed properties in classes are not handled here because references to this are illegal, - // so there is no point finding references to them. - default: - return undefined; - } - var references = []; - var possiblePositions; - if (searchSpaceNode.kind === 256 /* SourceFile */) { - ts.forEach(sourceFiles, function (sourceFile) { - possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", sourceFile.getStart(), sourceFile.getEnd()); - getThisReferencesInFile(sourceFile, sourceFile, possiblePositions, references); - }); - } - else { - var sourceFile = searchSpaceNode.getSourceFile(); - possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); - getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, references); - } - var thisOrSuperSymbol = typeChecker.getSymbolAtLocation(thisOrSuperKeyword); - var displayParts = thisOrSuperSymbol && getSymbolDisplayPartsDocumentationAndSymbolKind(thisOrSuperSymbol, thisOrSuperKeyword.getSourceFile(), getContainerNode(thisOrSuperKeyword), thisOrSuperKeyword).displayParts; - return [{ - definition: { - containerKind: "", - containerName: "", - fileName: node.getSourceFile().fileName, - kind: ts.ScriptElementKind.variableElement, - name: "this", - textSpan: ts.createTextSpanFromBounds(node.getStart(), node.getEnd()), - displayParts: displayParts - }, - references: references - }]; - function getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, result) { - ts.forEach(possiblePositions, function (position) { - cancellationToken.throwIfCancellationRequested(); - var node = ts.getTouchingWord(sourceFile, position); - if (!node || !isThis(node)) { - return; - } - var container = ts.getThisContainer(node, /* includeArrowFunctions */ false); - switch (searchSpaceNode.kind) { - case 179 /* FunctionExpression */: - case 220 /* FunctionDeclaration */: - if (searchSpaceNode.symbol === container.symbol) { - result.push(getReferenceEntryFromNode(node)); - } - break; - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - if (ts.isObjectLiteralMethod(searchSpaceNode) && searchSpaceNode.symbol === container.symbol) { - result.push(getReferenceEntryFromNode(node)); - } - break; - case 192 /* ClassExpression */: - case 221 /* ClassDeclaration */: - // Make sure the container belongs to the same class - // and has the appropriate static modifier from the original container. - if (container.parent && searchSpaceNode.symbol === container.parent.symbol && (container.flags & 32 /* Static */) === staticFlag) { - result.push(getReferenceEntryFromNode(node)); + case 230 /* ImportDeclaration */: + var importClause = node.importClause; + if (importClause) { + // Handle default import case e.g.: + // import d from "mod"; + if (importClause.name) { + addDeclaration(importClause); + } + // Handle named bindings in imports e.g.: + // import * as NS from "mod"; + // import {a, b as B} from "mod"; + if (importClause.namedBindings) { + if (importClause.namedBindings.kind === 232 /* NamespaceImport */) { + addDeclaration(importClause.namedBindings); } - break; - case 256 /* SourceFile */: - if (container.kind === 256 /* SourceFile */ && !ts.isExternalModule(container)) { - result.push(getReferenceEntryFromNode(node)); + else { + ts.forEach(importClause.namedBindings.elements, visit); } - break; + } } - }); + break; + default: + ts.forEachChild(node, visit); } } - function getReferencesForStringLiteral(node, sourceFiles) { - var typeChecker = program.getTypeChecker(); - var type = getStringLiteralTypeForNode(node, typeChecker); - if (!type) { - // nothing to do here. moving on - return undefined; - } - var references = []; - for (var _i = 0, sourceFiles_5 = sourceFiles; _i < sourceFiles_5.length; _i++) { - var sourceFile = sourceFiles_5[_i]; - var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, type.text, sourceFile.getStart(), sourceFile.getEnd()); - getReferencesForStringLiteralInFile(sourceFile, type, possiblePositions, references); + }; + return SourceFileObject; + }(NodeObject)); + function getServicesObjectAllocator() { + return { + getNodeConstructor: function () { return NodeObject; }, + getTokenConstructor: function () { return TokenObject; }, + getIdentifierConstructor: function () { return IdentifierObject; }, + getSourceFileConstructor: function () { return SourceFileObject; }, + getSymbolConstructor: function () { return SymbolObject; }, + getTypeConstructor: function () { return TypeObject; }, + getSignatureConstructor: function () { return SignatureObject; }, + }; + } + function toEditorSettings(optionsAsMap) { + var allPropertiesAreCamelCased = true; + for (var key in optionsAsMap) { + if (ts.hasProperty(optionsAsMap, key) && !isCamelCase(key)) { + allPropertiesAreCamelCased = false; + break; + } + } + if (allPropertiesAreCamelCased) { + return optionsAsMap; + } + var settings = {}; + for (var key in optionsAsMap) { + if (ts.hasProperty(optionsAsMap, key)) { + var newKey = isCamelCase(key) ? key : key.charAt(0).toLowerCase() + key.substr(1); + settings[newKey] = optionsAsMap[key]; + } + } + return settings; + } + ts.toEditorSettings = toEditorSettings; + function isCamelCase(s) { + return !s.length || s.charAt(0) === s.charAt(0).toLowerCase(); + } + function displayPartsToString(displayParts) { + if (displayParts) { + return ts.map(displayParts, function (displayPart) { return displayPart.text; }).join(""); + } + return ""; + } + ts.displayPartsToString = displayPartsToString; + function getDefaultCompilerOptions() { + // Always default to "ScriptTarget.ES5" for the language service + return { + target: 1 /* ES5 */, + jsx: 1 /* Preserve */ + }; + } + ts.getDefaultCompilerOptions = getDefaultCompilerOptions; + // Cache host information about script should be refreshed + // at each language service public entry point, since we don't know when + // set of scripts handled by the host changes. + var HostCache = (function () { + function HostCache(host, getCanonicalFileName) { + this.host = host; + this.getCanonicalFileName = getCanonicalFileName; + // script id => script index + this.currentDirectory = host.getCurrentDirectory(); + this.fileNameToEntry = ts.createFileMap(); + // Initialize the list with the root file names + var rootFileNames = host.getScriptFileNames(); + for (var _i = 0, rootFileNames_1 = rootFileNames; _i < rootFileNames_1.length; _i++) { + var fileName = rootFileNames_1[_i]; + this.createEntry(fileName, ts.toPath(fileName, this.currentDirectory, getCanonicalFileName)); + } + // store the compilation settings + this._compilationSettings = host.getCompilationSettings() || getDefaultCompilerOptions(); + } + HostCache.prototype.compilationSettings = function () { + return this._compilationSettings; + }; + HostCache.prototype.createEntry = function (fileName, path) { + var entry; + var scriptSnapshot = this.host.getScriptSnapshot(fileName); + if (scriptSnapshot) { + entry = { + hostFileName: fileName, + version: this.host.getScriptVersion(fileName), + scriptSnapshot: scriptSnapshot, + scriptKind: ts.getScriptKind(fileName, this.host) + }; + } + this.fileNameToEntry.set(path, entry); + return entry; + }; + HostCache.prototype.getEntry = function (path) { + return this.fileNameToEntry.get(path); + }; + HostCache.prototype.contains = function (path) { + return this.fileNameToEntry.contains(path); + }; + HostCache.prototype.getOrCreateEntry = function (fileName) { + var path = ts.toPath(fileName, this.currentDirectory, this.getCanonicalFileName); + return this.getOrCreateEntryByPath(fileName, path); + }; + HostCache.prototype.getOrCreateEntryByPath = function (fileName, path) { + return this.contains(path) + ? this.getEntry(path) + : this.createEntry(fileName, path); + }; + HostCache.prototype.getRootFileNames = function () { + var fileNames = []; + this.fileNameToEntry.forEachValue(function (path, value) { + if (value) { + fileNames.push(value.hostFileName); } - return [{ - definition: { - containerKind: "", - containerName: "", - fileName: node.getSourceFile().fileName, - kind: ts.ScriptElementKind.variableElement, - name: type.text, - textSpan: ts.createTextSpanFromBounds(node.getStart(), node.getEnd()), - displayParts: [ts.displayPart(ts.getTextOfNode(node), ts.SymbolDisplayPartKind.stringLiteral)] - }, - references: references - }]; - function getReferencesForStringLiteralInFile(sourceFile, searchType, possiblePositions, references) { - for (var _i = 0, possiblePositions_1 = possiblePositions; _i < possiblePositions_1.length; _i++) { - var position = possiblePositions_1[_i]; - cancellationToken.throwIfCancellationRequested(); - var node_2 = ts.getTouchingWord(sourceFile, position); - if (!node_2 || node_2.kind !== 9 /* StringLiteral */) { - return; - } - var type_1 = getStringLiteralTypeForNode(node_2, typeChecker); - if (type_1 === searchType) { - references.push(getReferenceEntryFromNode(node_2)); + }); + return fileNames; + }; + HostCache.prototype.getVersion = function (path) { + var file = this.getEntry(path); + return file && file.version; + }; + HostCache.prototype.getScriptSnapshot = function (path) { + var file = this.getEntry(path); + return file && file.scriptSnapshot; + }; + return HostCache; + }()); + var SyntaxTreeCache = (function () { + function SyntaxTreeCache(host) { + this.host = host; + } + SyntaxTreeCache.prototype.getCurrentSourceFile = function (fileName) { + var scriptSnapshot = this.host.getScriptSnapshot(fileName); + if (!scriptSnapshot) { + // The host does not know about this file. + throw new Error("Could not find file: '" + fileName + "'."); + } + var scriptKind = ts.getScriptKind(fileName, this.host); + var version = this.host.getScriptVersion(fileName); + var sourceFile; + if (this.currentFileName !== fileName) { + // This is a new file, just parse it + sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, 2 /* Latest */, version, /*setNodeParents*/ true, scriptKind); + } + else if (this.currentFileVersion !== version) { + // This is the same file, just a newer version. Incrementally parse the file. + var editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot); + sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, editRange); + } + if (sourceFile) { + // All done, ensure state is up to date + this.currentFileVersion = version; + this.currentFileName = fileName; + this.currentFileScriptSnapshot = scriptSnapshot; + this.currentSourceFile = sourceFile; + } + return this.currentSourceFile; + }; + return SyntaxTreeCache; + }()); + function setSourceFileFields(sourceFile, scriptSnapshot, version) { + sourceFile.version = version; + sourceFile.scriptSnapshot = scriptSnapshot; + } + function createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget, version, setNodeParents, scriptKind) { + var text = scriptSnapshot.getText(0, scriptSnapshot.getLength()); + var sourceFile = ts.createSourceFile(fileName, text, scriptTarget, setNodeParents, scriptKind); + setSourceFileFields(sourceFile, scriptSnapshot, version); + return sourceFile; + } + ts.createLanguageServiceSourceFile = createLanguageServiceSourceFile; + ts.disableIncrementalParsing = false; + function updateLanguageServiceSourceFile(sourceFile, scriptSnapshot, version, textChangeRange, aggressiveChecks) { + // If we were given a text change range, and our version or open-ness changed, then + // incrementally parse this file. + if (textChangeRange) { + if (version !== sourceFile.version) { + // Once incremental parsing is ready, then just call into this function. + if (!ts.disableIncrementalParsing) { + var newText = void 0; + // grab the fragment from the beginning of the original text to the beginning of the span + var prefix = textChangeRange.span.start !== 0 + ? sourceFile.text.substr(0, textChangeRange.span.start) + : ""; + // grab the fragment from the end of the span till the end of the original text + var suffix = ts.textSpanEnd(textChangeRange.span) !== sourceFile.text.length + ? sourceFile.text.substr(ts.textSpanEnd(textChangeRange.span)) + : ""; + if (textChangeRange.newLength === 0) { + // edit was a deletion - just combine prefix and suffix + newText = prefix && suffix ? prefix + suffix : prefix || suffix; + } + else { + // it was actual edit, fetch the fragment of new text that correspond to new span + var changedText = scriptSnapshot.getText(textChangeRange.span.start, textChangeRange.span.start + textChangeRange.newLength); + // combine prefix, changed text and suffix + newText = prefix && suffix + ? prefix + changedText + suffix + : prefix + ? (prefix + changedText) + : (changedText + suffix); + } + var newSourceFile = ts.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); + setSourceFileFields(newSourceFile, scriptSnapshot, version); + // after incremental parsing nameTable might not be up-to-date + // drop it so it can be lazily recreated later + newSourceFile.nameTable = undefined; + // dispose all resources held by old script snapshot + if (sourceFile !== newSourceFile && sourceFile.scriptSnapshot) { + if (sourceFile.scriptSnapshot.dispose) { + sourceFile.scriptSnapshot.dispose(); } + sourceFile.scriptSnapshot = undefined; } + return newSourceFile; } } - function populateSearchSymbolSet(symbol, location) { - // The search set contains at least the current symbol - var result = [symbol]; - // If the location is name of property symbol from object literal destructuring pattern - // Search the property symbol - // for ( { property: p2 } of elems) { } - var containingObjectLiteralElement = getContainingObjectLiteralElement(location); - if (containingObjectLiteralElement && containingObjectLiteralElement.kind !== 254 /* ShorthandPropertyAssignment */) { - var propertySymbol = getPropertySymbolOfDestructuringAssignment(location); - if (propertySymbol) { - result.push(propertySymbol); + } + // Otherwise, just create a new source file. + return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents*/ true, sourceFile.scriptKind); + } + ts.updateLanguageServiceSourceFile = updateLanguageServiceSourceFile; + var CancellationTokenObject = (function () { + function CancellationTokenObject(cancellationToken) { + this.cancellationToken = cancellationToken; + } + CancellationTokenObject.prototype.isCancellationRequested = function () { + return this.cancellationToken && this.cancellationToken.isCancellationRequested(); + }; + CancellationTokenObject.prototype.throwIfCancellationRequested = function () { + if (this.isCancellationRequested()) { + throw new ts.OperationCanceledException(); + } + }; + return CancellationTokenObject; + }()); + function createLanguageService(host, documentRegistry) { + if (documentRegistry === void 0) { documentRegistry = ts.createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory()); } + var syntaxTreeCache = new SyntaxTreeCache(host); + var ruleProvider; + var program; + var lastProjectVersion; + var lastTypesRootVersion = 0; + var useCaseSensitivefileNames = host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(); + var cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken()); + var currentDirectory = host.getCurrentDirectory(); + // Check if the localized messages json is set, otherwise query the host for it + if (!ts.localizedDiagnosticMessages && host.getLocalizedDiagnosticMessages) { + ts.localizedDiagnosticMessages = host.getLocalizedDiagnosticMessages(); + } + function log(message) { + if (host.log) { + host.log(message); + } + } + var getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitivefileNames); + function getValidSourceFile(fileName) { + var sourceFile = program.getSourceFile(fileName); + if (!sourceFile) { + throw new Error("Could not find file: '" + fileName + "'."); + } + return sourceFile; + } + function getRuleProvider(options) { + // Ensure rules are initialized and up to date wrt to formatting options + if (!ruleProvider) { + ruleProvider = new ts.formatting.RulesProvider(); + } + ruleProvider.ensureUpToDate(options); + return ruleProvider; + } + function synchronizeHostData() { + // perform fast check if host supports it + if (host.getProjectVersion) { + var hostProjectVersion = host.getProjectVersion(); + if (hostProjectVersion) { + if (lastProjectVersion === hostProjectVersion) { + return; } + lastProjectVersion = hostProjectVersion; } - // If the symbol is an alias, add what it aliases to the list - // import {a} from "mod"; - // export {a} - // If the symbol is an alias to default declaration, add what it aliases to the list - // declare "mod" { export default class B { } } - // import B from "mod"; - //// For export specifiers, the exported name can be referring to a local symbol, e.g.: - //// import {a} from "mod"; - //// export {a as somethingElse} - //// We want the *local* declaration of 'a' as declared in the import, - //// *not* as declared within "mod" (or farther) - var aliasSymbol = getAliasSymbolForPropertyNameSymbol(symbol, location); - if (aliasSymbol) { - result = result.concat(populateSearchSymbolSet(aliasSymbol, location)); + } + var typeRootsVersion = host.getTypeRootsVersion ? host.getTypeRootsVersion() : 0; + if (lastTypesRootVersion !== typeRootsVersion) { + log("TypeRoots version has changed; provide new program"); + program = undefined; + lastTypesRootVersion = typeRootsVersion; + } + // Get a fresh cache of the host information + var hostCache = new HostCache(host, getCanonicalFileName); + // If the program is already up-to-date, we can reuse it + if (programUpToDate()) { + return; + } + // IMPORTANT - It is critical from this moment onward that we do not check + // cancellation tokens. We are about to mutate source files from a previous program + // instance. If we cancel midway through, we may end up in an inconsistent state where + // the program points to old source files that have been invalidated because of + // incremental parsing. + var oldSettings = program && program.getCompilerOptions(); + var newSettings = hostCache.compilationSettings(); + var shouldCreateNewSourceFiles = oldSettings && + (oldSettings.target !== newSettings.target || + oldSettings.module !== newSettings.module || + oldSettings.moduleResolution !== newSettings.moduleResolution || + oldSettings.noResolve !== newSettings.noResolve || + oldSettings.jsx !== newSettings.jsx || + oldSettings.allowJs !== newSettings.allowJs || + oldSettings.disableSizeLimit !== oldSettings.disableSizeLimit || + oldSettings.baseUrl !== newSettings.baseUrl || + !ts.equalOwnProperties(oldSettings.paths, newSettings.paths)); + // Now create a new compiler + var compilerHost = { + getSourceFile: getOrCreateSourceFile, + getSourceFileByPath: getOrCreateSourceFileByPath, + getCancellationToken: function () { return cancellationToken; }, + getCanonicalFileName: getCanonicalFileName, + useCaseSensitiveFileNames: function () { return useCaseSensitivefileNames; }, + getNewLine: function () { return ts.getNewLineOrDefaultFromHost(host); }, + getDefaultLibFileName: function (options) { return host.getDefaultLibFileName(options); }, + writeFile: function (fileName, data, writeByteOrderMark) { }, + getCurrentDirectory: function () { return currentDirectory; }, + fileExists: function (fileName) { + // stub missing host functionality + return hostCache.getOrCreateEntry(fileName) !== undefined; + }, + readFile: function (fileName) { + // stub missing host functionality + var entry = hostCache.getOrCreateEntry(fileName); + return entry && entry.scriptSnapshot.getText(0, entry.scriptSnapshot.getLength()); + }, + directoryExists: function (directoryName) { + return ts.directoryProbablyExists(directoryName, host); + }, + getDirectories: function (path) { + return host.getDirectories ? host.getDirectories(path) : []; } - // If the location is in a context sensitive location (i.e. in an object literal) try - // to get a contextual type for it, and add the property symbol from the contextual - // type to the search set - if (containingObjectLiteralElement) { - ts.forEach(getPropertySymbolsFromContextualType(containingObjectLiteralElement), function (contextualSymbol) { - ts.addRange(result, typeChecker.getRootSymbols(contextualSymbol)); - }); - /* Because in short-hand property assignment, location has two meaning : property name and as value of the property - * When we do findAllReference at the position of the short-hand property assignment, we would want to have references to position of - * property name and variable declaration of the identifier. - * Like in below example, when querying for all references for an identifier 'name', of the property assignment, the language service - * should show both 'name' in 'obj' and 'name' in variable declaration - * const name = "Foo"; - * const obj = { name }; - * In order to do that, we will populate the search set with the value symbol of the identifier as a value of the property assignment - * so that when matching with potential reference symbol, both symbols from property declaration and variable declaration - * will be included correctly. - */ - var shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(location.parent); - if (shorthandValueSymbol) { - result.push(shorthandValueSymbol); + }; + if (host.trace) { + compilerHost.trace = function (message) { return host.trace(message); }; + } + if (host.resolveModuleNames) { + compilerHost.resolveModuleNames = function (moduleNames, containingFile) { return host.resolveModuleNames(moduleNames, containingFile); }; + } + if (host.resolveTypeReferenceDirectives) { + compilerHost.resolveTypeReferenceDirectives = function (typeReferenceDirectiveNames, containingFile) { + return host.resolveTypeReferenceDirectives(typeReferenceDirectiveNames, containingFile); + }; + } + var documentRegistryBucketKey = documentRegistry.getKeyForCompilationSettings(newSettings); + var newProgram = ts.createProgram(hostCache.getRootFileNames(), newSettings, compilerHost, program); + // Release any files we have acquired in the old program but are + // not part of the new program. + if (program) { + var oldSourceFiles = program.getSourceFiles(); + var oldSettingsKey = documentRegistry.getKeyForCompilationSettings(oldSettings); + for (var _i = 0, oldSourceFiles_1 = oldSourceFiles; _i < oldSourceFiles_1.length; _i++) { + var oldSourceFile = oldSourceFiles_1[_i]; + if (!newProgram.getSourceFile(oldSourceFile.fileName) || shouldCreateNewSourceFiles) { + documentRegistry.releaseDocumentWithKey(oldSourceFile.path, oldSettingsKey); } } - // If the symbol.valueDeclaration is a property parameter declaration, - // we should include both parameter declaration symbol and property declaration symbol - // Parameter Declaration symbol is only visible within function scope, so the symbol is stored in constructor.locals. - // Property Declaration symbol is a member of the class, so the symbol is stored in its class Declaration.symbol.members - if (symbol.valueDeclaration && symbol.valueDeclaration.kind === 142 /* Parameter */ && - ts.isParameterPropertyDeclaration(symbol.valueDeclaration)) { - result = result.concat(typeChecker.getSymbolsOfParameterPropertyDeclaration(symbol.valueDeclaration, symbol.name)); - } - // If this is symbol of binding element without propertyName declaration in Object binding pattern - // Include the property in the search - var bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol); - if (bindingElementPropertySymbol) { - result.push(bindingElementPropertySymbol); - } - // If this is a union property, add all the symbols from all its source symbols in all unioned types. - // If the symbol is an instantiation from a another symbol (e.g. widened symbol) , add the root the list - ts.forEach(typeChecker.getRootSymbols(symbol), function (rootSymbol) { - if (rootSymbol !== symbol) { - result.push(rootSymbol); - } - // Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions - if (rootSymbol.parent && rootSymbol.parent.flags & (32 /* Class */ | 64 /* Interface */)) { - getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ ts.createMap()); - } - }); - return result; } - /** - * Find symbol of the given property-name and add the symbol to the given result array - * @param symbol a symbol to start searching for the given propertyName - * @param propertyName a name of property to search for - * @param result an array of symbol of found property symbols - * @param previousIterationSymbolsCache a cache of symbol from previous iterations of calling this function to prevent infinite revisiting of the same symbol. - * The value of previousIterationSymbol is undefined when the function is first called. - */ - function getPropertySymbolsFromBaseTypes(symbol, propertyName, result, previousIterationSymbolsCache) { - if (!symbol) { - return; - } - // If the current symbol is the same as the previous-iteration symbol, we can just return the symbol that has already been visited - // This is particularly important for the following cases, so that we do not infinitely visit the same symbol. - // For example: - // interface C extends C { - // /*findRef*/propName: string; - // } - // The first time getPropertySymbolsFromBaseTypes is called when finding-all-references at propName, - // the symbol argument will be the symbol of an interface "C" and previousIterationSymbol is undefined, - // the function will add any found symbol of the property-name, then its sub-routine will call - // getPropertySymbolsFromBaseTypes again to walk up any base types to prevent revisiting already - // visited symbol, interface "C", the sub-routine will pass the current symbol as previousIterationSymbol. - if (symbol.name in previousIterationSymbolsCache) { - return; - } - if (symbol.flags & (32 /* Class */ | 64 /* Interface */)) { - ts.forEach(symbol.getDeclarations(), function (declaration) { - if (ts.isClassLike(declaration)) { - getPropertySymbolFromTypeReference(ts.getClassExtendsHeritageClauseElement(declaration)); - ts.forEach(ts.getClassImplementsHeritageClauseElements(declaration), getPropertySymbolFromTypeReference); - } - else if (declaration.kind === 222 /* InterfaceDeclaration */) { - ts.forEach(ts.getInterfaceBaseTypeNodes(declaration), getPropertySymbolFromTypeReference); - } - }); + // hostCache is captured in the closure for 'getOrCreateSourceFile' but it should not be used past this point. + // It needs to be cleared to allow all collected snapshots to be released + hostCache = undefined; + program = newProgram; + // Make sure all the nodes in the program are both bound, and have their parent + // pointers set property. + program.getTypeChecker(); + return; + function getOrCreateSourceFile(fileName) { + return getOrCreateSourceFileByPath(fileName, ts.toPath(fileName, currentDirectory, getCanonicalFileName)); + } + function getOrCreateSourceFileByPath(fileName, path) { + ts.Debug.assert(hostCache !== undefined); + // The program is asking for this file, check first if the host can locate it. + // If the host can not locate the file, then it does not exist. return undefined + // to the program to allow reporting of errors for missing files. + var hostFileInformation = hostCache.getOrCreateEntryByPath(fileName, path); + if (!hostFileInformation) { + return undefined; } - return; - function getPropertySymbolFromTypeReference(typeReference) { - if (typeReference) { - var type = typeChecker.getTypeAtLocation(typeReference); - if (type) { - var propertySymbol = typeChecker.getPropertyOfType(type, propertyName); - if (propertySymbol) { - result.push.apply(result, typeChecker.getRootSymbols(propertySymbol)); - } - // Visit the typeReference as well to see if it directly or indirectly use that property - previousIterationSymbolsCache[symbol.name] = symbol; - getPropertySymbolsFromBaseTypes(type.symbol, propertyName, result, previousIterationSymbolsCache); - } + // Check if the language version has changed since we last created a program; if they are the same, + // it is safe to reuse the sourceFiles; if not, then the shape of the AST can change, and the oldSourceFile + // can not be reused. we have to dump all syntax trees and create new ones. + if (!shouldCreateNewSourceFiles) { + // Check if the old program had this file already + var oldSourceFile = program && program.getSourceFileByPath(path); + if (oldSourceFile) { + // We already had a source file for this file name. Go to the registry to + // ensure that we get the right up to date version of it. We need this to + // address the following race-condition. Specifically, say we have the following: + // + // LS1 + // \ + // DocumentRegistry + // / + // LS2 + // + // Each LS has a reference to file 'foo.ts' at version 1. LS2 then updates + // it's version of 'foo.ts' to version 2. This will cause LS2 and the + // DocumentRegistry to have version 2 of the document. HOwever, LS1 will + // have version 1. And *importantly* this source file will be *corrupt*. + // The act of creating version 2 of the file irrevocably damages the version + // 1 file. + // + // So, later when we call into LS1, we need to make sure that it doesn't use + // it's source file any more, and instead defers to DocumentRegistry to get + // either version 1, version 2 (or some other version) depending on what the + // host says should be used. + // We do not support the scenario where a host can modify a registered + // file's script kind, i.e. in one project some file is treated as ".ts" + // and in another as ".js" + ts.Debug.assert(hostFileInformation.scriptKind === oldSourceFile.scriptKind, "Registered script kind (" + oldSourceFile.scriptKind + ") should match new script kind (" + hostFileInformation.scriptKind + ") for file: " + path); + return documentRegistry.updateDocumentWithKey(fileName, path, newSettings, documentRegistryBucketKey, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind); } } + // Could not find this file in the old program, create a new SourceFile for it. + return documentRegistry.acquireDocumentWithKey(fileName, path, newSettings, documentRegistryBucketKey, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind); } - function getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation, searchLocationIsConstructor) { - if (ts.contains(searchSymbols, referenceSymbol)) { - // If we are searching for constructor uses, they must be 'new' expressions. - return (!searchLocationIsConstructor || isNewExpressionTarget(referenceLocation)) && referenceSymbol; - } - // If the reference symbol is an alias, check if what it is aliasing is one of the search - // symbols but by looking up for related symbol of this alias so it can handle multiple level of indirectness. - var aliasSymbol = getAliasSymbolForPropertyNameSymbol(referenceSymbol, referenceLocation); - if (aliasSymbol) { - return getRelatedSymbol(searchSymbols, aliasSymbol, referenceLocation, searchLocationIsConstructor); + function sourceFileUpToDate(sourceFile) { + if (!sourceFile) { + return false; } - // If the reference location is in an object literal, try to get the contextual type for the - // object literal, lookup the property symbol in the contextual type, and use this symbol to - // compare to our searchSymbol - var containingObjectLiteralElement = getContainingObjectLiteralElement(referenceLocation); - if (containingObjectLiteralElement) { - var contextualSymbol = ts.forEach(getPropertySymbolsFromContextualType(containingObjectLiteralElement), function (contextualSymbol) { - return ts.forEach(typeChecker.getRootSymbols(contextualSymbol), function (s) { return searchSymbols.indexOf(s) >= 0 ? s : undefined; }); - }); - if (contextualSymbol) { - return contextualSymbol; - } - // If the reference location is the name of property from object literal destructuring pattern - // Get the property symbol from the object literal's type and look if thats the search symbol - // In below eg. get 'property' from type of elems iterating type - // for ( { property: p2 } of elems) { } - var propertySymbol = getPropertySymbolOfDestructuringAssignment(referenceLocation); - if (propertySymbol && searchSymbols.indexOf(propertySymbol) >= 0) { - return propertySymbol; - } + var path = sourceFile.path || ts.toPath(sourceFile.fileName, currentDirectory, getCanonicalFileName); + return sourceFile.version === hostCache.getVersion(path); + } + function programUpToDate() { + // If we haven't create a program yet, then it is not up-to-date + if (!program) { + return false; } - // If the reference location is the binding element and doesn't have property name - // then include the binding element in the related symbols - // let { a } : { a }; - var bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(referenceSymbol); - if (bindingElementPropertySymbol && searchSymbols.indexOf(bindingElementPropertySymbol) >= 0) { - return bindingElementPropertySymbol; + // If number of files in the program do not match, it is not up-to-date + var rootFileNames = hostCache.getRootFileNames(); + if (program.getSourceFiles().length !== rootFileNames.length) { + return false; } - // Unwrap symbols to get to the root (e.g. transient symbols as a result of widening) - // Or a union property, use its underlying unioned symbols - return ts.forEach(typeChecker.getRootSymbols(referenceSymbol), function (rootSymbol) { - // if it is in the list, then we are done - if (searchSymbols.indexOf(rootSymbol) >= 0) { - return rootSymbol; - } - // Finally, try all properties with the same name in any type the containing type extended or implemented, and - // see if any is in the list - if (rootSymbol.parent && rootSymbol.parent.flags & (32 /* Class */ | 64 /* Interface */)) { - var result_5 = []; - getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result_5, /*previousIterationSymbolsCache*/ ts.createMap()); - return ts.forEach(result_5, function (s) { return searchSymbols.indexOf(s) >= 0 ? s : undefined; }); + // If any file is not up-to-date, then the whole program is not up-to-date + for (var _i = 0, rootFileNames_2 = rootFileNames; _i < rootFileNames_2.length; _i++) { + var fileName = rootFileNames_2[_i]; + if (!sourceFileUpToDate(program.getSourceFile(fileName))) { + return false; } - return undefined; + } + // If the compilation settings do no match, then the program is not up-to-date + return ts.compareDataObjects(program.getCompilerOptions(), hostCache.compilationSettings()); + } + } + function getProgram() { + synchronizeHostData(); + return program; + } + function cleanupSemanticCache() { + // TODO: Should we jettison the program (or it's type checker) here? + } + function dispose() { + if (program) { + ts.forEach(program.getSourceFiles(), function (f) { + return documentRegistry.releaseDocument(f.fileName, program.getCompilerOptions()); }); } - function getNameFromObjectLiteralElement(node) { - if (node.name.kind === 140 /* ComputedPropertyName */) { - var nameExpression = node.name.expression; - // treat computed property names where expression is string/numeric literal as just string/numeric literal - if (ts.isStringOrNumericLiteral(nameExpression.kind)) { - return nameExpression.text; - } - return undefined; - } - return node.name.text; + } + /// Diagnostics + function getSyntacticDiagnostics(fileName) { + synchronizeHostData(); + return program.getSyntacticDiagnostics(getValidSourceFile(fileName), cancellationToken); + } + /** + * getSemanticDiagnostics return array of Diagnostics. If '-d' is not enabled, only report semantic errors + * If '-d' enabled, report both semantic and emitter errors + */ + function getSemanticDiagnostics(fileName) { + synchronizeHostData(); + var targetSourceFile = getValidSourceFile(fileName); + // Only perform the action per file regardless of '-out' flag as LanguageServiceHost is expected to call this function per file. + // Therefore only get diagnostics for given file. + var semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken); + if (!program.getCompilerOptions().declaration) { + return semanticDiagnostics; } - function getPropertySymbolsFromContextualType(node) { - var objectLiteral = node.parent; - var contextualType = typeChecker.getContextualType(objectLiteral); - var name = getNameFromObjectLiteralElement(node); - if (name && contextualType) { - var result_6 = []; - var symbol_2 = contextualType.getProperty(name); - if (symbol_2) { - result_6.push(symbol_2); - } - if (contextualType.flags & 524288 /* Union */) { - ts.forEach(contextualType.types, function (t) { - var symbol = t.getProperty(name); - if (symbol) { - result_6.push(symbol); - } - }); - } - return result_6; - } + // If '-d' is enabled, check for emitter error. One example of emitter error is export class implements non-export interface + var declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile, cancellationToken); + return ts.concatenate(semanticDiagnostics, declarationDiagnostics); + } + function getCompilerOptionsDiagnostics() { + synchronizeHostData(); + return program.getOptionsDiagnostics(cancellationToken).concat(program.getGlobalDiagnostics(cancellationToken)); + } + function getCompletionsAtPosition(fileName, position) { + synchronizeHostData(); + return ts.Completions.getCompletionsAtPosition(host, program.getTypeChecker(), log, program.getCompilerOptions(), getValidSourceFile(fileName), position); + } + function getCompletionEntryDetails(fileName, position, entryName) { + synchronizeHostData(); + return ts.Completions.getCompletionEntryDetails(program.getTypeChecker(), log, program.getCompilerOptions(), getValidSourceFile(fileName), position, entryName); + } + function getCompletionEntrySymbol(fileName, position, entryName) { + synchronizeHostData(); + return ts.Completions.getCompletionEntrySymbol(program.getTypeChecker(), log, program.getCompilerOptions(), getValidSourceFile(fileName), position, entryName); + } + function getQuickInfoAtPosition(fileName, position) { + synchronizeHostData(); + var sourceFile = getValidSourceFile(fileName); + var node = ts.getTouchingPropertyName(sourceFile, position); + if (node === sourceFile) { return undefined; } - /** Given an initial searchMeaning, extracted from a location, widen the search scope based on the declarations - * of the corresponding symbol. e.g. if we are searching for "Foo" in value position, but "Foo" references a class - * then we need to widen the search to include type positions as well. - * On the contrary, if we are searching for "Bar" in type position and we trace bar to an interface, and an uninstantiated - * module, we want to keep the search limited to only types, as the two declarations (interface and uninstantiated module) - * do not intersect in any of the three spaces. - */ - function getIntersectingMeaningFromDeclarations(meaning, declarations) { - if (declarations) { - var lastIterationMeaning = void 0; - do { - // The result is order-sensitive, for instance if initialMeaning === Namespace, and declarations = [class, instantiated module] - // we need to consider both as they initialMeaning intersects with the module in the namespace space, and the module - // intersects with the class in the value space. - // To achieve that we will keep iterating until the result stabilizes. - // Remember the last meaning - lastIterationMeaning = meaning; - for (var _i = 0, declarations_10 = declarations; _i < declarations_10.length; _i++) { - var declaration = declarations_10[_i]; - var declarationMeaning = getMeaningFromDeclaration(declaration); - if (declarationMeaning & meaning) { - meaning |= declarationMeaning; - } + if (ts.isLabelName(node)) { + return undefined; + } + var typeChecker = program.getTypeChecker(); + var symbol = typeChecker.getSymbolAtLocation(node); + if (!symbol || typeChecker.isUnknownSymbol(symbol)) { + // Try getting just type at this position and show + switch (node.kind) { + case 69 /* Identifier */: + case 172 /* PropertyAccessExpression */: + case 139 /* QualifiedName */: + case 97 /* ThisKeyword */: + case 165 /* ThisType */: + case 95 /* SuperKeyword */: + // For the identifiers/this/super etc get the type at position + var type = typeChecker.getTypeAtLocation(node); + if (type) { + return { + kind: ts.ScriptElementKind.unknown, + kindModifiers: ts.ScriptElementKindModifier.none, + textSpan: ts.createTextSpan(node.getStart(), node.getWidth()), + displayParts: ts.typeToDisplayParts(typeChecker, type, ts.getContainerNode(node)), + documentation: type.symbol ? type.symbol.getDocumentationComment() : undefined + }; } - } while (meaning !== lastIterationMeaning); } - return meaning; - } - } - function getReferenceEntryFromNode(node) { - var start = node.getStart(); - var end = node.getEnd(); - if (node.kind === 9 /* StringLiteral */) { - start += 1; - end -= 1; + return undefined; } + var displayPartsDocumentationsAndKind = ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, sourceFile, ts.getContainerNode(node), node); return { - fileName: node.getSourceFile().fileName, - textSpan: ts.createTextSpanFromBounds(start, end), - isWriteAccess: isWriteAccess(node), - isDefinition: ts.isDeclarationName(node) || ts.isLiteralComputedPropertyDeclarationName(node) + kind: displayPartsDocumentationsAndKind.symbolKind, + kindModifiers: ts.SymbolDisplay.getSymbolModifiers(symbol), + textSpan: ts.createTextSpan(node.getStart(), node.getWidth()), + displayParts: displayPartsDocumentationsAndKind.displayParts, + documentation: displayPartsDocumentationsAndKind.documentation }; } - /** A node is considered a writeAccess iff it is a name of a declaration or a target of an assignment */ - function isWriteAccess(node) { - if (node.kind === 69 /* Identifier */ && ts.isDeclarationName(node)) { - return true; + /// Goto definition + function getDefinitionAtPosition(fileName, position) { + synchronizeHostData(); + return ts.GoToDefinition.getDefinitionAtPosition(program, getValidSourceFile(fileName), position); + } + /// Goto implementation + function getImplementationAtPosition(fileName, position) { + synchronizeHostData(); + return ts.GoToImplementation.getImplementationAtPosition(program.getTypeChecker(), cancellationToken, program.getSourceFiles(), ts.getTouchingPropertyName(getValidSourceFile(fileName), position)); + } + function getTypeDefinitionAtPosition(fileName, position) { + synchronizeHostData(); + return ts.GoToDefinition.getTypeDefinitionAtPosition(program.getTypeChecker(), getValidSourceFile(fileName), position); + } + function getOccurrencesAtPosition(fileName, position) { + var results = getOccurrencesAtPositionCore(fileName, position); + if (results) { + var sourceFile_3 = getCanonicalFileName(ts.normalizeSlashes(fileName)); + // Get occurrences only supports reporting occurrences for the file queried. So + // filter down to that list. + results = ts.filter(results, function (r) { return getCanonicalFileName(ts.normalizeSlashes(r.fileName)) === sourceFile_3; }); } - var parent = node.parent; - if (parent) { - if (parent.kind === 186 /* PostfixUnaryExpression */ || parent.kind === 185 /* PrefixUnaryExpression */) { - return true; + return results; + } + function getDocumentHighlights(fileName, position, filesToSearch) { + synchronizeHostData(); + var sourceFilesToSearch = ts.map(filesToSearch, function (f) { return program.getSourceFile(f); }); + var sourceFile = getValidSourceFile(fileName); + return ts.DocumentHighlights.getDocumentHighlights(program.getTypeChecker(), cancellationToken, sourceFile, position, sourceFilesToSearch); + } + /// References and Occurrences + function getOccurrencesAtPositionCore(fileName, position) { + synchronizeHostData(); + return convertDocumentHighlights(getDocumentHighlights(fileName, position, [fileName])); + function convertDocumentHighlights(documentHighlights) { + if (!documentHighlights) { + return undefined; } - else if (parent.kind === 187 /* BinaryExpression */ && parent.left === node) { - var operator = parent.operatorToken.kind; - return 56 /* FirstAssignment */ <= operator && operator <= 68 /* LastAssignment */; + var result = []; + for (var _i = 0, documentHighlights_1 = documentHighlights; _i < documentHighlights_1.length; _i++) { + var entry = documentHighlights_1[_i]; + for (var _a = 0, _b = entry.highlightSpans; _a < _b.length; _a++) { + var highlightSpan = _b[_a]; + result.push({ + fileName: entry.fileName, + textSpan: highlightSpan.textSpan, + isWriteAccess: highlightSpan.kind === ts.HighlightSpanKind.writtenReference, + isDefinition: false + }); + } } + return result; } - return false; + } + function findRenameLocations(fileName, position, findInStrings, findInComments) { + var referencedSymbols = findReferencedSymbols(fileName, position, findInStrings, findInComments); + return ts.FindAllReferences.convertReferences(referencedSymbols); + } + function getReferencesAtPosition(fileName, position) { + var referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings*/ false, /*findInComments*/ false); + return ts.FindAllReferences.convertReferences(referencedSymbols); + } + function findReferences(fileName, position) { + var referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings*/ false, /*findInComments*/ false); + // Only include referenced symbols that have a valid definition. + return ts.filter(referencedSymbols, function (rs) { return !!rs.definition; }); + } + function findReferencedSymbols(fileName, position, findInStrings, findInComments) { + synchronizeHostData(); + return ts.FindAllReferences.findReferencedSymbols(program.getTypeChecker(), cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position, findInStrings, findInComments); } /// NavigateTo - function getNavigateToItems(searchValue, maxResultCount) { + function getNavigateToItems(searchValue, maxResultCount, fileName, excludeDtsFiles) { synchronizeHostData(); - var checker = getProgram().getTypeChecker(); - return ts.NavigateTo.getNavigateToItems(program, checker, cancellationToken, searchValue, maxResultCount); + var sourceFiles = fileName ? [getValidSourceFile(fileName)] : program.getSourceFiles(); + return ts.NavigateTo.getNavigateToItems(sourceFiles, program.getTypeChecker(), cancellationToken, searchValue, maxResultCount, excludeDtsFiles); } - function getEmitOutput(fileName) { + function getEmitOutput(fileName, emitOnlyDtsFiles) { synchronizeHostData(); var sourceFile = getValidSourceFile(fileName); var outputFiles = []; @@ -59418,140 +74451,12 @@ var ts; text: data }); } - var emitOutput = program.emit(sourceFile, writeFile, cancellationToken); + var emitOutput = program.emit(sourceFile, writeFile, cancellationToken, emitOnlyDtsFiles); return { outputFiles: outputFiles, emitSkipped: emitOutput.emitSkipped }; } - function getMeaningFromDeclaration(node) { - switch (node.kind) { - case 142 /* Parameter */: - case 218 /* VariableDeclaration */: - case 169 /* BindingElement */: - case 145 /* PropertyDeclaration */: - case 144 /* PropertySignature */: - case 253 /* PropertyAssignment */: - case 254 /* ShorthandPropertyAssignment */: - case 255 /* EnumMember */: - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - case 148 /* Constructor */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - case 180 /* ArrowFunction */: - case 252 /* CatchClause */: - return 1 /* Value */; - case 141 /* TypeParameter */: - case 222 /* InterfaceDeclaration */: - case 223 /* TypeAliasDeclaration */: - case 159 /* TypeLiteral */: - return 2 /* Type */; - case 221 /* ClassDeclaration */: - case 224 /* EnumDeclaration */: - return 1 /* Value */ | 2 /* Type */; - case 225 /* ModuleDeclaration */: - if (ts.isAmbientModule(node)) { - return 4 /* Namespace */ | 1 /* Value */; - } - else if (ts.getModuleInstanceState(node) === 1 /* Instantiated */) { - return 4 /* Namespace */ | 1 /* Value */; - } - else { - return 4 /* Namespace */; - } - case 233 /* NamedImports */: - case 234 /* ImportSpecifier */: - case 229 /* ImportEqualsDeclaration */: - case 230 /* ImportDeclaration */: - case 235 /* ExportAssignment */: - case 236 /* ExportDeclaration */: - return 1 /* Value */ | 2 /* Type */ | 4 /* Namespace */; - // An external module can be a Value - case 256 /* SourceFile */: - return 4 /* Namespace */ | 1 /* Value */; - } - return 1 /* Value */ | 2 /* Type */ | 4 /* Namespace */; - } - function isTypeReference(node) { - if (ts.isRightSideOfQualifiedNameOrPropertyAccess(node)) { - node = node.parent; - } - return node.parent.kind === 155 /* TypeReference */ || - (node.parent.kind === 194 /* ExpressionWithTypeArguments */ && !ts.isExpressionWithTypeArgumentsInClassExtendsClause(node.parent)) || - (node.kind === 97 /* ThisKeyword */ && !ts.isExpression(node)) || - node.kind === 165 /* ThisType */; - } - function isNamespaceReference(node) { - return isQualifiedNameNamespaceReference(node) || isPropertyAccessNamespaceReference(node); - } - function isPropertyAccessNamespaceReference(node) { - var root = node; - var isLastClause = true; - if (root.parent.kind === 172 /* PropertyAccessExpression */) { - while (root.parent && root.parent.kind === 172 /* PropertyAccessExpression */) { - root = root.parent; - } - isLastClause = root.name === node; - } - if (!isLastClause && root.parent.kind === 194 /* ExpressionWithTypeArguments */ && root.parent.parent.kind === 251 /* HeritageClause */) { - var decl = root.parent.parent.parent; - return (decl.kind === 221 /* ClassDeclaration */ && root.parent.parent.token === 106 /* ImplementsKeyword */) || - (decl.kind === 222 /* InterfaceDeclaration */ && root.parent.parent.token === 83 /* ExtendsKeyword */); - } - return false; - } - function isQualifiedNameNamespaceReference(node) { - var root = node; - var isLastClause = true; - if (root.parent.kind === 139 /* QualifiedName */) { - while (root.parent && root.parent.kind === 139 /* QualifiedName */) { - root = root.parent; - } - isLastClause = root.right === node; - } - return root.parent.kind === 155 /* TypeReference */ && !isLastClause; - } - function isInRightSideOfImport(node) { - while (node.parent.kind === 139 /* QualifiedName */) { - node = node.parent; - } - return ts.isInternalModuleImportEqualsDeclaration(node.parent) && node.parent.moduleReference === node; - } - function getMeaningFromRightHandSideOfImportEquals(node) { - ts.Debug.assert(node.kind === 69 /* Identifier */); - // import a = |b|; // Namespace - // import a = |b.c|; // Value, type, namespace - // import a = |b.c|.d; // Namespace - if (node.parent.kind === 139 /* QualifiedName */ && - node.parent.right === node && - node.parent.parent.kind === 229 /* ImportEqualsDeclaration */) { - return 1 /* Value */ | 2 /* Type */ | 4 /* Namespace */; - } - return 4 /* Namespace */; - } - function getMeaningFromLocation(node) { - if (node.parent.kind === 235 /* ExportAssignment */) { - return 1 /* Value */ | 2 /* Type */ | 4 /* Namespace */; - } - else if (isInRightSideOfImport(node)) { - return getMeaningFromRightHandSideOfImportEquals(node); - } - else if (ts.isDeclarationName(node)) { - return getMeaningFromDeclaration(node.parent); - } - else if (isTypeReference(node)) { - return 2 /* Type */; - } - else if (isNamespaceReference(node)) { - return 4 /* Namespace */; - } - else { - return 1 /* Value */; - } - } // Signature help /** * This is a semantic operation. @@ -59565,6 +74470,9 @@ var ts; function getNonBoundSourceFile(fileName) { return syntaxTreeCache.getCurrentSourceFile(fileName); } + function getSourceFile(fileName) { + return getNonBoundSourceFile(fileName); + } function getNameOrDottedNameSpan(fileName, startPos, endPos) { var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); // Get node at the location @@ -59590,11 +74498,11 @@ var ts; } var nodeForStartPos = node; while (true) { - if (isRightSideOfPropertyAccess(nodeForStartPos) || isRightSideOfQualifiedName(nodeForStartPos)) { + if (ts.isRightSideOfPropertyAccess(nodeForStartPos) || ts.isRightSideOfQualifiedName(nodeForStartPos)) { // If on the span is in right side of the the property or qualified name, return the span from the qualified name pos to end of this node nodeForStartPos = nodeForStartPos.parent; } - else if (isNameOfModuleDeclaration(nodeForStartPos)) { + else if (ts.isNameOfModuleDeclaration(nodeForStartPos)) { // If this is name of a module declarations, check if this is right side of dotted module name // If parent of the module declaration which is parent of this node is module declaration and its body is the module declaration that this node is name of // Then this name is name from dotted module @@ -59625,465 +74533,20 @@ var ts; return ts.NavigationBar.getNavigationBarItems(sourceFile); } function getSemanticClassifications(fileName, span) { - return convertClassifications(getEncodedSemanticClassifications(fileName, span)); - } - function checkForClassificationCancellation(kind) { - // We don't want to actually call back into our host on every node to find out if we've - // been canceled. That would be an enormous amount of chattyness, along with the all - // the overhead of marshalling the data to/from the host. So instead we pick a few - // reasonable node kinds to bother checking on. These node kinds represent high level - // constructs that we would expect to see commonly, but just at a far less frequent - // interval. - // - // For example, in checker.ts (around 750k) we only have around 600 of these constructs. - // That means we're calling back into the host around every 1.2k of the file we process. - // Lib.d.ts has similar numbers. - switch (kind) { - case 225 /* ModuleDeclaration */: - case 221 /* ClassDeclaration */: - case 222 /* InterfaceDeclaration */: - case 220 /* FunctionDeclaration */: - cancellationToken.throwIfCancellationRequested(); - } + synchronizeHostData(); + return ts.getSemanticClassifications(program.getTypeChecker(), cancellationToken, getValidSourceFile(fileName), program.getClassifiableNames(), span); } function getEncodedSemanticClassifications(fileName, span) { synchronizeHostData(); - var sourceFile = getValidSourceFile(fileName); - var typeChecker = program.getTypeChecker(); - var result = []; - var classifiableNames = program.getClassifiableNames(); - processNode(sourceFile); - return { spans: result, endOfLineState: 0 /* None */ }; - function pushClassification(start, length, type) { - result.push(start); - result.push(length); - result.push(type); - } - function classifySymbol(symbol, meaningAtPosition) { - var flags = symbol.getFlags(); - if ((flags & 788448 /* Classifiable */) === 0 /* None */) { - return; - } - if (flags & 32 /* Class */) { - return 11 /* className */; - } - else if (flags & 384 /* Enum */) { - return 12 /* enumName */; - } - else if (flags & 524288 /* TypeAlias */) { - return 16 /* typeAliasName */; - } - else if (meaningAtPosition & 2 /* Type */) { - if (flags & 64 /* Interface */) { - return 13 /* interfaceName */; - } - else if (flags & 262144 /* TypeParameter */) { - return 15 /* typeParameterName */; - } - } - else if (flags & 1536 /* Module */) { - // Only classify a module as such if - // - It appears in a namespace context. - // - There exists a module declaration which actually impacts the value side. - if (meaningAtPosition & 4 /* Namespace */ || - (meaningAtPosition & 1 /* Value */ && hasValueSideModule(symbol))) { - return 14 /* moduleName */; - } - } - return undefined; - /** - * Returns true if there exists a module that introduces entities on the value side. - */ - function hasValueSideModule(symbol) { - return ts.forEach(symbol.declarations, function (declaration) { - return declaration.kind === 225 /* ModuleDeclaration */ && - ts.getModuleInstanceState(declaration) === 1 /* Instantiated */; - }); - } - } - function processNode(node) { - // Only walk into nodes that intersect the requested span. - if (node && ts.textSpanIntersectsWith(span, node.getFullStart(), node.getFullWidth())) { - var kind = node.kind; - checkForClassificationCancellation(kind); - if (kind === 69 /* Identifier */ && !ts.nodeIsMissing(node)) { - var identifier = node; - // Only bother calling into the typechecker if this is an identifier that - // could possibly resolve to a type name. This makes classification run - // in a third of the time it would normally take. - if (classifiableNames[identifier.text]) { - var symbol = typeChecker.getSymbolAtLocation(node); - if (symbol) { - var type = classifySymbol(symbol, getMeaningFromLocation(node)); - if (type) { - pushClassification(node.getStart(), node.getWidth(), type); - } - } - } - } - ts.forEachChild(node, processNode); - } - } - } - function getClassificationTypeName(type) { - switch (type) { - case 1 /* comment */: return ts.ClassificationTypeNames.comment; - case 2 /* identifier */: return ts.ClassificationTypeNames.identifier; - case 3 /* keyword */: return ts.ClassificationTypeNames.keyword; - case 4 /* numericLiteral */: return ts.ClassificationTypeNames.numericLiteral; - case 5 /* operator */: return ts.ClassificationTypeNames.operator; - case 6 /* stringLiteral */: return ts.ClassificationTypeNames.stringLiteral; - case 8 /* whiteSpace */: return ts.ClassificationTypeNames.whiteSpace; - case 9 /* text */: return ts.ClassificationTypeNames.text; - case 10 /* punctuation */: return ts.ClassificationTypeNames.punctuation; - case 11 /* className */: return ts.ClassificationTypeNames.className; - case 12 /* enumName */: return ts.ClassificationTypeNames.enumName; - case 13 /* interfaceName */: return ts.ClassificationTypeNames.interfaceName; - case 14 /* moduleName */: return ts.ClassificationTypeNames.moduleName; - case 15 /* typeParameterName */: return ts.ClassificationTypeNames.typeParameterName; - case 16 /* typeAliasName */: return ts.ClassificationTypeNames.typeAliasName; - case 17 /* parameterName */: return ts.ClassificationTypeNames.parameterName; - case 18 /* docCommentTagName */: return ts.ClassificationTypeNames.docCommentTagName; - case 19 /* jsxOpenTagName */: return ts.ClassificationTypeNames.jsxOpenTagName; - case 20 /* jsxCloseTagName */: return ts.ClassificationTypeNames.jsxCloseTagName; - case 21 /* jsxSelfClosingTagName */: return ts.ClassificationTypeNames.jsxSelfClosingTagName; - case 22 /* jsxAttribute */: return ts.ClassificationTypeNames.jsxAttribute; - case 23 /* jsxText */: return ts.ClassificationTypeNames.jsxText; - case 24 /* jsxAttributeStringLiteralValue */: return ts.ClassificationTypeNames.jsxAttributeStringLiteralValue; - } - } - function convertClassifications(classifications) { - ts.Debug.assert(classifications.spans.length % 3 === 0); - var dense = classifications.spans; - var result = []; - for (var i = 0, n = dense.length; i < n; i += 3) { - result.push({ - textSpan: ts.createTextSpan(dense[i], dense[i + 1]), - classificationType: getClassificationTypeName(dense[i + 2]) - }); - } - return result; + return ts.getEncodedSemanticClassifications(program.getTypeChecker(), cancellationToken, getValidSourceFile(fileName), program.getClassifiableNames(), span); } function getSyntacticClassifications(fileName, span) { - return convertClassifications(getEncodedSyntacticClassifications(fileName, span)); + // doesn't use compiler - no need to synchronize with host + return ts.getSyntacticClassifications(cancellationToken, syntaxTreeCache.getCurrentSourceFile(fileName), span); } function getEncodedSyntacticClassifications(fileName, span) { // doesn't use compiler - no need to synchronize with host - var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - var spanStart = span.start; - var spanLength = span.length; - // Make a scanner we can get trivia from. - var triviaScanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text); - var mergeConflictScanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text); - var result = []; - processElement(sourceFile); - return { spans: result, endOfLineState: 0 /* None */ }; - function pushClassification(start, length, type) { - result.push(start); - result.push(length); - result.push(type); - } - function classifyLeadingTriviaAndGetTokenStart(token) { - triviaScanner.setTextPos(token.pos); - while (true) { - var start = triviaScanner.getTextPos(); - // only bother scanning if we have something that could be trivia. - if (!ts.couldStartTrivia(sourceFile.text, start)) { - return start; - } - var kind = triviaScanner.scan(); - var end = triviaScanner.getTextPos(); - var width = end - start; - // The moment we get something that isn't trivia, then stop processing. - if (!ts.isTrivia(kind)) { - return start; - } - // Don't bother with newlines/whitespace. - if (kind === 4 /* NewLineTrivia */ || kind === 5 /* WhitespaceTrivia */) { - continue; - } - // Only bother with the trivia if it at least intersects the span of interest. - if (ts.isComment(kind)) { - classifyComment(token, kind, start, width); - // Classifying a comment might cause us to reuse the trivia scanner - // (because of jsdoc comments). So after we classify the comment make - // sure we set the scanner position back to where it needs to be. - triviaScanner.setTextPos(end); - continue; - } - if (kind === 7 /* ConflictMarkerTrivia */) { - var text = sourceFile.text; - var ch = text.charCodeAt(start); - // for the <<<<<<< and >>>>>>> markers, we just add them in as comments - // in the classification stream. - if (ch === 60 /* lessThan */ || ch === 62 /* greaterThan */) { - pushClassification(start, width, 1 /* comment */); - continue; - } - // for the ======== add a comment for the first line, and then lex all - // subsequent lines up until the end of the conflict marker. - ts.Debug.assert(ch === 61 /* equals */); - classifyDisabledMergeCode(text, start, end); - } - } - } - function classifyComment(token, kind, start, width) { - if (kind === 3 /* MultiLineCommentTrivia */) { - // See if this is a doc comment. If so, we'll classify certain portions of it - // specially. - var docCommentAndDiagnostics = ts.parseIsolatedJSDocComment(sourceFile.text, start, width); - if (docCommentAndDiagnostics && docCommentAndDiagnostics.jsDocComment) { - docCommentAndDiagnostics.jsDocComment.parent = token; - classifyJSDocComment(docCommentAndDiagnostics.jsDocComment); - return; - } - } - // Simple comment. Just add as is. - pushCommentRange(start, width); - } - function pushCommentRange(start, width) { - pushClassification(start, width, 1 /* comment */); - } - function classifyJSDocComment(docComment) { - var pos = docComment.pos; - for (var _i = 0, _a = docComment.tags; _i < _a.length; _i++) { - var tag = _a[_i]; - // As we walk through each tag, classify the portion of text from the end of - // the last tag (or the start of the entire doc comment) as 'comment'. - if (tag.pos !== pos) { - pushCommentRange(pos, tag.pos - pos); - } - pushClassification(tag.atToken.pos, tag.atToken.end - tag.atToken.pos, 10 /* punctuation */); - pushClassification(tag.tagName.pos, tag.tagName.end - tag.tagName.pos, 18 /* docCommentTagName */); - pos = tag.tagName.end; - switch (tag.kind) { - case 275 /* JSDocParameterTag */: - processJSDocParameterTag(tag); - break; - case 278 /* JSDocTemplateTag */: - processJSDocTemplateTag(tag); - break; - case 277 /* JSDocTypeTag */: - processElement(tag.typeExpression); - break; - case 276 /* JSDocReturnTag */: - processElement(tag.typeExpression); - break; - } - pos = tag.end; - } - if (pos !== docComment.end) { - pushCommentRange(pos, docComment.end - pos); - } - return; - function processJSDocParameterTag(tag) { - if (tag.preParameterName) { - pushCommentRange(pos, tag.preParameterName.pos - pos); - pushClassification(tag.preParameterName.pos, tag.preParameterName.end - tag.preParameterName.pos, 17 /* parameterName */); - pos = tag.preParameterName.end; - } - if (tag.typeExpression) { - pushCommentRange(pos, tag.typeExpression.pos - pos); - processElement(tag.typeExpression); - pos = tag.typeExpression.end; - } - if (tag.postParameterName) { - pushCommentRange(pos, tag.postParameterName.pos - pos); - pushClassification(tag.postParameterName.pos, tag.postParameterName.end - tag.postParameterName.pos, 17 /* parameterName */); - pos = tag.postParameterName.end; - } - } - } - function processJSDocTemplateTag(tag) { - for (var _i = 0, _a = tag.getChildren(); _i < _a.length; _i++) { - var child = _a[_i]; - processElement(child); - } - } - function classifyDisabledMergeCode(text, start, end) { - // Classify the line that the ======= marker is on as a comment. Then just lex - // all further tokens and add them to the result. - var i; - for (i = start; i < end; i++) { - if (ts.isLineBreak(text.charCodeAt(i))) { - break; - } - } - pushClassification(start, i - start, 1 /* comment */); - mergeConflictScanner.setTextPos(i); - while (mergeConflictScanner.getTextPos() < end) { - classifyDisabledCodeToken(); - } - } - function classifyDisabledCodeToken() { - var start = mergeConflictScanner.getTextPos(); - var tokenKind = mergeConflictScanner.scan(); - var end = mergeConflictScanner.getTextPos(); - var type = classifyTokenType(tokenKind); - if (type) { - pushClassification(start, end - start, type); - } - } - /** - * Returns true if node should be treated as classified and no further processing is required. - * False will mean that node is not classified and traverse routine should recurse into node contents. - */ - function tryClassifyNode(node) { - if (ts.isJSDocTag(node)) { - return true; - } - if (ts.nodeIsMissing(node)) { - return true; - } - var classifiedElementName = tryClassifyJsxElementName(node); - if (!ts.isToken(node) && node.kind !== 244 /* JsxText */ && classifiedElementName === undefined) { - return false; - } - var tokenStart = node.kind === 244 /* JsxText */ ? node.pos : classifyLeadingTriviaAndGetTokenStart(node); - var tokenWidth = node.end - tokenStart; - ts.Debug.assert(tokenWidth >= 0); - if (tokenWidth > 0) { - var type = classifiedElementName || classifyTokenType(node.kind, node); - if (type) { - pushClassification(tokenStart, tokenWidth, type); - } - } - return true; - } - function tryClassifyJsxElementName(token) { - switch (token.parent && token.parent.kind) { - case 243 /* JsxOpeningElement */: - if (token.parent.tagName === token) { - return 19 /* jsxOpenTagName */; - } - break; - case 245 /* JsxClosingElement */: - if (token.parent.tagName === token) { - return 20 /* jsxCloseTagName */; - } - break; - case 242 /* JsxSelfClosingElement */: - if (token.parent.tagName === token) { - return 21 /* jsxSelfClosingTagName */; - } - break; - case 246 /* JsxAttribute */: - if (token.parent.name === token) { - return 22 /* jsxAttribute */; - } - break; - } - return undefined; - } - // for accurate classification, the actual token should be passed in. however, for - // cases like 'disabled merge code' classification, we just get the token kind and - // classify based on that instead. - function classifyTokenType(tokenKind, token) { - if (ts.isKeyword(tokenKind)) { - return 3 /* keyword */; - } - // Special case < and > If they appear in a generic context they are punctuation, - // not operators. - if (tokenKind === 25 /* LessThanToken */ || tokenKind === 27 /* GreaterThanToken */) { - // If the node owning the token has a type argument list or type parameter list, then - // we can effectively assume that a '<' and '>' belong to those lists. - if (token && ts.getTypeArgumentOrTypeParameterList(token.parent)) { - return 10 /* punctuation */; - } - } - if (ts.isPunctuation(tokenKind)) { - if (token) { - if (tokenKind === 56 /* EqualsToken */) { - // the '=' in a variable declaration is special cased here. - if (token.parent.kind === 218 /* VariableDeclaration */ || - token.parent.kind === 145 /* PropertyDeclaration */ || - token.parent.kind === 142 /* Parameter */ || - token.parent.kind === 246 /* JsxAttribute */) { - return 5 /* operator */; - } - } - if (token.parent.kind === 187 /* BinaryExpression */ || - token.parent.kind === 185 /* PrefixUnaryExpression */ || - token.parent.kind === 186 /* PostfixUnaryExpression */ || - token.parent.kind === 188 /* ConditionalExpression */) { - return 5 /* operator */; - } - } - return 10 /* punctuation */; - } - else if (tokenKind === 8 /* NumericLiteral */) { - return 4 /* numericLiteral */; - } - else if (tokenKind === 9 /* StringLiteral */) { - return token.parent.kind === 246 /* JsxAttribute */ ? 24 /* jsxAttributeStringLiteralValue */ : 6 /* stringLiteral */; - } - else if (tokenKind === 10 /* RegularExpressionLiteral */) { - // TODO: we should get another classification type for these literals. - return 6 /* stringLiteral */; - } - else if (ts.isTemplateLiteralKind(tokenKind)) { - // TODO (drosen): we should *also* get another classification type for these literals. - return 6 /* stringLiteral */; - } - else if (tokenKind === 244 /* JsxText */) { - return 23 /* jsxText */; - } - else if (tokenKind === 69 /* Identifier */) { - if (token) { - switch (token.parent.kind) { - case 221 /* ClassDeclaration */: - if (token.parent.name === token) { - return 11 /* className */; - } - return; - case 141 /* TypeParameter */: - if (token.parent.name === token) { - return 15 /* typeParameterName */; - } - return; - case 222 /* InterfaceDeclaration */: - if (token.parent.name === token) { - return 13 /* interfaceName */; - } - return; - case 224 /* EnumDeclaration */: - if (token.parent.name === token) { - return 12 /* enumName */; - } - return; - case 225 /* ModuleDeclaration */: - if (token.parent.name === token) { - return 14 /* moduleName */; - } - return; - case 142 /* Parameter */: - if (token.parent.name === token) { - var isThis_1 = token.kind === 69 /* Identifier */ && token.originalKeywordKind === 97 /* ThisKeyword */; - return isThis_1 ? 3 /* keyword */ : 17 /* parameterName */; - } - return; - } - } - return 2 /* identifier */; - } - } - function processElement(element) { - if (!element) { - return; - } - // Ignore nodes that don't intersect the original span to classify. - if (ts.decodedTextSpanIntersectsWith(spanStart, spanLength, element.pos, element.getFullWidth())) { - checkForClassificationCancellation(element.kind); - var children = element.getChildren(sourceFile); - for (var i = 0, n = children.length; i < n; i++) { - var child = children[i]; - if (!tryClassifyNode(child)) { - // Recurse into our child nodes. - processElement(child); - } - } - } - } + return ts.getEncodedSyntacticClassifications(cancellationToken, syntaxTreeCache.getCurrentSourceFile(fileName), span); } function getOutliningSpans(fileName) { // doesn't use compiler - no need to synchronize with host @@ -60134,121 +74597,40 @@ var ts; } function getIndentationAtPosition(fileName, position, editorOptions) { var start = ts.timestamp(); + var settings = toEditorSettings(editorOptions); var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); log("getIndentationAtPosition: getCurrentSourceFile: " + (ts.timestamp() - start)); start = ts.timestamp(); - var result = ts.formatting.SmartIndenter.getIndentation(position, sourceFile, editorOptions); + var result = ts.formatting.SmartIndenter.getIndentation(position, sourceFile, settings); log("getIndentationAtPosition: computeIndentation : " + (ts.timestamp() - start)); return result; } function getFormattingEditsForRange(fileName, start, end, options) { var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - return ts.formatting.formatSelection(start, end, sourceFile, getRuleProvider(options), options); + var settings = toEditorSettings(options); + return ts.formatting.formatSelection(start, end, sourceFile, getRuleProvider(settings), settings); } function getFormattingEditsForDocument(fileName, options) { var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - return ts.formatting.formatDocument(sourceFile, getRuleProvider(options), options); + var settings = toEditorSettings(options); + return ts.formatting.formatDocument(sourceFile, getRuleProvider(settings), settings); } function getFormattingEditsAfterKeystroke(fileName, position, key, options) { var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + var settings = toEditorSettings(options); if (key === "}") { - return ts.formatting.formatOnClosingCurly(position, sourceFile, getRuleProvider(options), options); + return ts.formatting.formatOnClosingCurly(position, sourceFile, getRuleProvider(settings), settings); } else if (key === ";") { - return ts.formatting.formatOnSemicolon(position, sourceFile, getRuleProvider(options), options); + return ts.formatting.formatOnSemicolon(position, sourceFile, getRuleProvider(settings), settings); } else if (key === "\n") { - return ts.formatting.formatOnEnter(position, sourceFile, getRuleProvider(options), options); + return ts.formatting.formatOnEnter(position, sourceFile, getRuleProvider(settings), settings); } return []; } - /** - * Checks if position points to a valid position to add JSDoc comments, and if so, - * returns the appropriate template. Otherwise returns an empty string. - * Valid positions are - * - outside of comments, statements, and expressions, and - * - preceding a: - * - function/constructor/method declaration - * - class declarations - * - variable statements - * - namespace declarations - * - * Hosts should ideally check that: - * - The line is all whitespace up to 'position' before performing the insertion. - * - If the keystroke sequence "/\*\*" induced the call, we also check that the next - * non-whitespace character is '*', which (approximately) indicates whether we added - * the second '*' to complete an existing (JSDoc) comment. - * @param fileName The file in which to perform the check. - * @param position The (character-indexed) position in the file where the check should - * be performed. - */ function getDocCommentTemplateAtPosition(fileName, position) { - var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - // Check if in a context where we don't want to perform any insertion - if (ts.isInString(sourceFile, position) || ts.isInComment(sourceFile, position) || ts.hasDocComment(sourceFile, position)) { - return undefined; - } - var tokenAtPos = ts.getTokenAtPosition(sourceFile, position); - var tokenStart = tokenAtPos.getStart(); - if (!tokenAtPos || tokenStart < position) { - return undefined; - } - // TODO: add support for: - // - enums/enum members - // - interfaces - // - property declarations - // - potentially property assignments - var commentOwner; - findOwner: for (commentOwner = tokenAtPos; commentOwner; commentOwner = commentOwner.parent) { - switch (commentOwner.kind) { - case 220 /* FunctionDeclaration */: - case 147 /* MethodDeclaration */: - case 148 /* Constructor */: - case 221 /* ClassDeclaration */: - case 200 /* VariableStatement */: - break findOwner; - case 256 /* SourceFile */: - return undefined; - case 225 /* ModuleDeclaration */: - // If in walking up the tree, we hit a a nested namespace declaration, - // then we must be somewhere within a dotted namespace name; however we don't - // want to give back a JSDoc template for the 'b' or 'c' in 'namespace a.b.c { }'. - if (commentOwner.parent.kind === 225 /* ModuleDeclaration */) { - return undefined; - } - break findOwner; - } - } - if (!commentOwner || commentOwner.getStart() < position) { - return undefined; - } - var parameters = getParametersForJsDocOwningNode(commentOwner); - var posLineAndChar = sourceFile.getLineAndCharacterOfPosition(position); - var lineStart = sourceFile.getLineStarts()[posLineAndChar.line]; - var indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character); - var newLine = ts.getNewLineOrDefaultFromHost(host); - var docParams = ""; - for (var i = 0, numParams = parameters.length; i < numParams; i++) { - var currentName = parameters[i].name; - var paramName = currentName.kind === 69 /* Identifier */ ? - currentName.text : - "param" + i; - docParams += indentationStr + " * @param " + paramName + newLine; - } - // A doc comment consists of the following - // * The opening comment line - // * the first line (without a param) for the object's untagged info (this is also where the caret ends up) - // * the '@param'-tagged lines - // * TODO: other tags. - // * the closing comment line - // * if the caret was directly in front of the object, then we add an extra line and indentation. - var preamble = "/**" + newLine + - indentationStr + " * "; - var result = preamble + newLine + - docParams + - indentationStr + " */" + - (tokenStart === position ? newLine + indentationStr : ""); - return { newText: result, caretOffset: preamble.length }; + return ts.JsDoc.getDocCommentTemplateAtPosition(ts.getNewLineOrDefaultFromHost(host), syntaxTreeCache.getCurrentSourceFile(fileName), position); } function isValidBraceCompletionAtPosition(fileName, position, openingBrace) { // '<' is currently not supported, figuring out if we're in a Generic Type vs. a comparison is too @@ -60273,46 +74655,6 @@ var ts; } return true; } - function getParametersForJsDocOwningNode(commentOwner) { - if (ts.isFunctionLike(commentOwner)) { - return commentOwner.parameters; - } - if (commentOwner.kind === 200 /* VariableStatement */) { - var varStatement = commentOwner; - var varDeclarations = varStatement.declarationList.declarations; - if (varDeclarations.length === 1 && varDeclarations[0].initializer) { - return getParametersFromRightHandSideOfAssignment(varDeclarations[0].initializer); - } - } - return emptyArray; - } - /** - * Digs into an an initializer or RHS operand of an assignment operation - * to get the parameters of an apt signature corresponding to a - * function expression or a class expression. - * - * @param rightHandSide the expression which may contain an appropriate set of parameters - * @returns the parameters of a signature found on the RHS if one exists; otherwise 'emptyArray'. - */ - function getParametersFromRightHandSideOfAssignment(rightHandSide) { - while (rightHandSide.kind === 178 /* ParenthesizedExpression */) { - rightHandSide = rightHandSide.expression; - } - switch (rightHandSide.kind) { - case 179 /* FunctionExpression */: - case 180 /* ArrowFunction */: - return rightHandSide.parameters; - case 192 /* ClassExpression */: - for (var _i = 0, _a = rightHandSide.members; _i < _a.length; _i++) { - var member = _a[_i]; - if (member.kind === 148 /* Constructor */) { - return member.parameters; - } - } - break; - } - return emptyArray; - } function getTodoComments(fileName, descriptors) { // Note: while getting todo comments seems like a syntactic operation, we actually // treat it as a semantic operation here. This is because we expect our host to call @@ -60354,7 +74696,7 @@ var ts; // OK, we have found a match in the file. This is only an acceptable match if // it is contained within a comment. var token = ts.getTokenAtPosition(sourceFile, matchPosition); - if (!isInsideComment(sourceFile, token, matchPosition)) { + if (!ts.isInsideComment(sourceFile, token, matchPosition)) { continue; } var descriptor = undefined; @@ -60437,104 +74779,10 @@ var ts; (char >= 48 /* _0 */ && char <= 57 /* _9 */); } } - function getStringLiteralTypeForNode(node, typeChecker) { - var searchNode = node.parent.kind === 166 /* LiteralType */ ? node.parent : node; - var type = typeChecker.getTypeAtLocation(searchNode); - if (type && type.flags & 32 /* StringLiteral */) { - return type; - } - return undefined; - } function getRenameInfo(fileName, position) { synchronizeHostData(); - var sourceFile = getValidSourceFile(fileName); - var typeChecker = program.getTypeChecker(); var defaultLibFileName = host.getDefaultLibFileName(host.getCompilationSettings()); - var canonicalDefaultLibName = getCanonicalFileName(ts.normalizePath(defaultLibFileName)); - var node = ts.getTouchingWord(sourceFile, position, /*includeJsDocComment*/ true); - if (node) { - if (node.kind === 69 /* Identifier */ || - node.kind === 9 /* StringLiteral */ || - isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || - isThis(node)) { - var symbol = typeChecker.getSymbolAtLocation(node); - // Only allow a symbol to be renamed if it actually has at least one declaration. - if (symbol) { - var declarations = symbol.getDeclarations(); - if (declarations && declarations.length > 0) { - // Disallow rename for elements that are defined in the standard TypeScript library. - if (ts.forEach(declarations, isDefinedInLibraryFile)) { - return getRenameInfoError(ts.getLocaleSpecificMessage(ts.Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library)); - } - var displayName = ts.stripQuotes(ts.getDeclaredName(typeChecker, symbol, node)); - var kind = getSymbolKind(symbol, node); - if (kind) { - return { - canRename: true, - kind: kind, - displayName: displayName, - localizedErrorMessage: undefined, - fullDisplayName: typeChecker.getFullyQualifiedName(symbol), - kindModifiers: getSymbolModifiers(symbol), - triggerSpan: createTriggerSpanForNode(node, sourceFile) - }; - } - } - } - else if (node.kind === 9 /* StringLiteral */) { - var type = getStringLiteralTypeForNode(node, typeChecker); - if (type) { - if (isDefinedInLibraryFile(node)) { - return getRenameInfoError(ts.getLocaleSpecificMessage(ts.Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library)); - } - else { - var displayName = ts.stripQuotes(type.text); - return { - canRename: true, - kind: ts.ScriptElementKind.variableElement, - displayName: displayName, - localizedErrorMessage: undefined, - fullDisplayName: displayName, - kindModifiers: ts.ScriptElementKindModifier.none, - triggerSpan: createTriggerSpanForNode(node, sourceFile) - }; - } - } - } - } - } - return getRenameInfoError(ts.getLocaleSpecificMessage(ts.Diagnostics.You_cannot_rename_this_element)); - function getRenameInfoError(localizedErrorMessage) { - return { - canRename: false, - localizedErrorMessage: localizedErrorMessage, - displayName: undefined, - fullDisplayName: undefined, - kind: undefined, - kindModifiers: undefined, - triggerSpan: undefined - }; - } - function isDefinedInLibraryFile(declaration) { - if (defaultLibFileName) { - var sourceFile_3 = declaration.getSourceFile(); - var canonicalName = getCanonicalFileName(ts.normalizePath(sourceFile_3.fileName)); - if (canonicalName === canonicalDefaultLibName) { - return true; - } - } - return false; - } - function createTriggerSpanForNode(node, sourceFile) { - var start = node.getStart(sourceFile); - var width = node.getWidth(sourceFile); - if (node.kind === 9 /* StringLiteral */) { - // Exclude the quotes - start += 1; - width -= 2; - } - return ts.createTextSpan(start, width); - } + return ts.Rename.getRenameInfo(program.getTypeChecker(), defaultLibFileName, getCanonicalFileName, getValidSourceFile(fileName), position); } return { dispose: dispose, @@ -60548,9 +74796,11 @@ var ts; getEncodedSemanticClassifications: getEncodedSemanticClassifications, getCompletionsAtPosition: getCompletionsAtPosition, getCompletionEntryDetails: getCompletionEntryDetails, + getCompletionEntrySymbol: getCompletionEntrySymbol, getSignatureHelpItems: getSignatureHelpItems, getQuickInfoAtPosition: getQuickInfoAtPosition, getDefinitionAtPosition: getDefinitionAtPosition, + getImplementationAtPosition: getImplementationAtPosition, getTypeDefinitionAtPosition: getTypeDefinitionAtPosition, getReferencesAtPosition: getReferencesAtPosition, findReferences: findReferences, @@ -60573,18 +74823,11 @@ var ts; isValidBraceCompletionAtPosition: isValidBraceCompletionAtPosition, getEmitOutput: getEmitOutput, getNonBoundSourceFile: getNonBoundSourceFile, + getSourceFile: getSourceFile, getProgram: getProgram }; } ts.createLanguageService = createLanguageService; - function forEachDescendantOfKind(node, kind, action) { - ts.forEachChild(node, function (child) { - if (child.kind === kind) { - action(child); - } - forEachDescendantOfKind(child, kind, action); - }); - } /* @internal */ function getNameTable(sourceFile) { if (!sourceFile.nameTable) { @@ -60632,425 +74875,6 @@ var ts; node.parent.kind === 173 /* ElementAccessExpression */ && node.parent.argumentExpression === node; } - /// Classifier - function createClassifier() { - var scanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ false); - /// We do not have a full parser support to know when we should parse a regex or not - /// If we consider every slash token to be a regex, we could be missing cases like "1/2/3", where - /// we have a series of divide operator. this list allows us to be more accurate by ruling out - /// locations where a regexp cannot exist. - var noRegexTable = []; - noRegexTable[69 /* Identifier */] = true; - noRegexTable[9 /* StringLiteral */] = true; - noRegexTable[8 /* NumericLiteral */] = true; - noRegexTable[10 /* RegularExpressionLiteral */] = true; - noRegexTable[97 /* ThisKeyword */] = true; - noRegexTable[41 /* PlusPlusToken */] = true; - noRegexTable[42 /* MinusMinusToken */] = true; - noRegexTable[18 /* CloseParenToken */] = true; - noRegexTable[20 /* CloseBracketToken */] = true; - noRegexTable[16 /* CloseBraceToken */] = true; - noRegexTable[99 /* TrueKeyword */] = true; - noRegexTable[84 /* FalseKeyword */] = true; - // Just a stack of TemplateHeads and OpenCurlyBraces, used to perform rudimentary (inexact) - // classification on template strings. Because of the context free nature of templates, - // the only precise way to classify a template portion would be by propagating the stack across - // lines, just as we do with the end-of-line state. However, this is a burden for implementers, - // and the behavior is entirely subsumed by the syntactic classifier anyway, so we instead - // flatten any nesting when the template stack is non-empty and encode it in the end-of-line state. - // Situations in which this fails are - // 1) When template strings are nested across different lines: - // `hello ${ `world - // ` }` - // - // Where on the second line, you will get the closing of a template, - // a closing curly, and a new template. - // - // 2) When substitution expressions have curly braces and the curly brace falls on the next line: - // `hello ${ () => { - // return "world" } } ` - // - // Where on the second line, you will get the 'return' keyword, - // a string literal, and a template end consisting of '} } `'. - var templateStack = []; - /** Returns true if 'keyword2' can legally follow 'keyword1' in any language construct. */ - function canFollow(keyword1, keyword2) { - if (ts.isAccessibilityModifier(keyword1)) { - if (keyword2 === 123 /* GetKeyword */ || - keyword2 === 131 /* SetKeyword */ || - keyword2 === 121 /* ConstructorKeyword */ || - keyword2 === 113 /* StaticKeyword */) { - // Allow things like "public get", "public constructor" and "public static". - // These are all legal. - return true; - } - // Any other keyword following "public" is actually an identifier an not a real - // keyword. - return false; - } - // Assume any other keyword combination is legal. This can be refined in the future - // if there are more cases we want the classifier to be better at. - return true; - } - function convertClassifications(classifications, text) { - var entries = []; - var dense = classifications.spans; - var lastEnd = 0; - for (var i = 0, n = dense.length; i < n; i += 3) { - var start = dense[i]; - var length_5 = dense[i + 1]; - var type = dense[i + 2]; - // Make a whitespace entry between the last item and this one. - if (lastEnd >= 0) { - var whitespaceLength_1 = start - lastEnd; - if (whitespaceLength_1 > 0) { - entries.push({ length: whitespaceLength_1, classification: ts.TokenClass.Whitespace }); - } - } - entries.push({ length: length_5, classification: convertClassification(type) }); - lastEnd = start + length_5; - } - var whitespaceLength = text.length - lastEnd; - if (whitespaceLength > 0) { - entries.push({ length: whitespaceLength, classification: ts.TokenClass.Whitespace }); - } - return { entries: entries, finalLexState: classifications.endOfLineState }; - } - function convertClassification(type) { - switch (type) { - case 1 /* comment */: return ts.TokenClass.Comment; - case 3 /* keyword */: return ts.TokenClass.Keyword; - case 4 /* numericLiteral */: return ts.TokenClass.NumberLiteral; - case 5 /* operator */: return ts.TokenClass.Operator; - case 6 /* stringLiteral */: return ts.TokenClass.StringLiteral; - case 8 /* whiteSpace */: return ts.TokenClass.Whitespace; - case 10 /* punctuation */: return ts.TokenClass.Punctuation; - case 2 /* identifier */: - case 11 /* className */: - case 12 /* enumName */: - case 13 /* interfaceName */: - case 14 /* moduleName */: - case 15 /* typeParameterName */: - case 16 /* typeAliasName */: - case 9 /* text */: - case 17 /* parameterName */: - default: - return ts.TokenClass.Identifier; - } - } - function getClassificationsForLine(text, lexState, syntacticClassifierAbsent) { - return convertClassifications(getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent), text); - } - // If there is a syntactic classifier ('syntacticClassifierAbsent' is false), - // we will be more conservative in order to avoid conflicting with the syntactic classifier. - function getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent) { - var offset = 0; - var token = 0 /* Unknown */; - var lastNonTriviaToken = 0 /* Unknown */; - // Empty out the template stack for reuse. - while (templateStack.length > 0) { - templateStack.pop(); - } - // If we're in a string literal, then prepend: "\ - // (and a newline). That way when we lex we'll think we're still in a string literal. - // - // If we're in a multiline comment, then prepend: /* - // (and a newline). That way when we lex we'll think we're still in a multiline comment. - switch (lexState) { - case 3 /* InDoubleQuoteStringLiteral */: - text = "\"\\\n" + text; - offset = 3; - break; - case 2 /* InSingleQuoteStringLiteral */: - text = "'\\\n" + text; - offset = 3; - break; - case 1 /* InMultiLineCommentTrivia */: - text = "/*\n" + text; - offset = 3; - break; - case 4 /* InTemplateHeadOrNoSubstitutionTemplate */: - text = "`\n" + text; - offset = 2; - break; - case 5 /* InTemplateMiddleOrTail */: - text = "}\n" + text; - offset = 2; - // fallthrough - case 6 /* InTemplateSubstitutionPosition */: - templateStack.push(12 /* TemplateHead */); - break; - } - scanner.setText(text); - var result = { - endOfLineState: 0 /* None */, - spans: [] - }; - // We can run into an unfortunate interaction between the lexical and syntactic classifier - // when the user is typing something generic. Consider the case where the user types: - // - // Foo tokens. It's a weak heuristic, but should - // work well enough in practice. - var angleBracketStack = 0; - do { - token = scanner.scan(); - if (!ts.isTrivia(token)) { - if ((token === 39 /* SlashToken */ || token === 61 /* SlashEqualsToken */) && !noRegexTable[lastNonTriviaToken]) { - if (scanner.reScanSlashToken() === 10 /* RegularExpressionLiteral */) { - token = 10 /* RegularExpressionLiteral */; - } - } - else if (lastNonTriviaToken === 21 /* DotToken */ && isKeyword(token)) { - token = 69 /* Identifier */; - } - else if (isKeyword(lastNonTriviaToken) && isKeyword(token) && !canFollow(lastNonTriviaToken, token)) { - // We have two keywords in a row. Only treat the second as a keyword if - // it's a sequence that could legally occur in the language. Otherwise - // treat it as an identifier. This way, if someone writes "private var" - // we recognize that 'var' is actually an identifier here. - token = 69 /* Identifier */; - } - else if (lastNonTriviaToken === 69 /* Identifier */ && - token === 25 /* LessThanToken */) { - // Could be the start of something generic. Keep track of that by bumping - // up the current count of generic contexts we may be in. - angleBracketStack++; - } - else if (token === 27 /* GreaterThanToken */ && angleBracketStack > 0) { - // If we think we're currently in something generic, then mark that that - // generic entity is complete. - angleBracketStack--; - } - else if (token === 117 /* AnyKeyword */ || - token === 132 /* StringKeyword */ || - token === 130 /* NumberKeyword */ || - token === 120 /* BooleanKeyword */ || - token === 133 /* SymbolKeyword */) { - if (angleBracketStack > 0 && !syntacticClassifierAbsent) { - // If it looks like we're could be in something generic, don't classify this - // as a keyword. We may just get overwritten by the syntactic classifier, - // causing a noisy experience for the user. - token = 69 /* Identifier */; - } - } - else if (token === 12 /* TemplateHead */) { - templateStack.push(token); - } - else if (token === 15 /* OpenBraceToken */) { - // If we don't have anything on the template stack, - // then we aren't trying to keep track of a previously scanned template head. - if (templateStack.length > 0) { - templateStack.push(token); - } - } - else if (token === 16 /* CloseBraceToken */) { - // If we don't have anything on the template stack, - // then we aren't trying to keep track of a previously scanned template head. - if (templateStack.length > 0) { - var lastTemplateStackToken = ts.lastOrUndefined(templateStack); - if (lastTemplateStackToken === 12 /* TemplateHead */) { - token = scanner.reScanTemplateToken(); - // Only pop on a TemplateTail; a TemplateMiddle indicates there is more for us. - if (token === 14 /* TemplateTail */) { - templateStack.pop(); - } - else { - ts.Debug.assert(token === 13 /* TemplateMiddle */, "Should have been a template middle. Was " + token); - } - } - else { - ts.Debug.assert(lastTemplateStackToken === 15 /* OpenBraceToken */, "Should have been an open brace. Was: " + token); - templateStack.pop(); - } - } - } - lastNonTriviaToken = token; - } - processToken(); - } while (token !== 1 /* EndOfFileToken */); - return result; - function processToken() { - var start = scanner.getTokenPos(); - var end = scanner.getTextPos(); - addResult(start, end, classFromKind(token)); - if (end >= text.length) { - if (token === 9 /* StringLiteral */) { - // Check to see if we finished up on a multiline string literal. - var tokenText = scanner.getTokenText(); - if (scanner.isUnterminated()) { - var lastCharIndex = tokenText.length - 1; - var numBackslashes = 0; - while (tokenText.charCodeAt(lastCharIndex - numBackslashes) === 92 /* backslash */) { - numBackslashes++; - } - // If we have an odd number of backslashes, then the multiline string is unclosed - if (numBackslashes & 1) { - var quoteChar = tokenText.charCodeAt(0); - result.endOfLineState = quoteChar === 34 /* doubleQuote */ - ? 3 /* InDoubleQuoteStringLiteral */ - : 2 /* InSingleQuoteStringLiteral */; - } - } - } - else if (token === 3 /* MultiLineCommentTrivia */) { - // Check to see if the multiline comment was unclosed. - if (scanner.isUnterminated()) { - result.endOfLineState = 1 /* InMultiLineCommentTrivia */; - } - } - else if (ts.isTemplateLiteralKind(token)) { - if (scanner.isUnterminated()) { - if (token === 14 /* TemplateTail */) { - result.endOfLineState = 5 /* InTemplateMiddleOrTail */; - } - else if (token === 11 /* NoSubstitutionTemplateLiteral */) { - result.endOfLineState = 4 /* InTemplateHeadOrNoSubstitutionTemplate */; - } - else { - ts.Debug.fail("Only 'NoSubstitutionTemplateLiteral's and 'TemplateTail's can be unterminated; got SyntaxKind #" + token); - } - } - } - else if (templateStack.length > 0 && ts.lastOrUndefined(templateStack) === 12 /* TemplateHead */) { - result.endOfLineState = 6 /* InTemplateSubstitutionPosition */; - } - } - } - function addResult(start, end, classification) { - if (classification === 8 /* whiteSpace */) { - // Don't bother with whitespace classifications. They're not needed. - return; - } - if (start === 0 && offset > 0) { - // We're classifying the first token, and this was a case where we prepended - // text. We should consider the start of this token to be at the start of - // the original text. - start += offset; - } - // All our tokens are in relation to the augmented text. Move them back to be - // relative to the original text. - start -= offset; - end -= offset; - var length = end - start; - if (length > 0) { - result.spans.push(start); - result.spans.push(length); - result.spans.push(classification); - } - } - } - function isBinaryExpressionOperatorToken(token) { - switch (token) { - case 37 /* AsteriskToken */: - case 39 /* SlashToken */: - case 40 /* PercentToken */: - case 35 /* PlusToken */: - case 36 /* MinusToken */: - case 43 /* LessThanLessThanToken */: - case 44 /* GreaterThanGreaterThanToken */: - case 45 /* GreaterThanGreaterThanGreaterThanToken */: - case 25 /* LessThanToken */: - case 27 /* GreaterThanToken */: - case 28 /* LessThanEqualsToken */: - case 29 /* GreaterThanEqualsToken */: - case 91 /* InstanceOfKeyword */: - case 90 /* InKeyword */: - case 116 /* AsKeyword */: - case 30 /* EqualsEqualsToken */: - case 31 /* ExclamationEqualsToken */: - case 32 /* EqualsEqualsEqualsToken */: - case 33 /* ExclamationEqualsEqualsToken */: - case 46 /* AmpersandToken */: - case 48 /* CaretToken */: - case 47 /* BarToken */: - case 51 /* AmpersandAmpersandToken */: - case 52 /* BarBarToken */: - case 67 /* BarEqualsToken */: - case 66 /* AmpersandEqualsToken */: - case 68 /* CaretEqualsToken */: - case 63 /* LessThanLessThanEqualsToken */: - case 64 /* GreaterThanGreaterThanEqualsToken */: - case 65 /* GreaterThanGreaterThanGreaterThanEqualsToken */: - case 57 /* PlusEqualsToken */: - case 58 /* MinusEqualsToken */: - case 59 /* AsteriskEqualsToken */: - case 61 /* SlashEqualsToken */: - case 62 /* PercentEqualsToken */: - case 56 /* EqualsToken */: - case 24 /* CommaToken */: - return true; - default: - return false; - } - } - function isPrefixUnaryExpressionOperatorToken(token) { - switch (token) { - case 35 /* PlusToken */: - case 36 /* MinusToken */: - case 50 /* TildeToken */: - case 49 /* ExclamationToken */: - case 41 /* PlusPlusToken */: - case 42 /* MinusMinusToken */: - return true; - default: - return false; - } - } - function isKeyword(token) { - return token >= 70 /* FirstKeyword */ && token <= 138 /* LastKeyword */; - } - function classFromKind(token) { - if (isKeyword(token)) { - return 3 /* keyword */; - } - else if (isBinaryExpressionOperatorToken(token) || isPrefixUnaryExpressionOperatorToken(token)) { - return 5 /* operator */; - } - else if (token >= 15 /* FirstPunctuation */ && token <= 68 /* LastPunctuation */) { - return 10 /* punctuation */; - } - switch (token) { - case 8 /* NumericLiteral */: - return 4 /* numericLiteral */; - case 9 /* StringLiteral */: - return 6 /* stringLiteral */; - case 10 /* RegularExpressionLiteral */: - return 7 /* regularExpressionLiteral */; - case 7 /* ConflictMarkerTrivia */: - case 3 /* MultiLineCommentTrivia */: - case 2 /* SingleLineCommentTrivia */: - return 1 /* comment */; - case 5 /* WhitespaceTrivia */: - case 4 /* NewLineTrivia */: - return 8 /* whiteSpace */; - case 69 /* Identifier */: - default: - if (ts.isTemplateLiteralKind(token)) { - return 6 /* stringLiteral */; - } - return 2 /* identifier */; - } - } - return { - getClassificationsForLine: getClassificationsForLine, - getEncodedLexicalClassifications: getEncodedLexicalClassifications - }; - } - ts.createClassifier = createClassifier; /** * Get the path of the default library files (lib.d.ts) as distributed with the typescript * node package. @@ -61065,15 +74889,7 @@ var ts; } ts.getDefaultLibFilePath = getDefaultLibFilePath; function initializeServices() { - ts.objectAllocator = { - getNodeConstructor: function () { return NodeObject; }, - getTokenConstructor: function () { return TokenObject; }, - getIdentifierConstructor: function () { return IdentifierObject; }, - getSourceFileConstructor: function () { return SourceFileObject; }, - getSymbolConstructor: function () { return SymbolObject; }, - getTypeConstructor: function () { return TypeObject; }, - getSignatureConstructor: function () { return SignatureObject; }, - }; + ts.objectAllocator = getServicesObjectAllocator(); } initializeServices(); })(ts || (ts = {})); @@ -61316,7 +75132,7 @@ var ts; return spanInNode(binaryExpression.left); } } - if (ts.isExpression(node)) { + if (ts.isPartOfExpression(node)) { switch (node.parent.kind) { case 204 /* DoStatement */: // Set span as if on while keyword @@ -61401,7 +75217,7 @@ var ts; // Breakpoint is possible in variableDeclaration only if there is initialization // or its declaration from 'for of' if (variableDeclaration.initializer || - (variableDeclaration.flags & 1 /* Export */) || + ts.hasModifier(variableDeclaration, 1 /* Export */) || variableDeclaration.parent.parent.kind === 208 /* ForOfStatement */) { return textSpanFromVariableDeclaration(variableDeclaration); } @@ -61417,7 +75233,7 @@ var ts; function canHaveSpanInParameterDeclaration(parameter) { // Breakpoint is possible on parameter only if it has initializer, is a rest parameter, or has public or private modifier return !!parameter.initializer || parameter.dotDotDotToken !== undefined || - !!(parameter.flags & 4 /* Public */) || !!(parameter.flags & 8 /* Private */); + ts.hasModifier(parameter, 4 /* Public */ | 8 /* Private */); } function spanInParameterDeclaration(parameter) { if (ts.isBindingPattern(parameter.name)) { @@ -61441,7 +75257,7 @@ var ts; } } function canFunctionHaveSpanInWholeDeclaration(functionDeclaration) { - return !!(functionDeclaration.flags & 1 /* Export */) || + return ts.hasModifier(functionDeclaration, 1 /* Export */) || (functionDeclaration.parent.kind === 221 /* ClassDeclaration */ && functionDeclaration.kind !== 148 /* Constructor */); } function spanInFunctionDeclaration(functionDeclaration) { @@ -61694,7 +75510,7 @@ var ts; // /// /* @internal */ -var debugObjectHost = new Function("return this")(); +var debugObjectHost = (function () { return this; })(); // We need to use 'null' to interface with the managed side. /* tslint:disable:no-null-keyword */ /* tslint:disable:no-in-operator */ @@ -61782,6 +75598,12 @@ var ts; } return this.shimHost.getProjectVersion(); }; + LanguageServiceShimHostAdapter.prototype.getTypeRootsVersion = function () { + if (!this.shimHost.getTypeRootsVersion) { + return 0; + } + return this.shimHost.getTypeRootsVersion(); + }; LanguageServiceShimHostAdapter.prototype.useCaseSensitiveFileNames = function () { return this.shimHost.useCaseSensitiveFileNames ? this.shimHost.useCaseSensitiveFileNames() : false; }; @@ -61838,6 +75660,16 @@ var ts; LanguageServiceShimHostAdapter.prototype.getDefaultLibFileName = function (options) { return this.shimHost.getDefaultLibFileName(JSON.stringify(options)); }; + LanguageServiceShimHostAdapter.prototype.readDirectory = function (path, extensions, exclude, include, depth) { + var pattern = ts.getFileMatcherPatterns(path, extensions, exclude, include, this.shimHost.useCaseSensitiveFileNames(), this.shimHost.getCurrentDirectory()); + return JSON.parse(this.shimHost.readDirectory(path, JSON.stringify(extensions), JSON.stringify(pattern.basePaths), pattern.excludePattern, pattern.includeFilePattern, pattern.includeDirectoryPattern, depth)); + }; + LanguageServiceShimHostAdapter.prototype.readFile = function (path, encoding) { + return this.shimHost.readFile(path, encoding); + }; + LanguageServiceShimHostAdapter.prototype.fileExists = function (path) { + return this.shimHost.fileExists(path); + }; return LanguageServiceShimHostAdapter; }()); ts.LanguageServiceShimHostAdapter = LanguageServiceShimHostAdapter; @@ -62110,6 +75942,15 @@ var ts; var _this = this; return this.forwardJSONCall("getTypeDefinitionAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getTypeDefinitionAtPosition(fileName, position); }); }; + /// GOTO Implementation + /** + * Computes the implementation location of the symbol + * at the requested position. + */ + LanguageServiceShimObject.prototype.getImplementationAtPosition = function (fileName, position) { + var _this = this; + return this.forwardJSONCall("getImplementationAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getImplementationAtPosition(fileName, position); }); + }; LanguageServiceShimObject.prototype.getRenameInfo = function (fileName, position) { var _this = this; return this.forwardJSONCall("getRenameInfo('" + fileName + "', " + position + ")", function () { return _this.languageService.getRenameInfo(fileName, position); }); @@ -62199,9 +76040,9 @@ var ts; }; /// NAVIGATE TO /** Return a list of symbols that are interesting to navigate to */ - LanguageServiceShimObject.prototype.getNavigateToItems = function (searchValue, maxResultCount) { + LanguageServiceShimObject.prototype.getNavigateToItems = function (searchValue, maxResultCount, fileName) { var _this = this; - return this.forwardJSONCall("getNavigateToItems('" + searchValue + "', " + maxResultCount + ")", function () { return _this.languageService.getNavigateToItems(searchValue, maxResultCount); }); + return this.forwardJSONCall("getNavigateToItems('" + searchValue + "', " + maxResultCount + ", " + fileName + ")", function () { return _this.languageService.getNavigateToItems(searchValue, maxResultCount, fileName); }); }; LanguageServiceShimObject.prototype.getNavigationBarItems = function (fileName) { var _this = this; diff --git a/bin/typescript.d.ts b/bin/typescript.d.ts index 8682c71..6abb935 100644 --- a/bin/typescript.d.ts +++ b/bin/typescript.d.ts @@ -14,6 +14,7 @@ declare namespace ts { contains(fileName: Path): boolean; remove(fileName: Path): void; forEachValue(f: (key: Path, v: T) => void): void; + getKeys(): Path[]; clear(): void; } interface TextRange { @@ -308,9 +309,13 @@ declare namespace ts { JSDocUndefinedKeyword = 284, JSDocNeverKeyword = 285, SyntaxList = 286, - Count = 287, + NotEmittedStatement = 287, + PartiallyEmittedExpression = 288, + Count = 289, FirstAssignment = 56, LastAssignment = 68, + FirstCompoundAssignment = 57, + LastCompoundAssignment = 68, FirstReservedWord = 70, LastReservedWord = 105, FirstKeyword = 70, @@ -338,6 +343,39 @@ declare namespace ts { LastJSDocTagNode = 285, } const enum NodeFlags { + None = 0, + Let = 1, + Const = 2, + NestedNamespace = 4, + Synthesized = 8, + Namespace = 16, + ExportContext = 32, + ContainsThis = 64, + HasImplicitReturn = 128, + HasExplicitReturn = 256, + GlobalAugmentation = 512, + HasClassExtends = 1024, + HasDecorators = 2048, + HasParamDecorators = 4096, + HasAsyncFunctions = 8192, + HasJsxSpreadAttributes = 16384, + DisallowInContext = 32768, + YieldContext = 65536, + DecoratorContext = 131072, + AwaitContext = 262144, + ThisNodeHasError = 524288, + JavaScriptFile = 1048576, + ThisNodeOrAnySubNodesHasError = 2097152, + HasAggregatedChildData = 4194304, + BlockScoped = 3, + ReachabilityCheckFlags = 384, + EmitHelperFlags = 31744, + ReachabilityAndEmitFlags = 32128, + ContextFlags = 1540096, + TypeExcludesFlags = 327680, + } + type ModifiersArray = NodeArray; + const enum ModifierFlags { None = 0, Export = 1, Ambient = 2, @@ -349,36 +387,11 @@ declare namespace ts { Abstract = 128, Async = 256, Default = 512, - Let = 1024, Const = 2048, - Namespace = 4096, - ExportContext = 8192, - ContainsThis = 16384, - HasImplicitReturn = 32768, - HasExplicitReturn = 65536, - GlobalAugmentation = 131072, - HasClassExtends = 262144, - HasDecorators = 524288, - HasParamDecorators = 1048576, - HasAsyncFunctions = 2097152, - DisallowInContext = 4194304, - YieldContext = 8388608, - DecoratorContext = 16777216, - AwaitContext = 33554432, - ThisNodeHasError = 67108864, - JavaScriptFile = 134217728, - ThisNodeOrAnySubNodesHasError = 268435456, - HasAggregatedChildData = 536870912, - HasJsxSpreadAttribute = 1073741824, - Modifier = 1023, + HasComputedFlags = 536870912, AccessibilityModifier = 28, ParameterPropertyModifier = 92, - BlockScoped = 3072, - ReachabilityCheckFlags = 98304, - EmitHelperFlags = 3932160, - ReachabilityAndEmitFlags = 4030464, - ContextFlags = 197132288, - TypeExcludesFlags = 41943040, + NonPublicAccessibilityModifier = 24, } const enum JsxFlags { None = 0, @@ -396,31 +409,45 @@ declare namespace ts { interface Node extends TextRange { kind: SyntaxKind; flags: NodeFlags; + modifierFlagsCache?: ModifierFlags; + transformFlags?: TransformFlags; decorators?: NodeArray; modifiers?: ModifiersArray; id?: number; parent?: Node; - jsDocComments?: JSDocComment[]; + original?: Node; + startsOnNewLine?: boolean; + jsDocComments?: JSDoc[]; symbol?: Symbol; locals?: SymbolTable; nextContainer?: Node; localSymbol?: Symbol; flowNode?: FlowNode; + emitNode?: EmitNode; } - interface NodeArray extends Array, TextRange { + interface NodeArray extends Array, TextRange { hasTrailingComma?: boolean; } - interface ModifiersArray extends NodeArray { - flags: NodeFlags; - } interface Token extends Node { __tokenTag: any; } interface Modifier extends Token { } + const enum GeneratedIdentifierKind { + None = 0, + Auto = 1, + Loop = 2, + Unique = 3, + Node = 4, + } interface Identifier extends PrimaryExpression { text: string; originalKeywordKind?: SyntaxKind; + autoGenerateKind?: GeneratedIdentifierKind; + autoGenerateId?: number; + } + interface TransientIdentifier extends Identifier { + resolvedSymbol: Symbol; } interface QualifiedName extends Node { left: EntityName; @@ -457,9 +484,10 @@ declare namespace ts { } interface ConstructSignatureDeclaration extends SignatureDeclaration, TypeElement { } + type BindingName = Identifier | BindingPattern; interface VariableDeclaration extends Declaration { parent?: VariableDeclarationList; - name: Identifier | BindingPattern; + name: BindingName; type?: TypeNode; initializer?: Expression; } @@ -468,7 +496,7 @@ declare namespace ts { } interface ParameterDeclaration extends Declaration { dotDotDotToken?: Node; - name: Identifier | BindingPattern; + name: BindingName; questionToken?: Node; type?: TypeNode; initializer?: Expression; @@ -476,7 +504,7 @@ declare namespace ts { interface BindingElement extends Declaration { propertyName?: PropertyName; dotDotDotToken?: Node; - name: Identifier | BindingPattern; + name: BindingName; initializer?: Expression; } interface PropertySignature extends TypeElement { @@ -495,6 +523,7 @@ declare namespace ts { _objectLiteralBrandBrand: any; name?: PropertyName; } + type ObjectLiteralElementLike = PropertyAssignment | ShorthandPropertyAssignment | MethodDeclaration | AccessorDeclaration; interface PropertyAssignment extends ObjectLiteralElement { _propertyAssignmentBrand: any; name: PropertyName; @@ -519,11 +548,14 @@ declare namespace ts { name: PropertyName; } interface BindingPattern extends Node { - elements: NodeArray; + elements: NodeArray; } interface ObjectBindingPattern extends BindingPattern { + elements: NodeArray; } + type ArrayBindingElement = BindingElement | OmittedExpression; interface ArrayBindingPattern extends BindingPattern { + elements: NodeArray; } /** * Several node kinds share function-like features such as a signature, @@ -617,12 +649,17 @@ declare namespace ts { } interface StringLiteral extends LiteralExpression { _stringLiteralBrand: any; + textSourceNode?: Identifier | StringLiteral; } interface Expression extends Node { _expressionBrand: any; contextualType?: Type; } interface OmittedExpression extends Expression { + _omittedExpressionBrand: any; + } + interface PartiallyEmittedExpression extends LeftHandSideExpression { + expression: Expression; } interface UnaryExpression extends Expression { _unaryExpressionBrand: any; @@ -697,9 +734,14 @@ declare namespace ts { interface LiteralExpression extends LiteralLikeNode, PrimaryExpression { _literalExpressionBrand: any; } + interface NumericLiteral extends LiteralExpression { + _numericLiteralBrand: any; + trailingComment?: string; + } interface TemplateLiteralFragment extends LiteralLikeNode { _templateLiteralFragmentBrand: any; } + type Template = TemplateExpression | LiteralExpression; interface TemplateExpression extends PrimaryExpression { head: TemplateLiteralFragment; templateSpans: NodeArray; @@ -718,8 +760,16 @@ declare namespace ts { interface SpreadElementExpression extends Expression { expression: Expression; } - interface ObjectLiteralExpression extends PrimaryExpression, Declaration { - properties: NodeArray; + /** + * This interface is a base interface for ObjectLiteralExpression and JSXAttributes to extend from. JSXAttributes is similar to + * ObjectLiteralExpression in that it contains array of properties; however, JSXAttributes' properties can only be + * JSXAttribute or JSXSpreadAttribute. ObjectLiteralExpression, on the other hand, can only have properties of type + * ObjectLiteralElement (e.g. PropertyAssignment, ShorthandPropertyAssignment etc.) + **/ + interface ObjectLiteralExpressionBase extends PrimaryExpression, Declaration { + properties: NodeArray; + } + interface ObjectLiteralExpression extends ObjectLiteralExpressionBase { multiLine?: boolean; } type EntityNameExpression = Identifier | PropertyAccessEntityNameExpression; @@ -750,7 +800,7 @@ declare namespace ts { } interface TaggedTemplateExpression extends MemberExpression { tag: LeftHandSideExpression; - template: LiteralExpression | TemplateExpression; + template: Template; } type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator; interface AsExpression extends Expression { @@ -780,9 +830,10 @@ declare namespace ts { _selfClosingElementBrand?: any; } type JsxOpeningLikeElement = JsxSelfClosingElement | JsxOpeningElement; + type JsxAttributeLike = JsxAttribute | JsxSpreadAttribute; interface JsxAttribute extends Node { name: Identifier; - initializer?: Expression; + initializer?: StringLiteral | JsxExpression; } interface JsxSpreadAttribute extends Node { expression: Expression; @@ -800,6 +851,8 @@ declare namespace ts { interface Statement extends Node { _statementBrand: any; } + interface NotEmittedStatement extends Statement { + } interface EmptyStatement extends Statement { } interface DebuggerStatement extends Statement { @@ -810,6 +863,7 @@ declare namespace ts { type BlockLike = SourceFile | Block | ModuleBlock | CaseClause; interface Block extends Statement { statements: NodeArray; + multiLine?: boolean; } interface VariableStatement extends Statement { declarationList: VariableDeclarationList; @@ -831,17 +885,18 @@ declare namespace ts { interface WhileStatement extends IterationStatement { expression: Expression; } + type ForInitializer = VariableDeclarationList | Expression; interface ForStatement extends IterationStatement { - initializer?: VariableDeclarationList | Expression; + initializer?: ForInitializer; condition?: Expression; incrementor?: Expression; } interface ForInStatement extends IterationStatement { - initializer: VariableDeclarationList | Expression; + initializer: ForInitializer; expression: Expression; } interface ForOfStatement extends IterationStatement { - initializer: VariableDeclarationList | Expression; + initializer: ForInitializer; expression: Expression; } interface BreakStatement extends Statement { @@ -927,7 +982,7 @@ declare namespace ts { type: TypeNode; } interface EnumMember extends Declaration { - name: DeclarationName; + name: PropertyName; initializer?: Expression; } interface EnumDeclaration extends DeclarationStatement { @@ -935,6 +990,7 @@ declare namespace ts { members: NodeArray; } type ModuleBody = ModuleBlock | ModuleDeclaration; + type ModuleName = Identifier | StringLiteral; interface ModuleDeclaration extends DeclarationStatement { name: Identifier | LiteralExpression; body?: ModuleBlock | ModuleDeclaration; @@ -942,9 +998,10 @@ declare namespace ts { interface ModuleBlock extends Node, Statement { statements: NodeArray; } + type ModuleReference = EntityName | ExternalModuleReference; interface ImportEqualsDeclaration extends DeclarationStatement { name: Identifier; - moduleReference: EntityName | ExternalModuleReference; + moduleReference: ModuleReference; } interface ExternalModuleReference extends Node { expression?: Expression; @@ -953,9 +1010,10 @@ declare namespace ts { importClause?: ImportClause; moduleSpecifier: Expression; } + type NamedImportBindings = NamespaceImport | NamedImports; interface ImportClause extends Declaration { name?: Identifier; - namedBindings?: NamespaceImport | NamedImports; + namedBindings?: NamedImportBindings; } interface NamespaceImport extends Declaration { name: Identifier; @@ -1023,7 +1081,7 @@ declare namespace ts { type: JSDocType; } interface JSDocRecordType extends JSDocType, TypeLiteralNode { - members: NodeArray; + literal: TypeLiteralNode; } interface JSDocTypeReference extends JSDocType { name: EntityName; @@ -1053,12 +1111,14 @@ declare namespace ts { name: Identifier | LiteralExpression; type?: JSDocType; } - interface JSDocComment extends Node { - tags: NodeArray; + interface JSDoc extends Node { + tags: NodeArray | undefined; + comment: string | undefined; } interface JSDocTag extends Node { atToken: Node; tagName: Identifier; + comment: string | undefined; } interface JSDocTemplateTag extends JSDocTag { typeParameters: NodeArray; @@ -1083,9 +1143,13 @@ declare namespace ts { jsDocTypeTag?: JSDocTypeTag; } interface JSDocParameterTag extends JSDocTag { + /** the parameter name, if provided *before* the type (TypeScript-style) */ preParameterName?: Identifier; typeExpression?: JSDocTypeExpression; + /** the parameter name, if provided *after* the type (JSDoc-standard) */ postParameterName?: Identifier; + /** the parameter name, regardless of the location it was provided */ + parameterName: Identifier; isBracketed: boolean; } const enum FlowFlags { @@ -1174,6 +1238,7 @@ declare namespace ts { imports: LiteralExpression[]; moduleAugmentations: LiteralExpression[]; patternAmbientModules?: PatternAmbientModule[]; + externalHelpersModuleName?: Identifier; } interface ScriptReferenceHost { getCompilerOptions(): CompilerOptions; @@ -1189,6 +1254,7 @@ declare namespace ts { * @param path The path to test. */ fileExists(path: string): boolean; + readFile(path: string): string; } interface WriteFileCallback { (fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void, sourceFiles?: SourceFile[]): void; @@ -1219,7 +1285,7 @@ declare namespace ts { * used for writing the JavaScript and declaration files. Otherwise, the writeFile parameter * will be invoked when writing the JavaScript and declaration files. */ - emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken): EmitResult; + emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean): EmitResult; getOptionsDiagnostics(cancellationToken?: CancellationToken): Diagnostic[]; getGlobalDiagnostics(cancellationToken?: CancellationToken): Diagnostic[]; getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[]; @@ -1231,6 +1297,7 @@ declare namespace ts { getTypeChecker(): TypeChecker; getCommonSourceDirectory(): string; getDiagnosticsProducingTypeChecker(): TypeChecker; + dropDiagnosticsProducingTypeChecker(): void; getClassifiableNames(): Map; getNodeCount(): number; getIdentifierCount(): number; @@ -1322,6 +1389,7 @@ declare namespace ts { getJsxElementAttributesType(elementNode: JsxOpeningLikeElement): Type; getJsxIntrinsicTagNames(): Symbol[]; isOptionalParameter(node: ParameterDeclaration): boolean; + getAmbientModules(): Symbol[]; getDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[]; getGlobalDiagnostics(): Diagnostic[]; getEmitResolver(sourceFile?: SourceFile, cancellationToken?: CancellationToken): EmitResolver; @@ -1369,6 +1437,7 @@ declare namespace ts { UseFullyQualifiedType = 128, InFirstTypeArgument = 256, InTypeAlias = 512, + UseTypeAliasValue = 1024, } const enum SymbolFormatFlags { None = 0, @@ -1411,18 +1480,19 @@ declare namespace ts { enum TypeReferenceSerializationKind { Unknown = 0, TypeWithConstructSignatureAndValue = 1, - VoidType = 2, + VoidNullableOrNeverType = 2, NumberLikeType = 3, StringLikeType = 4, BooleanType = 5, ArrayLikeType = 6, ESSymbolType = 7, - TypeWithCallSignature = 8, - ObjectType = 9, + Promise = 8, + TypeWithCallSignature = 9, + ObjectType = 10, } interface EmitResolver { hasGlobalName(name: string): boolean; - getReferencedExportContainer(node: Identifier): SourceFile | ModuleDeclaration | EnumDeclaration; + getReferencedExportContainer(node: Identifier, prefixLocals?: boolean): SourceFile | ModuleDeclaration | EnumDeclaration; getReferencedImportDeclaration(node: Identifier): Declaration; getReferencedDeclarationWithCollidingName(node: Identifier): Declaration; isDeclarationWithCollidingName(node: Declaration): boolean; @@ -1437,17 +1507,19 @@ declare namespace ts { writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; writeTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; writeBaseConstructorTypeOfClass(node: ClassLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; - isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessibilityResult; + isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, shouldComputeAliasToMarkVisible: boolean): SymbolAccessibilityResult; isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult; getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number; getReferencedValueDeclaration(reference: Identifier): Declaration; - getTypeReferenceSerializationKind(typeName: EntityName): TypeReferenceSerializationKind; + getTypeReferenceSerializationKind(typeName: EntityName, location?: Node): TypeReferenceSerializationKind; isOptionalParameter(node: ParameterDeclaration): boolean; moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean; isArgumentsLocalBinding(node: Identifier): boolean; getExternalModuleFileFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration): SourceFile; getTypeReferenceDirectivesForEntityName(name: EntityNameOrEntityNameExpression): string[]; getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[]; + isLiteralConstDeclaration(node: VariableDeclaration): boolean; + writeLiteralConstValue(node: VariableDeclaration, writer: SymbolWriter): void; } const enum SymbolFlags { None = 0, @@ -1545,7 +1617,8 @@ declare namespace ts { mapper?: TypeMapper; referenced?: boolean; containingType?: UnionOrIntersectionType; - hasCommonType?: boolean; + hasNonUniformType?: boolean; + isPartial?: boolean; isDiscriminantProperty?: boolean; resolvedExports?: SymbolTable; exportsChecked?: boolean; @@ -1585,6 +1658,8 @@ declare namespace ts { BodyScopedClassBinding = 1048576, NeedsLoopOutParameter = 2097152, AssignmentsMarked = 4194304, + ClassWithConstructorReference = 8388608, + ConstructorReferenceInClass = 16777216, } interface NodeLinks { flags?: NodeCheckFlags; @@ -1626,7 +1701,7 @@ declare namespace ts { Anonymous = 2097152, Instantiated = 4194304, ObjectLiteral = 8388608, - FreshObjectLiteral = 16777216, + FreshLiteral = 16777216, ContainsWideningType = 33554432, ContainsObjectLiteral = 67108864, ContainsAnyFunctionType = 134217728, @@ -1634,6 +1709,7 @@ declare namespace ts { ObjectLiteralPatternWithComputedProperties = 536870912, Nullable = 6144, Literal = 480, + StringOrNumberLiteral = 96, DefinitelyFalsy = 7392, PossiblyFalsy = 7406, Intrinsic = 16015, @@ -1665,6 +1741,8 @@ declare namespace ts { } interface LiteralType extends Type { text: string; + freshType?: LiteralType; + regularType?: LiteralType; } interface EnumType extends Type { memberTypes: Map; @@ -1769,10 +1847,11 @@ declare namespace ts { interface TypeInferences { primary: Type[]; secondary: Type[]; + topLevel: boolean; isFixed: boolean; } interface InferenceContext { - typeParameters: TypeParameter[]; + signature: Signature; inferUnionTypes: boolean; inferences: TypeInferences[]; inferredTypes: Type[]; @@ -1844,6 +1923,7 @@ declare namespace ts { experimentalDecorators?: boolean; forceConsistentCasingInFileNames?: boolean; help?: boolean; + importHelpers?: boolean; init?: boolean; inlineSourceMap?: boolean; inlineSources?: boolean; @@ -1965,6 +2045,7 @@ declare namespace ts { raw?: any; errors: Diagnostic[]; wildcardDirectories?: MapLike; + compileOnSave?: boolean; } const enum WatchDirectoryFlags { None = 0, @@ -2166,6 +2247,104 @@ declare namespace ts { * This method is a companion for 'resolveModuleNames' and is used to resolve 'types' references to actual type declaration files */ resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; + getEnvironmentVariable?(name: string): string; + } + const enum TransformFlags { + None = 0, + TypeScript = 1, + ContainsTypeScript = 2, + Jsx = 4, + ContainsJsx = 8, + ES7 = 16, + ContainsES7 = 32, + ES6 = 64, + ContainsES6 = 128, + DestructuringAssignment = 256, + Generator = 512, + ContainsGenerator = 1024, + ContainsDecorators = 2048, + ContainsPropertyInitializer = 4096, + ContainsLexicalThis = 8192, + ContainsCapturedLexicalThis = 16384, + ContainsLexicalThisInComputedPropertyName = 32768, + ContainsDefaultValueAssignments = 65536, + ContainsParameterPropertyAssignments = 131072, + ContainsSpreadElementExpression = 262144, + ContainsComputedPropertyName = 524288, + ContainsBlockScopedBinding = 1048576, + ContainsBindingPattern = 2097152, + ContainsYield = 4194304, + ContainsHoistedDeclarationOrCompletion = 8388608, + HasComputedFlags = 536870912, + AssertTypeScript = 3, + AssertJsx = 12, + AssertES7 = 48, + AssertES6 = 192, + AssertGenerator = 1536, + NodeExcludes = 536871765, + ArrowFunctionExcludes = 550710101, + FunctionExcludes = 550726485, + ConstructorExcludes = 550593365, + MethodOrAccessorExcludes = 550593365, + ClassExcludes = 537590613, + ModuleExcludes = 546335573, + TypeExcludes = -3, + ObjectLiteralExcludes = 537430869, + ArrayLiteralOrCallOrNewExcludes = 537133909, + VariableDeclarationListExcludes = 538968917, + ParameterExcludes = 538968917, + TypeScriptClassSyntaxMask = 137216, + ES6FunctionSyntaxMask = 81920, + } + interface EmitNode { + flags?: EmitFlags; + commentRange?: TextRange; + sourceMapRange?: TextRange; + tokenSourceMapRanges?: Map; + annotatedNodes?: Node[]; + constantValue?: number; + } + const enum EmitFlags { + EmitEmitHelpers = 1, + EmitExportStar = 2, + EmitSuperHelper = 4, + EmitAdvancedSuperHelper = 8, + UMDDefine = 16, + SingleLine = 32, + AdviseOnEmitNode = 64, + NoSubstitution = 128, + CapturesThis = 256, + NoLeadingSourceMap = 512, + NoTrailingSourceMap = 1024, + NoSourceMap = 1536, + NoNestedSourceMaps = 2048, + NoTokenLeadingSourceMaps = 4096, + NoTokenTrailingSourceMaps = 8192, + NoTokenSourceMaps = 12288, + NoLeadingComments = 16384, + NoTrailingComments = 32768, + NoComments = 49152, + NoNestedComments = 65536, + ExportName = 131072, + LocalName = 262144, + Indented = 524288, + NoIndentation = 1048576, + AsyncFunctionBody = 2097152, + ReuseTempVariableScope = 4194304, + CustomPrologue = 8388608, + } + const enum EmitContext { + SourceFile = 0, + Expression = 1, + IdentifierName = 2, + Unspecified = 3, + } + /** Additional context provided to `visitEachChild` */ + interface LexicalEnvironment { + /** Starts a new lexical environment. */ + startLexicalEnvironment(): void; + /** Ends a lexical environment, returning any declarations. */ + endLexicalEnvironment(): Statement[]; } interface TextSpan { start: number; @@ -2260,6 +2439,12 @@ declare namespace ts { * If no such value is found, the callback is applied to each element of array and undefined is returned. */ function forEach(array: T[] | undefined, callback: (element: T, index: number) => U | undefined): U | undefined; + /** + * Iterates through `array` by index and performs the callback on each element of array until the callback + * returns a falsey value, then returns false. + * If no such value is found, the callback is applied to each element of array and `true` is returned. + */ + function every(array: T[], callback: (element: T, index: number) => boolean): boolean; /** Works like Array.prototype.find, returning `undefined` if no element satisfying the predicate is found. */ function find(array: T[], predicate: (element: T, index: number) => boolean): T | undefined; /** @@ -2270,20 +2455,55 @@ declare namespace ts { function contains(array: T[], value: T): boolean; function indexOf(array: T[], value: T): number; function indexOfAnyCharCode(text: string, charCodes: number[], start?: number): number; - function countWhere(array: T[], predicate: (x: T) => boolean): number; + function countWhere(array: T[], predicate: (x: T, i: number) => boolean): number; /** * Filters an array by a predicate function. Returns the same array instance if the predicate is * true for all elements, otherwise returns a new array instance containing the filtered subset. */ + function filter(array: T[], f: (x: T) => x is U): U[]; function filter(array: T[], f: (x: T) => boolean): T[]; function removeWhere(array: T[], f: (x: T) => boolean): boolean; function filterMutate(array: T[], f: (x: T) => boolean): void; - function map(array: T[], f: (x: T) => U): U[]; + function map(array: T[], f: (x: T, i: number) => U): U[]; + /** + * Flattens an array containing a mix of array or non-array elements. + * + * @param array The array to flatten. + */ + function flatten(array: (T | T[])[]): T[]; + /** + * Maps an array. If the mapped value is an array, it is spread into the result. + * + * @param array The array to map. + * @param mapfn The callback used to map the result into one or more values. + */ + function flatMap(array: T[], mapfn: (x: T, i: number) => U | U[]): U[]; + /** + * Computes the first matching span of elements and returns a tuple of the first span + * and the remaining elements. + */ + function span(array: T[], f: (x: T, i: number) => boolean): [T[], T[]]; + /** + * Maps contiguous spans of values with the same key. + * + * @param array The array to map. + * @param keyfn A callback used to select the key for an element. + * @param mapfn A callback used to map a contiguous chunk of values to a single value. + */ + function spanMap(array: T[], keyfn: (x: T, i: number) => K, mapfn: (chunk: T[], key: K, start: number, end: number) => U): U[]; + function mapObject(object: MapLike, f: (key: string, x: T) => [string, U]): MapLike; function concatenate(array1: T[], array2: T[]): T[]; function deduplicate(array: T[], areEqual?: (a: T, b: T) => boolean): T[]; + /** + * Compacts an array, removing any falsey elements. + */ + function compact(array: T[]): T[]; function sum(array: any[], prop: string): number; function addRange(to: T[], from: T[]): void; function rangeEquals(array1: T[], array2: T[], pos: number, end: number): boolean; + function firstOrUndefined(array: T[]): T; + function singleOrUndefined(array: T[]): T; + function singleOrMany(array: T[]): T | T[]; /** * Returns the last element of an array if non-empty, undefined otherwise. */ @@ -2295,11 +2515,11 @@ declare namespace ts { * @param array A sorted array whose first element must be no larger than number * @param number The value to be searched for in the array. */ - function binarySearch(array: number[], value: number): number; - function reduceLeft(array: T[], f: (a: T, x: T) => T): T; - function reduceLeft(array: T[], f: (a: U, x: T) => U, initial: U): U; - function reduceRight(array: T[], f: (a: T, x: T) => T): T; - function reduceRight(array: T[], f: (a: U, x: T) => U, initial: U): U; + function binarySearch(array: T[], value: T, comparer?: (v1: T, v2: T) => number): number; + function reduceLeft(array: T[], f: (memo: U, value: T, i: number) => U, initial: U, start?: number, count?: number): U; + function reduceLeft(array: T[], f: (memo: T, value: T, i: number) => T): T; + function reduceRight(array: T[], f: (memo: U, value: T, i: number) => U, initial: U, start?: number, count?: number): U; + function reduceRight(array: T[], f: (memo: T, value: T, i: number) => T): T; /** * Indicates whether a map-like contains an own property with the specified key. * @@ -2350,6 +2570,9 @@ declare namespace ts { * @param target A map to which properties should be copied. */ function copyProperties(source: Map, target: MapLike): void; + function assign, T2, T3>(t: T1, arg1: T2, arg2: T3): T1 & T2 & T3; + function assign, T2>(t: T1, arg1: T2): T1 & T2; + function assign>(t: T1, ...args: any[]): any; /** * Reduce the properties of a map. * @@ -2391,6 +2614,7 @@ declare namespace ts { */ function arrayToMap(array: T[], makeKey: (value: T) => string): Map; function arrayToMap(array: T[], makeKey: (value: T) => string, makeValue: (value: T) => U): Map; + function isEmpty(map: Map): boolean; function cloneMap(map: Map): Map; function clone(object: T): T; function extend(first: T1, second: T2): T1 & T2; @@ -2399,11 +2623,31 @@ declare namespace ts { * Creates the array if it does not already exist. */ function multiMapAdd(map: Map, key: string, value: V): V[]; + /** + * Removes a value from an array of values associated with the key. + * Does not preserve the order of those values. + * Does nothing if `key` is not in `map`, or `value` is not in `map[key]`. + */ + function multiMapRemove(map: Map, key: string, value: V): void; /** * Tests whether a value is an array. */ function isArray(value: any): value is any[]; function memoize(callback: () => T): () => T; + /** + * 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. + */ + function chain(...args: ((t: T) => (u: U) => U)[]): (t: T) => (u: 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. + */ + function compose(...args: ((t: T) => T)[]): (t: T) => T; let localizedDiagnosticMessages: Map; function getLocaleSpecificMessage(message: DiagnosticMessage): string; function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: any[]): Diagnostic; @@ -2419,12 +2663,19 @@ declare namespace ts { function deduplicateSortedDiagnostics(diagnostics: Diagnostic[]): Diagnostic[]; function normalizeSlashes(path: string): string; function getRootLength(path: string): number; - let directorySeparator: string; + const directorySeparator = "/"; function normalizePath(path: string): string; + /** A path ending with '/' refers to a directory only, never a file. */ + function pathEndsWithDirectorySeparator(path: string): boolean; function getDirectoryPath(path: Path): Path; function getDirectoryPath(path: string): string; function isUrl(path: string): boolean; + function isExternalModuleNameRelative(moduleName: string): boolean; + function getEmitScriptTarget(compilerOptions: CompilerOptions): ScriptTarget; + function getEmitModuleKind(compilerOptions: CompilerOptions): ModuleKind; + function hasZeroOrOneAsteriskCharacter(str: string): boolean; function isRootedDiskPath(path: string): boolean; + function convertToRelativePath(absoluteOrRelativePath: string, basePath: string, getCanonicalFileName: (path: string) => string): string; function getNormalizedPathComponents(path: string, currentDirectory: string): string[]; function getNormalizedAbsolutePath(fileName: string, currentDirectory: string): string; function getNormalizedPathFromPathComponents(pathComponents: string[]): string; @@ -2470,6 +2721,8 @@ declare namespace ts { const supportedTypescriptExtensionsForExtractExtension: string[]; const supportedJavascriptExtensions: string[]; function getSupportedExtensions(options?: CompilerOptions): string[]; + function hasJavaScriptFileExtension(fileName: string): boolean; + function hasTypeScriptFileExtension(fileName: string): boolean; function isSupportedSourceFileName(fileName: string, compilerOptions?: CompilerOptions): boolean; /** * Extension boundaries by priority. Lower numbers indicate higher priorities, and are @@ -2518,12 +2771,29 @@ declare namespace ts { function assert(expression: boolean, message?: string, verboseDebugInfo?: () => string): void; function fail(message?: string): void; } + function getEnvironmentVariable(name: string, host?: CompilerHost): string; /** Remove an item from an array, moving everything to its right one space left. */ function orderedRemoveItemAt(array: T[], index: number): void; function unorderedRemoveItemAt(array: T[], index: number): void; /** Remove the *first* occurrence of `item` from the array. */ function unorderedRemoveItem(array: T[], item: T): void; function createGetCanonicalFileName(useCaseSensitiveFileNames: boolean): (fileName: string) => string; + /** + * patternStrings contains both pattern strings (containing "*") and regular strings. + * Return an exact match if possible, or a pattern match, or undefined. + * (These are verified by verifyCompilerOptions to have 0 or 1 "*" characters.) + */ + function matchPatternOrExact(patternStrings: string[], candidate: string): string | Pattern | undefined; + function patternText({prefix, suffix}: Pattern): string; + /** + * Given that candidate matches pattern, returns the text matching the '*'. + * E.g.: matchedText(tryParsePattern("foo*baz"), "foobarbaz") === "bar" + */ + function matchedText(pattern: Pattern, candidate: string): string; + /** Return the object corresponding to the best pattern to match `candidate`. */ + function findBestPatternMatch(values: T[], getPattern: (value: T) => Pattern, candidate: string): T | undefined; + function tryParsePattern(pattern: string): Pattern | undefined; + function positionIsSynthesized(pos: number): boolean; } declare namespace ts { type FileWatcherCallback = (fileName: string, removed?: boolean) => void; @@ -2556,6 +2826,8 @@ declare namespace ts { getMemoryUsage?(): number; exit(exitCode?: number): void; realpath?(path: string): string; + getEnvironmentVariable(name: string): string; + tryEnableSourceMapsForHost?(): void; } interface FileWatcher { close(): void; @@ -2567,17 +2839,13 @@ declare namespace ts { var sys: System; } declare namespace ts { + const externalHelpersModuleNameText = "tslib"; interface ReferencePathMatchResult { fileReference?: FileReference; diagnosticMessage?: DiagnosticMessage; isNoDefaultLib?: boolean; isTypeReferenceDirective?: boolean; } - interface SynthesizedNode extends Node { - leadingCommentRanges?: CommentRange[]; - trailingCommentRanges?: CommentRange[]; - startsOnNewLine: boolean; - } function getDeclarationOfKind(symbol: Symbol, kind: SyntaxKind): Declaration; interface StringSymbolWriter extends SymbolWriter { string(): string; @@ -2594,7 +2862,7 @@ declare namespace ts { function getSingleLineStringWriter(): StringSymbolWriter; function releaseStringWriter(writer: StringSymbolWriter): void; function getFullWidth(node: Node): number; - function arrayIsEqualTo(array1: T[], array2: T[], equaler?: (a: T, b: T) => boolean): boolean; + function arrayIsEqualTo(array1: ReadonlyArray, array2: ReadonlyArray, equaler?: (a: T, b: T) => boolean): boolean; function hasResolvedModule(sourceFile: SourceFile, moduleNameText: string): boolean; function getResolvedModule(sourceFile: SourceFile, moduleNameText: string): ResolvedModule; function setResolvedModule(sourceFile: SourceFile, moduleNameText: string, resolvedModule: ResolvedModule): void; @@ -2608,6 +2876,7 @@ declare namespace ts { function getStartPositionOfLine(line: number, sourceFile: SourceFile): number; function nodePosToString(node: Node): string; function getStartPosOfNode(node: Node): number; + function isDefined(value: any): boolean; function getEndLinePosition(line: number, sourceFile: SourceFile): number; function nodeIsMissing(node: Node): boolean; function nodeIsPresent(node: Node): boolean; @@ -2618,15 +2887,18 @@ declare namespace ts { function getSourceTextOfNodeFromSourceFile(sourceFile: SourceFile, node: Node, includeTrivia?: boolean): string; function getTextOfNodeFromSourceText(sourceText: string, node: Node): string; function getTextOfNode(node: Node, includeTrivia?: boolean): string; + function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile, languageVersion: ScriptTarget): string; + function isBinaryOrOctalIntegerLiteral(node: LiteralLikeNode, text: string): boolean; function escapeIdentifier(identifier: string): string; function unescapeIdentifier(identifier: string): string; function makeIdentifierFromModuleName(moduleName: string): string; function isBlockOrCatchScoped(declaration: Declaration): boolean; function isAmbientModule(node: Node): boolean; - function isShorthandAmbientModule(node: Node): boolean; + function isShorthandAmbientModuleSymbol(moduleSymbol: Symbol): boolean; function isBlockScopedContainerTopLevel(node: Node): boolean; function isGlobalScopeAugmentation(module: ModuleDeclaration): boolean; function isExternalModuleAugmentation(node: Node): boolean; + function isBlockScope(node: Node, parentNode: Node): boolean; function getEnclosingBlockScopeContainer(node: Node): Node; function isCatchClauseVariableDeclaration(declaration: Declaration): boolean; function declarationNameToString(name: DeclarationName): string; @@ -2637,7 +2909,6 @@ declare namespace ts { function isExternalOrCommonJsModule(file: SourceFile): boolean; function isDeclarationFile(file: SourceFile): boolean; function isConstEnumDeclaration(node: Node): boolean; - function getCombinedNodeFlags(node: Node): NodeFlags; function isConst(node: Node): boolean; function isLet(node: Node): boolean; function isSuperCallExpression(n: Node): boolean; @@ -2649,7 +2920,7 @@ declare namespace ts { let fullTripleSlashReferencePathRegEx: RegExp; let fullTripleSlashReferenceTypeReferenceDirectiveRegEx: RegExp; let fullTripleSlashAMDReferencePathRegEx: RegExp; - function isTypeNode(node: Node): boolean; + function isPartOfTypeNode(node: Node): boolean; function forEachReturnStatement(body: Block, visitor: (stmt: ReturnStatement) => T): T; function forEachYieldExpression(body: Block, visitor: (expr: YieldExpression) => void): void; function isVariableLike(node: Node): node is VariableLikeDeclaration; @@ -2658,7 +2929,7 @@ declare namespace ts { function isFunctionLike(node: Node): node is FunctionLikeDeclaration; function isFunctionLikeKind(kind: SyntaxKind): boolean; function introducesArgumentsExoticObject(node: Node): boolean; - function isIterationStatement(node: Node, lookInLabeledStatements: boolean): boolean; + function isIterationStatement(node: Node, lookInLabeledStatements: boolean): node is IterationStatement; function isFunctionBlock(node: Node): boolean; function isObjectLiteralMethod(node: Node): node is MethodDeclaration; function isIdentifierTypePredicate(predicate: TypePredicate): predicate is IdentifierTypePredicate; @@ -2667,11 +2938,11 @@ declare namespace ts { function getContainingClass(node: Node): ClassLikeDeclaration; function getThisContainer(node: Node, includeArrowFunctions: boolean): Node; /** - * Given an super call\property node returns a closest node where either - * - super call\property is legal in the node and not legal in the parent node the node. + * Given an super call/property node, returns the closest node where + * - a super call/property access is legal in the node and not legal in the parent node the node. * i.e. super call is legal in constructor but not legal in the class body. - * - node is arrow function (so caller might need to call getSuperContainer in case it needs to climb higher) - * - super call\property is definitely illegal in the node (but might be legal in some subnode) + * - the container is an arrow function (so caller might need to call getSuperContainer again in case it needs to climb higher) + * - a super call/property is definitely illegal in the container (but might be legal in some subnode) * i.e. super property access is illegal in function declaration but can be legal in the statement list */ function getSuperContainer(node: Node, stopOnFunctions: boolean): Node; @@ -2679,17 +2950,16 @@ declare namespace ts { /** * Determines whether a node is a property or element access expression for super. */ - function isSuperPropertyOrElementAccess(node: Node): boolean; + function isSuperProperty(node: Node): node is (PropertyAccessExpression | ElementAccessExpression); function getEntityNameFromTypeNode(node: TypeNode): EntityNameOrEntityNameExpression; function isCallLikeExpression(node: Node): node is CallLikeExpression; function getInvokedExpression(node: CallLikeExpression): Expression; function nodeCanBeDecorated(node: Node): boolean; function nodeIsDecorated(node: Node): boolean; - function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression; - function isElementAccessExpression(node: Node): node is ElementAccessExpression; + function nodeOrChildIsDecorated(node: Node): boolean; + function childIsDecorated(node: Node): boolean; function isJSXTagName(node: Node): boolean; - function isExpression(node: Node): boolean; - function isExternalModuleNameRelative(moduleName: string): boolean; + function isPartOfExpression(node: Node): boolean; function isInstantiatedModule(node: ModuleDeclaration, preserveConstEnums: boolean): boolean; function isExternalModuleImportEqualsDeclaration(node: Node): boolean; function getExternalModuleImportEqualsDeclarationExpression(node: Node): Expression; @@ -2710,8 +2980,11 @@ declare namespace ts { function isDeclarationOfFunctionExpression(s: Symbol): boolean; function getSpecialPropertyAssignmentKind(expression: Node): SpecialPropertyAssignmentKind; function getExternalModuleName(node: Node): Expression; + function getNamespaceDeclarationNode(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): NamespaceImport; + function isDefaultImport(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): boolean; function hasQuestionToken(node: Node): boolean; function isJSDocConstructSignature(node: Node): boolean; + function getJSDocComments(node: Node, checkParentVariableStatement: boolean): string[]; function getJSDocTypeTag(node: Node): JSDocTypeTag; function getJSDocReturnTag(node: Node): JSDocReturnTag; function getJSDocTemplateTag(node: Node): JSDocTemplateTag; @@ -2720,16 +2993,9 @@ declare namespace ts { function hasDeclaredRestParameter(s: SignatureDeclaration): boolean; function isRestParameter(node: ParameterDeclaration): boolean; function isDeclaredRestParam(node: ParameterDeclaration): boolean; - function isLiteralKind(kind: SyntaxKind): boolean; - function isTextualLiteralKind(kind: SyntaxKind): boolean; - function isTemplateLiteralKind(kind: SyntaxKind): boolean; - function isBindingPattern(node: Node): node is BindingPattern; function isAssignmentTarget(node: Node): boolean; - function isNodeDescendentOf(node: Node, ancestor: Node): boolean; + function isNodeDescendantOf(node: Node, ancestor: Node): boolean; function isInAmbientContext(node: Node): boolean; - function isDeclaration(node: Node): boolean; - function isStatement(n: Node): boolean; - function isClassElement(n: Node): boolean; function isDeclarationName(name: Node): boolean; function isLiteralComputedPropertyDeclarationName(node: Node): boolean; function isIdentifierName(node: Identifier): boolean; @@ -2770,27 +3036,41 @@ declare namespace ts { function isModifierKind(token: SyntaxKind): boolean; function isParameterDeclaration(node: VariableLikeDeclaration): boolean; function getRootDeclaration(node: Node): Node; - function nodeStartsNewLexicalEnvironment(n: Node): boolean; - /** - * Creates a shallow, memberwise clone of a node. The "kind", "pos", "end", "flags", and "parent" - * properties are excluded by default, and can be provided via the "location", "flags", and - * "parent" parameters. - * @param node The node to clone. - * @param location An optional TextRange to use to supply the new position. - * @param flags The NodeFlags to use for the cloned node. - * @param parent The parent for the new node. + function nodeStartsNewLexicalEnvironment(node: Node): boolean; + function nodeIsSynthesized(node: TextRange): boolean; + function getOriginalNode(node: Node): Node; + /** + * Gets a value indicating whether a node originated in the parse tree. + * + * @param node The node to test. */ - function cloneNode(node: T, location?: TextRange, flags?: NodeFlags, parent?: Node): T; + function isParseTreeNode(node: Node): boolean; /** - * Creates a deep clone of an EntityName, with new parent pointers. - * @param node The EntityName to clone. - * @param parent The parent for the cloned node. + * Gets the original parse tree node for a node. + * + * @param node The original node. + * @returns The original parse tree node if found; otherwise, undefined. */ - function cloneEntityName(node: EntityName, parent?: Node): EntityName; - function isQualifiedName(node: Node): node is QualifiedName; - function nodeIsSynthesized(node: Node): boolean; - function createSynthesizedNode(kind: SyntaxKind, startsOnNewLine?: boolean): Node; - function createSynthesizedNodeArray(): NodeArray; + function getParseTreeNode(node: Node): Node; + /** + * Gets the original parse tree node for a node. + * + * @param node The original node. + * @param nodeTest A callback used to ensure the correct type of parse tree node is returned. + * @returns The original parse tree node if found; otherwise, undefined. + */ + function getParseTreeNode(node: Node, nodeTest?: (node: Node) => node is T): T; + function getOriginalSourceFiles(sourceFiles: SourceFile[]): SourceFile[]; + function getOriginalNodeId(node: Node): number; + const enum Associativity { + Left = 0, + Right = 1, + } + function getExpressionAssociativity(expression: Expression): Associativity; + function getOperatorAssociativity(kind: SyntaxKind, operator: SyntaxKind, hasArguments?: boolean): Associativity; + function getExpressionPrecedence(expression: Expression): 0 | 1 | -1 | 2 | 4 | 3 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5; + function getOperator(expression: Expression): SyntaxKind; + function getOperatorPrecedence(nodeKind: SyntaxKind, operatorKind: SyntaxKind, hasArguments?: boolean): 0 | 1 | -1 | 2 | 4 | 3 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5; function createDiagnosticCollection(): DiagnosticCollection; /** * Based heavily on the abstract 'Quote'/'QuoteJSONString' operation from ECMA-262 (24.3.2.2), @@ -2813,60 +3093,98 @@ declare namespace ts { getLine(): number; getColumn(): number; getIndent(): number; + isAtStartOfLine(): boolean; reset(): void; } function getIndentString(level: number): string; function getIndentSize(): number; function createTextWriter(newLine: String): EmitTextWriter; + function getResolvedExternalModuleName(host: EmitHost, file: SourceFile): string; + function getExternalModuleNameFromDeclaration(host: EmitHost, resolver: EmitResolver, declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration): string; /** * Resolves a local path to a path which is absolute to the base of the emit */ function getExternalModuleNameFromPath(host: EmitHost, fileName: string): string; function getOwnEmitOutputFilePath(sourceFile: SourceFile, host: EmitHost, extension: string): string; function getDeclarationEmitOutputFilePath(sourceFile: SourceFile, host: EmitHost): string; - function getEmitScriptTarget(compilerOptions: CompilerOptions): ScriptTarget; - function getEmitModuleKind(compilerOptions: CompilerOptions): ModuleKind; interface EmitFileNames { jsFilePath: string; sourceMapFilePath: string; declarationFilePath: string; } - function forEachExpectedEmitFile(host: EmitHost, action: (emitFileNames: EmitFileNames, sourceFiles: SourceFile[], isBundledEmit: boolean) => void, targetSourceFile?: SourceFile): void; + /** + * Gets the source files that are expected to have an emit output. + * + * Originally part of `forEachExpectedEmitFile`, this functionality was extracted to support + * transformations. + * + * @param host An EmitHost. + * @param targetSourceFile An optional target source file to emit. + */ + function getSourceFilesToEmit(host: EmitHost, targetSourceFile?: SourceFile): SourceFile[]; + /** + * Iterates over each source file to emit. The source files are expected to have been + * transformed for use by the pretty printer. + * + * Originally part of `forEachExpectedEmitFile`, this functionality was extracted to support + * transformations. + * + * @param host An EmitHost. + * @param sourceFiles The transformed source files to emit. + * @param action The action to execute. + */ + function forEachTransformedEmitFile(host: EmitHost, sourceFiles: SourceFile[], action: (jsFilePath: string, sourceMapFilePath: string, declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) => void, emitOnlyDtsFiles?: boolean): void; + /** + * Iterates over the source files that are expected to have an emit output. This function + * is used by the legacy emitter and the declaration emitter and should not be used by + * the tree transforming emitter. + * + * @param host An EmitHost. + * @param action The action to execute. + * @param targetSourceFile An optional target source file to emit. + */ + function forEachExpectedEmitFile(host: EmitHost, action: (emitFileNames: EmitFileNames, sourceFiles: SourceFile[], isBundledEmit: boolean, emitOnlyDtsFiles: boolean) => void, targetSourceFile?: SourceFile, emitOnlyDtsFiles?: boolean): void; function getSourceFilePathInNewDir(sourceFile: SourceFile, host: EmitHost, newDirPath: string): string; function writeFile(host: EmitHost, diagnostics: DiagnosticCollection, fileName: string, data: string, writeByteOrderMark: boolean, sourceFiles?: SourceFile[]): void; function getLineOfLocalPosition(currentSourceFile: SourceFile, pos: number): number; function getLineOfLocalPositionFromLineMap(lineMap: number[], pos: number): number; function getFirstConstructorWithBody(node: ClassLikeDeclaration): ConstructorDeclaration; function getSetAccessorTypeAnnotationNode(accessor: AccessorDeclaration): TypeNode; - function getAllAccessorDeclarations(declarations: NodeArray, accessor: AccessorDeclaration): { + interface AllAccessorDeclarations { firstAccessor: AccessorDeclaration; secondAccessor: AccessorDeclaration; getAccessor: AccessorDeclaration; setAccessor: AccessorDeclaration; - }; + } + function getAllAccessorDeclarations(declarations: NodeArray, accessor: AccessorDeclaration): AllAccessorDeclarations; function emitNewLineBeforeLeadingComments(lineMap: number[], writer: EmitTextWriter, node: TextRange, leadingComments: CommentRange[]): void; - function emitComments(text: string, lineMap: number[], writer: EmitTextWriter, comments: CommentRange[], trailingSeparator: boolean, newLine: string, writeComment: (text: string, lineMap: number[], writer: EmitTextWriter, comment: CommentRange, newLine: string) => void): void; + function emitNewLineBeforeLeadingCommentsOfPosition(lineMap: number[], writer: EmitTextWriter, pos: number, leadingComments: CommentRange[]): void; + function emitNewLineBeforeLeadingCommentOfPosition(lineMap: number[], writer: EmitTextWriter, pos: number, commentPos: number): void; + function emitComments(text: string, lineMap: number[], writer: EmitTextWriter, comments: CommentRange[], leadingSeparator: boolean, trailingSeparator: boolean, newLine: string, writeComment: (text: string, lineMap: number[], writer: EmitTextWriter, commentPos: number, commentEnd: number, newLine: string) => void): void; /** * Detached comment is a comment at the top of file or function body that is separated from * the next statement by space. */ - function emitDetachedComments(text: string, lineMap: number[], writer: EmitTextWriter, writeComment: (text: string, lineMap: number[], writer: EmitTextWriter, comment: CommentRange, newLine: string) => void, node: TextRange, newLine: string, removeComments: boolean): { + function emitDetachedComments(text: string, lineMap: number[], writer: EmitTextWriter, writeComment: (text: string, lineMap: number[], writer: EmitTextWriter, commentPos: number, commentEnd: number, newLine: string) => void, node: TextRange, newLine: string, removeComments: boolean): { nodePos: number; detachedCommentEndPos: number; }; - function writeCommentRange(text: string, lineMap: number[], writer: EmitTextWriter, comment: CommentRange, newLine: string): void; - function modifierToFlag(token: SyntaxKind): NodeFlags; - function isLeftHandSideExpression(expr: Expression): boolean; + function writeCommentRange(text: string, lineMap: number[], writer: EmitTextWriter, commentPos: number, commentEnd: number, newLine: string): void; + function hasModifiers(node: Node): boolean; + function hasModifier(node: Node, flags: ModifierFlags): boolean; + function getModifierFlags(node: Node): ModifierFlags; + function modifierToFlag(token: SyntaxKind): ModifierFlags; + function isLogicalOperator(token: SyntaxKind): boolean; function isAssignmentOperator(token: SyntaxKind): boolean; /** Get `C` given `N` if `N` is in the position `class C extends N` where `N` is an ExpressionWithTypeArguments. */ function tryGetClassExtendingExpressionWithTypeArguments(node: Node): ClassLikeDeclaration | undefined; + function isDestructuringAssignment(node: Node): node is BinaryExpression; + function isSupportedExpressionWithTypeArguments(node: ExpressionWithTypeArguments): boolean; function isExpressionWithTypeArgumentsInClassExtendsClause(node: Node): boolean; function isEntityNameExpression(node: Expression): node is EntityNameExpression; function isRightSideOfQualifiedNameOrPropertyAccess(node: Node): boolean; function isEmptyObjectLiteralOrArrayLiteral(expression: Node): boolean; function getLocalSymbolForExportDefault(symbol: Symbol): Symbol; - function hasJavaScriptFileExtension(fileName: string): boolean; - function hasTypeScriptFileExtension(fileName: string): boolean; /** Return ".ts", ".d.ts", or ".tsx", if that is the extension. */ function tryExtractTypeScriptExtension(fileName: string): string | undefined; /** @@ -2878,8 +3196,189 @@ declare namespace ts { * Converts a string to a base-64 encoded ASCII string. */ function convertToBase64(input: string): string; - function convertToRelativePath(absoluteOrRelativePath: string, basePath: string, getCanonicalFileName: (path: string) => string): string; function getNewLineCharacter(options: CompilerOptions): string; + /** + * Tests whether a node and its subtree is simple enough to have its position + * information ignored when emitting source maps in a destructuring assignment. + * + * @param node The expression to test. + */ + function isSimpleExpression(node: Expression): boolean; + function formatSyntaxKind(kind: SyntaxKind): string; + /** + * Increases (or decreases) a position by the provided amount. + * + * @param pos The position. + * @param value The delta. + */ + function movePos(pos: number, value: number): number; + /** + * Creates a new TextRange from the provided pos and end. + * + * @param pos The start position. + * @param end The end position. + */ + function createRange(pos: number, end: number): TextRange; + /** + * Creates a new TextRange from a provided range with a new end position. + * + * @param range A TextRange. + * @param end The new end position. + */ + function moveRangeEnd(range: TextRange, end: number): TextRange; + /** + * Creates a new TextRange from a provided range with a new start position. + * + * @param range A TextRange. + * @param pos The new Start position. + */ + function moveRangePos(range: TextRange, pos: number): TextRange; + /** + * Moves the start position of a range past any decorators. + */ + function moveRangePastDecorators(node: Node): TextRange; + /** + * Moves the start position of a range past any decorators or modifiers. + */ + function moveRangePastModifiers(node: Node): TextRange; + /** + * Determines whether a TextRange has the same start and end positions. + * + * @param range A TextRange. + */ + function isCollapsedRange(range: TextRange): boolean; + /** + * Creates a new TextRange from a provided range with its end position collapsed to its + * start position. + * + * @param range A TextRange. + */ + function collapseRangeToStart(range: TextRange): TextRange; + /** + * Creates a new TextRange from a provided range with its start position collapsed to its + * end position. + * + * @param range A TextRange. + */ + function collapseRangeToEnd(range: TextRange): TextRange; + /** + * Creates a new TextRange for a token at the provides start position. + * + * @param pos The start position. + * @param token The token. + */ + function createTokenRange(pos: number, token: SyntaxKind): TextRange; + function rangeIsOnSingleLine(range: TextRange, sourceFile: SourceFile): boolean; + function rangeStartPositionsAreOnSameLine(range1: TextRange, range2: TextRange, sourceFile: SourceFile): boolean; + function rangeEndPositionsAreOnSameLine(range1: TextRange, range2: TextRange, sourceFile: SourceFile): boolean; + function rangeStartIsOnSameLineAsRangeEnd(range1: TextRange, range2: TextRange, sourceFile: SourceFile): boolean; + function rangeEndIsOnSameLineAsRangeStart(range1: TextRange, range2: TextRange, sourceFile: SourceFile): boolean; + function positionsAreOnSameLine(pos1: number, pos2: number, sourceFile: SourceFile): boolean; + function getStartPositionOfRange(range: TextRange, sourceFile: SourceFile): number; + function collectExternalModuleInfo(sourceFile: SourceFile, resolver: EmitResolver): { + externalImports: (ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration)[]; + exportSpecifiers: Map; + exportEquals: ExportAssignment; + hasExportStarsToExportValues: boolean; + }; + function getInitializedVariables(node: VariableDeclarationList): VariableDeclaration[]; + /** + * Gets a value indicating whether a node is merged with a class declaration in the same scope. + */ + function isMergedWithClass(node: Node): boolean; + /** + * Gets a value indicating whether a node is the first declaration of its kind. + * + * @param node A Declaration node. + * @param kind The SyntaxKind to find among related declarations. + */ + function isFirstDeclarationOfKind(node: Node, kind: SyntaxKind): boolean; + function isNodeArray(array: T[]): array is NodeArray; + function isNoSubstitutionTemplateLiteral(node: Node): node is LiteralExpression; + function isLiteralKind(kind: SyntaxKind): boolean; + function isTextualLiteralKind(kind: SyntaxKind): boolean; + function isLiteralExpression(node: Node): node is LiteralExpression; + function isTemplateLiteralKind(kind: SyntaxKind): boolean; + function isTemplateLiteralFragment(node: Node): node is TemplateLiteralFragment; + function isIdentifier(node: Node): node is Identifier; + function isGeneratedIdentifier(node: Node): boolean; + function isModifier(node: Node): node is Modifier; + function isQualifiedName(node: Node): node is QualifiedName; + function isComputedPropertyName(node: Node): node is ComputedPropertyName; + function isEntityName(node: Node): node is EntityName; + function isPropertyName(node: Node): node is PropertyName; + function isModuleName(node: Node): node is ModuleName; + function isBindingName(node: Node): node is BindingName; + function isTypeParameter(node: Node): node is TypeParameterDeclaration; + function isParameter(node: Node): node is ParameterDeclaration; + function isDecorator(node: Node): node is Decorator; + function isMethodDeclaration(node: Node): node is MethodDeclaration; + function isClassElement(node: Node): node is ClassElement; + function isObjectLiteralElementLike(node: Node): node is ObjectLiteralElementLike; + /** + * Node test that determines whether a node is a valid type node. + * This differs from the `isPartOfTypeNode` function which determines whether a node is *part* + * of a TypeNode. + */ + function isTypeNode(node: Node): node is TypeNode; + function isBindingPattern(node: Node): node is BindingPattern; + function isBindingElement(node: Node): node is BindingElement; + function isArrayBindingElement(node: Node): node is ArrayBindingElement; + function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression; + function isElementAccessExpression(node: Node): node is ElementAccessExpression; + function isBinaryExpression(node: Node): node is BinaryExpression; + function isConditionalExpression(node: Node): node is ConditionalExpression; + function isCallExpression(node: Node): node is CallExpression; + function isTemplate(node: Node): node is Template; + function isSpreadElementExpression(node: Node): node is SpreadElementExpression; + function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments; + function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression; + function isUnaryExpression(node: Node): node is UnaryExpression; + function isExpression(node: Node): node is Expression; + function isAssertionExpression(node: Node): node is AssertionExpression; + function isPartiallyEmittedExpression(node: Node): node is PartiallyEmittedExpression; + function isNotEmittedStatement(node: Node): node is NotEmittedStatement; + function isNotEmittedOrPartiallyEmittedNode(node: Node): node is NotEmittedStatement | PartiallyEmittedExpression; + function isOmittedExpression(node: Node): node is OmittedExpression; + function isTemplateSpan(node: Node): node is TemplateSpan; + function isBlock(node: Node): node is Block; + function isConciseBody(node: Node): node is ConciseBody; + function isFunctionBody(node: Node): node is FunctionBody; + function isForInitializer(node: Node): node is ForInitializer; + function isVariableDeclaration(node: Node): node is VariableDeclaration; + function isVariableDeclarationList(node: Node): node is VariableDeclarationList; + function isCaseBlock(node: Node): node is CaseBlock; + function isModuleBody(node: Node): node is ModuleBody; + function isImportEqualsDeclaration(node: Node): node is ImportEqualsDeclaration; + function isImportClause(node: Node): node is ImportClause; + function isNamedImportBindings(node: Node): node is NamedImportBindings; + function isImportSpecifier(node: Node): node is ImportSpecifier; + function isNamedExports(node: Node): node is NamedExports; + function isExportSpecifier(node: Node): node is ExportSpecifier; + function isModuleOrEnumDeclaration(node: Node): node is ModuleDeclaration | EnumDeclaration; + function isDeclaration(node: Node): node is Declaration; + function isDeclarationStatement(node: Node): node is DeclarationStatement; + /** + * Determines whether the node is a statement that is not also a declaration + */ + function isStatementButNotDeclaration(node: Node): node is Statement; + function isStatement(node: Node): node is Statement; + function isModuleReference(node: Node): node is ModuleReference; + function isJsxOpeningElement(node: Node): node is JsxOpeningElement; + function isJsxClosingElement(node: Node): node is JsxClosingElement; + function isJsxTagNameExpression(node: Node): node is JsxTagNameExpression; + function isJsxChild(node: Node): node is JsxChild; + function isJsxAttributeLike(node: Node): node is JsxAttributeLike; + function isJsxSpreadAttribute(node: Node): node is JsxSpreadAttribute; + function isJsxAttribute(node: Node): node is JsxAttribute; + function isStringLiteralOrJsxExpression(node: Node): node is StringLiteral | JsxExpression; + function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause; + function isHeritageClause(node: Node): node is HeritageClause; + function isCatchClause(node: Node): node is CatchClause; + function isPropertyAssignment(node: Node): node is PropertyAssignment; + function isShorthandPropertyAssignment(node: Node): node is ShorthandPropertyAssignment; + function isEnumMember(node: Node): node is EnumMember; + function isSourceFile(node: Node): node is SourceFile; function isWatchSet(options: CompilerOptions): boolean; } declare namespace ts { @@ -2912,6 +3411,8 @@ declare namespace ts { function collapseTextChangeRangesAcrossMultipleVersions(changes: TextChangeRange[]): TextChangeRange; function getTypeParameterOwner(d: Declaration): Declaration; function isParameterPropertyDeclaration(node: ParameterDeclaration): boolean; + function getCombinedModifierFlags(node: Node): ModifierFlags; + function getCombinedNodeFlags(node: Node): NodeFlags; } declare namespace ts { var Diagnostics: { @@ -4145,19 +4646,19 @@ declare namespace ts { key: string; message: string; }; - with_statements_are_not_allowed_in_an_async_function_block: { + A_const_initializer_in_an_ambient_context_must_be_a_string_or_numeric_literal: { code: number; category: DiagnosticCategory; key: string; message: string; }; - await_expression_is_only_allowed_within_an_async_function: { + with_statements_are_not_allowed_in_an_async_function_block: { code: number; category: DiagnosticCategory; key: string; message: string; }; - Async_functions_are_only_available_when_targeting_ECMAScript_2015_or_higher: { + await_expression_is_only_allowed_within_an_async_function: { code: number; category: DiagnosticCategory; key: string; @@ -4487,7 +4988,7 @@ declare namespace ts { key: string; message: string; }; - Cannot_invoke_an_expression_whose_type_lacks_a_call_signature: { + Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures: { code: number; category: DiagnosticCategory; key: string; @@ -4517,12 +5018,6 @@ declare namespace ts { key: string; message: string; }; - No_best_common_type_exists_among_return_expressions: { - code: number; - category: DiagnosticCategory; - key: string; - message: string; - }; A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value: { code: number; category: DiagnosticCategory; @@ -4841,7 +5336,7 @@ declare namespace ts { key: string; message: string; }; - All_symbols_within_a_with_block_will_be_resolved_to_any: { + The_with_statement_is_not_supported_All_symbols_in_a_with_block_will_have_type_any: { code: number; category: DiagnosticCategory; key: string; @@ -5369,12 +5864,6 @@ declare namespace ts { key: string; message: string; }; - No_best_common_type_exists_among_yield_expressions: { - code: number; - category: DiagnosticCategory; - key: string; - message: string; - }; A_generator_cannot_have_a_void_type_annotation: { code: number; category: DiagnosticCategory; @@ -5471,7 +5960,7 @@ declare namespace ts { key: string; message: string; }; - The_arguments_object_cannot_be_referenced_in_an_async_arrow_function_Consider_using_a_standard_async_function_expression: { + The_arguments_object_cannot_be_referenced_in_an_async_function_or_method_in_ES3_and_ES5_Consider_using_a_standard_function_or_method: { code: number; category: DiagnosticCategory; key: string; @@ -5855,6 +6344,30 @@ declare namespace ts { key: string; message: string; }; + _0_only_refers_to_a_type_but_is_being_used_as_a_value_here: { + code: number; + category: DiagnosticCategory; + key: string; + message: string; + }; + Namespace_0_has_no_exported_member_1: { + code: number; + category: DiagnosticCategory; + key: string; + message: string; + }; + Left_side_of_comma_operator_is_unused_and_has_no_side_effects: { + code: number; + category: DiagnosticCategory; + key: string; + message: string; + }; + The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead: { + code: number; + category: DiagnosticCategory; + key: string; + message: string; + }; Import_declaration_0_is_using_private_name_1: { code: number; category: DiagnosticCategory; @@ -6629,6 +7142,12 @@ declare namespace ts { key: string; message: string; }; + STRATEGY: { + code: number; + category: DiagnosticCategory; + key: string; + message: string; + }; Compilation_complete_Watching_for_file_changes: { code: number; category: DiagnosticCategory; @@ -7175,6 +7694,18 @@ declare namespace ts { key: string; message: string; }; + Import_emit_helpers_from_tslib: { + code: number; + category: DiagnosticCategory; + key: string; + message: string; + }; + Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using_cache_location_2: { + code: number; + category: DiagnosticCategory; + key: string; + message: string; + }; Variable_0_implicitly_has_an_1_type: { code: number; category: DiagnosticCategory; @@ -7487,6 +8018,18 @@ declare namespace ts { key: string; message: string; }; + Circularity_detected_while_resolving_configuration_Colon_0: { + code: number; + category: DiagnosticCategory; + key: string; + message: string; + }; + The_path_in_an_extends_options_must_be_relative_or_rooted: { + code: number; + category: DiagnosticCategory; + key: string; + message: string; + }; }; } declare namespace ts { @@ -7510,6 +8053,7 @@ declare namespace ts { reScanSlashToken(): SyntaxKind; reScanTemplateToken(): SyntaxKind; scanJsxIdentifier(): SyntaxKind; + scanJsxAttributeValue(): SyntaxKind; reScanJsxToken(): SyntaxKind; scanJsxToken(): SyntaxKind; scanJSDocToken(): SyntaxKind; @@ -7546,73 +8090,513 @@ declare namespace ts { function isOctalDigit(ch: number): boolean; function couldStartTrivia(text: string, pos: number): boolean; function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boolean, stopAtComments?: boolean): number; + function forEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: SyntaxKind, hasTrailingNewLine: boolean, state: T) => U, state?: T): U; + function forEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: SyntaxKind, hasTrailingNewLine: boolean, state: T) => U, state?: T): U; + function reduceEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: SyntaxKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U): U; + function reduceEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: SyntaxKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U): U; function getLeadingCommentRanges(text: string, pos: number): CommentRange[]; function getTrailingCommentRanges(text: string, pos: number): CommentRange[]; /** Optionally, get the shebang */ function getShebang(text: string): string; function isIdentifierStart(ch: number, languageVersion: ScriptTarget): boolean; function isIdentifierPart(ch: number, languageVersion: ScriptTarget): boolean; - function isIdentifier(name: string, languageVersion: ScriptTarget): boolean; + function isIdentifierText(name: string, languageVersion: ScriptTarget): boolean; function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean, languageVariant?: LanguageVariant, text?: string, onError?: ErrorCallback, start?: number, length?: number): Scanner; } declare namespace ts { - function createNode(kind: SyntaxKind, pos?: number, end?: number): Node; - function forEachChild(node: Node, cbNode: (node: Node) => T, cbNodeArray?: (nodes: Node[]) => T): T; - function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes?: boolean, scriptKind?: ScriptKind): SourceFile; - function isExternalModule(file: SourceFile): boolean; - function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile; - function parseIsolatedJSDocComment(content: string, start?: number, length?: number): { - jsDocComment: JSDocComment; - diagnostics: Diagnostic[]; - }; - function parseJSDocTypeExpressionForTests(content: string, start?: number, length?: number): { - jsDocTypeExpression: JSDocTypeExpression; - diagnostics: Diagnostic[]; - }; -} -declare namespace ts { - const enum ModuleInstanceState { - NonInstantiated = 0, - Instantiated = 1, - ConstEnumOnly = 2, - } - function getModuleInstanceState(node: Node): ModuleInstanceState; - function bindSourceFile(file: SourceFile, options: CompilerOptions): void; -} -declare namespace ts { - function getNodeId(node: Node): number; - function getSymbolId(symbol: Symbol): number; - function createTypeChecker(host: TypeCheckerHost, produceDiagnostics: boolean): TypeChecker; -} -declare namespace ts { - const optionDeclarations: CommandLineOption[]; - let typingOptionDeclarations: CommandLineOption[]; - interface OptionNameMap { - optionNameMap: Map; - shortOptionNames: Map; - } - const defaultInitCompilerOptions: CompilerOptions; - function getOptionNameMap(): OptionNameMap; - function createCompilerDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType): Diagnostic; - function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: string, errors: Diagnostic[]): number | string; - function parseListTypeOption(opt: CommandLineOptionOfListType, value: string, errors: Diagnostic[]): (string | number)[] | undefined; - function parseCommandLine(commandLine: string[], readFile?: (path: string) => string): ParsedCommandLine; + function updateNode(updated: T, original: T): T; + function createNodeArray(elements?: T[], location?: TextRange, hasTrailingComma?: boolean): NodeArray; + function createSynthesizedNode(kind: SyntaxKind, startsOnNewLine?: boolean): Node; + function createSynthesizedNodeArray(elements?: T[]): NodeArray; /** - * Read tsconfig.json file - * @param fileName The path to the config file - */ - function readConfigFile(fileName: string, readFile: (path: string) => string): { - config?: any; - error?: Diagnostic; - }; + * Creates a shallow, memberwise clone of a node with no source map location. + */ + function getSynthesizedClone(node: T): T; /** - * Parse the text of the tsconfig.json file - * @param fileName The path to the config file - * @param jsonText The text of the config file - */ - function parseConfigFileTextToJson(fileName: string, jsonText: string): { - config?: any; - error?: Diagnostic; + * Creates a shallow, memberwise clone of a node for mutation. + */ + function getMutableClone(node: T): T; + function createLiteral(textSource: StringLiteral | Identifier, location?: TextRange): StringLiteral; + function createLiteral(value: string, location?: TextRange): StringLiteral; + function createLiteral(value: number, location?: TextRange): NumericLiteral; + function createLiteral(value: string | number | boolean, location?: TextRange): PrimaryExpression; + function createIdentifier(text: string, location?: TextRange): Identifier; + function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, location?: TextRange): Identifier; + function createLoopVariable(location?: TextRange): Identifier; + function createUniqueName(text: string, location?: TextRange): Identifier; + function getGeneratedNameForNode(node: Node, location?: TextRange): Identifier; + function createToken(token: SyntaxKind): Node; + function createSuper(): PrimaryExpression; + function createThis(location?: TextRange): PrimaryExpression; + function createNull(): PrimaryExpression; + function createComputedPropertyName(expression: Expression, location?: TextRange): ComputedPropertyName; + function updateComputedPropertyName(node: ComputedPropertyName, expression: Expression): ComputedPropertyName; + function createParameter(name: string | Identifier | BindingPattern, initializer?: Expression, location?: TextRange): ParameterDeclaration; + function createParameterDeclaration(decorators: Decorator[], modifiers: Modifier[], dotDotDotToken: Node, name: string | Identifier | BindingPattern, questionToken: Node, type: TypeNode, initializer: Expression, location?: TextRange, flags?: NodeFlags): ParameterDeclaration; + function updateParameterDeclaration(node: ParameterDeclaration, decorators: Decorator[], modifiers: Modifier[], name: BindingName, type: TypeNode, initializer: Expression): ParameterDeclaration; + function createProperty(decorators: Decorator[], modifiers: Modifier[], name: string | PropertyName, questionToken: Node, type: TypeNode, initializer: Expression, location?: TextRange): PropertyDeclaration; + function updateProperty(node: PropertyDeclaration, decorators: Decorator[], modifiers: Modifier[], name: PropertyName, type: TypeNode, initializer: Expression): PropertyDeclaration; + function createMethod(decorators: Decorator[], modifiers: Modifier[], asteriskToken: Node, name: string | PropertyName, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block, location?: TextRange, flags?: NodeFlags): MethodDeclaration; + function updateMethod(node: MethodDeclaration, decorators: Decorator[], modifiers: Modifier[], name: PropertyName, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block): MethodDeclaration; + function createConstructor(decorators: Decorator[], modifiers: Modifier[], parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags): ConstructorDeclaration; + function updateConstructor(node: ConstructorDeclaration, decorators: Decorator[], modifiers: Modifier[], parameters: ParameterDeclaration[], body: Block): ConstructorDeclaration; + function createGetAccessor(decorators: Decorator[], modifiers: Modifier[], name: string | PropertyName, parameters: ParameterDeclaration[], type: TypeNode, body: Block, location?: TextRange, flags?: NodeFlags): GetAccessorDeclaration; + function updateGetAccessor(node: GetAccessorDeclaration, decorators: Decorator[], modifiers: Modifier[], name: PropertyName, parameters: ParameterDeclaration[], type: TypeNode, body: Block): GetAccessorDeclaration; + function createSetAccessor(decorators: Decorator[], modifiers: Modifier[], name: string | PropertyName, parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags): SetAccessorDeclaration; + function updateSetAccessor(node: SetAccessorDeclaration, decorators: Decorator[], modifiers: Modifier[], name: PropertyName, parameters: ParameterDeclaration[], body: Block): SetAccessorDeclaration; + function createObjectBindingPattern(elements: BindingElement[], location?: TextRange): ObjectBindingPattern; + function updateObjectBindingPattern(node: ObjectBindingPattern, elements: BindingElement[]): ObjectBindingPattern; + function createArrayBindingPattern(elements: ArrayBindingElement[], location?: TextRange): ArrayBindingPattern; + function updateArrayBindingPattern(node: ArrayBindingPattern, elements: ArrayBindingElement[]): ArrayBindingPattern; + function createBindingElement(propertyName: string | PropertyName, dotDotDotToken: Node, name: string | BindingName, initializer?: Expression, location?: TextRange): BindingElement; + function updateBindingElement(node: BindingElement, propertyName: PropertyName, name: BindingName, initializer: Expression): BindingElement; + function createArrayLiteral(elements?: Expression[], location?: TextRange, multiLine?: boolean): ArrayLiteralExpression; + function updateArrayLiteral(node: ArrayLiteralExpression, elements: Expression[]): ArrayLiteralExpression; + function createObjectLiteral(properties?: ObjectLiteralElementLike[], location?: TextRange, multiLine?: boolean): ObjectLiteralExpression; + function updateObjectLiteral(node: ObjectLiteralExpression, properties: ObjectLiteralElementLike[]): ObjectLiteralExpression; + function createPropertyAccess(expression: Expression, name: string | Identifier, location?: TextRange, flags?: NodeFlags): PropertyAccessExpression; + function updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier): PropertyAccessExpression; + function createElementAccess(expression: Expression, index: number | Expression, location?: TextRange): ElementAccessExpression; + function updateElementAccess(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression): ElementAccessExpression; + function createCall(expression: Expression, typeArguments: TypeNode[], argumentsArray: Expression[], location?: TextRange, flags?: NodeFlags): CallExpression; + function updateCall(node: CallExpression, expression: Expression, typeArguments: TypeNode[], argumentsArray: Expression[]): CallExpression; + function createNew(expression: Expression, typeArguments: TypeNode[], argumentsArray: Expression[], location?: TextRange, flags?: NodeFlags): NewExpression; + function updateNew(node: NewExpression, expression: Expression, typeArguments: TypeNode[], argumentsArray: Expression[]): NewExpression; + function createTaggedTemplate(tag: Expression, template: Template, location?: TextRange): TaggedTemplateExpression; + function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: Template): TaggedTemplateExpression; + function createParen(expression: Expression, location?: TextRange): ParenthesizedExpression; + function updateParen(node: ParenthesizedExpression, expression: Expression): ParenthesizedExpression; + function createFunctionExpression(asteriskToken: Node, name: string | Identifier, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block, location?: TextRange, flags?: NodeFlags): FunctionExpression; + function updateFunctionExpression(node: FunctionExpression, name: Identifier, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block): FunctionExpression; + function createArrowFunction(modifiers: Modifier[], typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, equalsGreaterThanToken: Node, body: ConciseBody, location?: TextRange, flags?: NodeFlags): ArrowFunction; + function updateArrowFunction(node: ArrowFunction, modifiers: Modifier[], typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: ConciseBody): ArrowFunction; + function createDelete(expression: Expression, location?: TextRange): DeleteExpression; + function updateDelete(node: DeleteExpression, expression: Expression): Expression; + function createTypeOf(expression: Expression, location?: TextRange): TypeOfExpression; + function updateTypeOf(node: TypeOfExpression, expression: Expression): Expression; + function createVoid(expression: Expression, location?: TextRange): VoidExpression; + function updateVoid(node: VoidExpression, expression: Expression): VoidExpression; + function createAwait(expression: Expression, location?: TextRange): AwaitExpression; + function updateAwait(node: AwaitExpression, expression: Expression): AwaitExpression; + function createPrefix(operator: SyntaxKind, operand: Expression, location?: TextRange): PrefixUnaryExpression; + function updatePrefix(node: PrefixUnaryExpression, operand: Expression): PrefixUnaryExpression; + function createPostfix(operand: Expression, operator: SyntaxKind, location?: TextRange): PostfixUnaryExpression; + function updatePostfix(node: PostfixUnaryExpression, operand: Expression): PostfixUnaryExpression; + function createBinary(left: Expression, operator: SyntaxKind | Node, right: Expression, location?: TextRange): BinaryExpression; + function updateBinary(node: BinaryExpression, left: Expression, right: Expression): BinaryExpression; + function createConditional(condition: Expression, questionToken: Node, whenTrue: Expression, colonToken: Node, whenFalse: Expression, location?: TextRange): ConditionalExpression; + function updateConditional(node: ConditionalExpression, condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression; + function createTemplateExpression(head: TemplateLiteralFragment, templateSpans: TemplateSpan[], location?: TextRange): TemplateExpression; + function updateTemplateExpression(node: TemplateExpression, head: TemplateLiteralFragment, templateSpans: TemplateSpan[]): TemplateExpression; + function createYield(asteriskToken: Node, expression: Expression, location?: TextRange): YieldExpression; + function updateYield(node: YieldExpression, expression: Expression): YieldExpression; + function createSpread(expression: Expression, location?: TextRange): SpreadElementExpression; + function updateSpread(node: SpreadElementExpression, expression: Expression): SpreadElementExpression; + function createClassExpression(modifiers: Modifier[], name: Identifier, typeParameters: TypeParameterDeclaration[], heritageClauses: HeritageClause[], members: ClassElement[], location?: TextRange): ClassExpression; + function updateClassExpression(node: ClassExpression, modifiers: Modifier[], name: Identifier, typeParameters: TypeParameterDeclaration[], heritageClauses: HeritageClause[], members: ClassElement[]): ClassExpression; + function createOmittedExpression(location?: TextRange): OmittedExpression; + function createExpressionWithTypeArguments(typeArguments: TypeNode[], expression: Expression, location?: TextRange): ExpressionWithTypeArguments; + function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, typeArguments: TypeNode[], expression: Expression): ExpressionWithTypeArguments; + function createTemplateSpan(expression: Expression, literal: TemplateLiteralFragment, location?: TextRange): TemplateSpan; + function updateTemplateSpan(node: TemplateSpan, expression: Expression, literal: TemplateLiteralFragment): TemplateSpan; + function createBlock(statements: Statement[], location?: TextRange, multiLine?: boolean, flags?: NodeFlags): Block; + function updateBlock(node: Block, statements: Statement[]): Block; + function createVariableStatement(modifiers: Modifier[], declarationList: VariableDeclarationList | VariableDeclaration[], location?: TextRange, flags?: NodeFlags): VariableStatement; + function updateVariableStatement(node: VariableStatement, modifiers: Modifier[], declarationList: VariableDeclarationList): VariableStatement; + function createVariableDeclarationList(declarations: VariableDeclaration[], location?: TextRange, flags?: NodeFlags): VariableDeclarationList; + function updateVariableDeclarationList(node: VariableDeclarationList, declarations: VariableDeclaration[]): VariableDeclarationList; + function createVariableDeclaration(name: string | BindingPattern | Identifier, type?: TypeNode, initializer?: Expression, location?: TextRange, flags?: NodeFlags): VariableDeclaration; + function updateVariableDeclaration(node: VariableDeclaration, name: BindingName, type: TypeNode, initializer: Expression): VariableDeclaration; + function createEmptyStatement(location: TextRange): EmptyStatement; + function createStatement(expression: Expression, location?: TextRange, flags?: NodeFlags): ExpressionStatement; + function updateStatement(node: ExpressionStatement, expression: Expression): ExpressionStatement; + function createIf(expression: Expression, thenStatement: Statement, elseStatement?: Statement, location?: TextRange): IfStatement; + function updateIf(node: IfStatement, expression: Expression, thenStatement: Statement, elseStatement: Statement): IfStatement; + function createDo(statement: Statement, expression: Expression, location?: TextRange): DoStatement; + function updateDo(node: DoStatement, statement: Statement, expression: Expression): DoStatement; + function createWhile(expression: Expression, statement: Statement, location?: TextRange): WhileStatement; + function updateWhile(node: WhileStatement, expression: Expression, statement: Statement): WhileStatement; + function createFor(initializer: ForInitializer, condition: Expression, incrementor: Expression, statement: Statement, location?: TextRange): ForStatement; + function updateFor(node: ForStatement, initializer: ForInitializer, condition: Expression, incrementor: Expression, statement: Statement): ForStatement; + function createForIn(initializer: ForInitializer, expression: Expression, statement: Statement, location?: TextRange): ForInStatement; + function updateForIn(node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; + function createForOf(initializer: ForInitializer, expression: Expression, statement: Statement, location?: TextRange): ForOfStatement; + function updateForOf(node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement): ForInStatement; + function createContinue(label?: Identifier, location?: TextRange): BreakStatement; + function updateContinue(node: ContinueStatement, label: Identifier): BreakStatement; + function createBreak(label?: Identifier, location?: TextRange): BreakStatement; + function updateBreak(node: BreakStatement, label: Identifier): BreakStatement; + function createReturn(expression?: Expression, location?: TextRange): ReturnStatement; + function updateReturn(node: ReturnStatement, expression: Expression): ReturnStatement; + function createWith(expression: Expression, statement: Statement, location?: TextRange): WithStatement; + function updateWith(node: WithStatement, expression: Expression, statement: Statement): WithStatement; + function createSwitch(expression: Expression, caseBlock: CaseBlock, location?: TextRange): SwitchStatement; + function updateSwitch(node: SwitchStatement, expression: Expression, caseBlock: CaseBlock): SwitchStatement; + function createLabel(label: string | Identifier, statement: Statement, location?: TextRange): LabeledStatement; + function updateLabel(node: LabeledStatement, label: Identifier, statement: Statement): LabeledStatement; + function createThrow(expression: Expression, location?: TextRange): ThrowStatement; + function updateThrow(node: ThrowStatement, expression: Expression): ThrowStatement; + function createTry(tryBlock: Block, catchClause: CatchClause, finallyBlock: Block, location?: TextRange): TryStatement; + function updateTry(node: TryStatement, tryBlock: Block, catchClause: CatchClause, finallyBlock: Block): TryStatement; + function createCaseBlock(clauses: CaseOrDefaultClause[], location?: TextRange): CaseBlock; + function updateCaseBlock(node: CaseBlock, clauses: CaseOrDefaultClause[]): CaseBlock; + function createFunctionDeclaration(decorators: Decorator[], modifiers: Modifier[], asteriskToken: Node, name: string | Identifier, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block, location?: TextRange, flags?: NodeFlags): FunctionDeclaration; + function updateFunctionDeclaration(node: FunctionDeclaration, decorators: Decorator[], modifiers: Modifier[], name: Identifier, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block): FunctionDeclaration; + function createClassDeclaration(decorators: Decorator[], modifiers: Modifier[], name: Identifier, typeParameters: TypeParameterDeclaration[], heritageClauses: HeritageClause[], members: ClassElement[], location?: TextRange): ClassDeclaration; + function updateClassDeclaration(node: ClassDeclaration, decorators: Decorator[], modifiers: Modifier[], name: Identifier, typeParameters: TypeParameterDeclaration[], heritageClauses: HeritageClause[], members: ClassElement[]): ClassDeclaration; + function createImportDeclaration(decorators: Decorator[], modifiers: Modifier[], importClause: ImportClause, moduleSpecifier?: Expression, location?: TextRange): ImportDeclaration; + function updateImportDeclaration(node: ImportDeclaration, decorators: Decorator[], modifiers: Modifier[], importClause: ImportClause, moduleSpecifier: Expression): ImportDeclaration; + function createImportClause(name: Identifier, namedBindings: NamedImportBindings, location?: TextRange): ImportClause; + function updateImportClause(node: ImportClause, name: Identifier, namedBindings: NamedImportBindings): ImportClause; + function createNamespaceImport(name: Identifier, location?: TextRange): NamespaceImport; + function updateNamespaceImport(node: NamespaceImport, name: Identifier): NamespaceImport; + function createNamedImports(elements: ImportSpecifier[], location?: TextRange): NamedImports; + function updateNamedImports(node: NamedImports, elements: ImportSpecifier[]): NamedImports; + function createImportSpecifier(propertyName: Identifier, name: Identifier, location?: TextRange): ImportSpecifier; + function updateImportSpecifier(node: ImportSpecifier, propertyName: Identifier, name: Identifier): ImportSpecifier; + function createExportAssignment(decorators: Decorator[], modifiers: Modifier[], isExportEquals: boolean, expression: Expression, location?: TextRange): ExportAssignment; + function updateExportAssignment(node: ExportAssignment, decorators: Decorator[], modifiers: Modifier[], expression: Expression): ExportAssignment; + function createExportDeclaration(decorators: Decorator[], modifiers: Modifier[], exportClause: NamedExports, moduleSpecifier?: Expression, location?: TextRange): ExportDeclaration; + function updateExportDeclaration(node: ExportDeclaration, decorators: Decorator[], modifiers: Modifier[], exportClause: NamedExports, moduleSpecifier: Expression): ExportDeclaration; + function createNamedExports(elements: ExportSpecifier[], location?: TextRange): NamedExports; + function updateNamedExports(node: NamedExports, elements: ExportSpecifier[]): NamedExports; + function createExportSpecifier(name: string | Identifier, propertyName?: string | Identifier, location?: TextRange): ExportSpecifier; + function updateExportSpecifier(node: ExportSpecifier, name: Identifier, propertyName: Identifier): ExportSpecifier; + function createJsxElement(openingElement: JsxOpeningElement, children: JsxChild[], closingElement: JsxClosingElement, location?: TextRange): JsxElement; + function updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: JsxChild[], closingElement: JsxClosingElement): JsxElement; + function createJsxSelfClosingElement(tagName: JsxTagNameExpression, attributes: JsxAttributeLike[], location?: TextRange): JsxSelfClosingElement; + function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, attributes: JsxAttributeLike[]): JsxSelfClosingElement; + function createJsxOpeningElement(tagName: JsxTagNameExpression, attributes: JsxAttributeLike[], location?: TextRange): JsxOpeningElement; + function updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, attributes: JsxAttributeLike[]): JsxOpeningElement; + function createJsxClosingElement(tagName: JsxTagNameExpression, location?: TextRange): JsxClosingElement; + function updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression): JsxClosingElement; + function createJsxAttribute(name: Identifier, initializer: StringLiteral | JsxExpression, location?: TextRange): JsxAttribute; + function updateJsxAttribute(node: JsxAttribute, name: Identifier, initializer: StringLiteral | JsxExpression): JsxAttribute; + function createJsxSpreadAttribute(expression: Expression, location?: TextRange): JsxSpreadAttribute; + function updateJsxSpreadAttribute(node: JsxSpreadAttribute, expression: Expression): JsxSpreadAttribute; + function createJsxExpression(expression: Expression, location?: TextRange): JsxExpression; + function updateJsxExpression(node: JsxExpression, expression: Expression): JsxExpression; + function createHeritageClause(token: SyntaxKind, types: ExpressionWithTypeArguments[], location?: TextRange): HeritageClause; + function updateHeritageClause(node: HeritageClause, types: ExpressionWithTypeArguments[]): HeritageClause; + function createCaseClause(expression: Expression, statements: Statement[], location?: TextRange): CaseClause; + function updateCaseClause(node: CaseClause, expression: Expression, statements: Statement[]): CaseClause; + function createDefaultClause(statements: Statement[], location?: TextRange): DefaultClause; + function updateDefaultClause(node: DefaultClause, statements: Statement[]): DefaultClause; + function createCatchClause(variableDeclaration: string | VariableDeclaration, block: Block, location?: TextRange): CatchClause; + function updateCatchClause(node: CatchClause, variableDeclaration: VariableDeclaration, block: Block): CatchClause; + function createPropertyAssignment(name: string | PropertyName, initializer: Expression, location?: TextRange): PropertyAssignment; + function updatePropertyAssignment(node: PropertyAssignment, name: PropertyName, initializer: Expression): PropertyAssignment; + function createShorthandPropertyAssignment(name: string | Identifier, objectAssignmentInitializer: Expression, location?: TextRange): ShorthandPropertyAssignment; + function updateShorthandPropertyAssignment(node: ShorthandPropertyAssignment, name: Identifier, objectAssignmentInitializer: Expression): ShorthandPropertyAssignment; + function updateSourceFileNode(node: SourceFile, statements: Statement[]): SourceFile; + /** + * Creates a synthetic statement to act as a placeholder for a not-emitted statement in + * order to preserve comments. + * + * @param original The original statement. + */ + function createNotEmittedStatement(original: Node): NotEmittedStatement; + /** + * Creates a synthetic expression to act as a placeholder for a not-emitted expression in + * order to preserve comments or sourcemap positions. + * + * @param expression The inner expression to emit. + * @param original The original outer expression. + * @param location The location for the expression. Defaults to the positions from "original" if provided. + */ + function createPartiallyEmittedExpression(expression: Expression, original?: Node, location?: TextRange): PartiallyEmittedExpression; + function updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression): PartiallyEmittedExpression; + function createComma(left: Expression, right: Expression): Expression; + function createLessThan(left: Expression, right: Expression, location?: TextRange): Expression; + function createAssignment(left: Expression, right: Expression, location?: TextRange): BinaryExpression; + function createStrictEquality(left: Expression, right: Expression): BinaryExpression; + function createStrictInequality(left: Expression, right: Expression): BinaryExpression; + function createAdd(left: Expression, right: Expression): BinaryExpression; + function createSubtract(left: Expression, right: Expression): BinaryExpression; + function createPostfixIncrement(operand: Expression, location?: TextRange): PostfixUnaryExpression; + function createLogicalAnd(left: Expression, right: Expression): BinaryExpression; + function createLogicalOr(left: Expression, right: Expression): BinaryExpression; + function createLogicalNot(operand: Expression): PrefixUnaryExpression; + function createVoidZero(): VoidExpression; + function createMemberAccessForPropertyName(target: Expression, memberName: PropertyName, location?: TextRange): MemberExpression; + function createRestParameter(name: string | Identifier): ParameterDeclaration; + function createFunctionCall(func: Expression, thisArg: Expression, argumentsList: Expression[], location?: TextRange): CallExpression; + function createFunctionApply(func: Expression, thisArg: Expression, argumentsExpression: Expression, location?: TextRange): CallExpression; + function createArraySlice(array: Expression, start?: number | Expression): CallExpression; + function createArrayConcat(array: Expression, values: Expression[]): CallExpression; + function createMathPow(left: Expression, right: Expression, location?: TextRange): CallExpression; + function createReactCreateElement(reactNamespace: string, tagName: Expression, props: Expression, children: Expression[], parentElement: JsxOpeningLikeElement, location: TextRange): LeftHandSideExpression; + function createLetDeclarationList(declarations: VariableDeclaration[], location?: TextRange): VariableDeclarationList; + function createConstDeclarationList(declarations: VariableDeclaration[], location?: TextRange): VariableDeclarationList; + function createHelperName(externalHelpersModuleName: Identifier | undefined, name: string): Identifier | PropertyAccessExpression; + function createExtendsHelper(externalHelpersModuleName: Identifier | undefined, name: Identifier): CallExpression; + function createAssignHelper(externalHelpersModuleName: Identifier | undefined, attributesSegments: Expression[]): CallExpression; + function createParamHelper(externalHelpersModuleName: Identifier | undefined, expression: Expression, parameterOffset: number, location?: TextRange): CallExpression; + function createMetadataHelper(externalHelpersModuleName: Identifier | undefined, metadataKey: string, metadataValue: Expression): CallExpression; + function createDecorateHelper(externalHelpersModuleName: Identifier | undefined, decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression, location?: TextRange): CallExpression; + function createAwaiterHelper(externalHelpersModuleName: Identifier | undefined, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression, body: Block): CallExpression; + function createHasOwnProperty(target: LeftHandSideExpression, propertyName: Expression): CallExpression; + function createAdvancedAsyncSuperHelper(): VariableStatement; + function createSimpleAsyncSuperHelper(): VariableStatement; + interface CallBinding { + target: LeftHandSideExpression; + thisArg: Expression; + } + function createCallBinding(expression: Expression, recordTempVariable: (temp: Identifier) => void, languageVersion?: ScriptTarget, cacheIdentifiers?: boolean): CallBinding; + function inlineExpressions(expressions: Expression[]): Expression; + function createExpressionFromEntityName(node: EntityName | Expression): Expression; + function createExpressionForPropertyName(memberName: PropertyName): Expression; + function createExpressionForObjectLiteralElementLike(node: ObjectLiteralExpression, property: ObjectLiteralElementLike, receiver: Expression): Expression; + /** + * Add any necessary prologue-directives into target statement-array. + * The function needs to be called during each transformation step. + * This function needs to be called whenever we transform the statement + * list of a source file, namespace, or function-like body. + * + * @param target: result statements array + * @param source: origin statements array + * @param ensureUseStrict: boolean determining whether the function need to add prologue-directives + * @param visitor: Optional callback used to visit any custom prologue directives. + */ + function addPrologueDirectives(target: Statement[], source: Statement[], ensureUseStrict?: boolean, visitor?: (node: Node) => VisitResult): number; + /** + * Wraps the operand to a BinaryExpression in parentheses if they are needed to preserve the intended + * order of operations. + * + * @param binaryOperator The operator for the BinaryExpression. + * @param operand The operand for the BinaryExpression. + * @param isLeftSideOfBinary A value indicating whether the operand is the left side of the + * BinaryExpression. + */ + function parenthesizeBinaryOperand(binaryOperator: SyntaxKind, operand: Expression, isLeftSideOfBinary: boolean, leftOperand?: Expression): Expression; + /** + * Wraps an expression in parentheses if it is needed in order to use the expression + * as the expression of a NewExpression node. + * + * @param expression The Expression node. + */ + function parenthesizeForNew(expression: Expression): LeftHandSideExpression; + /** + * Wraps an expression in parentheses if it is needed in order to use the expression for + * property or element access. + * + * @param expr The expression node. + */ + function parenthesizeForAccess(expression: Expression): LeftHandSideExpression; + function parenthesizePostfixOperand(operand: Expression): LeftHandSideExpression; + function parenthesizePrefixOperand(operand: Expression): UnaryExpression; + function parenthesizeExpressionForList(expression: Expression): Expression; + function parenthesizeExpressionForExpressionStatement(expression: Expression): Expression; + function parenthesizeConciseBody(body: ConciseBody): ConciseBody; + const enum OuterExpressionKinds { + Parentheses = 1, + Assertions = 2, + PartiallyEmittedExpressions = 4, + All = 7, + } + function skipOuterExpressions(node: Expression, kinds?: OuterExpressionKinds): Expression; + function skipOuterExpressions(node: Node, kinds?: OuterExpressionKinds): Node; + function skipParentheses(node: Expression): Expression; + function skipParentheses(node: Node): Node; + function skipAssertions(node: Expression): Expression; + function skipAssertions(node: Node): Node; + function skipPartiallyEmittedExpressions(node: Expression): Expression; + function skipPartiallyEmittedExpressions(node: Node): Node; + function startOnNewLine(node: T): T; + function setOriginalNode(node: T, original: Node): T; + /** + * Clears any EmitNode entries from parse-tree nodes. + * @param sourceFile A source file. + */ + function disposeEmitNodes(sourceFile: SourceFile): void; + /** + * Gets flags that control emit behavior of a node. + * + * @param node The node. + */ + function getEmitFlags(node: Node): EmitFlags; + /** + * Sets flags that control emit behavior of a node. + * + * @param node The node. + * @param emitFlags The NodeEmitFlags for the node. + */ + function setEmitFlags(node: T, emitFlags: EmitFlags): T; + /** + * Sets a custom text range to use when emitting source maps. + * + * @param node The node. + * @param range The text range. + */ + function setSourceMapRange(node: T, range: TextRange): T; + /** + * Sets the TextRange to use for source maps for a token of a node. + * + * @param node The node. + * @param token The token. + * @param range The text range. + */ + function setTokenSourceMapRange(node: T, token: SyntaxKind, range: TextRange): T; + /** + * Sets a custom text range to use when emitting comments. + */ + function setCommentRange(node: T, range: TextRange): T; + /** + * Gets a custom text range to use when emitting comments. + * + * @param node The node. + */ + function getCommentRange(node: Node): TextRange; + /** + * Gets a custom text range to use when emitting source maps. + * + * @param node The node. + */ + function getSourceMapRange(node: Node): TextRange; + /** + * Gets the TextRange to use for source maps for a token of a node. + * + * @param node The node. + * @param token The token. + */ + function getTokenSourceMapRange(node: Node, token: SyntaxKind): TextRange; + /** + * Gets the constant value to emit for an expression. + */ + function getConstantValue(node: PropertyAccessExpression | ElementAccessExpression): number; + /** + * Sets the constant value to emit for an expression. + */ + function setConstantValue(node: PropertyAccessExpression | ElementAccessExpression, value: number): PropertyAccessExpression | ElementAccessExpression; + function setTextRange(node: T, location: TextRange): T; + function setNodeFlags(node: T, flags: NodeFlags): T; + function setMultiLine(node: T, multiLine: boolean): T; + function setHasTrailingComma(nodes: NodeArray, hasTrailingComma: boolean): NodeArray; + /** + * Get the name of that target module from an import or export declaration + */ + function getLocalNameForExternalImport(node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile): Identifier; + /** + * Get the name of a target module from an import/export declaration as should be written in the emitted output. + * The emitted output name can be different from the input if: + * 1. The module has a /// + * 2. --out or --outFile is used, making the name relative to the rootDir + * 3- The containing SourceFile has an entry in renamedDependencies for the import as requested by some module loaders (e.g. System). + * Otherwise, a new StringLiteral node representing the module name will be returned. + */ + function getExternalModuleNameLiteral(importNode: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile, host: EmitHost, resolver: EmitResolver, compilerOptions: CompilerOptions): StringLiteral; + /** + * Get the name of a module as should be written in the emitted output. + * The emitted output name can be different from the input if: + * 1. The module has a /// + * 2. --out or --outFile is used, making the name relative to the rootDir + * Otherwise, a new StringLiteral node representing the module name will be returned. + */ + function tryGetModuleNameFromFile(file: SourceFile, host: EmitHost, options: CompilerOptions): StringLiteral; +} +declare namespace ts { + function createNode(kind: SyntaxKind, pos?: number, end?: number): Node; + function forEachChild(node: Node, cbNode: (node: Node) => T, cbNodeArray?: (nodes: Node[]) => T): T; + function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes?: boolean, scriptKind?: ScriptKind): SourceFile; + function isExternalModule(file: SourceFile): boolean; + function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile; + function parseIsolatedJSDocComment(content: string, start?: number, length?: number): { + jsDoc: JSDoc; + diagnostics: Diagnostic[]; + }; + function parseJSDocTypeExpressionForTests(content: string, start?: number, length?: number): { + jsDocTypeExpression: JSDocTypeExpression; + diagnostics: Diagnostic[]; + }; +} +declare namespace ts { + const enum ModuleInstanceState { + NonInstantiated = 0, + Instantiated = 1, + ConstEnumOnly = 2, + } + function getModuleInstanceState(node: Node): ModuleInstanceState; + function bindSourceFile(file: SourceFile, options: CompilerOptions): void; + /** + * Computes the transform flags for a node, given the transform flags of its subtree + * + * @param node The node to analyze + * @param subtreeFlags Transform flags computed for this node's subtree + */ + function computeTransformFlagsForNode(node: Node, subtreeFlags: TransformFlags): TransformFlags; +} +declare namespace ts { + function trace(host: ModuleResolutionHost, message: DiagnosticMessage, ...args: any[]): void; + function isTraceEnabled(compilerOptions: CompilerOptions, host: ModuleResolutionHost): boolean; + function createResolvedModule(resolvedFileName: string, isExternalLibraryImport: boolean, failedLookupLocations: string[]): ResolvedModuleWithFailedLookupLocations; + interface ModuleResolutionState { + host: ModuleResolutionHost; + compilerOptions: CompilerOptions; + traceEnabled: boolean; + skipTsx: boolean; + } + function getEffectiveTypeRoots(options: CompilerOptions, host: { + directoryExists?: (directoryName: string) => boolean; + getCurrentDirectory?: () => string; + }): string[] | undefined; + /** + * @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. + * This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups + * is assumed to be the same as root directory of the project. + */ + function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string, options: CompilerOptions, host: ModuleResolutionHost): ResolvedTypeReferenceDirectiveWithFailedLookupLocations; + /** + * Given a set of options, returns the set of type directive names + * that should be included for this program automatically. + * This list could either come from the config file, + * or from enumerating the types root + initial secondary types lookup location. + * More type directives might appear in the program later as a result of loading actual source files; + * this list is only the set of defaults that are implicitly included. + */ + function getAutomaticTypeDirectiveNames(options: CompilerOptions, host: ModuleResolutionHost): string[]; + function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations; + function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations; + function directoryProbablyExists(directoryName: string, host: { + directoryExists?: (directoryName: string) => boolean; + }): boolean; + function loadModuleFromNodeModules(moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState, checkOneLevel: boolean): string; + function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations; +} +declare namespace ts { + function getNodeId(node: Node): number; + function getSymbolId(symbol: Symbol): number; + function createTypeChecker(host: TypeCheckerHost, produceDiagnostics: boolean): TypeChecker; +} +declare namespace ts { + const compileOnSaveCommandLineOption: CommandLineOption; + const optionDeclarations: CommandLineOption[]; + let typingOptionDeclarations: CommandLineOption[]; + interface OptionNameMap { + optionNameMap: Map; + shortOptionNames: Map; + } + const defaultInitCompilerOptions: CompilerOptions; + function getOptionNameMap(): OptionNameMap; + function createCompilerDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType): Diagnostic; + function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: string, errors: Diagnostic[]): string | number; + function parseListTypeOption(opt: CommandLineOptionOfListType, value: string, errors: Diagnostic[]): (string | number)[] | undefined; + function parseCommandLine(commandLine: string[], readFile?: (path: string) => string): ParsedCommandLine; + /** + * Read tsconfig.json file + * @param fileName The path to the config file + */ + function readConfigFile(fileName: string, readFile: (path: string) => string): { + config?: any; + error?: Diagnostic; + }; + /** + * Parse the text of the tsconfig.json file + * @param fileName The path to the config file + * @param jsonText The text of the config file + */ + function parseConfigFileTextToJson(fileName: string, jsonText: string, stripComments?: boolean): { + config?: any; + error?: Diagnostic; }; /** * Generate tsconfig configuration when running command line "--init" @@ -7629,63 +8613,311 @@ declare namespace ts { * @param basePath A root directory to resolve relative path entries in the config * file to. e.g. outDir */ - function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string): ParsedCommandLine; + function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[]): ParsedCommandLine; + function convertCompileOnSaveOptionFromJson(jsonOption: any, basePath: string, errors: Diagnostic[]): boolean; function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: CompilerOptions; errors: Diagnostic[]; }; function convertTypingOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { - options: CompilerOptions; + options: TypingOptions; errors: Diagnostic[]; }; } declare namespace ts { function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, targetSourceFile: SourceFile): Diagnostic[]; - function writeDeclarationFile(declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection): boolean; + function writeDeclarationFile(declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection, emitOnlyDtsFiles: boolean): boolean; +} +declare namespace ts { + type VisitResult = T | T[]; + /** + * Similar to `reduceLeft`, performs a reduction against each child of a node. + * NOTE: Unlike `forEachChild`, this does *not* visit every node. Only nodes added to the + * `nodeEdgeTraversalMap` above will be visited. + * + * @param node The node containing the children to reduce. + * @param f The callback function + * @param initial The initial value to supply to the reduction. + */ + function reduceEachChild(node: Node, f: (memo: T, node: Node) => T, initial: T): T; + /** + * Visits a Node using the supplied visitor, possibly returning a new Node in its place. + * + * @param node The Node to visit. + * @param visitor The callback used to visit the Node. + * @param test A callback to execute to verify the Node is valid. + * @param optional An optional value indicating whether the Node is itself optional. + * @param lift An optional callback to execute to lift a NodeArrayNode into a valid Node. + */ + function visitNode(node: T, visitor: (node: Node) => VisitResult, test: (node: Node) => boolean, optional?: boolean, lift?: (node: NodeArray) => T): T; + function visitNode(node: T, visitor: (node: Node) => VisitResult, test: (node: Node) => boolean, optional: boolean, lift: (node: NodeArray) => T, parenthesize: (node: Node, parentNode: Node) => Node, parentNode: Node): T; + /** + * Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place. + * + * @param nodes The NodeArray to visit. + * @param visitor The callback used to visit a Node. + * @param test A node test to execute for each node. + * @param start An optional value indicating the starting offset at which to start visiting. + * @param count An optional value indicating the maximum number of nodes to visit. + */ + function visitNodes(nodes: NodeArray, visitor: (node: Node) => VisitResult, test: (node: Node) => boolean, start?: number, count?: number): NodeArray; + function visitNodes(nodes: NodeArray, visitor: (node: Node) => VisitResult, test: (node: Node) => boolean, start: number, count: number, parenthesize: (node: Node, parentNode: Node) => Node, parentNode: Node): NodeArray; + /** + * Visits each child of a Node using the supplied visitor, possibly returning a new Node of the same kind in its place. + * + * @param node The Node whose children will be visited. + * @param visitor The callback used to visit each child. + * @param context A lexical environment context for the visitor. + */ + function visitEachChild(node: T, visitor: (node: Node) => VisitResult, context: LexicalEnvironment): T; + /** + * Merges generated lexical declarations into the FunctionBody of a non-arrow function-like declaration. + * + * @param node The ConciseBody of an arrow function. + * @param declarations The lexical declarations to merge. + */ + function mergeFunctionBodyLexicalEnvironment(body: FunctionBody, declarations: Statement[]): FunctionBody; + /** + * Merges generated lexical declarations into the ConciseBody of an ArrowFunction. + * + * @param node The ConciseBody of an arrow function. + * @param declarations The lexical declarations to merge. + */ + function mergeFunctionBodyLexicalEnvironment(body: ConciseBody, declarations: Statement[]): ConciseBody; + /** + * Lifts a NodeArray containing only Statement nodes to a block. + * + * @param nodes The NodeArray. + */ + function liftToBlock(nodes: Node[]): Statement; + /** + * Aggregates the TransformFlags for a Node and its subtree. + */ + function aggregateTransformFlags(node: T): T; + namespace Debug { + const failNotOptional: (message?: string) => void; + const failBadSyntaxKind: (node: Node, message?: string) => void; + const assertNode: (node: Node, test: (node: Node) => boolean, message?: string) => void; + } +} +declare namespace ts { + /** + * Flattens a destructuring assignment expression. + * + * @param root The destructuring assignment expression. + * @param needsValue Indicates whether the value from the right-hand-side of the + * destructuring assignment is needed as part of a larger expression. + * @param recordTempVariable A callback used to record new temporary variables. + * @param visitor An optional visitor to use to visit expressions. + */ + function flattenDestructuringAssignment(context: TransformationContext, node: BinaryExpression, needsValue: boolean, recordTempVariable: (node: Identifier) => void, visitor?: (node: Node) => VisitResult): Expression; + /** + * Flattens binding patterns in a parameter declaration. + * + * @param node The ParameterDeclaration to flatten. + * @param value The rhs value for the binding pattern. + * @param visitor An optional visitor to use to visit expressions. + */ + function flattenParameterDestructuring(context: TransformationContext, node: ParameterDeclaration, value: Expression, visitor?: (node: Node) => VisitResult): VariableDeclaration[]; + /** + * Flattens binding patterns in a variable declaration. + * + * @param node The VariableDeclaration to flatten. + * @param value An optional rhs value for the binding pattern. + * @param visitor An optional visitor to use to visit expressions. + */ + function flattenVariableDestructuring(context: TransformationContext, node: VariableDeclaration, value?: Expression, visitor?: (node: Node) => VisitResult, recordTempVariable?: (node: Identifier) => void): VariableDeclaration[]; + /** + * Flattens binding patterns in a variable declaration and transforms them into an expression. + * + * @param node The VariableDeclaration to flatten. + * @param recordTempVariable A callback used to record new temporary variables. + * @param nameSubstitution An optional callback used to substitute binding names. + * @param visitor An optional visitor to use to visit expressions. + */ + function flattenVariableDestructuringToExpression(context: TransformationContext, node: VariableDeclaration, recordTempVariable: (name: Identifier) => void, nameSubstitution?: (name: Identifier) => Expression, visitor?: (node: Node) => VisitResult): Expression; +} +declare namespace ts { + function transformTypeScript(context: TransformationContext): (node: SourceFile) => SourceFile; +} +declare namespace ts { + function transformJsx(context: TransformationContext): (node: SourceFile) => SourceFile; +} +declare namespace ts { + function transformES7(context: TransformationContext): (node: SourceFile) => SourceFile; +} +declare namespace ts { + function transformES6(context: TransformationContext): (node: SourceFile) => SourceFile; +} +declare namespace ts { + function transformGenerators(context: TransformationContext): (node: SourceFile) => SourceFile; +} +declare namespace ts { + function transformModule(context: TransformationContext): (node: SourceFile) => SourceFile; +} +declare namespace ts { + function transformSystemModule(context: TransformationContext): (node: SourceFile) => SourceFile; +} +declare namespace ts { + function transformES6Module(context: TransformationContext): (node: SourceFile) => SourceFile; +} +declare namespace ts { + interface TransformationResult { + /** + * Gets the transformed source files. + */ + transformed: SourceFile[]; + /** + * Emits the substitute for a node, if one is available; otherwise, emits the node. + * + * @param emitContext The current emit context. + * @param node The node to substitute. + * @param emitCallback A callback used to emit the node or its substitute. + */ + emitNodeWithSubstitution(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void; + /** + * Emits a node with possible notification. + * + * @param emitContext The current emit context. + * @param node The node to emit. + * @param emitCallback A callback used to emit the node. + */ + emitNodeWithNotification(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void; + } + interface TransformationContext extends LexicalEnvironment { + getCompilerOptions(): CompilerOptions; + getEmitResolver(): EmitResolver; + getEmitHost(): EmitHost; + /** + * Hoists a function declaration to the containing scope. + */ + hoistFunctionDeclaration(node: FunctionDeclaration): void; + /** + * Hoists a variable declaration to the containing scope. + */ + hoistVariableDeclaration(node: Identifier): void; + /** + * Enables expression substitutions in the pretty printer for the provided SyntaxKind. + */ + enableSubstitution(kind: SyntaxKind): void; + /** + * Determines whether expression substitutions are enabled for the provided node. + */ + isSubstitutionEnabled(node: Node): boolean; + /** + * Hook used by transformers to substitute expressions just before they + * are emitted by the pretty printer. + */ + onSubstituteNode?: (emitContext: EmitContext, node: Node) => Node; + /** + * Enables before/after emit notifications in the pretty printer for the provided + * SyntaxKind. + */ + enableEmitNotification(kind: SyntaxKind): void; + /** + * Determines whether before/after emit notifications should be raised in the pretty + * printer when it emits a node. + */ + isEmitNotificationEnabled(node: Node): boolean; + /** + * Hook used to allow transformers to capture state before or after + * the printer emits a node. + */ + onEmitNode?: (emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) => void; + } + type Transformer = (context: TransformationContext) => (node: SourceFile) => SourceFile; + function getTransformers(compilerOptions: CompilerOptions): Transformer[]; + /** + * Transforms an array of SourceFiles by passing them through each transformer. + * + * @param resolver The emit resolver provided by the checker. + * @param host The emit host. + * @param sourceFiles An array of source files + * @param transforms An array of Transformers. + */ + function transformFiles(resolver: EmitResolver, host: EmitHost, sourceFiles: SourceFile[], transformers: Transformer[]): TransformationResult; } declare namespace ts { interface SourceMapWriter { - getSourceMapData(): SourceMapData; + /** + * Initialize the SourceMapWriter for a new output file. + * + * @param filePath The path to the generated output file. + * @param sourceMapFilePath The path to the output source map file. + * @param sourceFiles The input source files for the program. + * @param isBundledEmit A value indicating whether the generated output file is a bundle. + */ + initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean): void; + /** + * Reset the SourceMapWriter to an empty state. + */ + reset(): void; + /** + * Set the current source file. + * + * @param sourceFile The source file. + */ setSourceFile(sourceFile: SourceFile): void; + /** + * Emits a mapping. + * + * If the position is synthetic (undefined or a negative value), no mapping will be + * created. + * + * @param pos The position. + */ emitPos(pos: number): void; - emitStart(range: TextRange): void; - emitEnd(range: TextRange, stopOverridingSpan?: boolean): void; - changeEmitSourcePos(): void; + /** + * Emits a node with possible leading and trailing source maps. + * + * @param emitContext The current emit context + * @param node The node to emit. + * @param emitCallback The callback used to emit the node. + */ + emitNodeWithSourceMap(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void; + /** + * Emits a token of a node node with possible leading and trailing source maps. + * + * @param node The node containing the token. + * @param token The token to emit. + * @param tokenStartPos The start pos of the token. + * @param emitCallback The callback used to emit the token. + */ + emitTokenWithSourceMap(node: Node, token: SyntaxKind, tokenStartPos: number, emitCallback: (token: SyntaxKind, tokenStartPos: number) => number): number; + /** + * Gets the text for the source map. + */ getText(): string; + /** + * Gets the SourceMappingURL for the source map. + */ getSourceMappingURL(): string; - initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean): void; - reset(): void; + /** + * Gets test data for source maps. + */ + getSourceMapData(): SourceMapData; } - function getNullSourceMapWriter(): SourceMapWriter; function createSourceMapWriter(host: EmitHost, writer: EmitTextWriter): SourceMapWriter; } declare namespace ts { - function getResolvedExternalModuleName(host: EmitHost, file: SourceFile): string; - function getExternalModuleNameFromDeclaration(host: EmitHost, resolver: EmitResolver, declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration): string; - function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile): EmitResult; + interface CommentWriter { + reset(): void; + setSourceFile(sourceFile: SourceFile): void; + emitNodeWithComments(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void; + emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void): void; + emitTrailingCommentsOfPosition(pos: number): void; + } + function createCommentWriter(host: EmitHost, writer: EmitTextWriter, sourceMap: SourceMapWriter): CommentWriter; +} +declare namespace ts { + function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile, emitOnlyDtsFiles?: boolean): EmitResult; } declare namespace ts { /** The version of the TypeScript compiler release */ - const version: string; - function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean): string; + const version = "2.1.0"; + function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean, configName?: string): string; function resolveTripleslashReference(moduleName: string, containingFile: string): string; function computeCommonSourceDirectoryOfFilenames(fileNames: string[], currentDirectory: string, getCanonicalFileName: (fileName: string) => string): string; - function hasZeroOrOneAsteriskCharacter(str: string): boolean; - /** - * @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. - * This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups - * is assumed to be the same as root directory of the project. - */ - function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string, options: CompilerOptions, host: ModuleResolutionHost): ResolvedTypeReferenceDirectiveWithFailedLookupLocations; - function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations; - /** Return the object corresponding to the best pattern to match `candidate`. */ - function findBestPatternMatch(values: T[], getPattern: (value: T) => Pattern, candidate: string): T | undefined; - function tryParsePattern(pattern: string): Pattern | undefined; - function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations; - function directoryProbablyExists(directoryName: string, host: { - directoryExists?: (directoryName: string) => boolean; - }): boolean; - function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations; function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost; function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[]; interface FormatDiagnosticsHost { @@ -7695,15 +8927,6 @@ declare namespace ts { } function formatDiagnostics(diagnostics: Diagnostic[], host: FormatDiagnosticsHost): string; function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain, newLine: string): string; - /** - * Given a set of options, returns the set of type directive names - * that should be included for this program automatically. - * This list could either come from the config file, - * or from enumerating the types root + initial secondary types lookup location. - * More type directives might appear in the program later as a result of loading actual source files; - * this list is only the set of defaults that are implicitly included. - */ - function getAutomaticTypeDirectiveNames(options: CompilerOptions, host: ModuleResolutionHost): string[]; function createProgram(rootNames: string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program): Program; } declare namespace ts { @@ -7712,53 +8935,6 @@ declare namespace ts { } function executeCommandLine(args: string[]): void; } -declare namespace ts.OutliningElementsCollector { - function collectElements(sourceFile: SourceFile): OutliningSpan[]; -} -declare namespace ts.NavigateTo { - function getNavigateToItems(program: Program, checker: TypeChecker, cancellationToken: CancellationToken, searchValue: string, maxResultCount: number): NavigateToItem[]; -} -declare namespace ts.NavigationBar { - function getNavigationBarItems(sourceFile: SourceFile): NavigationBarItem[]; -} -declare namespace ts { - enum PatternMatchKind { - exact = 0, - prefix = 1, - substring = 2, - camelCase = 3, - } - interface PatternMatch { - kind: PatternMatchKind; - camelCaseWeight?: number; - isCaseSensitive: boolean; - punctuationStripped: boolean; - } - interface PatternMatcher { - getMatchesForLastSegmentOfPattern(candidate: string): PatternMatch[]; - getMatches(candidateContainers: string[], candidate: string): PatternMatch[]; - patternContainsDots: boolean; - } - function createPatternMatcher(pattern: string): PatternMatcher; - function breakIntoCharacterSpans(identifier: string): TextSpan[]; - function breakIntoWordSpans(identifier: string): TextSpan[]; -} -declare namespace ts.SignatureHelp { - const enum ArgumentListKind { - TypeArguments = 0, - CallArguments = 1, - TaggedTemplateArguments = 2, - } - interface ArgumentListInfo { - kind: ArgumentListKind; - invocation: CallLikeExpression; - argumentsSpan: TextSpan; - argumentIndex?: number; - argumentCount: number; - } - function getSignatureHelpItems(program: Program, sourceFile: SourceFile, position: number, cancellationToken: CancellationToken): SignatureHelpItems; - function getContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile): ArgumentListInfo; -} declare namespace ts { interface Node { getSourceFile(): SourceFile; @@ -7862,6 +9038,10 @@ declare namespace ts { trace?(s: string): void; error?(s: string): void; useCaseSensitiveFileNames?(): boolean; + readDirectory?(path: string, extensions?: string[], exclude?: string[], include?: string[]): string[]; + readFile?(path: string, encoding?: string): string; + fileExists?(path: string): boolean; + getTypeRootsVersion?(): number; resolveModuleNames?(moduleNames: string[], containingFile: string): ResolvedModule[]; resolveTypeReferenceDirectives?(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; directoryExists?(directoryName: string): boolean; @@ -7884,6 +9064,7 @@ declare namespace ts { getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications; getCompletionsAtPosition(fileName: string, position: number): CompletionInfo; getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails; + getCompletionEntrySymbol(fileName: string, position: number, entryName: string): Symbol; getQuickInfoAtPosition(fileName: string, position: number): QuickInfo; getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan; getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan; @@ -7892,25 +9073,31 @@ declare namespace ts { findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[]; getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[]; getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[]; + getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[]; getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[]; findReferences(fileName: string, position: number): ReferencedSymbol[]; getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[]; /** @deprecated */ getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[]; - getNavigateToItems(searchValue: string, maxResultCount?: number): NavigateToItem[]; + getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles?: boolean): NavigateToItem[]; getNavigationBarItems(fileName: string): NavigationBarItem[]; getOutliningSpans(fileName: string): OutliningSpan[]; getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[]; getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[]; - getIndentationAtPosition(fileName: string, position: number, options: EditorOptions): number; - getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions): TextChange[]; - getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[]; - getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[]; + getIndentationAtPosition(fileName: string, position: number, options: EditorOptions | EditorSettings): number; + getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; + getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; + getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion; isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean; - getEmitOutput(fileName: string): EmitOutput; + getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput; getProgram(): Program; getNonBoundSourceFile(fileName: string): SourceFile; + /** + * @internal + * @deprecated Use ts.createSourceFile instead. + */ + getSourceFile(fileName: string): SourceFile; dispose(): void; } interface Classifications { @@ -7959,15 +9146,19 @@ declare namespace ts { isWriteAccess: boolean; isDefinition: boolean; } + interface ImplementationLocation { + textSpan: TextSpan; + fileName: string; + } interface DocumentHighlights { fileName: string; highlightSpans: HighlightSpan[]; } namespace HighlightSpanKind { - const none: string; - const definition: string; - const reference: string; - const writtenReference: string; + const none = "none"; + const definition = "definition"; + const reference = "reference"; + const writtenReference = "writtenReference"; } interface HighlightSpan { fileName?: string; @@ -7985,6 +9176,11 @@ declare namespace ts { containerName: string; containerKind: string; } + enum IndentStyle { + None = 0, + Block = 1, + Smart = 2, + } interface EditorOptions { BaseIndentSize?: number; IndentSize: number; @@ -7993,10 +9189,13 @@ declare namespace ts { ConvertTabsToSpaces: boolean; IndentStyle: IndentStyle; } - enum IndentStyle { - None = 0, - Block = 1, - Smart = 2, + interface EditorSettings { + baseIndentSize?: number; + indentSize: number; + tabSize: number; + newLineCharacter: string; + convertTabsToSpaces: boolean; + indentStyle: IndentStyle; } interface FormatCodeOptions extends EditorOptions { InsertSpaceAfterCommaDelimiter: boolean; @@ -8006,11 +9205,27 @@ declare namespace ts { InsertSpaceAfterFunctionKeywordForAnonymousFunctions: boolean; InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean; InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean; + InsertSpaceAfterOpeningAndBeforeClosingNonemptyBraces?: boolean; InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: boolean; InsertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces?: boolean; + InsertSpaceAfterTypeAssertion?: boolean; PlaceOpenBraceOnNewLineForFunctions: boolean; PlaceOpenBraceOnNewLineForControlBlocks: boolean; - [s: string]: boolean | number | string | undefined; + } + interface FormatCodeSettings extends EditorSettings { + insertSpaceAfterCommaDelimiter: boolean; + insertSpaceAfterSemicolonInForStatements: boolean; + insertSpaceBeforeAndAfterBinaryOperators: boolean; + insertSpaceAfterKeywordsInControlFlowStatements: boolean; + insertSpaceAfterFunctionKeywordForAnonymousFunctions: boolean; + insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean; + insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean; + insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces?: boolean; + insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: boolean; + insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: boolean; + insertSpaceAfterTypeAssertion?: boolean; + placeOpenBraceOnNewLineForFunctions: boolean; + placeOpenBraceOnNewLineForControlBlocks: boolean; } interface DefinitionInfo { fileName: string; @@ -8112,6 +9327,12 @@ declare namespace ts { kind: string; kindModifiers: string; sortText: string; + /** + * An optional span that indicates the text to be replaced by this completion item. It will be + * set if the required span differs from the one generated by the default replacement behavior and should + * be used in that case + */ + replacementSpan?: TextSpan; } interface CompletionEntryDetails { name: string; @@ -8199,139 +9420,78 @@ declare namespace ts { getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): ClassificationResult; getEncodedLexicalClassifications(text: string, endOfLineState: EndOfLineState, syntacticClassifierAbsent: boolean): Classifications; } - /** - * The document registry represents a store of SourceFile objects that can be shared between - * multiple LanguageService instances. A LanguageService instance holds on the SourceFile (AST) - * of files in the context. - * SourceFile objects account for most of the memory usage by the language service. Sharing - * the same DocumentRegistry instance between different instances of LanguageService allow - * for more efficient memory utilization since all projects will share at least the library - * file (lib.d.ts). - * - * A more advanced use of the document registry is to serialize sourceFile objects to disk - * and re-hydrate them when needed. - * - * To create a default DocumentRegistry, use createDocumentRegistry to create one, and pass it - * to all subsequent createLanguageService calls. - */ - interface DocumentRegistry { - /** - * Request a stored SourceFile with a given fileName and compilationSettings. - * The first call to acquire will call createLanguageServiceSourceFile to generate - * the SourceFile if was not found in the registry. - * - * @param fileName The name of the file requested - * @param compilationSettings Some compilation settings like target affects the - * shape of a the resulting SourceFile. This allows the DocumentRegistry to store - * multiple copies of the same file for different compilation settings. - * @parm scriptSnapshot Text of the file. Only used if the file was not found - * in the registry and a new one was created. - * @parm version Current version of the file. Only used if the file was not found - * in the registry and a new one was created. - */ - acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; - acquireDocumentWithKey(fileName: string, path: Path, compilationSettings: CompilerOptions, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; - /** - * Request an updated version of an already existing SourceFile with a given fileName - * and compilationSettings. The update will in-turn call updateLanguageServiceSourceFile - * to get an updated SourceFile. - * - * @param fileName The name of the file requested - * @param compilationSettings Some compilation settings like target affects the - * shape of a the resulting SourceFile. This allows the DocumentRegistry to store - * multiple copies of the same file for different compilation settings. - * @param scriptSnapshot Text of the file. - * @param version Current version of the file. - */ - updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; - updateDocumentWithKey(fileName: string, path: Path, compilationSettings: CompilerOptions, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; - getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey; - /** - * Informs the DocumentRegistry that a file is not needed any longer. - * - * Note: It is not allowed to call release on a SourceFile that was not acquired from - * this registry originally. - * - * @param fileName The name of the file to be released - * @param compilationSettings The compilation settings used to acquire the file - */ - releaseDocument(fileName: string, compilationSettings: CompilerOptions): void; - releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey): void; - reportStats(): string; - } - type DocumentRegistryBucketKey = string & { - __bucketKey: any; - }; namespace ScriptElementKind { - const unknown: string; - const warning: string; + const unknown = ""; + const warning = "warning"; /** predefined type (void) or keyword (class) */ - const keyword: string; + const keyword = "keyword"; /** top level script node */ - const scriptElement: string; + const scriptElement = "script"; /** module foo {} */ - const moduleElement: string; + const moduleElement = "module"; /** class X {} */ - const classElement: string; + const classElement = "class"; /** var x = class X {} */ - const localClassElement: string; + const localClassElement = "local class"; /** interface Y {} */ - const interfaceElement: string; + const interfaceElement = "interface"; /** type T = ... */ - const typeElement: string; + const typeElement = "type"; /** enum E */ - const enumElement: string; - const enumMemberElement: string; + const enumElement = "enum"; + const enumMemberElement = "const"; /** * Inside module and script only * const v = .. */ - const variableElement: string; + const variableElement = "var"; /** Inside function */ - const localVariableElement: string; + const localVariableElement = "local var"; /** * Inside module and script only * function f() { } */ - const functionElement: string; + const functionElement = "function"; /** Inside function */ - const localFunctionElement: string; + const localFunctionElement = "local function"; /** class X { [public|private]* foo() {} } */ - const memberFunctionElement: string; + const memberFunctionElement = "method"; /** class X { [public|private]* [get|set] foo:number; } */ - const memberGetAccessorElement: string; - const memberSetAccessorElement: string; + const memberGetAccessorElement = "getter"; + const memberSetAccessorElement = "setter"; /** * class X { [public|private]* foo:number; } * interface Y { foo:number; } */ - const memberVariableElement: string; + const memberVariableElement = "property"; /** class X { constructor() { } } */ - const constructorImplementationElement: string; + const constructorImplementationElement = "constructor"; /** interface Y { ():number; } */ - const callSignatureElement: string; + const callSignatureElement = "call"; /** interface Y { []:number; } */ - const indexSignatureElement: string; + const indexSignatureElement = "index"; /** interface Y { new():Y; } */ - const constructSignatureElement: string; + const constructSignatureElement = "construct"; /** function foo(*Y*: string) */ - const parameterElement: string; - const typeParameterElement: string; - const primitiveType: string; - const label: string; - const alias: string; - const constElement: string; - const letElement: string; + const parameterElement = "parameter"; + const typeParameterElement = "type parameter"; + const primitiveType = "primitive type"; + const label = "label"; + const alias = "alias"; + const constElement = "const"; + const letElement = "let"; + const directory = "directory"; + const externalModuleName = "external module name"; } namespace ScriptElementKindModifier { - const none: string; - const publicMemberModifier: string; - const privateMemberModifier: string; - const protectedMemberModifier: string; - const exportedModifier: string; - const ambientModifier: string; - const staticModifier: string; - const abstractModifier: string; + const none = ""; + const publicMemberModifier = "public"; + const privateMemberModifier = "private"; + const protectedMemberModifier = "protected"; + const exportedModifier = "export"; + const ambientModifier = "declare"; + const staticModifier = "static"; + const abstractModifier = "abstract"; } class ClassificationTypeNames { static comment: string; @@ -8386,6 +9546,35 @@ declare namespace ts { } } declare namespace ts { + const scanner: Scanner; + const emptyArray: any[]; + const enum SemanticMeaning { + None = 0, + Value = 1, + Type = 2, + Namespace = 4, + All = 7, + } + function getMeaningFromDeclaration(node: Node): SemanticMeaning; + function getMeaningFromLocation(node: Node): SemanticMeaning; + function isCallExpressionTarget(node: Node): boolean; + function isNewExpressionTarget(node: Node): boolean; + function climbPastPropertyAccess(node: Node): Node; + function getTargetLabel(referenceNode: Node, labelName: string): Identifier; + function isJumpStatementTarget(node: Node): boolean; + function isLabelName(node: Node): boolean; + function isRightSideOfQualifiedName(node: Node): boolean; + function isRightSideOfPropertyAccess(node: Node): boolean; + function isNameOfModuleDeclaration(node: Node): boolean; + function isNameOfFunctionDeclaration(node: Node): boolean; + function isLiteralNameOfPropertyDeclarationOrIndexAccess(node: Node): boolean; + function isExpressionOfExternalModuleImportEqualsDeclaration(node: Node): boolean; + /** Returns true if the position is within a comment */ + function isInsideComment(sourceFile: SourceFile, token: Node, position: number): boolean; + function getContainerNode(node: Node): Declaration; + function getNodeKind(node: Node): string; + function getStringLiteralTypeForNode(node: StringLiteral | LiteralTypeNode, typeChecker: TypeChecker): LiteralType; + function isThis(node: Node): boolean; interface ListItemInfo { listItemIndex: number; list: Node; @@ -8447,6 +9636,9 @@ declare namespace ts { function isAccessibilityModifier(kind: SyntaxKind): boolean; function compareDataObjects(dst: any, src: any): boolean; function isArrayLiteralOrObjectLiteralDestructuringPattern(node: Node): boolean; + function hasTrailingDirectorySeparator(path: string): boolean; + function isInReferenceComment(sourceFile: SourceFile, position: number): boolean; + function isInNonReferenceComment(sourceFile: SourceFile, position: number): boolean; } declare namespace ts { function isFirstDeclarationOfSymbolParameter(symbol: Symbol): boolean; @@ -8477,11 +9669,131 @@ declare namespace ts { function stripQuotes(name: string): string; function scriptKindIs(fileName: string, host: LanguageServiceHost, ...scriptKinds: ScriptKind[]): boolean; function getScriptKind(fileName: string, host?: LanguageServiceHost): ScriptKind; - function parseAndReEmitConfigJSONFile(content: string): { + function sanitizeConfigFile(configFileName: string, content: string): { configJsonObject: any; diagnostics: Diagnostic[]; }; } +declare namespace ts { + function createClassifier(): Classifier; + function getSemanticClassifications(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, classifiableNames: Map, span: TextSpan): ClassifiedSpan[]; + function getEncodedSemanticClassifications(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, classifiableNames: Map, span: TextSpan): Classifications; + function getSyntacticClassifications(cancellationToken: CancellationToken, sourceFile: SourceFile, span: TextSpan): ClassifiedSpan[]; + function getEncodedSyntacticClassifications(cancellationToken: CancellationToken, sourceFile: SourceFile, span: TextSpan): Classifications; +} +declare namespace ts.Completions { + function getCompletionsAtPosition(host: LanguageServiceHost, typeChecker: TypeChecker, log: (message: string) => void, compilerOptions: CompilerOptions, sourceFile: SourceFile, position: number): CompletionInfo; + function getCompletionEntryDetails(typeChecker: TypeChecker, log: (message: string) => void, compilerOptions: CompilerOptions, sourceFile: SourceFile, position: number, entryName: string): CompletionEntryDetails; + function getCompletionEntrySymbol(typeChecker: TypeChecker, log: (message: string) => void, compilerOptions: CompilerOptions, sourceFile: SourceFile, position: number, entryName: string): Symbol; +} +declare namespace ts.DocumentHighlights { + function getDocumentHighlights(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, position: number, sourceFilesToSearch: SourceFile[]): DocumentHighlights[]; +} +declare namespace ts { + /** + * The document registry represents a store of SourceFile objects that can be shared between + * multiple LanguageService instances. A LanguageService instance holds on the SourceFile (AST) + * of files in the context. + * SourceFile objects account for most of the memory usage by the language service. Sharing + * the same DocumentRegistry instance between different instances of LanguageService allow + * for more efficient memory utilization since all projects will share at least the library + * file (lib.d.ts). + * + * A more advanced use of the document registry is to serialize sourceFile objects to disk + * and re-hydrate them when needed. + * + * To create a default DocumentRegistry, use createDocumentRegistry to create one, and pass it + * to all subsequent createLanguageService calls. + */ + interface DocumentRegistry { + /** + * Request a stored SourceFile with a given fileName and compilationSettings. + * The first call to acquire will call createLanguageServiceSourceFile to generate + * the SourceFile if was not found in the registry. + * + * @param fileName The name of the file requested + * @param compilationSettings Some compilation settings like target affects the + * shape of a the resulting SourceFile. This allows the DocumentRegistry to store + * multiple copies of the same file for different compilation settings. + * @parm scriptSnapshot Text of the file. Only used if the file was not found + * in the registry and a new one was created. + * @parm version Current version of the file. Only used if the file was not found + * in the registry and a new one was created. + */ + acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; + acquireDocumentWithKey(fileName: string, path: Path, compilationSettings: CompilerOptions, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; + /** + * Request an updated version of an already existing SourceFile with a given fileName + * and compilationSettings. The update will in-turn call updateLanguageServiceSourceFile + * to get an updated SourceFile. + * + * @param fileName The name of the file requested + * @param compilationSettings Some compilation settings like target affects the + * shape of a the resulting SourceFile. This allows the DocumentRegistry to store + * multiple copies of the same file for different compilation settings. + * @param scriptSnapshot Text of the file. + * @param version Current version of the file. + */ + updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; + updateDocumentWithKey(fileName: string, path: Path, compilationSettings: CompilerOptions, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; + getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey; + /** + * Informs the DocumentRegistry that a file is not needed any longer. + * + * Note: It is not allowed to call release on a SourceFile that was not acquired from + * this registry originally. + * + * @param fileName The name of the file to be released + * @param compilationSettings The compilation settings used to acquire the file + */ + releaseDocument(fileName: string, compilationSettings: CompilerOptions): void; + releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey): void; + reportStats(): string; + } + type DocumentRegistryBucketKey = string & { + __bucketKey: any; + }; + function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory?: string): DocumentRegistry; +} +declare namespace ts.FindAllReferences { + function findReferencedSymbols(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFiles: SourceFile[], sourceFile: SourceFile, position: number, findInStrings: boolean, findInComments: boolean): ReferencedSymbol[]; + function getReferencedSymbolsForNode(typeChecker: TypeChecker, cancellationToken: CancellationToken, node: Node, sourceFiles: SourceFile[], findInStrings: boolean, findInComments: boolean, implementations: boolean): ReferencedSymbol[]; + function convertReferences(referenceSymbols: ReferencedSymbol[]): ReferenceEntry[]; + function getReferenceEntriesForShorthandPropertyAssignment(node: Node, typeChecker: TypeChecker, result: ReferenceEntry[]): void; + function getReferenceEntryFromNode(node: Node): ReferenceEntry; +} +declare namespace ts.GoToDefinition { + function getDefinitionAtPosition(program: Program, sourceFile: SourceFile, position: number): DefinitionInfo[]; + function getTypeDefinitionAtPosition(typeChecker: TypeChecker, sourceFile: SourceFile, position: number): DefinitionInfo[]; +} +declare namespace ts.GoToImplementation { + function getImplementationAtPosition(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFiles: SourceFile[], node: Node): ImplementationLocation[]; +} +declare namespace ts.JsDoc { + function getJsDocCommentsFromDeclarations(declarations: Declaration[], name: string, canUseParsedParamTagComments: boolean): SymbolDisplayPart[]; + function getAllJsDocCompletionEntries(): CompletionEntry[]; + /** + * Checks if position points to a valid position to add JSDoc comments, and if so, + * returns the appropriate template. Otherwise returns an empty string. + * Valid positions are + * - outside of comments, statements, and expressions, and + * - preceding a: + * - function/constructor/method declaration + * - class declarations + * - variable statements + * - namespace declarations + * + * Hosts should ideally check that: + * - The line is all whitespace up to 'position' before performing the insertion. + * - If the keystroke sequence "/\*\*" induced the call, we also check that the next + * non-whitespace character is '*', which (approximately) indicates whether we added + * the second '*' to complete an existing (JSDoc) comment. + * @param fileName The file in which to perform the check. + * @param position The (character-indexed) position in the file where the check should + * be performed. + */ + function getDocCommentTemplateAtPosition(newLine: string, sourceFile: SourceFile, position: number): TextInsertion; +} declare namespace ts.JsTyping { interface TypingResolutionHost { directoryExists: (path: string) => boolean; @@ -8504,6 +9816,84 @@ declare namespace ts.JsTyping { filesToWatch: string[]; }; } +declare namespace ts.NavigateTo { + function getNavigateToItems(sourceFiles: SourceFile[], checker: TypeChecker, cancellationToken: CancellationToken, searchValue: string, maxResultCount: number, excludeDtsFiles: boolean): NavigateToItem[]; +} +declare namespace ts.NavigationBar { + function getNavigationBarItems(sourceFile: SourceFile): NavigationBarItem[]; +} +declare namespace ts.OutliningElementsCollector { + function collectElements(sourceFile: SourceFile): OutliningSpan[]; +} +declare namespace ts { + enum PatternMatchKind { + exact = 0, + prefix = 1, + substring = 2, + camelCase = 3, + } + interface PatternMatch { + kind: PatternMatchKind; + camelCaseWeight?: number; + isCaseSensitive: boolean; + punctuationStripped: boolean; + } + interface PatternMatcher { + getMatchesForLastSegmentOfPattern(candidate: string): PatternMatch[]; + getMatches(candidateContainers: string[], candidate: string): PatternMatch[]; + patternContainsDots: boolean; + } + function createPatternMatcher(pattern: string): PatternMatcher; + function breakIntoCharacterSpans(identifier: string): TextSpan[]; + function breakIntoWordSpans(identifier: string): TextSpan[]; +} +declare namespace ts { + function preProcessFile(sourceText: string, readImportFiles?: boolean, detectJavaScriptImports?: boolean): PreProcessedFileInfo; +} +declare namespace ts.Rename { + function getRenameInfo(typeChecker: TypeChecker, defaultLibFileName: string, getCanonicalFileName: (fileName: string) => string, sourceFile: SourceFile, position: number): RenameInfo; +} +declare namespace ts.SignatureHelp { + const enum ArgumentListKind { + TypeArguments = 0, + CallArguments = 1, + TaggedTemplateArguments = 2, + } + interface ArgumentListInfo { + kind: ArgumentListKind; + invocation: CallLikeExpression; + argumentsSpan: TextSpan; + argumentIndex?: number; + argumentCount: number; + } + function getSignatureHelpItems(program: Program, sourceFile: SourceFile, position: number, cancellationToken: CancellationToken): SignatureHelpItems; + function getContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile): ArgumentListInfo; +} +declare namespace ts.SymbolDisplay { + function getSymbolKind(typeChecker: TypeChecker, symbol: Symbol, location: Node): string; + function getSymbolModifiers(symbol: Symbol): string; + function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: TypeChecker, symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node, location: Node, semanticMeaning?: SemanticMeaning): { + displayParts: SymbolDisplayPart[]; + documentation: SymbolDisplayPart[]; + symbolKind: string; + }; +} +declare namespace ts { + interface TranspileOptions { + compilerOptions?: CompilerOptions; + fileName?: string; + reportDiagnostics?: boolean; + moduleName?: string; + renamedDependencies?: MapLike; + } + interface TranspileOutput { + outputText: string; + diagnostics?: Diagnostic[]; + sourceMapText?: string; + } + function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput; + function transpile(input: string, compilerOptions?: CompilerOptions, fileName?: string, diagnostics?: Diagnostic[], moduleName?: string): string; +} declare namespace ts.formatting { interface FormattingScanner { advance(): void; @@ -8629,6 +10019,8 @@ declare namespace ts.formatting { NoSpaceAfterCloseBracket: Rule; SpaceAfterOpenBrace: Rule; SpaceBeforeCloseBrace: Rule; + NoSpaceAfterOpenBrace: Rule; + NoSpaceBeforeCloseBrace: Rule; NoSpaceBetweenEmptyBraceBrackets: Rule; NewLineAfterOpenBraceInBlockContext: Rule; NewLineBeforeCloseBraceInBlockContext: Rule; @@ -8670,7 +10062,6 @@ declare namespace ts.formatting { NoSpaceAfterOpenAngularBracket: Rule; NoSpaceBeforeCloseAngularBracket: Rule; NoSpaceAfterCloseAngularBracket: Rule; - NoSpaceAfterTypeAssertion: Rule; NoSpaceBetweenEmptyInterfaceBraceBrackets: Rule; HighPriorityCommonRules: Rule[]; LowPriorityCommonRules: Rule[]; @@ -8728,6 +10119,8 @@ declare namespace ts.formatting { NoSpaceBeforeGreaterThanTokenInJsxOpeningElement: Rule; NoSpaceBeforeEqualInJsxAttribute: Rule; NoSpaceAfterEqualInJsxAttribute: Rule; + NoSpaceAfterTypeAssertion: Rule; + SpaceAfterTypeAssertion: Rule; constructor(); static IsForContext(context: FormattingContext): boolean; static IsNotForContext(context: FormattingContext): boolean; @@ -8872,7 +10265,7 @@ declare namespace ts.formatting { getRuleName(rule: Rule): string; getRuleByName(name: string): Rule; getRulesMap(): RulesMap; - ensureUpToDate(options: ts.FormatCodeOptions): void; + ensureUpToDate(options: ts.FormatCodeSettings): void; private createActiveRules(options); } } @@ -8885,60 +10278,43 @@ declare namespace ts.formatting { token: TextRangeWithKind; trailingTrivia: TextRangeWithKind[]; } - function formatOnEnter(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[]; - function formatOnSemicolon(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[]; - function formatOnClosingCurly(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[]; - function formatDocument(sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[]; - function formatSelection(start: number, end: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[]; - function getIndentationString(indentation: number, options: FormatCodeOptions): string; + function formatOnEnter(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[]; + function formatOnSemicolon(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[]; + function formatOnClosingCurly(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[]; + function formatDocument(sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[]; + function formatSelection(start: number, end: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[]; + function getIndentationString(indentation: number, options: EditorSettings): string; } declare namespace ts.formatting { namespace SmartIndenter { - function getIndentation(position: number, sourceFile: SourceFile, options: EditorOptions): number; - function getBaseIndentation(options: EditorOptions): number; - function getIndentationForNode(n: Node, ignoreActualIndentationRange: TextRange, sourceFile: SourceFile, options: FormatCodeOptions): number; + function getIndentation(position: number, sourceFile: SourceFile, options: EditorSettings): number; + function getIndentationForNode(n: Node, ignoreActualIndentationRange: TextRange, sourceFile: SourceFile, options: EditorSettings): number; + function getBaseIndentation(options: EditorSettings): number; function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFile): boolean; - function findFirstNonWhitespaceCharacterAndColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorOptions): { + function findFirstNonWhitespaceCharacterAndColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorSettings): { column: number; character: number; }; - function findFirstNonWhitespaceColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorOptions): number; + function findFirstNonWhitespaceColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorSettings): number; function nodeWillIndentChild(parent: TextRangeWithKind, child: TextRangeWithKind, indentByDefault: boolean): boolean; function shouldIndentChildNode(parent: TextRangeWithKind, child?: TextRangeWithKind): boolean; } } declare namespace ts { /** The version of the language service API */ - const servicesVersion: string; + const servicesVersion = "0.5"; interface DisplayPartsSymbolWriter extends SymbolWriter { displayParts(): SymbolDisplayPart[]; } + function toEditorSettings(options: FormatCodeOptions | FormatCodeSettings): FormatCodeSettings; + function toEditorSettings(options: EditorOptions | EditorSettings): EditorSettings; function displayPartsToString(displayParts: SymbolDisplayPart[]): string; function getDefaultCompilerOptions(): CompilerOptions; - interface TranspileOptions { - compilerOptions?: CompilerOptions; - fileName?: string; - reportDiagnostics?: boolean; - moduleName?: string; - renamedDependencies?: MapLike; - } - interface TranspileOutput { - outputText: string; - diagnostics?: Diagnostic[]; - sourceMapText?: string; - } - function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput; - function transpile(input: string, compilerOptions?: CompilerOptions, fileName?: string, diagnostics?: Diagnostic[], moduleName?: string): string; function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, setNodeParents: boolean, scriptKind?: ScriptKind): SourceFile; let disableIncrementalParsing: boolean; function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile; - function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory?: string): DocumentRegistry; - function preProcessFile(sourceText: string, readImportFiles?: boolean, detectJavaScriptImports?: boolean): PreProcessedFileInfo; - function getContainerNode(node: Node): Declaration; - function getNodeKind(node: Node): string; function createLanguageService(host: LanguageServiceHost, documentRegistry?: DocumentRegistry): LanguageService; function getNameTable(sourceFile: SourceFile): Map; - function createClassifier(): Classifier; /** * Get the path of the default library files (lib.d.ts) as distributed with the typescript * node package. @@ -8990,6 +10366,10 @@ declare namespace ts { getNewLine?(): string; getProjectVersion?(): string; useCaseSensitiveFileNames?(): boolean; + getTypeRootsVersion?(): number; + readDirectory(rootDir: string, extension: string, basePaths?: string, excludeEx?: string, includeFileEx?: string, includeDirEx?: string, depth?: number): string; + readFile(path: string, encoding?: string): string; + fileExists(path: string): boolean; getModuleResolutionsForFile?(fileName: string): string; getTypeReferenceDirectiveResolutionsForFile?(fileName: string): string; directoryExists(directoryName: string): boolean; @@ -9070,6 +10450,11 @@ declare namespace ts { * Or undefined value if no definition can be found. */ getTypeDefinitionAtPosition(fileName: string, position: number): string; + /** + * Returns a JSON-encoded value of the type: + * { fileName: string; textSpan: { start: number; length: number}; }[] + */ + getImplementationAtPosition(fileName: string, position: number): string; /** * Returns a JSON-encoded value of the type: * { fileName: string; textSpan: { start: number; length: number}; isWriteAccess: boolean, isDefinition?: boolean }[] @@ -9098,7 +10483,7 @@ declare namespace ts { * Returns a JSON-encoded value of the type: * { name: string; kind: string; kindModifiers: string; containerName: string; containerKind: string; matchKind: string; fileName: string; textSpan: { start: number; length: number}; } [] = []; */ - getNavigateToItems(searchValue: string, maxResultCount?: number): string; + getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string): string; /** * Returns a JSON-encoded value of the type: * { text: string; kind: string; kindModifiers: string; bolded: boolean; grayed: boolean; indent: number; spans: { start: number; length: number; }[]; childItems: [] } [] = []; @@ -9152,6 +10537,7 @@ declare namespace ts { trace(s: string): void; error(s: string): void; getProjectVersion(): string; + getTypeRootsVersion(): number; useCaseSensitiveFileNames(): boolean; getCompilationSettings(): CompilerOptions; getScriptFileNames(): string[]; @@ -9163,6 +10549,9 @@ declare namespace ts { getCurrentDirectory(): string; getDirectories(path: string): string[]; getDefaultLibFileName(options: CompilerOptions): string; + readDirectory(path: string, extensions?: string[], exclude?: string[], include?: string[], depth?: number): string[]; + readFile(path: string, encoding?: string): string; + fileExists(path: string): boolean; } class CoreServicesShimHostAdapter implements ParseConfigHost, ModuleResolutionHost { private shimHost; @@ -9198,7 +10587,7 @@ declare namespace ts { declare namespace TypeScript.Services { const TypeScriptServicesFactory: typeof ts.TypeScriptServicesFactory; } -declare const toolsVersion: string; +declare const toolsVersion = "2.1"; /** * Sample: add a new utility function */ diff --git a/bin/typescript.js b/bin/typescript.js index 37ee435..4346c0f 100644 --- a/bin/typescript.js +++ b/bin/typescript.js @@ -325,11 +325,16 @@ var ts; SyntaxKind[SyntaxKind["JSDocNeverKeyword"] = 285] = "JSDocNeverKeyword"; // Synthesized list SyntaxKind[SyntaxKind["SyntaxList"] = 286] = "SyntaxList"; + // Transformation nodes + SyntaxKind[SyntaxKind["NotEmittedStatement"] = 287] = "NotEmittedStatement"; + SyntaxKind[SyntaxKind["PartiallyEmittedExpression"] = 288] = "PartiallyEmittedExpression"; // Enum value count - SyntaxKind[SyntaxKind["Count"] = 287] = "Count"; + SyntaxKind[SyntaxKind["Count"] = 289] = "Count"; // Markers SyntaxKind[SyntaxKind["FirstAssignment"] = 56] = "FirstAssignment"; SyntaxKind[SyntaxKind["LastAssignment"] = 68] = "LastAssignment"; + SyntaxKind[SyntaxKind["FirstCompoundAssignment"] = 57] = "FirstCompoundAssignment"; + SyntaxKind[SyntaxKind["LastCompoundAssignment"] = 68] = "LastCompoundAssignment"; SyntaxKind[SyntaxKind["FirstReservedWord"] = 70] = "FirstReservedWord"; SyntaxKind[SyntaxKind["LastReservedWord"] = 105] = "LastReservedWord"; SyntaxKind[SyntaxKind["FirstKeyword"] = 70] = "FirstKeyword"; @@ -359,51 +364,59 @@ var ts; var SyntaxKind = ts.SyntaxKind; (function (NodeFlags) { NodeFlags[NodeFlags["None"] = 0] = "None"; - NodeFlags[NodeFlags["Export"] = 1] = "Export"; - NodeFlags[NodeFlags["Ambient"] = 2] = "Ambient"; - NodeFlags[NodeFlags["Public"] = 4] = "Public"; - NodeFlags[NodeFlags["Private"] = 8] = "Private"; - NodeFlags[NodeFlags["Protected"] = 16] = "Protected"; - NodeFlags[NodeFlags["Static"] = 32] = "Static"; - NodeFlags[NodeFlags["Readonly"] = 64] = "Readonly"; - NodeFlags[NodeFlags["Abstract"] = 128] = "Abstract"; - NodeFlags[NodeFlags["Async"] = 256] = "Async"; - NodeFlags[NodeFlags["Default"] = 512] = "Default"; - NodeFlags[NodeFlags["Let"] = 1024] = "Let"; - NodeFlags[NodeFlags["Const"] = 2048] = "Const"; - NodeFlags[NodeFlags["Namespace"] = 4096] = "Namespace"; - NodeFlags[NodeFlags["ExportContext"] = 8192] = "ExportContext"; - NodeFlags[NodeFlags["ContainsThis"] = 16384] = "ContainsThis"; - NodeFlags[NodeFlags["HasImplicitReturn"] = 32768] = "HasImplicitReturn"; - NodeFlags[NodeFlags["HasExplicitReturn"] = 65536] = "HasExplicitReturn"; - NodeFlags[NodeFlags["GlobalAugmentation"] = 131072] = "GlobalAugmentation"; - NodeFlags[NodeFlags["HasClassExtends"] = 262144] = "HasClassExtends"; - NodeFlags[NodeFlags["HasDecorators"] = 524288] = "HasDecorators"; - NodeFlags[NodeFlags["HasParamDecorators"] = 1048576] = "HasParamDecorators"; - NodeFlags[NodeFlags["HasAsyncFunctions"] = 2097152] = "HasAsyncFunctions"; - NodeFlags[NodeFlags["DisallowInContext"] = 4194304] = "DisallowInContext"; - NodeFlags[NodeFlags["YieldContext"] = 8388608] = "YieldContext"; - NodeFlags[NodeFlags["DecoratorContext"] = 16777216] = "DecoratorContext"; - NodeFlags[NodeFlags["AwaitContext"] = 33554432] = "AwaitContext"; - NodeFlags[NodeFlags["ThisNodeHasError"] = 67108864] = "ThisNodeHasError"; - NodeFlags[NodeFlags["JavaScriptFile"] = 134217728] = "JavaScriptFile"; - NodeFlags[NodeFlags["ThisNodeOrAnySubNodesHasError"] = 268435456] = "ThisNodeOrAnySubNodesHasError"; - NodeFlags[NodeFlags["HasAggregatedChildData"] = 536870912] = "HasAggregatedChildData"; - NodeFlags[NodeFlags["HasJsxSpreadAttribute"] = 1073741824] = "HasJsxSpreadAttribute"; - NodeFlags[NodeFlags["Modifier"] = 1023] = "Modifier"; - NodeFlags[NodeFlags["AccessibilityModifier"] = 28] = "AccessibilityModifier"; - // Accessibility modifiers and 'readonly' can be attached to a parameter in a constructor to make it a property. - NodeFlags[NodeFlags["ParameterPropertyModifier"] = 92] = "ParameterPropertyModifier"; - NodeFlags[NodeFlags["BlockScoped"] = 3072] = "BlockScoped"; - NodeFlags[NodeFlags["ReachabilityCheckFlags"] = 98304] = "ReachabilityCheckFlags"; - NodeFlags[NodeFlags["EmitHelperFlags"] = 3932160] = "EmitHelperFlags"; - NodeFlags[NodeFlags["ReachabilityAndEmitFlags"] = 4030464] = "ReachabilityAndEmitFlags"; + NodeFlags[NodeFlags["Let"] = 1] = "Let"; + NodeFlags[NodeFlags["Const"] = 2] = "Const"; + NodeFlags[NodeFlags["NestedNamespace"] = 4] = "NestedNamespace"; + NodeFlags[NodeFlags["Synthesized"] = 8] = "Synthesized"; + NodeFlags[NodeFlags["Namespace"] = 16] = "Namespace"; + NodeFlags[NodeFlags["ExportContext"] = 32] = "ExportContext"; + NodeFlags[NodeFlags["ContainsThis"] = 64] = "ContainsThis"; + NodeFlags[NodeFlags["HasImplicitReturn"] = 128] = "HasImplicitReturn"; + NodeFlags[NodeFlags["HasExplicitReturn"] = 256] = "HasExplicitReturn"; + NodeFlags[NodeFlags["GlobalAugmentation"] = 512] = "GlobalAugmentation"; + NodeFlags[NodeFlags["HasClassExtends"] = 1024] = "HasClassExtends"; + NodeFlags[NodeFlags["HasDecorators"] = 2048] = "HasDecorators"; + NodeFlags[NodeFlags["HasParamDecorators"] = 4096] = "HasParamDecorators"; + NodeFlags[NodeFlags["HasAsyncFunctions"] = 8192] = "HasAsyncFunctions"; + NodeFlags[NodeFlags["HasJsxSpreadAttributes"] = 16384] = "HasJsxSpreadAttributes"; + NodeFlags[NodeFlags["DisallowInContext"] = 32768] = "DisallowInContext"; + NodeFlags[NodeFlags["YieldContext"] = 65536] = "YieldContext"; + NodeFlags[NodeFlags["DecoratorContext"] = 131072] = "DecoratorContext"; + NodeFlags[NodeFlags["AwaitContext"] = 262144] = "AwaitContext"; + NodeFlags[NodeFlags["ThisNodeHasError"] = 524288] = "ThisNodeHasError"; + NodeFlags[NodeFlags["JavaScriptFile"] = 1048576] = "JavaScriptFile"; + NodeFlags[NodeFlags["ThisNodeOrAnySubNodesHasError"] = 2097152] = "ThisNodeOrAnySubNodesHasError"; + NodeFlags[NodeFlags["HasAggregatedChildData"] = 4194304] = "HasAggregatedChildData"; + NodeFlags[NodeFlags["BlockScoped"] = 3] = "BlockScoped"; + NodeFlags[NodeFlags["ReachabilityCheckFlags"] = 384] = "ReachabilityCheckFlags"; + NodeFlags[NodeFlags["EmitHelperFlags"] = 31744] = "EmitHelperFlags"; + NodeFlags[NodeFlags["ReachabilityAndEmitFlags"] = 32128] = "ReachabilityAndEmitFlags"; // Parsing context flags - NodeFlags[NodeFlags["ContextFlags"] = 197132288] = "ContextFlags"; + NodeFlags[NodeFlags["ContextFlags"] = 1540096] = "ContextFlags"; // Exclude these flags when parsing a Type - NodeFlags[NodeFlags["TypeExcludesFlags"] = 41943040] = "TypeExcludesFlags"; + NodeFlags[NodeFlags["TypeExcludesFlags"] = 327680] = "TypeExcludesFlags"; })(ts.NodeFlags || (ts.NodeFlags = {})); var NodeFlags = ts.NodeFlags; + (function (ModifierFlags) { + ModifierFlags[ModifierFlags["None"] = 0] = "None"; + ModifierFlags[ModifierFlags["Export"] = 1] = "Export"; + ModifierFlags[ModifierFlags["Ambient"] = 2] = "Ambient"; + ModifierFlags[ModifierFlags["Public"] = 4] = "Public"; + ModifierFlags[ModifierFlags["Private"] = 8] = "Private"; + ModifierFlags[ModifierFlags["Protected"] = 16] = "Protected"; + ModifierFlags[ModifierFlags["Static"] = 32] = "Static"; + ModifierFlags[ModifierFlags["Readonly"] = 64] = "Readonly"; + ModifierFlags[ModifierFlags["Abstract"] = 128] = "Abstract"; + ModifierFlags[ModifierFlags["Async"] = 256] = "Async"; + ModifierFlags[ModifierFlags["Default"] = 512] = "Default"; + ModifierFlags[ModifierFlags["Const"] = 2048] = "Const"; + ModifierFlags[ModifierFlags["HasComputedFlags"] = 536870912] = "HasComputedFlags"; + ModifierFlags[ModifierFlags["AccessibilityModifier"] = 28] = "AccessibilityModifier"; + // Accessibility modifiers and 'readonly' can be attached to a parameter in a constructor to make it a property. + ModifierFlags[ModifierFlags["ParameterPropertyModifier"] = 92] = "ParameterPropertyModifier"; + ModifierFlags[ModifierFlags["NonPublicAccessibilityModifier"] = 24] = "NonPublicAccessibilityModifier"; + })(ts.ModifierFlags || (ts.ModifierFlags = {})); + var ModifierFlags = ts.ModifierFlags; (function (JsxFlags) { JsxFlags[JsxFlags["None"] = 0] = "None"; /** An element from a named property of the JSX.IntrinsicElements interface */ @@ -420,6 +433,15 @@ var ts; RelationComparisonResult[RelationComparisonResult["FailedAndReported"] = 3] = "FailedAndReported"; })(ts.RelationComparisonResult || (ts.RelationComparisonResult = {})); var RelationComparisonResult = ts.RelationComparisonResult; + /*@internal*/ + (function (GeneratedIdentifierKind) { + GeneratedIdentifierKind[GeneratedIdentifierKind["None"] = 0] = "None"; + GeneratedIdentifierKind[GeneratedIdentifierKind["Auto"] = 1] = "Auto"; + GeneratedIdentifierKind[GeneratedIdentifierKind["Loop"] = 2] = "Loop"; + GeneratedIdentifierKind[GeneratedIdentifierKind["Unique"] = 3] = "Unique"; + GeneratedIdentifierKind[GeneratedIdentifierKind["Node"] = 4] = "Node"; + })(ts.GeneratedIdentifierKind || (ts.GeneratedIdentifierKind = {})); + var GeneratedIdentifierKind = ts.GeneratedIdentifierKind; (function (FlowFlags) { FlowFlags[FlowFlags["Unreachable"] = 1] = "Unreachable"; FlowFlags[FlowFlags["Start"] = 2] = "Start"; @@ -465,6 +487,7 @@ var ts; TypeFormatFlags[TypeFormatFlags["UseFullyQualifiedType"] = 128] = "UseFullyQualifiedType"; TypeFormatFlags[TypeFormatFlags["InFirstTypeArgument"] = 256] = "InFirstTypeArgument"; TypeFormatFlags[TypeFormatFlags["InTypeAlias"] = 512] = "InTypeAlias"; + TypeFormatFlags[TypeFormatFlags["UseTypeAliasValue"] = 1024] = "UseTypeAliasValue"; })(ts.TypeFormatFlags || (ts.TypeFormatFlags = {})); var TypeFormatFlags = ts.TypeFormatFlags; (function (SymbolFormatFlags) { @@ -502,15 +525,16 @@ var ts; // function that can be reached at runtime (e.g. a `class` // declaration or a `var` declaration for the static side // of a type, such as the global `Promise` type in lib.d.ts). - TypeReferenceSerializationKind[TypeReferenceSerializationKind["VoidType"] = 2] = "VoidType"; + TypeReferenceSerializationKind[TypeReferenceSerializationKind["VoidNullableOrNeverType"] = 2] = "VoidNullableOrNeverType"; TypeReferenceSerializationKind[TypeReferenceSerializationKind["NumberLikeType"] = 3] = "NumberLikeType"; TypeReferenceSerializationKind[TypeReferenceSerializationKind["StringLikeType"] = 4] = "StringLikeType"; TypeReferenceSerializationKind[TypeReferenceSerializationKind["BooleanType"] = 5] = "BooleanType"; TypeReferenceSerializationKind[TypeReferenceSerializationKind["ArrayLikeType"] = 6] = "ArrayLikeType"; TypeReferenceSerializationKind[TypeReferenceSerializationKind["ESSymbolType"] = 7] = "ESSymbolType"; - TypeReferenceSerializationKind[TypeReferenceSerializationKind["TypeWithCallSignature"] = 8] = "TypeWithCallSignature"; + TypeReferenceSerializationKind[TypeReferenceSerializationKind["Promise"] = 8] = "Promise"; + TypeReferenceSerializationKind[TypeReferenceSerializationKind["TypeWithCallSignature"] = 9] = "TypeWithCallSignature"; // with call signatures. - TypeReferenceSerializationKind[TypeReferenceSerializationKind["ObjectType"] = 9] = "ObjectType"; + TypeReferenceSerializationKind[TypeReferenceSerializationKind["ObjectType"] = 10] = "ObjectType"; })(ts.TypeReferenceSerializationKind || (ts.TypeReferenceSerializationKind = {})); var TypeReferenceSerializationKind = ts.TypeReferenceSerializationKind; (function (SymbolFlags) { @@ -609,6 +633,8 @@ var ts; NodeCheckFlags[NodeCheckFlags["BodyScopedClassBinding"] = 1048576] = "BodyScopedClassBinding"; NodeCheckFlags[NodeCheckFlags["NeedsLoopOutParameter"] = 2097152] = "NeedsLoopOutParameter"; NodeCheckFlags[NodeCheckFlags["AssignmentsMarked"] = 4194304] = "AssignmentsMarked"; + NodeCheckFlags[NodeCheckFlags["ClassWithConstructorReference"] = 8388608] = "ClassWithConstructorReference"; + NodeCheckFlags[NodeCheckFlags["ConstructorReferenceInClass"] = 16777216] = "ConstructorReferenceInClass"; })(ts.NodeCheckFlags || (ts.NodeCheckFlags = {})); var NodeCheckFlags = ts.NodeCheckFlags; (function (TypeFlags) { @@ -638,7 +664,7 @@ var ts; /* @internal */ TypeFlags[TypeFlags["ObjectLiteral"] = 8388608] = "ObjectLiteral"; /* @internal */ - TypeFlags[TypeFlags["FreshObjectLiteral"] = 16777216] = "FreshObjectLiteral"; + TypeFlags[TypeFlags["FreshLiteral"] = 16777216] = "FreshLiteral"; /* @internal */ TypeFlags[TypeFlags["ContainsWideningType"] = 33554432] = "ContainsWideningType"; /* @internal */ @@ -650,6 +676,7 @@ var ts; /* @internal */ TypeFlags[TypeFlags["Nullable"] = 6144] = "Nullable"; TypeFlags[TypeFlags["Literal"] = 480] = "Literal"; + TypeFlags[TypeFlags["StringOrNumberLiteral"] = 96] = "StringOrNumberLiteral"; /* @internal */ TypeFlags[TypeFlags["DefinitelyFalsy"] = 7392] = "DefinitelyFalsy"; TypeFlags[TypeFlags["PossiblyFalsy"] = 7406] = "PossiblyFalsy"; @@ -891,6 +918,105 @@ var ts; CharacterCodes[CharacterCodes["verticalTab"] = 11] = "verticalTab"; })(ts.CharacterCodes || (ts.CharacterCodes = {})); var CharacterCodes = ts.CharacterCodes; + /* @internal */ + (function (TransformFlags) { + TransformFlags[TransformFlags["None"] = 0] = "None"; + // Facts + // - Flags used to indicate that a node or subtree contains syntax that requires transformation. + TransformFlags[TransformFlags["TypeScript"] = 1] = "TypeScript"; + TransformFlags[TransformFlags["ContainsTypeScript"] = 2] = "ContainsTypeScript"; + TransformFlags[TransformFlags["Jsx"] = 4] = "Jsx"; + TransformFlags[TransformFlags["ContainsJsx"] = 8] = "ContainsJsx"; + TransformFlags[TransformFlags["ES7"] = 16] = "ES7"; + TransformFlags[TransformFlags["ContainsES7"] = 32] = "ContainsES7"; + TransformFlags[TransformFlags["ES6"] = 64] = "ES6"; + TransformFlags[TransformFlags["ContainsES6"] = 128] = "ContainsES6"; + TransformFlags[TransformFlags["DestructuringAssignment"] = 256] = "DestructuringAssignment"; + TransformFlags[TransformFlags["Generator"] = 512] = "Generator"; + TransformFlags[TransformFlags["ContainsGenerator"] = 1024] = "ContainsGenerator"; + // Markers + // - Flags used to indicate that a subtree contains a specific transformation. + TransformFlags[TransformFlags["ContainsDecorators"] = 2048] = "ContainsDecorators"; + TransformFlags[TransformFlags["ContainsPropertyInitializer"] = 4096] = "ContainsPropertyInitializer"; + TransformFlags[TransformFlags["ContainsLexicalThis"] = 8192] = "ContainsLexicalThis"; + TransformFlags[TransformFlags["ContainsCapturedLexicalThis"] = 16384] = "ContainsCapturedLexicalThis"; + TransformFlags[TransformFlags["ContainsLexicalThisInComputedPropertyName"] = 32768] = "ContainsLexicalThisInComputedPropertyName"; + TransformFlags[TransformFlags["ContainsDefaultValueAssignments"] = 65536] = "ContainsDefaultValueAssignments"; + TransformFlags[TransformFlags["ContainsParameterPropertyAssignments"] = 131072] = "ContainsParameterPropertyAssignments"; + TransformFlags[TransformFlags["ContainsSpreadElementExpression"] = 262144] = "ContainsSpreadElementExpression"; + TransformFlags[TransformFlags["ContainsComputedPropertyName"] = 524288] = "ContainsComputedPropertyName"; + TransformFlags[TransformFlags["ContainsBlockScopedBinding"] = 1048576] = "ContainsBlockScopedBinding"; + TransformFlags[TransformFlags["ContainsBindingPattern"] = 2097152] = "ContainsBindingPattern"; + TransformFlags[TransformFlags["ContainsYield"] = 4194304] = "ContainsYield"; + TransformFlags[TransformFlags["ContainsHoistedDeclarationOrCompletion"] = 8388608] = "ContainsHoistedDeclarationOrCompletion"; + TransformFlags[TransformFlags["HasComputedFlags"] = 536870912] = "HasComputedFlags"; + // Assertions + // - Bitmasks that are used to assert facts about the syntax of a node and its subtree. + TransformFlags[TransformFlags["AssertTypeScript"] = 3] = "AssertTypeScript"; + TransformFlags[TransformFlags["AssertJsx"] = 12] = "AssertJsx"; + TransformFlags[TransformFlags["AssertES7"] = 48] = "AssertES7"; + TransformFlags[TransformFlags["AssertES6"] = 192] = "AssertES6"; + TransformFlags[TransformFlags["AssertGenerator"] = 1536] = "AssertGenerator"; + // Scope Exclusions + // - Bitmasks that exclude flags from propagating out of a specific context + // into the subtree flags of their container. + TransformFlags[TransformFlags["NodeExcludes"] = 536871765] = "NodeExcludes"; + TransformFlags[TransformFlags["ArrowFunctionExcludes"] = 550710101] = "ArrowFunctionExcludes"; + TransformFlags[TransformFlags["FunctionExcludes"] = 550726485] = "FunctionExcludes"; + TransformFlags[TransformFlags["ConstructorExcludes"] = 550593365] = "ConstructorExcludes"; + TransformFlags[TransformFlags["MethodOrAccessorExcludes"] = 550593365] = "MethodOrAccessorExcludes"; + TransformFlags[TransformFlags["ClassExcludes"] = 537590613] = "ClassExcludes"; + TransformFlags[TransformFlags["ModuleExcludes"] = 546335573] = "ModuleExcludes"; + TransformFlags[TransformFlags["TypeExcludes"] = -3] = "TypeExcludes"; + TransformFlags[TransformFlags["ObjectLiteralExcludes"] = 537430869] = "ObjectLiteralExcludes"; + TransformFlags[TransformFlags["ArrayLiteralOrCallOrNewExcludes"] = 537133909] = "ArrayLiteralOrCallOrNewExcludes"; + TransformFlags[TransformFlags["VariableDeclarationListExcludes"] = 538968917] = "VariableDeclarationListExcludes"; + TransformFlags[TransformFlags["ParameterExcludes"] = 538968917] = "ParameterExcludes"; + // Masks + // - Additional bitmasks + TransformFlags[TransformFlags["TypeScriptClassSyntaxMask"] = 137216] = "TypeScriptClassSyntaxMask"; + TransformFlags[TransformFlags["ES6FunctionSyntaxMask"] = 81920] = "ES6FunctionSyntaxMask"; + })(ts.TransformFlags || (ts.TransformFlags = {})); + var TransformFlags = ts.TransformFlags; + /* @internal */ + (function (EmitFlags) { + EmitFlags[EmitFlags["EmitEmitHelpers"] = 1] = "EmitEmitHelpers"; + EmitFlags[EmitFlags["EmitExportStar"] = 2] = "EmitExportStar"; + EmitFlags[EmitFlags["EmitSuperHelper"] = 4] = "EmitSuperHelper"; + EmitFlags[EmitFlags["EmitAdvancedSuperHelper"] = 8] = "EmitAdvancedSuperHelper"; + EmitFlags[EmitFlags["UMDDefine"] = 16] = "UMDDefine"; + EmitFlags[EmitFlags["SingleLine"] = 32] = "SingleLine"; + EmitFlags[EmitFlags["AdviseOnEmitNode"] = 64] = "AdviseOnEmitNode"; + EmitFlags[EmitFlags["NoSubstitution"] = 128] = "NoSubstitution"; + EmitFlags[EmitFlags["CapturesThis"] = 256] = "CapturesThis"; + EmitFlags[EmitFlags["NoLeadingSourceMap"] = 512] = "NoLeadingSourceMap"; + EmitFlags[EmitFlags["NoTrailingSourceMap"] = 1024] = "NoTrailingSourceMap"; + EmitFlags[EmitFlags["NoSourceMap"] = 1536] = "NoSourceMap"; + EmitFlags[EmitFlags["NoNestedSourceMaps"] = 2048] = "NoNestedSourceMaps"; + EmitFlags[EmitFlags["NoTokenLeadingSourceMaps"] = 4096] = "NoTokenLeadingSourceMaps"; + EmitFlags[EmitFlags["NoTokenTrailingSourceMaps"] = 8192] = "NoTokenTrailingSourceMaps"; + EmitFlags[EmitFlags["NoTokenSourceMaps"] = 12288] = "NoTokenSourceMaps"; + EmitFlags[EmitFlags["NoLeadingComments"] = 16384] = "NoLeadingComments"; + EmitFlags[EmitFlags["NoTrailingComments"] = 32768] = "NoTrailingComments"; + EmitFlags[EmitFlags["NoComments"] = 49152] = "NoComments"; + EmitFlags[EmitFlags["NoNestedComments"] = 65536] = "NoNestedComments"; + EmitFlags[EmitFlags["ExportName"] = 131072] = "ExportName"; + EmitFlags[EmitFlags["LocalName"] = 262144] = "LocalName"; + EmitFlags[EmitFlags["Indented"] = 524288] = "Indented"; + EmitFlags[EmitFlags["NoIndentation"] = 1048576] = "NoIndentation"; + EmitFlags[EmitFlags["AsyncFunctionBody"] = 2097152] = "AsyncFunctionBody"; + EmitFlags[EmitFlags["ReuseTempVariableScope"] = 4194304] = "ReuseTempVariableScope"; + EmitFlags[EmitFlags["CustomPrologue"] = 8388608] = "CustomPrologue"; + })(ts.EmitFlags || (ts.EmitFlags = {})); + var EmitFlags = ts.EmitFlags; + /* @internal */ + (function (EmitContext) { + EmitContext[EmitContext["SourceFile"] = 0] = "SourceFile"; + EmitContext[EmitContext["Expression"] = 1] = "Expression"; + EmitContext[EmitContext["IdentifierName"] = 2] = "IdentifierName"; + EmitContext[EmitContext["Unspecified"] = 3] = "Unspecified"; + })(ts.EmitContext || (ts.EmitContext = {})); + var EmitContext = ts.EmitContext; })(ts || (ts = {})); /*@internal*/ var ts; @@ -1032,6 +1158,7 @@ var ts; contains: contains, remove: remove, forEachValue: forEachValueInMap, + getKeys: getKeys, clear: clear, }; function forEachValueInMap(f) { @@ -1039,6 +1166,13 @@ var ts; f(key, files[key]); } } + function getKeys() { + var keys = []; + for (var key in files) { + keys.push(key); + } + return keys; + } // path should already be well-formed so it does not need to be normalized function get(path) { return files[toKey(path)]; @@ -1091,6 +1225,22 @@ var ts; return undefined; } ts.forEach = forEach; + /** + * Iterates through `array` by index and performs the callback on each element of array until the callback + * returns a falsey value, then returns false. + * If no such value is found, the callback is applied to each element of array and `true` is returned. + */ + function every(array, callback) { + if (array) { + for (var i = 0, len = array.length; i < len; i++) { + if (!callback(array[i], i)) { + return false; + } + } + } + return true; + } + ts.every = every; /** Works like Array.prototype.find, returning `undefined` if no element satisfying the predicate is found. */ function find(array, predicate) { for (var i = 0, len = array.length; i < len; i++) { @@ -1151,9 +1301,9 @@ var ts; function countWhere(array, predicate) { var count = 0; if (array) { - for (var _i = 0, array_2 = array; _i < array_2.length; _i++) { - var v = array_2[_i]; - if (predicate(v)) { + for (var i = 0; i < array.length; i++) { + var v = array[i]; + if (predicate(v, i)) { count++; } } @@ -1161,10 +1311,6 @@ var ts; return count; } ts.countWhere = countWhere; - /** - * Filters an array by a predicate function. Returns the same array instance if the predicate is - * true for all elements, otherwise returns a new array instance containing the filtered subset. - */ function filter(array, f) { if (array) { var len = array.length; @@ -1189,8 +1335,8 @@ var ts; ts.filter = filter; function removeWhere(array, f) { var outIndex = 0; - for (var _i = 0, array_3 = array; _i < array_3.length; _i++) { - var item = array_3[_i]; + for (var _i = 0, array_2 = array; _i < array_2.length; _i++) { + var item = array_2[_i]; if (!f(item)) { array[outIndex] = item; outIndex++; @@ -1205,8 +1351,8 @@ var ts; ts.removeWhere = removeWhere; function filterMutate(array, f) { var outIndex = 0; - for (var _i = 0, array_4 = array; _i < array_4.length; _i++) { - var item = array_4[_i]; + for (var _i = 0, array_3 = array; _i < array_3.length; _i++) { + var item = array_3[_i]; if (f(item)) { array[outIndex] = item; outIndex++; @@ -1219,14 +1365,136 @@ var ts; var result; if (array) { result = []; - for (var _i = 0, array_5 = array; _i < array_5.length; _i++) { - var v = array_5[_i]; - result.push(f(v)); + for (var i = 0; i < array.length; i++) { + var v = array[i]; + result.push(f(v, i)); } } return result; } ts.map = map; + /** + * Flattens an array containing a mix of array or non-array elements. + * + * @param array The array to flatten. + */ + function flatten(array) { + var result; + if (array) { + result = []; + for (var _i = 0, array_4 = array; _i < array_4.length; _i++) { + var v = array_4[_i]; + if (v) { + if (isArray(v)) { + addRange(result, v); + } + else { + result.push(v); + } + } + } + } + return result; + } + ts.flatten = flatten; + /** + * Maps an array. If the mapped value is an array, it is spread into the result. + * + * @param array The array to map. + * @param mapfn The callback used to map the result into one or more values. + */ + function flatMap(array, mapfn) { + var result; + if (array) { + result = []; + for (var i = 0; i < array.length; i++) { + var v = mapfn(array[i], i); + if (v) { + if (isArray(v)) { + addRange(result, v); + } + else { + result.push(v); + } + } + } + } + return result; + } + ts.flatMap = flatMap; + /** + * Computes the first matching span of elements and returns a tuple of the first span + * and the remaining elements. + */ + function span(array, f) { + if (array) { + for (var i = 0; i < array.length; i++) { + if (!f(array[i], i)) { + return [array.slice(0, i), array.slice(i)]; + } + } + return [array.slice(0), []]; + } + return undefined; + } + ts.span = span; + /** + * Maps contiguous spans of values with the same key. + * + * @param array The array to map. + * @param keyfn A callback used to select the key for an element. + * @param mapfn A callback used to map a contiguous chunk of values to a single value. + */ + function spanMap(array, keyfn, mapfn) { + var result; + if (array) { + result = []; + var len = array.length; + var previousKey = void 0; + var key = void 0; + var start = 0; + var pos = 0; + while (start < len) { + while (pos < len) { + var value = array[pos]; + key = keyfn(value, pos); + if (pos === 0) { + previousKey = key; + } + else if (key !== previousKey) { + break; + } + pos++; + } + if (start < pos) { + var v = mapfn(array.slice(start, pos), previousKey, start, pos); + if (v) { + result.push(v); + } + start = pos; + } + previousKey = key; + pos++; + } + } + return result; + } + ts.spanMap = spanMap; + function mapObject(object, f) { + var result; + if (object) { + result = {}; + for (var _i = 0, _a = getOwnKeys(object); _i < _a.length; _i++) { + var v = _a[_i]; + var _b = f(v, object[v]) || [undefined, undefined], key = _b[0], value = _b[1]; + if (key !== undefined) { + result[key] = value; + } + } + } + return result; + } + ts.mapObject = mapObject; function concatenate(array1, array2) { if (!array2 || !array2.length) return array1; @@ -1235,12 +1503,13 @@ var ts; return array1.concat(array2); } ts.concatenate = concatenate; + // TODO: fixme (N^2) - add optional comparer so collection can be sorted before deduplication. function deduplicate(array, areEqual) { var result; if (array) { result = []; - loop: for (var _i = 0, array_6 = array; _i < array_6.length; _i++) { - var item = array_6[_i]; + loop: for (var _i = 0, array_5 = array; _i < array_5.length; _i++) { + var item = array_5[_i]; for (var _a = 0, result_1 = result; _a < result_1.length; _a++) { var res = result_1[_a]; if (areEqual ? areEqual(res, item) : res === item) { @@ -1253,10 +1522,31 @@ var ts; return result; } ts.deduplicate = deduplicate; + /** + * Compacts an array, removing any falsey elements. + */ + function compact(array) { + var result; + if (array) { + for (var i = 0; i < array.length; i++) { + var v = array[i]; + if (result || !v) { + if (!result) { + result = array.slice(0, i); + } + if (v) { + result.push(v); + } + } + } + } + return result || array; + } + ts.compact = compact; function sum(array, prop) { var result = 0; - for (var _i = 0, array_7 = array; _i < array_7.length; _i++) { - var v = array_7[_i]; + for (var _i = 0, array_6 = array; _i < array_6.length; _i++) { + var v = array_6[_i]; result += v[prop]; } return result; @@ -1266,7 +1556,9 @@ var ts; if (to && from) { for (var _i = 0, from_1 = from; _i < from_1.length; _i++) { var v = from_1[_i]; - to.push(v); + if (v !== undefined) { + to.push(v); + } } } } @@ -1281,14 +1573,31 @@ var ts; return true; } ts.rangeEquals = rangeEquals; + function firstOrUndefined(array) { + return array && array.length > 0 + ? array[0] + : undefined; + } + ts.firstOrUndefined = firstOrUndefined; + function singleOrUndefined(array) { + return array && array.length === 1 + ? array[0] + : undefined; + } + ts.singleOrUndefined = singleOrUndefined; + function singleOrMany(array) { + return array && array.length === 1 + ? array[0] + : array; + } + ts.singleOrMany = singleOrMany; /** * Returns the last element of an array if non-empty, undefined otherwise. */ function lastOrUndefined(array) { - if (array.length === 0) { - return undefined; - } - return array[array.length - 1]; + return array && array.length > 0 + ? array[array.length - 1] + : undefined; } ts.lastOrUndefined = lastOrUndefined; /** @@ -1298,16 +1607,22 @@ var ts; * @param array A sorted array whose first element must be no larger than number * @param number The value to be searched for in the array. */ - function binarySearch(array, value) { + function binarySearch(array, value, comparer) { + if (!array || array.length === 0) { + return -1; + } var low = 0; var high = array.length - 1; + comparer = comparer !== undefined + ? comparer + : function (v1, v2) { return (v1 < v2 ? -1 : (v1 > v2 ? 1 : 0)); }; while (low <= high) { var middle = low + ((high - low) >> 1); var midValue = array[middle]; - if (midValue === value) { + if (comparer(midValue, value) === 0) { return middle; } - else if (midValue > value) { + else if (comparer(midValue, value) > 0) { high = middle - 1; } else { @@ -1317,11 +1632,12 @@ var ts; return ~low; } ts.binarySearch = binarySearch; - function reduceLeft(array, f, initial) { - if (array) { - var count = array.length; - if (count > 0) { - var pos = 0; + function reduceLeft(array, f, initial, start, count) { + if (array && array.length > 0) { + var size = array.length; + if (size > 0) { + var pos = start === undefined || start < 0 ? 0 : start; + var end = count === undefined || pos + count > size - 1 ? size - 1 : pos + count; var result = void 0; if (arguments.length <= 2) { result = array[pos]; @@ -1330,8 +1646,8 @@ var ts; else { result = initial; } - while (pos < count) { - result = f(result, array[pos]); + while (pos <= end) { + result = f(result, array[pos], pos); pos++; } return result; @@ -1340,10 +1656,12 @@ var ts; return initial; } ts.reduceLeft = reduceLeft; - function reduceRight(array, f, initial) { + function reduceRight(array, f, initial, start, count) { if (array) { - var pos = array.length - 1; - if (pos >= 0) { + var size = array.length; + if (size > 0) { + var pos = start === undefined || start > size - 1 ? size - 1 : start; + var end = count === undefined || pos - count < 0 ? 0 : pos - count; var result = void 0; if (arguments.length <= 2) { result = array[pos]; @@ -1352,8 +1670,8 @@ var ts; else { result = initial; } - while (pos >= 0) { - result = f(result, array[pos]); + while (pos >= end) { + result = f(result, array[pos], pos); pos--; } return result; @@ -1447,6 +1765,21 @@ var ts; } } ts.copyProperties = copyProperties; + function assign(t) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + for (var _a = 0, args_1 = args; _a < args_1.length; _a++) { + var arg = args_1[_a]; + for (var _b = 0, _c = getOwnKeys(arg); _b < _c.length; _b++) { + var p = _c[_b]; + t[p] = arg[p]; + } + } + return t; + } + ts.assign = assign; /** * Reduce the properties of a map. * @@ -1512,13 +1845,22 @@ var ts; ts.equalOwnProperties = equalOwnProperties; function arrayToMap(array, makeKey, makeValue) { var result = createMap(); - for (var _i = 0, array_8 = array; _i < array_8.length; _i++) { - var value = array_8[_i]; + for (var _i = 0, array_7 = array; _i < array_7.length; _i++) { + var value = array_7[_i]; result[makeKey(value)] = makeValue ? makeValue(value) : value; } return result; } ts.arrayToMap = arrayToMap; + function isEmpty(map) { + for (var id in map) { + if (hasProperty(map, id)) { + return false; + } + } + return true; + } + ts.isEmpty = isEmpty; function cloneMap(map) { var clone = createMap(); copyProperties(map, clone); @@ -1563,6 +1905,21 @@ var ts; } } ts.multiMapAdd = multiMapAdd; + /** + * Removes a value from an array of values associated with the key. + * Does not preserve the order of those values. + * Does nothing if `key` is not in `map`, or `value` is not in `map[key]`. + */ + function multiMapRemove(map, key, value) { + var values = map[key]; + if (values) { + unorderedRemoveItem(values, value); + if (!values.length) { + delete map[key]; + } + } + } + ts.multiMapRemove = multiMapRemove; /** * Tests whether a value is an array. */ @@ -1581,6 +1938,56 @@ var ts; }; } ts.memoize = memoize; + function chain(a, b, c, d, e) { + if (e) { + var args_2 = []; + for (var i = 0; i < arguments.length; i++) { + args_2[i] = arguments[i]; + } + return function (t) { return compose.apply(void 0, map(args_2, function (f) { return f(t); })); }; + } + else if (d) { + return function (t) { return compose(a(t), b(t), c(t), d(t)); }; + } + else if (c) { + return function (t) { return compose(a(t), b(t), c(t)); }; + } + else if (b) { + return function (t) { return compose(a(t), b(t)); }; + } + else if (a) { + return function (t) { return compose(a(t)); }; + } + else { + return function (t) { return function (u) { return u; }; }; + } + } + ts.chain = chain; + function compose(a, b, c, d, e) { + if (e) { + var args_3 = []; + for (var i = 0; i < arguments.length; i++) { + args_3[i] = arguments[i]; + } + return function (t) { return reduceLeft(args_3, function (u, f) { return f(u); }, t); }; + } + else if (d) { + return function (t) { return d(c(b(a(t)))); }; + } + else if (c) { + return function (t) { return c(b(a(t))); }; + } + else if (b) { + return function (t) { return b(a(t)); }; + } + else if (a) { + return function (t) { return a(t); }; + } + else { + return function (t) { return t; }; + } + } + ts.compose = compose; function formatStringFromArgs(text, args, baseIndex) { baseIndex = baseIndex || 0; return text.replace(/{(\d+)}/g, function (match, index) { return args[+index + baseIndex]; }); @@ -1782,6 +2189,7 @@ var ts; } ts.getRootLength = getRootLength; ts.directorySeparator = "/"; + var directorySeparatorCharCode = 47 /* slash */; function getNormalizedParts(normalizedSlashedPath, rootLength) { var parts = normalizedSlashedPath.substr(rootLength).split(ts.directorySeparator); var normalized = []; @@ -1805,10 +2213,22 @@ var ts; function normalizePath(path) { path = normalizeSlashes(path); var rootLength = getRootLength(path); + var root = path.substr(0, rootLength); var normalized = getNormalizedParts(path, rootLength); - return path.substr(0, rootLength) + normalized.join(ts.directorySeparator); + if (normalized.length) { + var joinedParts = root + normalized.join(ts.directorySeparator); + return pathEndsWithDirectorySeparator(path) ? joinedParts + ts.directorySeparator : joinedParts; + } + else { + return root; + } } ts.normalizePath = normalizePath; + /** A path ending with '/' refers to a directory only, never a file. */ + function pathEndsWithDirectorySeparator(path) { + return path.charCodeAt(path.length - 1) === directorySeparatorCharCode; + } + ts.pathEndsWithDirectorySeparator = pathEndsWithDirectorySeparator; function getDirectoryPath(path) { return path.substr(0, Math.max(getRootLength(path), path.lastIndexOf(ts.directorySeparator))); } @@ -1817,10 +2237,49 @@ var ts; return path && !isRootedDiskPath(path) && path.indexOf("://") !== -1; } ts.isUrl = isUrl; + function isExternalModuleNameRelative(moduleName) { + // TypeScript 1.0 spec (April 2014): 11.2.1 + // An external module name is "relative" if the first term is "." or "..". + return /^\.\.?($|[\\/])/.test(moduleName); + } + ts.isExternalModuleNameRelative = isExternalModuleNameRelative; + function getEmitScriptTarget(compilerOptions) { + return compilerOptions.target || 0 /* ES3 */; + } + ts.getEmitScriptTarget = getEmitScriptTarget; + function getEmitModuleKind(compilerOptions) { + return typeof compilerOptions.module === "number" ? + compilerOptions.module : + getEmitScriptTarget(compilerOptions) === 2 /* ES6 */ ? ts.ModuleKind.ES6 : ts.ModuleKind.CommonJS; + } + ts.getEmitModuleKind = getEmitModuleKind; + /* @internal */ + function hasZeroOrOneAsteriskCharacter(str) { + var seenAsterisk = false; + for (var i = 0; i < str.length; i++) { + if (str.charCodeAt(i) === 42 /* asterisk */) { + if (!seenAsterisk) { + seenAsterisk = true; + } + else { + // have already seen asterisk + return false; + } + } + } + return true; + } + ts.hasZeroOrOneAsteriskCharacter = hasZeroOrOneAsteriskCharacter; function isRootedDiskPath(path) { return getRootLength(path) !== 0; } ts.isRootedDiskPath = isRootedDiskPath; + function convertToRelativePath(absoluteOrRelativePath, basePath, getCanonicalFileName) { + return !isRootedDiskPath(absoluteOrRelativePath) + ? absoluteOrRelativePath + : getRelativePathToDirectoryOrUrl(basePath, absoluteOrRelativePath, basePath, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false); + } + ts.convertToRelativePath = convertToRelativePath; function normalizedPathComponents(path, rootLength) { var normalizedParts = getNormalizedParts(path, rootLength); return [path.substr(0, rootLength)].concat(normalizedParts); @@ -2264,6 +2723,14 @@ var ts; return options && options.allowJs ? allSupportedExtensions : ts.supportedTypeScriptExtensions; } ts.getSupportedExtensions = getSupportedExtensions; + function hasJavaScriptFileExtension(fileName) { + return forEach(ts.supportedJavascriptExtensions, function (extension) { return fileExtensionIs(fileName, extension); }); + } + ts.hasJavaScriptFileExtension = hasJavaScriptFileExtension; + function hasTypeScriptFileExtension(fileName) { + return forEach(ts.supportedTypeScriptExtensions, function (extension) { return fileExtensionIs(fileName, extension); }); + } + ts.hasTypeScriptFileExtension = hasTypeScriptFileExtension; function isSupportedSourceFileName(fileName, compilerOptions) { if (!fileName) { return false; @@ -2367,11 +2834,15 @@ var ts; function Signature(checker) { } function Node(kind, pos, end) { + this.id = 0; this.kind = kind; this.pos = pos; this.end = end; this.flags = 0 /* None */; + this.modifierFlagsCache = 0 /* None */; + this.transformFlags = 0 /* None */; this.parent = undefined; + this.original = undefined; } ts.objectAllocator = { getNodeConstructor: function () { return Node; }, @@ -2391,9 +2862,9 @@ var ts; var AssertionLevel = ts.AssertionLevel; var Debug; (function (Debug) { - var currentAssertionLevel = 0 /* None */; + var currentAssertionLevel; function shouldAssert(level) { - return currentAssertionLevel >= level; + return getCurrentAssertionLevel() >= level; } Debug.shouldAssert = shouldAssert; function assert(expression, message, verboseDebugInfo) { @@ -2411,7 +2882,30 @@ var ts; Debug.assert(/*expression*/ false, message); } Debug.fail = fail; + function getCurrentAssertionLevel() { + if (currentAssertionLevel !== undefined) { + return currentAssertionLevel; + } + if (ts.sys === undefined) { + return 0 /* None */; + } + var developmentMode = /^development$/i.test(getEnvironmentVariable("NODE_ENV")); + currentAssertionLevel = developmentMode + ? 1 /* Normal */ + : 0 /* None */; + return currentAssertionLevel; + } })(Debug = ts.Debug || (ts.Debug = {})); + function getEnvironmentVariable(name, host) { + if (host && host.getEnvironmentVariable) { + return host.getEnvironmentVariable(name); + } + if (ts.sys && ts.sys.getEnvironmentVariable) { + return ts.sys.getEnvironmentVariable(name); + } + return ""; + } + ts.getEnvironmentVariable = getEnvironmentVariable; /** Remove an item from an array, moving everything to its right one space left. */ function orderedRemoveItemAt(array, index) { // This seems to be faster than either `array.splice(i, 1)` or `array.copyWithin(i, i+ 1)`. @@ -2447,6 +2941,84 @@ var ts; : (function (fileName) { return fileName.toLowerCase(); }); } ts.createGetCanonicalFileName = createGetCanonicalFileName; + /** + * patternStrings contains both pattern strings (containing "*") and regular strings. + * Return an exact match if possible, or a pattern match, or undefined. + * (These are verified by verifyCompilerOptions to have 0 or 1 "*" characters.) + */ + /* @internal */ + function matchPatternOrExact(patternStrings, candidate) { + var patterns = []; + for (var _i = 0, patternStrings_1 = patternStrings; _i < patternStrings_1.length; _i++) { + var patternString = patternStrings_1[_i]; + var pattern = tryParsePattern(patternString); + if (pattern) { + patterns.push(pattern); + } + else if (patternString === candidate) { + // pattern was matched as is - no need to search further + return patternString; + } + } + return findBestPatternMatch(patterns, function (_) { return _; }, candidate); + } + ts.matchPatternOrExact = matchPatternOrExact; + /* @internal */ + function patternText(_a) { + var prefix = _a.prefix, suffix = _a.suffix; + return prefix + "*" + suffix; + } + ts.patternText = patternText; + /** + * Given that candidate matches pattern, returns the text matching the '*'. + * E.g.: matchedText(tryParsePattern("foo*baz"), "foobarbaz") === "bar" + */ + /* @internal */ + function matchedText(pattern, candidate) { + Debug.assert(isPatternMatch(pattern, candidate)); + return candidate.substr(pattern.prefix.length, candidate.length - pattern.suffix.length); + } + ts.matchedText = matchedText; + /** Return the object corresponding to the best pattern to match `candidate`. */ + /* @internal */ + function findBestPatternMatch(values, getPattern, candidate) { + var matchedValue = undefined; + // use length of prefix as betterness criteria + var longestMatchPrefixLength = -1; + for (var _i = 0, values_1 = values; _i < values_1.length; _i++) { + var v = values_1[_i]; + var pattern = getPattern(v); + if (isPatternMatch(pattern, candidate) && pattern.prefix.length > longestMatchPrefixLength) { + longestMatchPrefixLength = pattern.prefix.length; + matchedValue = v; + } + } + return matchedValue; + } + ts.findBestPatternMatch = findBestPatternMatch; + function isPatternMatch(_a, candidate) { + var prefix = _a.prefix, suffix = _a.suffix; + return candidate.length >= prefix.length + suffix.length && + startsWith(candidate, prefix) && + endsWith(candidate, suffix); + } + /* @internal */ + function tryParsePattern(pattern) { + // This should be verified outside of here and a proper error thrown. + Debug.assert(hasZeroOrOneAsteriskCharacter(pattern)); + var indexOfStar = pattern.indexOf("*"); + return indexOfStar === -1 ? undefined : { + prefix: pattern.substr(0, indexOfStar), + suffix: pattern.substr(indexOfStar + 1) + }; + } + ts.tryParsePattern = tryParsePattern; + function positionIsSynthesized(pos) { + // This is a fast way of testing the following conditions: + // pos === undefined || pos === null || isNaN(pos) || pos < 0; + return !(pos >= 0); + } + ts.positionIsSynthesized = positionIsSynthesized; })(ts || (ts = {})); /// var ts; @@ -2571,6 +3143,9 @@ var ts; return shell.CurrentDirectory; }, getDirectories: getDirectories, + getEnvironmentVariable: function (name) { + return new ActiveXObject("WScript.Shell").ExpandEnvironmentStrings("%" + name + "%"); + }, readDirectory: readDirectory, exit: function (exitCode) { try { @@ -2628,13 +3203,7 @@ var ts; reduceDirWatcherRefCountForFile(watchedFile.fileName); } function removeFileWatcherCallback(filePath, callback) { - var callbacks = fileWatcherCallbacks[filePath]; - if (callbacks) { - ts.unorderedRemoveItem(callbacks, callback); - if (callbacks.length === 0) { - delete fileWatcherCallbacks[filePath]; - } - } + ts.multiMapRemove(fileWatcherCallbacks, filePath, callback); } function fileEventHandler(eventName, relativeFileName, baseDirPath) { // When files are deleted from disk, the triggered "rename" event would have a relativefileName of "undefined" @@ -2761,7 +3330,7 @@ var ts; return fileSystemEntryExists(path, 1 /* Directory */); } function getDirectories(path) { - return ts.filter(_fs.readdirSync(path), function (p) { return fileSystemEntryExists(ts.combinePaths(path, p), 1 /* Directory */); }); + return ts.filter(_fs.readdirSync(path), function (dir) { return fileSystemEntryExists(ts.combinePaths(path, dir), 1 /* Directory */); }); } var nodeSystem = { args: process.argv.slice(2), @@ -2830,6 +3399,9 @@ var ts; return process.cwd(); }, getDirectories: getDirectories, + getEnvironmentVariable: function (name) { + return process.env[name] || ""; + }, readDirectory: readDirectory, getModifiedTime: function (path) { try { @@ -2865,6 +3437,13 @@ var ts; }, realpath: function (path) { return _fs.realpathSync(path); + }, + tryEnableSourceMapsForHost: function () { + try { + require("source-map-support").install(); + } + catch (e) { + } } }; return nodeSystem; @@ -2894,6 +3473,7 @@ var ts; getExecutingFilePath: function () { return ChakraHost.executingFile; }, getCurrentDirectory: function () { return ChakraHost.currentDirectory; }, getDirectories: ChakraHost.getDirectories, + getEnvironmentVariable: ChakraHost.getEnvironmentVariable || (function (name) { return ""; }), readDirectory: function (path, extensions, excludes, includes) { var pattern = ts.getFileMatcherPatterns(path, extensions, excludes, includes, !!ChakraHost.useCaseSensitiveFileNames, ChakraHost.currentDirectory); return ChakraHost.readDirectory(path, extensions, pattern.basePaths, pattern.excludePattern, pattern.includeFilePattern, pattern.includeDirectoryPattern); @@ -2902,26 +3482,47 @@ var ts; realpath: realpath }; } + function recursiveCreateDirectory(directoryPath, sys) { + var basePath = ts.getDirectoryPath(directoryPath); + var shouldCreateParent = directoryPath !== basePath && !sys.directoryExists(basePath); + if (shouldCreateParent) { + recursiveCreateDirectory(basePath, sys); + } + if (shouldCreateParent || !sys.directoryExists(directoryPath)) { + sys.createDirectory(directoryPath); + } + } + var sys; if (typeof ChakraHost !== "undefined") { - return getChakraSystem(); + sys = getChakraSystem(); } else if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") { - return getWScriptSystem(); + sys = getWScriptSystem(); } else if (typeof process !== "undefined" && process.nextTick && !process.browser && typeof require !== "undefined") { // process and process.nextTick checks if current environment is node-like // process.browser check excludes webpack and browserify - return getNodeSystem(); + sys = getNodeSystem(); } - else { - return undefined; // Unsupported host + if (sys) { + // patch writefile to create folder before writing the file + var originalWriteFile_1 = sys.writeFile; + sys.writeFile = function (path, data, writeBom) { + var directoryPath = ts.getDirectoryPath(ts.normalizeSlashes(path)); + if (directoryPath && !sys.directoryExists(directoryPath)) { + recursiveCreateDirectory(directoryPath, sys); + } + originalWriteFile_1.call(sys, path, data, writeBom); + }; } + return sys; })(); })(ts || (ts = {})); /// /* @internal */ var ts; (function (ts) { + ts.externalHelpersModuleNameText = "tslib"; function getDeclarationOfKind(symbol, kind) { var declarations = symbol.declarations; if (declarations) { @@ -2989,7 +3590,7 @@ var ts; } ts.arrayIsEqualTo = arrayIsEqualTo; function hasResolvedModule(sourceFile, moduleNameText) { - return !!(sourceFile.resolvedModules && sourceFile.resolvedModules[moduleNameText]); + return !!(sourceFile && sourceFile.resolvedModules && sourceFile.resolvedModules[moduleNameText]); } ts.hasResolvedModule = hasResolvedModule; function getResolvedModule(sourceFile, moduleNameText) { @@ -3041,24 +3642,24 @@ var ts; // Returns true if this node contains a parse error anywhere underneath it. function containsParseError(node) { aggregateChildData(node); - return (node.flags & 268435456 /* ThisNodeOrAnySubNodesHasError */) !== 0; + return (node.flags & 2097152 /* ThisNodeOrAnySubNodesHasError */) !== 0; } ts.containsParseError = containsParseError; function aggregateChildData(node) { - if (!(node.flags & 536870912 /* HasAggregatedChildData */)) { + if (!(node.flags & 4194304 /* HasAggregatedChildData */)) { // A node is considered to contain a parse error if: // a) the parser explicitly marked that it had an error // b) any of it's children reported that it had an error. - var thisNodeOrAnySubNodesHasError = ((node.flags & 67108864 /* ThisNodeHasError */) !== 0) || + var thisNodeOrAnySubNodesHasError = ((node.flags & 524288 /* ThisNodeHasError */) !== 0) || ts.forEachChild(node, containsParseError); // If so, mark ourselves accordingly. if (thisNodeOrAnySubNodesHasError) { - node.flags |= 268435456 /* ThisNodeOrAnySubNodesHasError */; + node.flags |= 2097152 /* ThisNodeOrAnySubNodesHasError */; } // Also mark that we've propagated the child information to this node. This way we can // always consult the bit directly on this node without needing to check its children // again. - node.flags |= 536870912 /* HasAggregatedChildData */; + node.flags |= 4194304 /* HasAggregatedChildData */; } } function getSourceFileOfNode(node) { @@ -3096,6 +3697,10 @@ var ts; return node.pos; } ts.getStartPosOfNode = getStartPosOfNode; + function isDefined(value) { + return value !== undefined; + } + ts.isDefined = isDefined; function getEndLinePosition(line, sourceFile) { ts.Debug.assert(line >= 0); var lineStarts = ts.getLineStarts(sourceFile); @@ -3135,7 +3740,7 @@ var ts; // However, this node will be 'missing' in the sense that no actual source-code/tokens are // contained within it. function nodeIsMissing(node) { - if (!node) { + if (node === undefined) { return true; } return node.pos === node.end && node.pos >= 0 && node.kind !== 1 /* EndOfFileToken */; @@ -3203,6 +3808,56 @@ var ts; return getSourceTextOfNodeFromSourceFile(getSourceFileOfNode(node), node, includeTrivia); } ts.getTextOfNode = getTextOfNode; + function getLiteralText(node, sourceFile, languageVersion) { + // Any template literal or string literal with an extended escape + // (e.g. "\u{0067}") will need to be downleveled as a escaped string literal. + if (languageVersion < 2 /* ES6 */ && (isTemplateLiteralKind(node.kind) || node.hasExtendedUnicodeEscape)) { + return getQuotedEscapedLiteralText('"', node.text, '"'); + } + // If we don't need to downlevel and we can reach the original source text using + // the node's parent reference, then simply get the text as it was originally written. + if (!nodeIsSynthesized(node) && node.parent) { + var text = getSourceTextOfNodeFromSourceFile(sourceFile, node); + if (languageVersion < 2 /* ES6 */ && isBinaryOrOctalIntegerLiteral(node, text)) { + return node.text; + } + return text; + } + // If we can't reach the original source text, use the canonical form if it's a number, + // or an escaped quoted form of the original text if it's string-like. + switch (node.kind) { + case 9 /* StringLiteral */: + return getQuotedEscapedLiteralText('"', node.text, '"'); + case 11 /* NoSubstitutionTemplateLiteral */: + return getQuotedEscapedLiteralText("`", node.text, "`"); + case 12 /* TemplateHead */: + return getQuotedEscapedLiteralText("`", node.text, "${"); + case 13 /* TemplateMiddle */: + return getQuotedEscapedLiteralText("}", node.text, "${"); + case 14 /* TemplateTail */: + return getQuotedEscapedLiteralText("}", node.text, "`"); + case 8 /* NumericLiteral */: + return node.text; + } + ts.Debug.fail("Literal kind '" + node.kind + "' not accounted for."); + } + ts.getLiteralText = getLiteralText; + function isBinaryOrOctalIntegerLiteral(node, text) { + if (node.kind === 8 /* NumericLiteral */ && text.length > 1) { + switch (text.charCodeAt(1)) { + case 98 /* b */: + case 66 /* B */: + case 111 /* o */: + case 79 /* O */: + return true; + } + } + return false; + } + ts.isBinaryOrOctalIntegerLiteral = isBinaryOrOctalIntegerLiteral; + function getQuotedEscapedLiteralText(leftQuote, text, rightQuote) { + return leftQuote + escapeNonAsciiCharacters(escapeString(text)) + rightQuote; + } // Add an extra underscore to identifiers that start with two underscores to avoid issues with magic names like '__proto__' function escapeIdentifier(identifier) { return identifier.length >= 2 && identifier.charCodeAt(0) === 95 /* _ */ && identifier.charCodeAt(1) === 95 /* _ */ ? "_" + identifier : identifier; @@ -3220,7 +3875,7 @@ var ts; } ts.makeIdentifierFromModuleName = makeIdentifierFromModuleName; function isBlockOrCatchScoped(declaration) { - return (getCombinedNodeFlags(declaration) & 3072 /* BlockScoped */) !== 0 || + return (ts.getCombinedNodeFlags(declaration) & 3 /* BlockScoped */) !== 0 || isCatchClauseVariableDeclaration(declaration); } ts.isBlockOrCatchScoped = isBlockOrCatchScoped; @@ -3229,20 +3884,22 @@ var ts; (node.name.kind === 9 /* StringLiteral */ || isGlobalScopeAugmentation(node)); } ts.isAmbientModule = isAmbientModule; + function isShorthandAmbientModuleSymbol(moduleSymbol) { + return isShorthandAmbientModule(moduleSymbol.valueDeclaration); + } + ts.isShorthandAmbientModuleSymbol = isShorthandAmbientModuleSymbol; function isShorthandAmbientModule(node) { // The only kind of module that can be missing a body is a shorthand ambient module. return node.kind === 225 /* ModuleDeclaration */ && (!node.body); } - ts.isShorthandAmbientModule = isShorthandAmbientModule; function isBlockScopedContainerTopLevel(node) { return node.kind === 256 /* SourceFile */ || node.kind === 225 /* ModuleDeclaration */ || - isFunctionLike(node) || - isFunctionBlock(node); + isFunctionLike(node); } ts.isBlockScopedContainerTopLevel = isBlockScopedContainerTopLevel; function isGlobalScopeAugmentation(module) { - return !!(module.flags & 131072 /* GlobalAugmentation */); + return !!(module.flags & 512 /* GlobalAugmentation */); } ts.isGlobalScopeAugmentation = isGlobalScopeAugmentation; function isExternalModuleAugmentation(node) { @@ -3261,30 +3918,39 @@ var ts; return false; } ts.isExternalModuleAugmentation = isExternalModuleAugmentation; + function isBlockScope(node, parentNode) { + switch (node.kind) { + case 256 /* SourceFile */: + case 227 /* CaseBlock */: + case 252 /* CatchClause */: + case 225 /* ModuleDeclaration */: + case 206 /* ForStatement */: + case 207 /* ForInStatement */: + case 208 /* ForOfStatement */: + case 148 /* Constructor */: + case 147 /* MethodDeclaration */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + case 180 /* ArrowFunction */: + return true; + case 199 /* Block */: + // function block is not considered block-scope container + // see comment in binder.ts: bind(...), case for SyntaxKind.Block + return parentNode && !isFunctionLike(parentNode); + } + return false; + } + ts.isBlockScope = isBlockScope; // Gets the nearest enclosing block scope container that has the provided node // as a descendant, that is not the provided node. function getEnclosingBlockScopeContainer(node) { var current = node.parent; while (current) { - if (isFunctionLike(current)) { + if (isBlockScope(current, current.parent)) { return current; } - switch (current.kind) { - case 256 /* SourceFile */: - case 227 /* CaseBlock */: - case 252 /* CatchClause */: - case 225 /* ModuleDeclaration */: - case 206 /* ForStatement */: - case 207 /* ForInStatement */: - case 208 /* ForOfStatement */: - return current; - case 199 /* Block */: - // function block is not considered block-scope container - // see comment in binder.ts: bind(...), case for SyntaxKind.Block - if (!isFunctionLike(current.parent)) { - return current; - } - } current = current.parent; } } @@ -3396,41 +4062,13 @@ var ts; return node.kind === 224 /* EnumDeclaration */ && isConst(node); } ts.isConstEnumDeclaration = isConstEnumDeclaration; - function walkUpBindingElementsAndPatterns(node) { - while (node && (node.kind === 169 /* BindingElement */ || isBindingPattern(node))) { - node = node.parent; - } - return node; - } - // Returns the node flags for this node and all relevant parent nodes. This is done so that - // nodes like variable declarations and binding elements can returned a view of their flags - // that includes the modifiers from their container. i.e. flags like export/declare aren't - // stored on the variable declaration directly, but on the containing variable statement - // (if it has one). Similarly, flags for let/const are store on the variable declaration - // list. By calling this function, all those flags are combined so that the client can treat - // the node as if it actually had those flags. - function getCombinedNodeFlags(node) { - node = walkUpBindingElementsAndPatterns(node); - var flags = node.flags; - if (node.kind === 218 /* VariableDeclaration */) { - node = node.parent; - } - if (node && node.kind === 219 /* VariableDeclarationList */) { - flags |= node.flags; - node = node.parent; - } - if (node && node.kind === 200 /* VariableStatement */) { - flags |= node.flags; - } - return flags; - } - ts.getCombinedNodeFlags = getCombinedNodeFlags; function isConst(node) { - return !!(getCombinedNodeFlags(node) & 2048 /* Const */); + return !!(ts.getCombinedNodeFlags(node) & 2 /* Const */) + || !!(ts.getCombinedModifierFlags(node) & 2048 /* Const */); } ts.isConst = isConst; function isLet(node) { - return !!(getCombinedNodeFlags(node) & 1024 /* Let */); + return !!(ts.getCombinedNodeFlags(node) & 1 /* Let */); } ts.isLet = isLet; function isSuperCallExpression(n) { @@ -3472,7 +4110,7 @@ var ts; ts.fullTripleSlashReferencePathRegEx = /^(\/\/\/\s*/; ts.fullTripleSlashReferenceTypeReferenceDirectiveRegEx = /^(\/\/\/\s*/; ts.fullTripleSlashAMDReferencePathRegEx = /^(\/\/\/\s*/; - function isTypeNode(node) { + function isPartOfTypeNode(node) { if (154 /* FirstTypeNode */ <= node.kind && node.kind <= 166 /* LastTypeNode */) { return true; } @@ -3500,7 +4138,7 @@ var ts; node = node.parent; } // At this point, node is either a qualified name or an identifier - ts.Debug.assert(node.kind === 69 /* Identifier */ || node.kind === 139 /* QualifiedName */ || node.kind === 172 /* PropertyAccessExpression */, "'node' was expected to be a qualified name, identifier or property access in 'isTypeNode'."); + ts.Debug.assert(node.kind === 69 /* Identifier */ || node.kind === 139 /* QualifiedName */ || node.kind === 172 /* PropertyAccessExpression */, "'node' was expected to be a qualified name, identifier or property access in 'isPartOfTypeNode'."); case 139 /* QualifiedName */: case 172 /* PropertyAccessExpression */: case 97 /* ThisKeyword */: @@ -3508,11 +4146,11 @@ var ts; if (parent_1.kind === 158 /* TypeQuery */) { return false; } - // Do not recursively call isTypeNode on the parent. In the example: + // Do not recursively call isPartOfTypeNode on the parent. In the example: // // let a: A.B.C; // - // Calling isTypeNode would consider the qualified name A.B a type node. Only C or + // Calling isPartOfTypeNode would consider the qualified name A.B a type node. Only C or // A.B.C is a type node. if (154 /* FirstTypeNode */ <= parent_1.kind && parent_1.kind <= 166 /* LastTypeNode */) { return true; @@ -3552,7 +4190,7 @@ var ts; } return false; } - ts.isTypeNode = isTypeNode; + ts.isPartOfTypeNode = isPartOfTypeNode; // Warning: This has the same semantics as the forEach family of functions, // in that traversal terminates in the event that 'visitor' supplies a truthy value. function forEachReturnStatement(body, visitor) { @@ -3611,7 +4249,7 @@ var ts; return; } } - else if (!isTypeNode(node)) { + else if (!isPartOfTypeNode(node)) { // This is the general case, which should include mostly expressions and statements. // Also includes NodeArrays. ts.forEachChild(node, traverse); @@ -3792,11 +4430,11 @@ var ts; } ts.getThisContainer = getThisContainer; /** - * Given an super call\property node returns a closest node where either - * - super call\property is legal in the node and not legal in the parent node the node. + * Given an super call/property node, returns the closest node where + * - a super call/property access is legal in the node and not legal in the parent node the node. * i.e. super call is legal in constructor but not legal in the class body. - * - node is arrow function (so caller might need to call getSuperContainer in case it needs to climb higher) - * - super call\property is definitely illegal in the node (but might be legal in some subnode) + * - the container is an arrow function (so caller might need to call getSuperContainer again in case it needs to climb higher) + * - a super call/property is definitely illegal in the container (but might be legal in some subnode) * i.e. super property access is illegal in function declaration but can be legal in the statement list */ function getSuperContainer(node, stopOnFunctions) { @@ -3857,12 +4495,12 @@ var ts; /** * Determines whether a node is a property or element access expression for super. */ - function isSuperPropertyOrElementAccess(node) { - return (node.kind === 172 /* PropertyAccessExpression */ - || node.kind === 173 /* ElementAccessExpression */) + function isSuperProperty(node) { + var kind = node.kind; + return (kind === 172 /* PropertyAccessExpression */ || kind === 173 /* ElementAccessExpression */) && node.expression.kind === 95 /* SuperKeyword */; } - ts.isSuperPropertyOrElementAccess = isSuperPropertyOrElementAccess; + ts.isSuperProperty = isSuperProperty; function getEntityNameFromTypeNode(node) { if (node) { switch (node.kind) { @@ -3929,14 +4567,20 @@ var ts; && nodeCanBeDecorated(node); } ts.nodeIsDecorated = nodeIsDecorated; - function isPropertyAccessExpression(node) { - return node.kind === 172 /* PropertyAccessExpression */; + function nodeOrChildIsDecorated(node) { + return nodeIsDecorated(node) || childIsDecorated(node); } - ts.isPropertyAccessExpression = isPropertyAccessExpression; - function isElementAccessExpression(node) { - return node.kind === 173 /* ElementAccessExpression */; + ts.nodeOrChildIsDecorated = nodeOrChildIsDecorated; + function childIsDecorated(node) { + switch (node.kind) { + case 221 /* ClassDeclaration */: + return ts.forEach(node.members, nodeOrChildIsDecorated); + case 147 /* MethodDeclaration */: + case 150 /* SetAccessor */: + return ts.forEach(node.parameters, nodeIsDecorated); + } } - ts.isElementAccessExpression = isElementAccessExpression; + ts.childIsDecorated = childIsDecorated; function isJSXTagName(node) { var parent = node.parent; if (parent.kind === 243 /* JsxOpeningElement */ || @@ -3947,7 +4591,7 @@ var ts; return false; } ts.isJSXTagName = isJSXTagName; - function isExpression(node) { + function isPartOfExpression(node) { switch (node.kind) { case 97 /* ThisKeyword */: case 95 /* SuperKeyword */: @@ -4043,20 +4687,14 @@ var ts; case 194 /* ExpressionWithTypeArguments */: return parent_3.expression === node && isExpressionWithTypeArgumentsInClassExtendsClause(parent_3); default: - if (isExpression(parent_3)) { + if (isPartOfExpression(parent_3)) { return true; } } } return false; } - ts.isExpression = isExpression; - function isExternalModuleNameRelative(moduleName) { - // TypeScript 1.0 spec (April 2014): 11.2.1 - // An external module name is "relative" if the first term is "." or "..". - return /^\.\.?($|[\\/])/.test(moduleName); - } - ts.isExternalModuleNameRelative = isExternalModuleNameRelative; + ts.isPartOfExpression = isPartOfExpression; function isInstantiatedModule(node, preserveConstEnums) { var moduleState = ts.getModuleInstanceState(node); return moduleState === 1 /* Instantiated */ || @@ -4081,7 +4719,7 @@ var ts; } ts.isSourceFileJavaScript = isSourceFileJavaScript; function isInJavaScriptFile(node) { - return node && !!(node.flags & 134217728 /* JavaScriptFile */); + return node && !!(node.flags & 1048576 /* JavaScriptFile */); } ts.isInJavaScriptFile = isInJavaScriptFile; /** @@ -4177,6 +4815,22 @@ var ts; } } ts.getExternalModuleName = getExternalModuleName; + function getNamespaceDeclarationNode(node) { + if (node.kind === 229 /* ImportEqualsDeclaration */) { + return node; + } + var importClause = node.importClause; + if (importClause && importClause.namedBindings && importClause.namedBindings.kind === 232 /* NamespaceImport */) { + return importClause.namedBindings; + } + } + ts.getNamespaceDeclarationNode = getNamespaceDeclarationNode; + function isDefaultImport(node) { + return node.kind === 230 /* ImportDeclaration */ + && node.importClause + && !!node.importClause.name; + } + ts.isDefaultImport = isDefaultImport; function hasQuestionToken(node) { if (node) { switch (node.kind) { @@ -4203,37 +4857,71 @@ var ts; if (!node) { return undefined; } - var jsDocComments = getJSDocComments(node, checkParentVariableStatement); - if (!jsDocComments) { + var jsDocTags = getJSDocTags(node, checkParentVariableStatement); + if (!jsDocTags) { return undefined; } - for (var _i = 0, jsDocComments_1 = jsDocComments; _i < jsDocComments_1.length; _i++) { - var jsDocComment = jsDocComments_1[_i]; - for (var _a = 0, _b = jsDocComment.tags; _a < _b.length; _a++) { - var tag = _b[_a]; - if (tag.kind === kind) { - return tag; - } + for (var _i = 0, jsDocTags_1 = jsDocTags; _i < jsDocTags_1.length; _i++) { + var tag = jsDocTags_1[_i]; + if (tag.kind === kind) { + return tag; } } } + function append(previous, additional) { + if (additional) { + if (!previous) { + previous = []; + } + for (var _i = 0, additional_1 = additional; _i < additional_1.length; _i++) { + var x = additional_1[_i]; + previous.push(x); + } + } + return previous; + } function getJSDocComments(node, checkParentVariableStatement) { - if (node.jsDocComments) { - return node.jsDocComments; - } - // Try to recognize this pattern when node is initializer of variable declaration and JSDoc comments are on containing variable statement. - // /** - // * @param {number} name - // * @returns {number} - // */ - // var x = function(name) { return name.length; } + return getJSDocs(node, checkParentVariableStatement, function (docs) { return ts.map(docs, function (doc) { return doc.comment; }); }, function (tags) { return ts.map(tags, function (tag) { return tag.comment; }); }); + } + ts.getJSDocComments = getJSDocComments; + function getJSDocTags(node, checkParentVariableStatement) { + return getJSDocs(node, checkParentVariableStatement, function (docs) { + var result = []; + for (var _i = 0, docs_1 = docs; _i < docs_1.length; _i++) { + var doc = docs_1[_i]; + if (doc.tags) { + result.push.apply(result, doc.tags); + } + } + return result; + }, function (tags) { return tags; }); + } + function getJSDocs(node, checkParentVariableStatement, getDocs, getTags) { + // TODO: Get rid of getJsDocComments and friends (note the lowercase 's' in Js) + // TODO: A lot of this work should be cached, maybe. I guess it's only used in services right now... + var result = undefined; + // prepend documentation from parent sources if (checkParentVariableStatement) { - var isInitializerOfVariableDeclarationInStatement = node.parent.kind === 218 /* VariableDeclaration */ && - node.parent.initializer === node && + // Try to recognize this pattern when node is initializer of variable declaration and JSDoc comments are on containing variable statement. + // /** + // * @param {number} name + // * @returns {number} + // */ + // var x = function(name) { return name.length; } + var isInitializerOfVariableDeclarationInStatement = isVariableLike(node.parent) && + (node.parent).initializer === node && node.parent.parent.parent.kind === 200 /* VariableStatement */; - var variableStatementNode = isInitializerOfVariableDeclarationInStatement ? node.parent.parent.parent : undefined; + var isVariableOfVariableDeclarationStatement = isVariableLike(node) && + node.parent.parent.kind === 200 /* VariableStatement */; + var variableStatementNode = isInitializerOfVariableDeclarationInStatement ? node.parent.parent.parent : + isVariableOfVariableDeclarationStatement ? node.parent.parent : + undefined; if (variableStatementNode) { - return variableStatementNode.jsDocComments; + result = append(result, getJSDocs(variableStatementNode, checkParentVariableStatement, getDocs, getTags)); + } + if (node.kind === 225 /* ModuleDeclaration */ && + node.parent && node.parent.kind === 225 /* ModuleDeclaration */) { + result = append(result, getJSDocs(node.parent, checkParentVariableStatement, getDocs, getTags)); } // Also recognize when the node is the RHS of an assignment expression var parent_4 = node.parent; @@ -4242,14 +4930,56 @@ var ts; parent_4.operatorToken.kind === 56 /* EqualsToken */ && parent_4.parent.kind === 202 /* ExpressionStatement */; if (isSourceOfAssignmentExpressionStatement) { - return parent_4.parent.jsDocComments; + result = append(result, getJSDocs(parent_4.parent, checkParentVariableStatement, getDocs, getTags)); } var isPropertyAssignmentExpression = parent_4 && parent_4.kind === 253 /* PropertyAssignment */; if (isPropertyAssignmentExpression) { - return parent_4.jsDocComments; + result = append(result, getJSDocs(parent_4, checkParentVariableStatement, getDocs, getTags)); + } + // Pull parameter comments from declaring function as well + if (node.kind === 142 /* Parameter */) { + var paramTags = getJSDocParameterTag(node, checkParentVariableStatement); + if (paramTags) { + result = append(result, getTags(paramTags)); + } } } - return undefined; + if (isVariableLike(node) && node.initializer) { + result = append(result, getJSDocs(node.initializer, /*checkParentVariableStatement*/ false, getDocs, getTags)); + } + if (node.jsDocComments) { + if (result) { + result = append(result, getDocs(node.jsDocComments)); + } + else { + return getDocs(node.jsDocComments); + } + } + return result; + } + function getJSDocParameterTag(param, checkParentVariableStatement) { + var func = param.parent; + var tags = getJSDocTags(func, checkParentVariableStatement); + if (!param.name) { + // this is an anonymous jsdoc param from a `function(type1, type2): type3` specification + var i = func.parameters.indexOf(param); + var paramTags = ts.filter(tags, function (tag) { return tag.kind === 275 /* JSDocParameterTag */; }); + if (paramTags && 0 <= i && i < paramTags.length) { + return [paramTags[i]]; + } + } + else if (param.name.kind === 69 /* Identifier */) { + var name_5 = param.name.text; + var paramTags = ts.filter(tags, function (tag) { return tag.kind === 275 /* JSDocParameterTag */ && tag.parameterName.text === name_5; }); + if (paramTags) { + return paramTags; + } + } + else { + // TODO: it's a destructured parameter, so it should look up an "object type" series of multiple lines + // But multi-line object types aren't supported yet either + return undefined; + } } function getJSDocTypeTag(node) { return getJSDocTag(node, 277 /* JSDocTypeTag */, /*checkParentVariableStatement*/ false); @@ -4268,19 +4998,16 @@ var ts; // If it's a parameter, see if the parent has a jsdoc comment with an @param // annotation. var parameterName = parameter.name.text; - var jsDocComments = getJSDocComments(parameter.parent, /*checkParentVariableStatement*/ true); - if (jsDocComments) { - for (var _i = 0, jsDocComments_2 = jsDocComments; _i < jsDocComments_2.length; _i++) { - var jsDocComment = jsDocComments_2[_i]; - for (var _a = 0, _b = jsDocComment.tags; _a < _b.length; _a++) { - var tag = _b[_a]; - if (tag.kind === 275 /* JSDocParameterTag */) { - var parameterTag = tag; - var name_5 = parameterTag.preParameterName || parameterTag.postParameterName; - if (name_5.text === parameterName) { - return parameterTag; - } - } + var jsDocTags = getJSDocTags(parameter.parent, /*checkParentVariableStatement*/ true); + if (!jsDocTags) { + return undefined; + } + for (var _i = 0, jsDocTags_2 = jsDocTags; _i < jsDocTags_2.length; _i++) { + var tag = jsDocTags_2[_i]; + if (tag.kind === 275 /* JSDocParameterTag */) { + var parameterTag = tag; + if (parameterTag.parameterName.text === parameterName) { + return parameterTag; } } } @@ -4297,7 +5024,7 @@ var ts; } ts.hasDeclaredRestParameter = hasDeclaredRestParameter; function isRestParameter(node) { - if (node && (node.flags & 134217728 /* JavaScriptFile */)) { + if (node && (node.flags & 1048576 /* JavaScriptFile */)) { if (node.type && node.type.kind === 270 /* JSDocVariadicType */) { return true; } @@ -4313,22 +5040,6 @@ var ts; return node && node.dotDotDotToken !== undefined; } ts.isDeclaredRestParam = isDeclaredRestParam; - function isLiteralKind(kind) { - return 8 /* FirstLiteralToken */ <= kind && kind <= 11 /* LastLiteralToken */; - } - ts.isLiteralKind = isLiteralKind; - function isTextualLiteralKind(kind) { - return kind === 9 /* StringLiteral */ || kind === 11 /* NoSubstitutionTemplateLiteral */; - } - ts.isTextualLiteralKind = isTextualLiteralKind; - function isTemplateLiteralKind(kind) { - return 11 /* FirstTemplateToken */ <= kind && kind <= 14 /* LastTemplateToken */; - } - ts.isTemplateLiteralKind = isTemplateLiteralKind; - function isBindingPattern(node) { - return !!node && (node.kind === 168 /* ArrayBindingPattern */ || node.kind === 167 /* ObjectBindingPattern */); - } - ts.isBindingPattern = isBindingPattern; // A node is an assignment target if it is on the left hand side of an '=' token, if it is parented by a property // assignment in an object literal that is an assignment target, or if it is parented by an array literal that is // an assignment target. Examples include 'a = xxx', '{ p: a } = xxx', '[{ p: a}] = xxx'. @@ -4354,7 +5065,7 @@ var ts; } } ts.isAssignmentTarget = isAssignmentTarget; - function isNodeDescendentOf(node, ancestor) { + function isNodeDescendantOf(node, ancestor) { while (node) { if (node === ancestor) return true; @@ -4362,10 +5073,10 @@ var ts; } return false; } - ts.isNodeDescendentOf = isNodeDescendentOf; + ts.isNodeDescendantOf = isNodeDescendantOf; function isInAmbientContext(node) { while (node) { - if (node.flags & 2 /* Ambient */ || (node.kind === 256 /* SourceFile */ && node.isDeclarationFile)) { + if (hasModifier(node, 2 /* Ambient */) || (node.kind === 256 /* SourceFile */ && node.isDeclarationFile)) { return true; } node = node.parent; @@ -4373,85 +5084,6 @@ var ts; return false; } ts.isInAmbientContext = isInAmbientContext; - function isDeclaration(node) { - switch (node.kind) { - case 180 /* ArrowFunction */: - case 169 /* BindingElement */: - case 221 /* ClassDeclaration */: - case 192 /* ClassExpression */: - case 148 /* Constructor */: - case 224 /* EnumDeclaration */: - case 255 /* EnumMember */: - case 238 /* ExportSpecifier */: - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - case 149 /* GetAccessor */: - case 231 /* ImportClause */: - case 229 /* ImportEqualsDeclaration */: - case 234 /* ImportSpecifier */: - case 222 /* InterfaceDeclaration */: - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - case 225 /* ModuleDeclaration */: - case 232 /* NamespaceImport */: - case 228 /* NamespaceExportDeclaration */: - case 142 /* Parameter */: - case 253 /* PropertyAssignment */: - case 145 /* PropertyDeclaration */: - case 144 /* PropertySignature */: - case 150 /* SetAccessor */: - case 254 /* ShorthandPropertyAssignment */: - case 223 /* TypeAliasDeclaration */: - case 141 /* TypeParameter */: - case 218 /* VariableDeclaration */: - case 279 /* JSDocTypedefTag */: - return true; - } - return false; - } - ts.isDeclaration = isDeclaration; - function isStatement(n) { - switch (n.kind) { - case 210 /* BreakStatement */: - case 209 /* ContinueStatement */: - case 217 /* DebuggerStatement */: - case 204 /* DoStatement */: - case 202 /* ExpressionStatement */: - case 201 /* EmptyStatement */: - case 207 /* ForInStatement */: - case 208 /* ForOfStatement */: - case 206 /* ForStatement */: - case 203 /* IfStatement */: - case 214 /* LabeledStatement */: - case 211 /* ReturnStatement */: - case 213 /* SwitchStatement */: - case 215 /* ThrowStatement */: - case 216 /* TryStatement */: - case 200 /* VariableStatement */: - case 205 /* WhileStatement */: - case 212 /* WithStatement */: - case 235 /* ExportAssignment */: - return true; - default: - return false; - } - } - ts.isStatement = isStatement; - function isClassElement(n) { - switch (n.kind) { - case 148 /* Constructor */: - case 145 /* PropertyDeclaration */: - case 147 /* MethodDeclaration */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 146 /* MethodSignature */: - case 153 /* IndexSignature */: - return true; - default: - return false; - } - } - ts.isClassElement = isClassElement; // True if the given identifier, string literal, or number literal is the name of a declaration node function isDeclarationName(name) { if (name.kind !== 69 /* Identifier */ && name.kind !== 9 /* StringLiteral */ && name.kind !== 8 /* NumericLiteral */) { @@ -4619,7 +5251,7 @@ var ts; } ts.isTrivia = isTrivia; function isAsyncFunctionLike(node) { - return isFunctionLike(node) && (node.flags & 256 /* Async */) !== 0 && !isAccessor(node); + return isFunctionLike(node) && hasModifier(node, 256 /* Async */) && !isAccessor(node); } ts.isAsyncFunctionLike = isAsyncFunctionLike; function isStringOrNumericLiteral(kind) { @@ -4710,77 +5342,241 @@ var ts; return node; } ts.getRootDeclaration = getRootDeclaration; - function nodeStartsNewLexicalEnvironment(n) { - return isFunctionLike(n) || n.kind === 225 /* ModuleDeclaration */ || n.kind === 256 /* SourceFile */; + function nodeStartsNewLexicalEnvironment(node) { + var kind = node.kind; + return kind === 148 /* Constructor */ + || kind === 179 /* FunctionExpression */ + || kind === 220 /* FunctionDeclaration */ + || kind === 180 /* ArrowFunction */ + || kind === 147 /* MethodDeclaration */ + || kind === 149 /* GetAccessor */ + || kind === 150 /* SetAccessor */ + || kind === 225 /* ModuleDeclaration */ + || kind === 256 /* SourceFile */; } ts.nodeStartsNewLexicalEnvironment = nodeStartsNewLexicalEnvironment; - /** - * Creates a shallow, memberwise clone of a node. The "kind", "pos", "end", "flags", and "parent" - * properties are excluded by default, and can be provided via the "location", "flags", and - * "parent" parameters. - * @param node The node to clone. - * @param location An optional TextRange to use to supply the new position. - * @param flags The NodeFlags to use for the cloned node. - * @param parent The parent for the new node. - */ - function cloneNode(node, location, flags, parent) { - // We don't use "clone" from core.ts here, as we need to preserve the prototype chain of - // the original node. We also need to exclude specific properties and only include own- - // properties (to skip members already defined on the shared prototype). - var clone = location !== undefined - ? ts.createNode(node.kind, location.pos, location.end) - : createSynthesizedNode(node.kind); - for (var key in node) { - if (clone.hasOwnProperty(key) || !node.hasOwnProperty(key)) { - continue; + function nodeIsSynthesized(node) { + return ts.positionIsSynthesized(node.pos) + || ts.positionIsSynthesized(node.end); + } + ts.nodeIsSynthesized = nodeIsSynthesized; + function getOriginalNode(node) { + if (node) { + while (node.original !== undefined) { + node = node.original; } - clone[key] = node[key]; - } - if (flags !== undefined) { - clone.flags = flags; - } - if (parent !== undefined) { - clone.parent = parent; } - return clone; + return node; } - ts.cloneNode = cloneNode; + ts.getOriginalNode = getOriginalNode; /** - * Creates a deep clone of an EntityName, with new parent pointers. - * @param node The EntityName to clone. - * @param parent The parent for the cloned node. + * Gets a value indicating whether a node originated in the parse tree. + * + * @param node The node to test. */ - function cloneEntityName(node, parent) { - var clone = cloneNode(node, node, node.flags, parent); - if (isQualifiedName(clone)) { - var left = clone.left, right = clone.right; - clone.left = cloneEntityName(left, clone); - clone.right = cloneNode(right, right, right.flags, parent); + function isParseTreeNode(node) { + return (node.flags & 8 /* Synthesized */) === 0; + } + ts.isParseTreeNode = isParseTreeNode; + function getParseTreeNode(node, nodeTest) { + if (isParseTreeNode(node)) { + return node; } - return clone; + node = getOriginalNode(node); + if (isParseTreeNode(node) && (!nodeTest || nodeTest(node))) { + return node; + } + return undefined; } - ts.cloneEntityName = cloneEntityName; - function isQualifiedName(node) { - return node.kind === 139 /* QualifiedName */; + ts.getParseTreeNode = getParseTreeNode; + function getOriginalSourceFiles(sourceFiles) { + var originalSourceFiles = []; + for (var _i = 0, sourceFiles_1 = sourceFiles; _i < sourceFiles_1.length; _i++) { + var sourceFile = sourceFiles_1[_i]; + var originalSourceFile = getParseTreeNode(sourceFile, isSourceFile); + if (originalSourceFile) { + originalSourceFiles.push(originalSourceFile); + } + } + return originalSourceFiles; + } + ts.getOriginalSourceFiles = getOriginalSourceFiles; + function getOriginalNodeId(node) { + node = getOriginalNode(node); + return node ? ts.getNodeId(node) : 0; + } + ts.getOriginalNodeId = getOriginalNodeId; + (function (Associativity) { + Associativity[Associativity["Left"] = 0] = "Left"; + Associativity[Associativity["Right"] = 1] = "Right"; + })(ts.Associativity || (ts.Associativity = {})); + var Associativity = ts.Associativity; + function getExpressionAssociativity(expression) { + var operator = getOperator(expression); + var hasArguments = expression.kind === 175 /* NewExpression */ && expression.arguments !== undefined; + return getOperatorAssociativity(expression.kind, operator, hasArguments); + } + ts.getExpressionAssociativity = getExpressionAssociativity; + function getOperatorAssociativity(kind, operator, hasArguments) { + switch (kind) { + case 175 /* NewExpression */: + return hasArguments ? 0 /* Left */ : 1 /* Right */; + case 185 /* PrefixUnaryExpression */: + case 182 /* TypeOfExpression */: + case 183 /* VoidExpression */: + case 181 /* DeleteExpression */: + case 184 /* AwaitExpression */: + case 188 /* ConditionalExpression */: + case 190 /* YieldExpression */: + return 1 /* Right */; + case 187 /* BinaryExpression */: + switch (operator) { + case 38 /* AsteriskAsteriskToken */: + case 56 /* EqualsToken */: + case 57 /* PlusEqualsToken */: + case 58 /* MinusEqualsToken */: + case 60 /* AsteriskAsteriskEqualsToken */: + case 59 /* AsteriskEqualsToken */: + case 61 /* SlashEqualsToken */: + case 62 /* PercentEqualsToken */: + case 63 /* LessThanLessThanEqualsToken */: + case 64 /* GreaterThanGreaterThanEqualsToken */: + case 65 /* GreaterThanGreaterThanGreaterThanEqualsToken */: + case 66 /* AmpersandEqualsToken */: + case 68 /* CaretEqualsToken */: + case 67 /* BarEqualsToken */: + return 1 /* Right */; + } + } + return 0 /* Left */; } - ts.isQualifiedName = isQualifiedName; - function nodeIsSynthesized(node) { - return node.pos === -1; + ts.getOperatorAssociativity = getOperatorAssociativity; + function getExpressionPrecedence(expression) { + var operator = getOperator(expression); + var hasArguments = expression.kind === 175 /* NewExpression */ && expression.arguments !== undefined; + return getOperatorPrecedence(expression.kind, operator, hasArguments); } - ts.nodeIsSynthesized = nodeIsSynthesized; - function createSynthesizedNode(kind, startsOnNewLine) { - var node = ts.createNode(kind, /* pos */ -1, /* end */ -1); - node.startsOnNewLine = startsOnNewLine; - return node; + ts.getExpressionPrecedence = getExpressionPrecedence; + function getOperator(expression) { + if (expression.kind === 187 /* BinaryExpression */) { + return expression.operatorToken.kind; + } + else if (expression.kind === 185 /* PrefixUnaryExpression */ || expression.kind === 186 /* PostfixUnaryExpression */) { + return expression.operator; + } + else { + return expression.kind; + } } - ts.createSynthesizedNode = createSynthesizedNode; - function createSynthesizedNodeArray() { - var array = []; - array.pos = -1; - array.end = -1; - return array; + ts.getOperator = getOperator; + function getOperatorPrecedence(nodeKind, operatorKind, hasArguments) { + switch (nodeKind) { + case 97 /* ThisKeyword */: + case 95 /* SuperKeyword */: + case 69 /* Identifier */: + case 93 /* NullKeyword */: + case 99 /* TrueKeyword */: + case 84 /* FalseKeyword */: + case 8 /* NumericLiteral */: + case 9 /* StringLiteral */: + case 170 /* ArrayLiteralExpression */: + case 171 /* ObjectLiteralExpression */: + case 179 /* FunctionExpression */: + case 180 /* ArrowFunction */: + case 192 /* ClassExpression */: + case 241 /* JsxElement */: + case 242 /* JsxSelfClosingElement */: + case 10 /* RegularExpressionLiteral */: + case 11 /* NoSubstitutionTemplateLiteral */: + case 189 /* TemplateExpression */: + case 178 /* ParenthesizedExpression */: + case 193 /* OmittedExpression */: + return 19; + case 176 /* TaggedTemplateExpression */: + case 172 /* PropertyAccessExpression */: + case 173 /* ElementAccessExpression */: + return 18; + case 175 /* NewExpression */: + return hasArguments ? 18 : 17; + case 174 /* CallExpression */: + return 17; + case 186 /* PostfixUnaryExpression */: + return 16; + case 185 /* PrefixUnaryExpression */: + case 182 /* TypeOfExpression */: + case 183 /* VoidExpression */: + case 181 /* DeleteExpression */: + case 184 /* AwaitExpression */: + return 15; + case 187 /* BinaryExpression */: + switch (operatorKind) { + case 49 /* ExclamationToken */: + case 50 /* TildeToken */: + return 15; + case 38 /* AsteriskAsteriskToken */: + case 37 /* AsteriskToken */: + case 39 /* SlashToken */: + case 40 /* PercentToken */: + return 14; + case 35 /* PlusToken */: + case 36 /* MinusToken */: + return 13; + case 43 /* LessThanLessThanToken */: + case 44 /* GreaterThanGreaterThanToken */: + case 45 /* GreaterThanGreaterThanGreaterThanToken */: + return 12; + case 25 /* LessThanToken */: + case 28 /* LessThanEqualsToken */: + case 27 /* GreaterThanToken */: + case 29 /* GreaterThanEqualsToken */: + case 90 /* InKeyword */: + case 91 /* InstanceOfKeyword */: + return 11; + case 30 /* EqualsEqualsToken */: + case 32 /* EqualsEqualsEqualsToken */: + case 31 /* ExclamationEqualsToken */: + case 33 /* ExclamationEqualsEqualsToken */: + return 10; + case 46 /* AmpersandToken */: + return 9; + case 48 /* CaretToken */: + return 8; + case 47 /* BarToken */: + return 7; + case 51 /* AmpersandAmpersandToken */: + return 6; + case 52 /* BarBarToken */: + return 5; + case 56 /* EqualsToken */: + case 57 /* PlusEqualsToken */: + case 58 /* MinusEqualsToken */: + case 60 /* AsteriskAsteriskEqualsToken */: + case 59 /* AsteriskEqualsToken */: + case 61 /* SlashEqualsToken */: + case 62 /* PercentEqualsToken */: + case 63 /* LessThanLessThanEqualsToken */: + case 64 /* GreaterThanGreaterThanEqualsToken */: + case 65 /* GreaterThanGreaterThanGreaterThanEqualsToken */: + case 66 /* AmpersandEqualsToken */: + case 68 /* CaretEqualsToken */: + case 67 /* BarEqualsToken */: + return 3; + case 24 /* CommaToken */: + return 0; + default: + return -1; + } + case 188 /* ConditionalExpression */: + return 4; + case 190 /* YieldExpression */: + return 2; + case 191 /* SpreadElementExpression */: + return 1; + default: + return -1; + } } - ts.createSynthesizedNodeArray = createSynthesizedNodeArray; + ts.getOperatorPrecedence = getOperatorPrecedence; function createDiagnosticCollection() { var nonFileDiagnostics = []; var fileDiagnostics = ts.createMap(); @@ -4797,12 +5593,12 @@ var ts; return modificationCount; } function reattachFileDiagnostics(newFile) { - var diagnostics = fileDiagnostics[newFile.fileName]; - if (diagnostics) { - for (var _i = 0, diagnostics_1 = diagnostics; _i < diagnostics_1.length; _i++) { - var diagnostic = diagnostics_1[_i]; - diagnostic.file = newFile; - } + if (!ts.hasProperty(fileDiagnostics, newFile.fileName)) { + return; + } + for (var _i = 0, _a = fileDiagnostics[newFile.fileName]; _i < _a.length; _i++) { + var diagnostic = _a[_i]; + diagnostic.file = newFile; } } function add(diagnostic) { @@ -4981,10 +5777,23 @@ var ts; getLine: function () { return lineCount + 1; }, getColumn: function () { return lineStart ? indent * getIndentSize() + 1 : output.length - linePos + 1; }, getText: function () { return output; }, + isAtStartOfLine: function () { return lineStart; }, reset: reset }; } ts.createTextWriter = createTextWriter; + function getResolvedExternalModuleName(host, file) { + return file.moduleName || getExternalModuleNameFromPath(host, file.fileName); + } + ts.getResolvedExternalModuleName = getResolvedExternalModuleName; + function getExternalModuleNameFromDeclaration(host, resolver, declaration) { + var file = resolver.getExternalModuleFileFromDeclaration(declaration); + if (!file || isDeclarationFile(file)) { + return undefined; + } + return getResolvedExternalModuleName(host, file); + } + ts.getExternalModuleNameFromDeclaration = getExternalModuleNameFromDeclaration; /** * Resolves a local path to a path which is absolute to the base of the emit */ @@ -5011,25 +5820,112 @@ var ts; function getDeclarationEmitOutputFilePath(sourceFile, host) { var options = host.getCompilerOptions(); var outputDir = options.declarationDir || options.outDir; // Prefer declaration folder if specified - if (options.declaration) { - var path = outputDir - ? getSourceFilePathInNewDir(sourceFile, host, outputDir) - : sourceFile.fileName; - return ts.removeFileExtension(path) + ".d.ts"; - } + var path = outputDir + ? getSourceFilePathInNewDir(sourceFile, host, outputDir) + : sourceFile.fileName; + return ts.removeFileExtension(path) + ".d.ts"; } ts.getDeclarationEmitOutputFilePath = getDeclarationEmitOutputFilePath; - function getEmitScriptTarget(compilerOptions) { - return compilerOptions.target || 0 /* ES3 */; + /** + * Gets the source files that are expected to have an emit output. + * + * Originally part of `forEachExpectedEmitFile`, this functionality was extracted to support + * transformations. + * + * @param host An EmitHost. + * @param targetSourceFile An optional target source file to emit. + */ + function getSourceFilesToEmit(host, targetSourceFile) { + var options = host.getCompilerOptions(); + if (options.outFile || options.out) { + var moduleKind = ts.getEmitModuleKind(options); + var moduleEmitEnabled = moduleKind === ts.ModuleKind.AMD || moduleKind === ts.ModuleKind.System; + var sourceFiles = host.getSourceFiles(); + // Can emit only sources that are not declaration file and are either non module code or module with --module or --target es6 specified + return ts.filter(sourceFiles, moduleEmitEnabled ? isNonDeclarationFile : isBundleEmitNonExternalModule); + } + else { + var sourceFiles = targetSourceFile === undefined ? host.getSourceFiles() : [targetSourceFile]; + return ts.filter(sourceFiles, isNonDeclarationFile); + } } - ts.getEmitScriptTarget = getEmitScriptTarget; - function getEmitModuleKind(compilerOptions) { - return typeof compilerOptions.module === "number" ? - compilerOptions.module : - getEmitScriptTarget(compilerOptions) === 2 /* ES6 */ ? ts.ModuleKind.ES6 : ts.ModuleKind.CommonJS; + ts.getSourceFilesToEmit = getSourceFilesToEmit; + function isNonDeclarationFile(sourceFile) { + return !isDeclarationFile(sourceFile); } - ts.getEmitModuleKind = getEmitModuleKind; - function forEachExpectedEmitFile(host, action, targetSourceFile) { + function isBundleEmitNonExternalModule(sourceFile) { + return !isDeclarationFile(sourceFile) && !ts.isExternalModule(sourceFile); + } + /** + * Iterates over each source file to emit. The source files are expected to have been + * transformed for use by the pretty printer. + * + * Originally part of `forEachExpectedEmitFile`, this functionality was extracted to support + * transformations. + * + * @param host An EmitHost. + * @param sourceFiles The transformed source files to emit. + * @param action The action to execute. + */ + function forEachTransformedEmitFile(host, sourceFiles, action, emitOnlyDtsFiles) { + var options = host.getCompilerOptions(); + // Emit on each source file + if (options.outFile || options.out) { + onBundledEmit(host, sourceFiles); + } + else { + for (var _i = 0, sourceFiles_2 = sourceFiles; _i < sourceFiles_2.length; _i++) { + var sourceFile = sourceFiles_2[_i]; + // Don't emit if source file is a declaration file, or was located under node_modules + if (!isDeclarationFile(sourceFile) && !host.isSourceFileFromExternalLibrary(sourceFile)) { + onSingleFileEmit(host, sourceFile); + } + } + } + function onSingleFileEmit(host, sourceFile) { + // JavaScript files are always LanguageVariant.JSX, as JSX syntax is allowed in .js files also. + // So for JavaScript files, '.jsx' is only emitted if the input was '.jsx', and JsxEmit.Preserve. + // For TypeScript, the only time to emit with a '.jsx' extension, is on JSX input, and JsxEmit.Preserve + var extension = ".js"; + if (options.jsx === 1 /* Preserve */) { + if (isSourceFileJavaScript(sourceFile)) { + if (ts.fileExtensionIs(sourceFile.fileName, ".jsx")) { + extension = ".jsx"; + } + } + else if (sourceFile.languageVariant === 1 /* JSX */) { + // TypeScript source file preserving JSX syntax + extension = ".jsx"; + } + } + var jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, extension); + var sourceMapFilePath = getSourceMapFilePath(jsFilePath, options); + var declarationFilePath = !isSourceFileJavaScript(sourceFile) && (options.declaration || emitOnlyDtsFiles) ? getDeclarationEmitOutputFilePath(sourceFile, host) : undefined; + action(jsFilePath, sourceMapFilePath, declarationFilePath, [sourceFile], /*isBundledEmit*/ false); + } + function onBundledEmit(host, sourceFiles) { + if (sourceFiles.length) { + var jsFilePath = options.outFile || options.out; + var sourceMapFilePath = getSourceMapFilePath(jsFilePath, options); + var declarationFilePath = options.declaration ? ts.removeFileExtension(jsFilePath) + ".d.ts" : undefined; + action(jsFilePath, sourceMapFilePath, declarationFilePath, sourceFiles, /*isBundledEmit*/ true); + } + } + } + ts.forEachTransformedEmitFile = forEachTransformedEmitFile; + function getSourceMapFilePath(jsFilePath, options) { + return options.sourceMap ? jsFilePath + ".map" : undefined; + } + /** + * Iterates over the source files that are expected to have an emit output. This function + * is used by the legacy emitter and the declaration emitter and should not be used by + * the tree transforming emitter. + * + * @param host An EmitHost. + * @param action The action to execute. + * @param targetSourceFile An optional target source file to emit. + */ + function forEachExpectedEmitFile(host, action, targetSourceFile, emitOnlyDtsFiles) { var options = host.getCompilerOptions(); // Emit on each source file if (options.outFile || options.out) { @@ -5037,8 +5933,8 @@ var ts; } else { var sourceFiles = targetSourceFile === undefined ? host.getSourceFiles() : [targetSourceFile]; - for (var _i = 0, sourceFiles_1 = sourceFiles; _i < sourceFiles_1.length; _i++) { - var sourceFile = sourceFiles_1[_i]; + for (var _i = 0, sourceFiles_3 = sourceFiles; _i < sourceFiles_3.length; _i++) { + var sourceFile = sourceFiles_3[_i]; // Don't emit if source file is a declaration file, or was located under node_modules if (!isDeclarationFile(sourceFile) && !host.isSourceFileFromExternalLibrary(sourceFile)) { onSingleFileEmit(host, sourceFile); @@ -5062,12 +5958,13 @@ var ts; } } var jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, extension); + var declarationFilePath = !isSourceFileJavaScript(sourceFile) && (emitOnlyDtsFiles || options.declaration) ? getDeclarationEmitOutputFilePath(sourceFile, host) : undefined; var emitFileNames = { jsFilePath: jsFilePath, sourceMapFilePath: getSourceMapFilePath(jsFilePath, options), - declarationFilePath: !isSourceFileJavaScript(sourceFile) ? getDeclarationEmitOutputFilePath(sourceFile, host) : undefined + declarationFilePath: declarationFilePath }; - action(emitFileNames, [sourceFile], /*isBundledEmit*/ false); + action(emitFileNames, [sourceFile], /*isBundledEmit*/ false, emitOnlyDtsFiles); } function onBundledEmit(host) { // Can emit only sources that are not declaration file and are either non module code or module with @@ -5075,7 +5972,7 @@ var ts; var bundledSources = ts.filter(host.getSourceFiles(), function (sourceFile) { return !isDeclarationFile(sourceFile) && !host.isSourceFileFromExternalLibrary(sourceFile) && (!ts.isExternalModule(sourceFile) || - !!getEmitModuleKind(options)); }); + !!ts.getEmitModuleKind(options)); }); if (bundledSources.length) { var jsFilePath = options.outFile || options.out; var emitFileNames = { @@ -5083,12 +5980,9 @@ var ts; sourceMapFilePath: getSourceMapFilePath(jsFilePath, options), declarationFilePath: options.declaration ? ts.removeFileExtension(jsFilePath) + ".d.ts" : undefined }; - action(emitFileNames, bundledSources, /*isBundledEmit*/ true); + action(emitFileNames, bundledSources, /*isBundledEmit*/ true, emitOnlyDtsFiles); } } - function getSourceMapFilePath(jsFilePath, options) { - return options.sourceMap ? jsFilePath + ".map" : undefined; - } } ts.forEachExpectedEmitFile = forEachExpectedEmitFile; function getSourceFilePathInNewDir(sourceFile, host, newDirPath) { @@ -5150,7 +6044,7 @@ var ts; else { ts.forEach(declarations, function (member) { if ((member.kind === 149 /* GetAccessor */ || member.kind === 150 /* SetAccessor */) - && (member.flags & 32 /* Static */) === (accessor.flags & 32 /* Static */)) { + && hasModifier(member, 32 /* Static */) === hasModifier(accessor, 32 /* Static */)) { var memberName = getPropertyNameForPropertyNameNode(member.name); var accessorName = getPropertyNameForPropertyNameNode(accessor.name); if (memberName === accessorName) { @@ -5179,32 +6073,49 @@ var ts; } ts.getAllAccessorDeclarations = getAllAccessorDeclarations; function emitNewLineBeforeLeadingComments(lineMap, writer, node, leadingComments) { + emitNewLineBeforeLeadingCommentsOfPosition(lineMap, writer, node.pos, leadingComments); + } + ts.emitNewLineBeforeLeadingComments = emitNewLineBeforeLeadingComments; + function emitNewLineBeforeLeadingCommentsOfPosition(lineMap, writer, pos, leadingComments) { // If the leading comments start on different line than the start of node, write new line - if (leadingComments && leadingComments.length && node.pos !== leadingComments[0].pos && - getLineOfLocalPositionFromLineMap(lineMap, node.pos) !== getLineOfLocalPositionFromLineMap(lineMap, leadingComments[0].pos)) { + if (leadingComments && leadingComments.length && pos !== leadingComments[0].pos && + getLineOfLocalPositionFromLineMap(lineMap, pos) !== getLineOfLocalPositionFromLineMap(lineMap, leadingComments[0].pos)) { writer.writeLine(); } } - ts.emitNewLineBeforeLeadingComments = emitNewLineBeforeLeadingComments; - function emitComments(text, lineMap, writer, comments, trailingSeparator, newLine, writeComment) { - var emitLeadingSpace = !trailingSeparator; - ts.forEach(comments, function (comment) { - if (emitLeadingSpace) { + ts.emitNewLineBeforeLeadingCommentsOfPosition = emitNewLineBeforeLeadingCommentsOfPosition; + function emitNewLineBeforeLeadingCommentOfPosition(lineMap, writer, pos, commentPos) { + // If the leading comments start on different line than the start of node, write new line + if (pos !== commentPos && + getLineOfLocalPositionFromLineMap(lineMap, pos) !== getLineOfLocalPositionFromLineMap(lineMap, commentPos)) { + writer.writeLine(); + } + } + ts.emitNewLineBeforeLeadingCommentOfPosition = emitNewLineBeforeLeadingCommentOfPosition; + function emitComments(text, lineMap, writer, comments, leadingSeparator, trailingSeparator, newLine, writeComment) { + if (comments && comments.length > 0) { + if (leadingSeparator) { writer.write(" "); - emitLeadingSpace = false; } - writeComment(text, lineMap, writer, comment, newLine); - if (comment.hasTrailingNewLine) { - writer.writeLine(); + var emitInterveningSeparator = false; + for (var _i = 0, comments_1 = comments; _i < comments_1.length; _i++) { + var comment = comments_1[_i]; + if (emitInterveningSeparator) { + writer.write(" "); + emitInterveningSeparator = false; + } + writeComment(text, lineMap, writer, comment.pos, comment.end, newLine); + if (comment.hasTrailingNewLine) { + writer.writeLine(); + } + else { + emitInterveningSeparator = true; + } } - else if (trailingSeparator) { + if (emitInterveningSeparator && trailingSeparator) { writer.write(" "); } - else { - // Emit leading space to separate comment during next comment emit - emitLeadingSpace = true; - } - }); + } } ts.emitComments = emitComments; /** @@ -5255,7 +6166,7 @@ var ts; if (nodeLine >= lastCommentLine + 2) { // Valid detachedComments emitNewLineBeforeLeadingComments(lineMap, writer, node, leadingComments); - emitComments(text, lineMap, writer, detachedComments, /*trailingSeparator*/ true, newLine, writeComment); + emitComments(text, lineMap, writer, detachedComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeComment); currentDetachedCommentInfo = { nodePos: node.pos, detachedCommentEndPos: ts.lastOrUndefined(detachedComments).end }; } } @@ -5267,19 +6178,19 @@ var ts; } } ts.emitDetachedComments = emitDetachedComments; - function writeCommentRange(text, lineMap, writer, comment, newLine) { - if (text.charCodeAt(comment.pos + 1) === 42 /* asterisk */) { - var firstCommentLineAndCharacter = ts.computeLineAndCharacterOfPosition(lineMap, comment.pos); + function writeCommentRange(text, lineMap, writer, commentPos, commentEnd, newLine) { + if (text.charCodeAt(commentPos + 1) === 42 /* asterisk */) { + var firstCommentLineAndCharacter = ts.computeLineAndCharacterOfPosition(lineMap, commentPos); var lineCount = lineMap.length; var firstCommentLineIndent = void 0; - for (var pos = comment.pos, currentLine = firstCommentLineAndCharacter.line; pos < comment.end; currentLine++) { + for (var pos = commentPos, currentLine = firstCommentLineAndCharacter.line; pos < commentEnd; currentLine++) { var nextLineStart = (currentLine + 1) === lineCount ? text.length + 1 : lineMap[currentLine + 1]; - if (pos !== comment.pos) { + if (pos !== commentPos) { // If we are not emitting first line, we need to write the spaces to adjust the alignment if (firstCommentLineIndent === undefined) { - firstCommentLineIndent = calculateIndent(text, lineMap[firstCommentLineAndCharacter.line], comment.pos); + firstCommentLineIndent = calculateIndent(text, lineMap[firstCommentLineAndCharacter.line], commentPos); } // These are number of spaces writer is going to write at current indent var currentWriterIndentSpacing = writer.getIndent() * getIndentSize(); @@ -5315,23 +6226,23 @@ var ts; } } // Write the comment line text - writeTrimmedCurrentLine(text, comment, writer, newLine, pos, nextLineStart); + writeTrimmedCurrentLine(text, commentEnd, writer, newLine, pos, nextLineStart); pos = nextLineStart; } } else { // Single line comment of style //.... - writer.write(text.substring(comment.pos, comment.end)); + writer.write(text.substring(commentPos, commentEnd)); } } ts.writeCommentRange = writeCommentRange; - function writeTrimmedCurrentLine(text, comment, writer, newLine, pos, nextLineStart) { - var end = Math.min(comment.end, nextLineStart - 1); + function writeTrimmedCurrentLine(text, commentEnd, writer, newLine, pos, nextLineStart) { + var end = Math.min(commentEnd, nextLineStart - 1); var currentLineText = text.substring(pos, end).replace(/^\s+|\s+$/g, ""); if (currentLineText) { // trimmed forward and ending spaces text writer.write(currentLineText); - if (end !== comment.end) { + if (end !== commentEnd) { writer.writeLine(); } } @@ -5354,6 +6265,32 @@ var ts; } return currentLineIndent; } + function hasModifiers(node) { + return getModifierFlags(node) !== 0 /* None */; + } + ts.hasModifiers = hasModifiers; + function hasModifier(node, flags) { + return (getModifierFlags(node) & flags) !== 0; + } + ts.hasModifier = hasModifier; + function getModifierFlags(node) { + if (node.modifierFlagsCache & 536870912 /* HasComputedFlags */) { + return node.modifierFlagsCache & ~536870912 /* HasComputedFlags */; + } + var flags = 0 /* None */; + if (node.modifiers) { + for (var _i = 0, _a = node.modifiers; _i < _a.length; _i++) { + var modifier = _a[_i]; + flags |= modifierToFlag(modifier.kind); + } + } + if (node.flags & 4 /* NestedNamespace */) { + flags |= 1 /* Export */; + } + node.modifierFlagsCache = flags | 536870912 /* HasComputedFlags */; + return flags; + } + ts.getModifierFlags = getModifierFlags; function modifierToFlag(token) { switch (token) { case 113 /* StaticKeyword */: return 32 /* Static */; @@ -5368,42 +6305,15 @@ var ts; case 118 /* AsyncKeyword */: return 256 /* Async */; case 128 /* ReadonlyKeyword */: return 64 /* Readonly */; } - return 0; + return 0 /* None */; } ts.modifierToFlag = modifierToFlag; - function isLeftHandSideExpression(expr) { - if (expr) { - switch (expr.kind) { - case 172 /* PropertyAccessExpression */: - case 173 /* ElementAccessExpression */: - case 175 /* NewExpression */: - case 174 /* CallExpression */: - case 196 /* NonNullExpression */: - case 241 /* JsxElement */: - case 242 /* JsxSelfClosingElement */: - case 176 /* TaggedTemplateExpression */: - case 170 /* ArrayLiteralExpression */: - case 178 /* ParenthesizedExpression */: - case 171 /* ObjectLiteralExpression */: - case 192 /* ClassExpression */: - case 179 /* FunctionExpression */: - case 69 /* Identifier */: - case 10 /* RegularExpressionLiteral */: - case 8 /* NumericLiteral */: - case 9 /* StringLiteral */: - case 11 /* NoSubstitutionTemplateLiteral */: - case 189 /* TemplateExpression */: - case 84 /* FalseKeyword */: - case 93 /* NullKeyword */: - case 97 /* ThisKeyword */: - case 99 /* TrueKeyword */: - case 95 /* SuperKeyword */: - return true; - } - } - return false; + function isLogicalOperator(token) { + return token === 52 /* BarBarToken */ + || token === 51 /* AmpersandAmpersandToken */ + || token === 49 /* ExclamationToken */; } - ts.isLeftHandSideExpression = isLeftHandSideExpression; + ts.isLogicalOperator = isLogicalOperator; function isAssignmentOperator(token) { return token >= 56 /* FirstAssignment */ && token <= 68 /* LastAssignment */; } @@ -5417,6 +6327,34 @@ var ts; } } ts.tryGetClassExtendingExpressionWithTypeArguments = tryGetClassExtendingExpressionWithTypeArguments; + function isDestructuringAssignment(node) { + if (isBinaryExpression(node)) { + if (node.operatorToken.kind === 56 /* EqualsToken */) { + var kind = node.left.kind; + return kind === 171 /* ObjectLiteralExpression */ + || kind === 170 /* ArrayLiteralExpression */; + } + } + return false; + } + ts.isDestructuringAssignment = isDestructuringAssignment; + // Returns false if this heritage clause element's expression contains something unsupported + // (i.e. not a name or dotted name). + function isSupportedExpressionWithTypeArguments(node) { + return isSupportedExpressionWithTypeArgumentsRest(node.expression); + } + ts.isSupportedExpressionWithTypeArguments = isSupportedExpressionWithTypeArguments; + function isSupportedExpressionWithTypeArgumentsRest(node) { + if (node.kind === 69 /* Identifier */) { + return true; + } + else if (isPropertyAccessExpression(node)) { + return isSupportedExpressionWithTypeArgumentsRest(node.expression); + } + else { + return false; + } + } function isExpressionWithTypeArgumentsInClassExtendsClause(node) { return tryGetClassExtendingExpressionWithTypeArguments(node) !== undefined; } @@ -5443,17 +6381,9 @@ var ts; } ts.isEmptyObjectLiteralOrArrayLiteral = isEmptyObjectLiteralOrArrayLiteral; function getLocalSymbolForExportDefault(symbol) { - return symbol && symbol.valueDeclaration && (symbol.valueDeclaration.flags & 512 /* Default */) ? symbol.valueDeclaration.localSymbol : undefined; + return symbol && symbol.valueDeclaration && hasModifier(symbol.valueDeclaration, 512 /* Default */) ? symbol.valueDeclaration.localSymbol : undefined; } ts.getLocalSymbolForExportDefault = getLocalSymbolForExportDefault; - function hasJavaScriptFileExtension(fileName) { - return ts.forEach(ts.supportedJavascriptExtensions, function (extension) { return ts.fileExtensionIs(fileName, extension); }); - } - ts.hasJavaScriptFileExtension = hasJavaScriptFileExtension; - function hasTypeScriptFileExtension(fileName) { - return ts.forEach(ts.supportedTypeScriptExtensions, function (extension) { return ts.fileExtensionIs(fileName, extension); }); - } - ts.hasTypeScriptFileExtension = hasTypeScriptFileExtension; /** Return ".ts", ".d.ts", or ".tsx", if that is the extension. */ function tryExtractTypeScriptExtension(fileName) { return ts.find(ts.supportedTypescriptExtensionsForExtractExtension, function (extension) { return ts.fileExtensionIs(fileName, extension); }); @@ -5566,12 +6496,6 @@ var ts; return result; } ts.convertToBase64 = convertToBase64; - function convertToRelativePath(absoluteOrRelativePath, basePath, getCanonicalFileName) { - return !ts.isRootedDiskPath(absoluteOrRelativePath) - ? absoluteOrRelativePath - : ts.getRelativePathToDirectoryOrUrl(basePath, absoluteOrRelativePath, basePath, getCanonicalFileName, /* isAbsolutePathAnUrl */ false); - } - ts.convertToRelativePath = convertToRelativePath; var carriageReturnLineFeed = "\r\n"; var lineFeed = "\n"; function getNewLineCharacter(options) { @@ -5587,6 +6511,847 @@ var ts; return carriageReturnLineFeed; } ts.getNewLineCharacter = getNewLineCharacter; + /** + * Tests whether a node and its subtree is simple enough to have its position + * information ignored when emitting source maps in a destructuring assignment. + * + * @param node The expression to test. + */ + function isSimpleExpression(node) { + return isSimpleExpressionWorker(node, 0); + } + ts.isSimpleExpression = isSimpleExpression; + function isSimpleExpressionWorker(node, depth) { + if (depth <= 5) { + var kind = node.kind; + if (kind === 9 /* StringLiteral */ + || kind === 8 /* NumericLiteral */ + || kind === 10 /* RegularExpressionLiteral */ + || kind === 11 /* NoSubstitutionTemplateLiteral */ + || kind === 69 /* Identifier */ + || kind === 97 /* ThisKeyword */ + || kind === 95 /* SuperKeyword */ + || kind === 99 /* TrueKeyword */ + || kind === 84 /* FalseKeyword */ + || kind === 93 /* NullKeyword */) { + return true; + } + else if (kind === 172 /* PropertyAccessExpression */) { + return isSimpleExpressionWorker(node.expression, depth + 1); + } + else if (kind === 173 /* ElementAccessExpression */) { + return isSimpleExpressionWorker(node.expression, depth + 1) + && isSimpleExpressionWorker(node.argumentExpression, depth + 1); + } + else if (kind === 185 /* PrefixUnaryExpression */ + || kind === 186 /* PostfixUnaryExpression */) { + return isSimpleExpressionWorker(node.operand, depth + 1); + } + else if (kind === 187 /* BinaryExpression */) { + return node.operatorToken.kind !== 38 /* AsteriskAsteriskToken */ + && isSimpleExpressionWorker(node.left, depth + 1) + && isSimpleExpressionWorker(node.right, depth + 1); + } + else if (kind === 188 /* ConditionalExpression */) { + return isSimpleExpressionWorker(node.condition, depth + 1) + && isSimpleExpressionWorker(node.whenTrue, depth + 1) + && isSimpleExpressionWorker(node.whenFalse, depth + 1); + } + else if (kind === 183 /* VoidExpression */ + || kind === 182 /* TypeOfExpression */ + || kind === 181 /* DeleteExpression */) { + return isSimpleExpressionWorker(node.expression, depth + 1); + } + else if (kind === 170 /* ArrayLiteralExpression */) { + return node.elements.length === 0; + } + else if (kind === 171 /* ObjectLiteralExpression */) { + return node.properties.length === 0; + } + else if (kind === 174 /* CallExpression */) { + if (!isSimpleExpressionWorker(node.expression, depth + 1)) { + return false; + } + for (var _i = 0, _a = node.arguments; _i < _a.length; _i++) { + var argument = _a[_i]; + if (!isSimpleExpressionWorker(argument, depth + 1)) { + return false; + } + } + return true; + } + } + return false; + } + var syntaxKindCache = ts.createMap(); + function formatSyntaxKind(kind) { + var syntaxKindEnum = ts.SyntaxKind; + if (syntaxKindEnum) { + if (syntaxKindCache[kind]) { + return syntaxKindCache[kind]; + } + for (var name_6 in syntaxKindEnum) { + if (syntaxKindEnum[name_6] === kind) { + return syntaxKindCache[kind] = kind.toString() + " (" + name_6 + ")"; + } + } + } + else { + return kind.toString(); + } + } + ts.formatSyntaxKind = formatSyntaxKind; + /** + * Increases (or decreases) a position by the provided amount. + * + * @param pos The position. + * @param value The delta. + */ + function movePos(pos, value) { + return ts.positionIsSynthesized(pos) ? -1 : pos + value; + } + ts.movePos = movePos; + /** + * Creates a new TextRange from the provided pos and end. + * + * @param pos The start position. + * @param end The end position. + */ + function createRange(pos, end) { + return { pos: pos, end: end }; + } + ts.createRange = createRange; + /** + * Creates a new TextRange from a provided range with a new end position. + * + * @param range A TextRange. + * @param end The new end position. + */ + function moveRangeEnd(range, end) { + return createRange(range.pos, end); + } + ts.moveRangeEnd = moveRangeEnd; + /** + * Creates a new TextRange from a provided range with a new start position. + * + * @param range A TextRange. + * @param pos The new Start position. + */ + function moveRangePos(range, pos) { + return createRange(pos, range.end); + } + ts.moveRangePos = moveRangePos; + /** + * Moves the start position of a range past any decorators. + */ + function moveRangePastDecorators(node) { + return node.decorators && node.decorators.length > 0 + ? moveRangePos(node, node.decorators.end) + : node; + } + ts.moveRangePastDecorators = moveRangePastDecorators; + /** + * Moves the start position of a range past any decorators or modifiers. + */ + function moveRangePastModifiers(node) { + return node.modifiers && node.modifiers.length > 0 + ? moveRangePos(node, node.modifiers.end) + : moveRangePastDecorators(node); + } + ts.moveRangePastModifiers = moveRangePastModifiers; + /** + * Determines whether a TextRange has the same start and end positions. + * + * @param range A TextRange. + */ + function isCollapsedRange(range) { + return range.pos === range.end; + } + ts.isCollapsedRange = isCollapsedRange; + /** + * Creates a new TextRange from a provided range with its end position collapsed to its + * start position. + * + * @param range A TextRange. + */ + function collapseRangeToStart(range) { + return isCollapsedRange(range) ? range : moveRangeEnd(range, range.pos); + } + ts.collapseRangeToStart = collapseRangeToStart; + /** + * Creates a new TextRange from a provided range with its start position collapsed to its + * end position. + * + * @param range A TextRange. + */ + function collapseRangeToEnd(range) { + return isCollapsedRange(range) ? range : moveRangePos(range, range.end); + } + ts.collapseRangeToEnd = collapseRangeToEnd; + /** + * Creates a new TextRange for a token at the provides start position. + * + * @param pos The start position. + * @param token The token. + */ + function createTokenRange(pos, token) { + return createRange(pos, pos + ts.tokenToString(token).length); + } + ts.createTokenRange = createTokenRange; + function rangeIsOnSingleLine(range, sourceFile) { + return rangeStartIsOnSameLineAsRangeEnd(range, range, sourceFile); + } + ts.rangeIsOnSingleLine = rangeIsOnSingleLine; + function rangeStartPositionsAreOnSameLine(range1, range2, sourceFile) { + return positionsAreOnSameLine(getStartPositionOfRange(range1, sourceFile), getStartPositionOfRange(range2, sourceFile), sourceFile); + } + ts.rangeStartPositionsAreOnSameLine = rangeStartPositionsAreOnSameLine; + function rangeEndPositionsAreOnSameLine(range1, range2, sourceFile) { + return positionsAreOnSameLine(range1.end, range2.end, sourceFile); + } + ts.rangeEndPositionsAreOnSameLine = rangeEndPositionsAreOnSameLine; + function rangeStartIsOnSameLineAsRangeEnd(range1, range2, sourceFile) { + return positionsAreOnSameLine(getStartPositionOfRange(range1, sourceFile), range2.end, sourceFile); + } + ts.rangeStartIsOnSameLineAsRangeEnd = rangeStartIsOnSameLineAsRangeEnd; + function rangeEndIsOnSameLineAsRangeStart(range1, range2, sourceFile) { + return positionsAreOnSameLine(range1.end, getStartPositionOfRange(range2, sourceFile), sourceFile); + } + ts.rangeEndIsOnSameLineAsRangeStart = rangeEndIsOnSameLineAsRangeStart; + function positionsAreOnSameLine(pos1, pos2, sourceFile) { + return pos1 === pos2 || + getLineOfLocalPosition(sourceFile, pos1) === getLineOfLocalPosition(sourceFile, pos2); + } + ts.positionsAreOnSameLine = positionsAreOnSameLine; + function getStartPositionOfRange(range, sourceFile) { + return ts.positionIsSynthesized(range.pos) ? -1 : ts.skipTrivia(sourceFile.text, range.pos); + } + ts.getStartPositionOfRange = getStartPositionOfRange; + function collectExternalModuleInfo(sourceFile, resolver) { + var externalImports = []; + var exportSpecifiers = ts.createMap(); + var exportEquals = undefined; + var hasExportStarsToExportValues = false; + for (var _i = 0, _a = sourceFile.statements; _i < _a.length; _i++) { + var node = _a[_i]; + switch (node.kind) { + case 230 /* ImportDeclaration */: + if (!node.importClause || + resolver.isReferencedAliasDeclaration(node.importClause, /*checkChildren*/ true)) { + // import "mod" + // import x from "mod" where x is referenced + // import * as x from "mod" where x is referenced + // import { x, y } from "mod" where at least one import is referenced + externalImports.push(node); + } + break; + case 229 /* ImportEqualsDeclaration */: + if (node.moduleReference.kind === 240 /* ExternalModuleReference */ && resolver.isReferencedAliasDeclaration(node)) { + // import x = require("mod") where x is referenced + externalImports.push(node); + } + break; + case 236 /* ExportDeclaration */: + if (node.moduleSpecifier) { + if (!node.exportClause) { + // export * from "mod" + if (resolver.moduleExportsSomeValue(node.moduleSpecifier)) { + externalImports.push(node); + hasExportStarsToExportValues = true; + } + } + else if (resolver.isValueAliasDeclaration(node)) { + // export { x, y } from "mod" where at least one export is a value symbol + externalImports.push(node); + } + } + else { + // export { x, y } + for (var _b = 0, _c = node.exportClause.elements; _b < _c.length; _b++) { + var specifier = _c[_b]; + var name_7 = (specifier.propertyName || specifier.name).text; + (exportSpecifiers[name_7] || (exportSpecifiers[name_7] = [])).push(specifier); + } + } + break; + case 235 /* ExportAssignment */: + if (node.isExportEquals && !exportEquals) { + // export = x + exportEquals = node; + } + break; + } + } + return { externalImports: externalImports, exportSpecifiers: exportSpecifiers, exportEquals: exportEquals, hasExportStarsToExportValues: hasExportStarsToExportValues }; + } + ts.collectExternalModuleInfo = collectExternalModuleInfo; + function getInitializedVariables(node) { + return ts.filter(node.declarations, isInitializedVariable); + } + ts.getInitializedVariables = getInitializedVariables; + function isInitializedVariable(node) { + return node.initializer !== undefined; + } + /** + * Gets a value indicating whether a node is merged with a class declaration in the same scope. + */ + function isMergedWithClass(node) { + if (node.symbol) { + for (var _i = 0, _a = node.symbol.declarations; _i < _a.length; _i++) { + var declaration = _a[_i]; + if (declaration.kind === 221 /* ClassDeclaration */ && declaration !== node) { + return true; + } + } + } + return false; + } + ts.isMergedWithClass = isMergedWithClass; + /** + * Gets a value indicating whether a node is the first declaration of its kind. + * + * @param node A Declaration node. + * @param kind The SyntaxKind to find among related declarations. + */ + function isFirstDeclarationOfKind(node, kind) { + return node.symbol && getDeclarationOfKind(node.symbol, kind) === node; + } + ts.isFirstDeclarationOfKind = isFirstDeclarationOfKind; + // Node tests + // + // All node tests in the following list should *not* reference parent pointers so that + // they may be used with transformations. + // Node Arrays + function isNodeArray(array) { + return array.hasOwnProperty("pos") + && array.hasOwnProperty("end"); + } + ts.isNodeArray = isNodeArray; + // Literals + function isNoSubstitutionTemplateLiteral(node) { + return node.kind === 11 /* NoSubstitutionTemplateLiteral */; + } + ts.isNoSubstitutionTemplateLiteral = isNoSubstitutionTemplateLiteral; + function isLiteralKind(kind) { + return 8 /* FirstLiteralToken */ <= kind && kind <= 11 /* LastLiteralToken */; + } + ts.isLiteralKind = isLiteralKind; + function isTextualLiteralKind(kind) { + return kind === 9 /* StringLiteral */ || kind === 11 /* NoSubstitutionTemplateLiteral */; + } + ts.isTextualLiteralKind = isTextualLiteralKind; + function isLiteralExpression(node) { + return isLiteralKind(node.kind); + } + ts.isLiteralExpression = isLiteralExpression; + // Pseudo-literals + function isTemplateLiteralKind(kind) { + return 11 /* FirstTemplateToken */ <= kind && kind <= 14 /* LastTemplateToken */; + } + ts.isTemplateLiteralKind = isTemplateLiteralKind; + function isTemplateLiteralFragmentKind(kind) { + return kind === 12 /* TemplateHead */ + || kind === 13 /* TemplateMiddle */ + || kind === 14 /* TemplateTail */; + } + function isTemplateLiteralFragment(node) { + return isTemplateLiteralFragmentKind(node.kind); + } + ts.isTemplateLiteralFragment = isTemplateLiteralFragment; + // Identifiers + function isIdentifier(node) { + return node.kind === 69 /* Identifier */; + } + ts.isIdentifier = isIdentifier; + function isGeneratedIdentifier(node) { + // Using `>` here catches both `GeneratedIdentifierKind.None` and `undefined`. + return isIdentifier(node) && node.autoGenerateKind > 0 /* None */; + } + ts.isGeneratedIdentifier = isGeneratedIdentifier; + // Keywords + function isModifier(node) { + return isModifierKind(node.kind); + } + ts.isModifier = isModifier; + // Names + function isQualifiedName(node) { + return node.kind === 139 /* QualifiedName */; + } + ts.isQualifiedName = isQualifiedName; + function isComputedPropertyName(node) { + return node.kind === 140 /* ComputedPropertyName */; + } + ts.isComputedPropertyName = isComputedPropertyName; + function isEntityName(node) { + var kind = node.kind; + return kind === 139 /* QualifiedName */ + || kind === 69 /* Identifier */; + } + ts.isEntityName = isEntityName; + function isPropertyName(node) { + var kind = node.kind; + return kind === 69 /* Identifier */ + || kind === 9 /* StringLiteral */ + || kind === 8 /* NumericLiteral */ + || kind === 140 /* ComputedPropertyName */; + } + ts.isPropertyName = isPropertyName; + function isModuleName(node) { + var kind = node.kind; + return kind === 69 /* Identifier */ + || kind === 9 /* StringLiteral */; + } + ts.isModuleName = isModuleName; + function isBindingName(node) { + var kind = node.kind; + return kind === 69 /* Identifier */ + || kind === 167 /* ObjectBindingPattern */ + || kind === 168 /* ArrayBindingPattern */; + } + ts.isBindingName = isBindingName; + // Signature elements + function isTypeParameter(node) { + return node.kind === 141 /* TypeParameter */; + } + ts.isTypeParameter = isTypeParameter; + function isParameter(node) { + return node.kind === 142 /* Parameter */; + } + ts.isParameter = isParameter; + function isDecorator(node) { + return node.kind === 143 /* Decorator */; + } + ts.isDecorator = isDecorator; + // Type members + function isMethodDeclaration(node) { + return node.kind === 147 /* MethodDeclaration */; + } + ts.isMethodDeclaration = isMethodDeclaration; + function isClassElement(node) { + var kind = node.kind; + return kind === 148 /* Constructor */ + || kind === 145 /* PropertyDeclaration */ + || kind === 147 /* MethodDeclaration */ + || kind === 149 /* GetAccessor */ + || kind === 150 /* SetAccessor */ + || kind === 153 /* IndexSignature */ + || kind === 198 /* SemicolonClassElement */; + } + ts.isClassElement = isClassElement; + function isObjectLiteralElementLike(node) { + var kind = node.kind; + return kind === 253 /* PropertyAssignment */ + || kind === 254 /* ShorthandPropertyAssignment */ + || kind === 147 /* MethodDeclaration */ + || kind === 149 /* GetAccessor */ + || kind === 150 /* SetAccessor */ + || kind === 239 /* MissingDeclaration */; + } + ts.isObjectLiteralElementLike = isObjectLiteralElementLike; + // Type + function isTypeNodeKind(kind) { + return (kind >= 154 /* FirstTypeNode */ && kind <= 166 /* LastTypeNode */) + || kind === 117 /* AnyKeyword */ + || kind === 130 /* NumberKeyword */ + || kind === 120 /* BooleanKeyword */ + || kind === 132 /* StringKeyword */ + || kind === 133 /* SymbolKeyword */ + || kind === 103 /* VoidKeyword */ + || kind === 127 /* NeverKeyword */ + || kind === 194 /* ExpressionWithTypeArguments */; + } + /** + * Node test that determines whether a node is a valid type node. + * This differs from the `isPartOfTypeNode` function which determines whether a node is *part* + * of a TypeNode. + */ + function isTypeNode(node) { + return isTypeNodeKind(node.kind); + } + ts.isTypeNode = isTypeNode; + // Binding patterns + function isBindingPattern(node) { + if (node) { + var kind = node.kind; + return kind === 168 /* ArrayBindingPattern */ + || kind === 167 /* ObjectBindingPattern */; + } + return false; + } + ts.isBindingPattern = isBindingPattern; + function isBindingElement(node) { + return node.kind === 169 /* BindingElement */; + } + ts.isBindingElement = isBindingElement; + function isArrayBindingElement(node) { + var kind = node.kind; + return kind === 169 /* BindingElement */ + || kind === 193 /* OmittedExpression */; + } + ts.isArrayBindingElement = isArrayBindingElement; + // Expression + function isPropertyAccessExpression(node) { + return node.kind === 172 /* PropertyAccessExpression */; + } + ts.isPropertyAccessExpression = isPropertyAccessExpression; + function isElementAccessExpression(node) { + return node.kind === 173 /* ElementAccessExpression */; + } + ts.isElementAccessExpression = isElementAccessExpression; + function isBinaryExpression(node) { + return node.kind === 187 /* BinaryExpression */; + } + ts.isBinaryExpression = isBinaryExpression; + function isConditionalExpression(node) { + return node.kind === 188 /* ConditionalExpression */; + } + ts.isConditionalExpression = isConditionalExpression; + function isCallExpression(node) { + return node.kind === 174 /* CallExpression */; + } + ts.isCallExpression = isCallExpression; + function isTemplate(node) { + var kind = node.kind; + return kind === 189 /* TemplateExpression */ + || kind === 11 /* NoSubstitutionTemplateLiteral */; + } + ts.isTemplate = isTemplate; + function isSpreadElementExpression(node) { + return node.kind === 191 /* SpreadElementExpression */; + } + ts.isSpreadElementExpression = isSpreadElementExpression; + function isExpressionWithTypeArguments(node) { + return node.kind === 194 /* ExpressionWithTypeArguments */; + } + ts.isExpressionWithTypeArguments = isExpressionWithTypeArguments; + function isLeftHandSideExpressionKind(kind) { + return kind === 172 /* PropertyAccessExpression */ + || kind === 173 /* ElementAccessExpression */ + || kind === 175 /* NewExpression */ + || kind === 174 /* CallExpression */ + || kind === 241 /* JsxElement */ + || kind === 242 /* JsxSelfClosingElement */ + || kind === 176 /* TaggedTemplateExpression */ + || kind === 170 /* ArrayLiteralExpression */ + || kind === 178 /* ParenthesizedExpression */ + || kind === 171 /* ObjectLiteralExpression */ + || kind === 192 /* ClassExpression */ + || kind === 179 /* FunctionExpression */ + || kind === 69 /* Identifier */ + || kind === 10 /* RegularExpressionLiteral */ + || kind === 8 /* NumericLiteral */ + || kind === 9 /* StringLiteral */ + || kind === 11 /* NoSubstitutionTemplateLiteral */ + || kind === 189 /* TemplateExpression */ + || kind === 84 /* FalseKeyword */ + || kind === 93 /* NullKeyword */ + || kind === 97 /* ThisKeyword */ + || kind === 99 /* TrueKeyword */ + || kind === 95 /* SuperKeyword */ + || kind === 196 /* NonNullExpression */; + } + function isLeftHandSideExpression(node) { + return isLeftHandSideExpressionKind(ts.skipPartiallyEmittedExpressions(node).kind); + } + ts.isLeftHandSideExpression = isLeftHandSideExpression; + function isUnaryExpressionKind(kind) { + return kind === 185 /* PrefixUnaryExpression */ + || kind === 186 /* PostfixUnaryExpression */ + || kind === 181 /* DeleteExpression */ + || kind === 182 /* TypeOfExpression */ + || kind === 183 /* VoidExpression */ + || kind === 184 /* AwaitExpression */ + || kind === 177 /* TypeAssertionExpression */ + || isLeftHandSideExpressionKind(kind); + } + function isUnaryExpression(node) { + return isUnaryExpressionKind(ts.skipPartiallyEmittedExpressions(node).kind); + } + ts.isUnaryExpression = isUnaryExpression; + function isExpressionKind(kind) { + return kind === 188 /* ConditionalExpression */ + || kind === 190 /* YieldExpression */ + || kind === 180 /* ArrowFunction */ + || kind === 187 /* BinaryExpression */ + || kind === 191 /* SpreadElementExpression */ + || kind === 195 /* AsExpression */ + || kind === 193 /* OmittedExpression */ + || isUnaryExpressionKind(kind); + } + function isExpression(node) { + return isExpressionKind(ts.skipPartiallyEmittedExpressions(node).kind); + } + ts.isExpression = isExpression; + function isAssertionExpression(node) { + var kind = node.kind; + return kind === 177 /* TypeAssertionExpression */ + || kind === 195 /* AsExpression */; + } + ts.isAssertionExpression = isAssertionExpression; + function isPartiallyEmittedExpression(node) { + return node.kind === 288 /* PartiallyEmittedExpression */; + } + ts.isPartiallyEmittedExpression = isPartiallyEmittedExpression; + function isNotEmittedStatement(node) { + return node.kind === 287 /* NotEmittedStatement */; + } + ts.isNotEmittedStatement = isNotEmittedStatement; + function isNotEmittedOrPartiallyEmittedNode(node) { + return isNotEmittedStatement(node) + || isPartiallyEmittedExpression(node); + } + ts.isNotEmittedOrPartiallyEmittedNode = isNotEmittedOrPartiallyEmittedNode; + function isOmittedExpression(node) { + return node.kind === 193 /* OmittedExpression */; + } + ts.isOmittedExpression = isOmittedExpression; + // Misc + function isTemplateSpan(node) { + return node.kind === 197 /* TemplateSpan */; + } + ts.isTemplateSpan = isTemplateSpan; + // Element + function isBlock(node) { + return node.kind === 199 /* Block */; + } + ts.isBlock = isBlock; + function isConciseBody(node) { + return isBlock(node) + || isExpression(node); + } + ts.isConciseBody = isConciseBody; + function isFunctionBody(node) { + return isBlock(node); + } + ts.isFunctionBody = isFunctionBody; + function isForInitializer(node) { + return isVariableDeclarationList(node) + || isExpression(node); + } + ts.isForInitializer = isForInitializer; + function isVariableDeclaration(node) { + return node.kind === 218 /* VariableDeclaration */; + } + ts.isVariableDeclaration = isVariableDeclaration; + function isVariableDeclarationList(node) { + return node.kind === 219 /* VariableDeclarationList */; + } + ts.isVariableDeclarationList = isVariableDeclarationList; + function isCaseBlock(node) { + return node.kind === 227 /* CaseBlock */; + } + ts.isCaseBlock = isCaseBlock; + function isModuleBody(node) { + var kind = node.kind; + return kind === 226 /* ModuleBlock */ + || kind === 225 /* ModuleDeclaration */; + } + ts.isModuleBody = isModuleBody; + function isImportEqualsDeclaration(node) { + return node.kind === 229 /* ImportEqualsDeclaration */; + } + ts.isImportEqualsDeclaration = isImportEqualsDeclaration; + function isImportClause(node) { + return node.kind === 231 /* ImportClause */; + } + ts.isImportClause = isImportClause; + function isNamedImportBindings(node) { + var kind = node.kind; + return kind === 233 /* NamedImports */ + || kind === 232 /* NamespaceImport */; + } + ts.isNamedImportBindings = isNamedImportBindings; + function isImportSpecifier(node) { + return node.kind === 234 /* ImportSpecifier */; + } + ts.isImportSpecifier = isImportSpecifier; + function isNamedExports(node) { + return node.kind === 237 /* NamedExports */; + } + ts.isNamedExports = isNamedExports; + function isExportSpecifier(node) { + return node.kind === 238 /* ExportSpecifier */; + } + ts.isExportSpecifier = isExportSpecifier; + function isModuleOrEnumDeclaration(node) { + return node.kind === 225 /* ModuleDeclaration */ || node.kind === 224 /* EnumDeclaration */; + } + ts.isModuleOrEnumDeclaration = isModuleOrEnumDeclaration; + function isDeclarationKind(kind) { + return kind === 180 /* ArrowFunction */ + || kind === 169 /* BindingElement */ + || kind === 221 /* ClassDeclaration */ + || kind === 192 /* ClassExpression */ + || kind === 148 /* Constructor */ + || kind === 224 /* EnumDeclaration */ + || kind === 255 /* EnumMember */ + || kind === 238 /* ExportSpecifier */ + || kind === 220 /* FunctionDeclaration */ + || kind === 179 /* FunctionExpression */ + || kind === 149 /* GetAccessor */ + || kind === 231 /* ImportClause */ + || kind === 229 /* ImportEqualsDeclaration */ + || kind === 234 /* ImportSpecifier */ + || kind === 222 /* InterfaceDeclaration */ + || kind === 147 /* MethodDeclaration */ + || kind === 146 /* MethodSignature */ + || kind === 225 /* ModuleDeclaration */ + || kind === 228 /* NamespaceExportDeclaration */ + || kind === 232 /* NamespaceImport */ + || kind === 142 /* Parameter */ + || kind === 253 /* PropertyAssignment */ + || kind === 145 /* PropertyDeclaration */ + || kind === 144 /* PropertySignature */ + || kind === 150 /* SetAccessor */ + || kind === 254 /* ShorthandPropertyAssignment */ + || kind === 223 /* TypeAliasDeclaration */ + || kind === 141 /* TypeParameter */ + || kind === 218 /* VariableDeclaration */ + || kind === 279 /* JSDocTypedefTag */; + } + function isDeclarationStatementKind(kind) { + return kind === 220 /* FunctionDeclaration */ + || kind === 239 /* MissingDeclaration */ + || kind === 221 /* ClassDeclaration */ + || kind === 222 /* InterfaceDeclaration */ + || kind === 223 /* TypeAliasDeclaration */ + || kind === 224 /* EnumDeclaration */ + || kind === 225 /* ModuleDeclaration */ + || kind === 230 /* ImportDeclaration */ + || kind === 229 /* ImportEqualsDeclaration */ + || kind === 236 /* ExportDeclaration */ + || kind === 235 /* ExportAssignment */ + || kind === 228 /* NamespaceExportDeclaration */; + } + function isStatementKindButNotDeclarationKind(kind) { + return kind === 210 /* BreakStatement */ + || kind === 209 /* ContinueStatement */ + || kind === 217 /* DebuggerStatement */ + || kind === 204 /* DoStatement */ + || kind === 202 /* ExpressionStatement */ + || kind === 201 /* EmptyStatement */ + || kind === 207 /* ForInStatement */ + || kind === 208 /* ForOfStatement */ + || kind === 206 /* ForStatement */ + || kind === 203 /* IfStatement */ + || kind === 214 /* LabeledStatement */ + || kind === 211 /* ReturnStatement */ + || kind === 213 /* SwitchStatement */ + || kind === 215 /* ThrowStatement */ + || kind === 216 /* TryStatement */ + || kind === 200 /* VariableStatement */ + || kind === 205 /* WhileStatement */ + || kind === 212 /* WithStatement */ + || kind === 287 /* NotEmittedStatement */; + } + function isDeclaration(node) { + return isDeclarationKind(node.kind); + } + ts.isDeclaration = isDeclaration; + function isDeclarationStatement(node) { + return isDeclarationStatementKind(node.kind); + } + ts.isDeclarationStatement = isDeclarationStatement; + /** + * Determines whether the node is a statement that is not also a declaration + */ + function isStatementButNotDeclaration(node) { + return isStatementKindButNotDeclarationKind(node.kind); + } + ts.isStatementButNotDeclaration = isStatementButNotDeclaration; + function isStatement(node) { + var kind = node.kind; + return isStatementKindButNotDeclarationKind(kind) + || isDeclarationStatementKind(kind) + || kind === 199 /* Block */; + } + ts.isStatement = isStatement; + // Module references + function isModuleReference(node) { + var kind = node.kind; + return kind === 240 /* ExternalModuleReference */ + || kind === 139 /* QualifiedName */ + || kind === 69 /* Identifier */; + } + ts.isModuleReference = isModuleReference; + // JSX + function isJsxOpeningElement(node) { + return node.kind === 243 /* JsxOpeningElement */; + } + ts.isJsxOpeningElement = isJsxOpeningElement; + function isJsxClosingElement(node) { + return node.kind === 245 /* JsxClosingElement */; + } + ts.isJsxClosingElement = isJsxClosingElement; + function isJsxTagNameExpression(node) { + var kind = node.kind; + return kind === 97 /* ThisKeyword */ + || kind === 69 /* Identifier */ + || kind === 172 /* PropertyAccessExpression */; + } + ts.isJsxTagNameExpression = isJsxTagNameExpression; + function isJsxChild(node) { + var kind = node.kind; + return kind === 241 /* JsxElement */ + || kind === 248 /* JsxExpression */ + || kind === 242 /* JsxSelfClosingElement */ + || kind === 244 /* JsxText */; + } + ts.isJsxChild = isJsxChild; + function isJsxAttributeLike(node) { + var kind = node.kind; + return kind === 246 /* JsxAttribute */ + || kind === 247 /* JsxSpreadAttribute */; + } + ts.isJsxAttributeLike = isJsxAttributeLike; + function isJsxSpreadAttribute(node) { + return node.kind === 247 /* JsxSpreadAttribute */; + } + ts.isJsxSpreadAttribute = isJsxSpreadAttribute; + function isJsxAttribute(node) { + return node.kind === 246 /* JsxAttribute */; + } + ts.isJsxAttribute = isJsxAttribute; + function isStringLiteralOrJsxExpression(node) { + var kind = node.kind; + return kind === 9 /* StringLiteral */ + || kind === 248 /* JsxExpression */; + } + ts.isStringLiteralOrJsxExpression = isStringLiteralOrJsxExpression; + // Clauses + function isCaseOrDefaultClause(node) { + var kind = node.kind; + return kind === 249 /* CaseClause */ + || kind === 250 /* DefaultClause */; + } + ts.isCaseOrDefaultClause = isCaseOrDefaultClause; + function isHeritageClause(node) { + return node.kind === 251 /* HeritageClause */; + } + ts.isHeritageClause = isHeritageClause; + function isCatchClause(node) { + return node.kind === 252 /* CatchClause */; + } + ts.isCatchClause = isCatchClause; + // Property assignments + function isPropertyAssignment(node) { + return node.kind === 253 /* PropertyAssignment */; + } + ts.isPropertyAssignment = isPropertyAssignment; + function isShorthandPropertyAssignment(node) { + return node.kind === 254 /* ShorthandPropertyAssignment */; + } + ts.isShorthandPropertyAssignment = isShorthandPropertyAssignment; + // Enum + function isEnumMember(node) { + return node.kind === 255 /* EnumMember */; + } + ts.isEnumMember = isEnumMember; + // Top-level nodes + function isSourceFile(node) { + return node.kind === 256 /* SourceFile */; + } + ts.isSourceFile = isSourceFile; function isWatchSet(options) { // Firefox has Object.prototype.watch return options.watch && options.hasOwnProperty("watch"); @@ -5815,9 +7580,54 @@ var ts; } ts.getTypeParameterOwner = getTypeParameterOwner; function isParameterPropertyDeclaration(node) { - return node.flags & 92 /* ParameterPropertyModifier */ && node.parent.kind === 148 /* Constructor */ && ts.isClassLike(node.parent.parent); + return ts.hasModifier(node, 92 /* ParameterPropertyModifier */) && node.parent.kind === 148 /* Constructor */ && ts.isClassLike(node.parent.parent); } ts.isParameterPropertyDeclaration = isParameterPropertyDeclaration; + function walkUpBindingElementsAndPatterns(node) { + while (node && (node.kind === 169 /* BindingElement */ || ts.isBindingPattern(node))) { + node = node.parent; + } + return node; + } + function getCombinedModifierFlags(node) { + node = walkUpBindingElementsAndPatterns(node); + var flags = ts.getModifierFlags(node); + if (node.kind === 218 /* VariableDeclaration */) { + node = node.parent; + } + if (node && node.kind === 219 /* VariableDeclarationList */) { + flags |= ts.getModifierFlags(node); + node = node.parent; + } + if (node && node.kind === 200 /* VariableStatement */) { + flags |= ts.getModifierFlags(node); + } + return flags; + } + ts.getCombinedModifierFlags = getCombinedModifierFlags; + // Returns the node flags for this node and all relevant parent nodes. This is done so that + // nodes like variable declarations and binding elements can returned a view of their flags + // that includes the modifiers from their container. i.e. flags like export/declare aren't + // stored on the variable declaration directly, but on the containing variable statement + // (if it has one). Similarly, flags for let/const are store on the variable declaration + // list. By calling this function, all those flags are combined so that the client can treat + // the node as if it actually had those flags. + function getCombinedNodeFlags(node) { + node = walkUpBindingElementsAndPatterns(node); + var flags = node.flags; + if (node.kind === 218 /* VariableDeclaration */) { + node = node.parent; + } + if (node && node.kind === 219 /* VariableDeclarationList */) { + flags |= node.flags; + node = node.parent; + } + if (node && node.kind === 200 /* VariableStatement */) { + flags |= node.flags; + } + return flags; + } + ts.getCombinedNodeFlags = getCombinedNodeFlags; })(ts || (ts = {})); // /// @@ -6030,9 +7840,9 @@ var ts; Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Class_definitions_are_automatically_in_strict_mode: { code: 1251, category: ts.DiagnosticCategory.Error, key: "Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Class_d_1251", message: "Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Class definitions are automatically in strict mode." }, Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Modules_are_automatically_in_strict_mode: { code: 1252, category: ts.DiagnosticCategory.Error, key: "Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Modules_1252", message: "Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Modules are automatically in strict mode." }, _0_tag_cannot_be_used_independently_as_a_top_level_JSDoc_tag: { code: 1253, category: ts.DiagnosticCategory.Error, key: "_0_tag_cannot_be_used_independently_as_a_top_level_JSDoc_tag_1253", message: "'{0}' tag cannot be used independently as a top level JSDoc tag." }, + A_const_initializer_in_an_ambient_context_must_be_a_string_or_numeric_literal: { code: 1254, category: ts.DiagnosticCategory.Error, key: "A_const_initializer_in_an_ambient_context_must_be_a_string_or_numeric_literal_1254", message: "A 'const' initializer in an ambient context must be a string or numeric literal." }, with_statements_are_not_allowed_in_an_async_function_block: { code: 1300, category: ts.DiagnosticCategory.Error, key: "with_statements_are_not_allowed_in_an_async_function_block_1300", message: "'with' statements are not allowed in an async function block." }, await_expression_is_only_allowed_within_an_async_function: { code: 1308, category: ts.DiagnosticCategory.Error, key: "await_expression_is_only_allowed_within_an_async_function_1308", message: "'await' expression is only allowed within an async function." }, - Async_functions_are_only_available_when_targeting_ECMAScript_2015_or_higher: { code: 1311, category: ts.DiagnosticCategory.Error, key: "Async_functions_are_only_available_when_targeting_ECMAScript_2015_or_higher_1311", message: "Async functions are only available when targeting ECMAScript 2015 or higher." }, can_only_be_used_in_an_object_literal_property_inside_a_destructuring_assignment: { code: 1312, category: ts.DiagnosticCategory.Error, key: "can_only_be_used_in_an_object_literal_property_inside_a_destructuring_assignment_1312", message: "'=' can only be used in an object literal property inside a destructuring assignment." }, The_body_of_an_if_statement_cannot_be_the_empty_statement: { code: 1313, category: ts.DiagnosticCategory.Error, key: "The_body_of_an_if_statement_cannot_be_the_empty_statement_1313", message: "The body of an 'if' statement cannot be the empty statement." }, Global_module_exports_may_only_appear_in_module_files: { code: 1314, category: ts.DiagnosticCategory.Error, key: "Global_module_exports_may_only_appear_in_module_files_1314", message: "Global module exports may only appear in module files." }, @@ -6087,12 +7897,11 @@ var ts; Supplied_parameters_do_not_match_any_signature_of_call_target: { code: 2346, category: ts.DiagnosticCategory.Error, key: "Supplied_parameters_do_not_match_any_signature_of_call_target_2346", message: "Supplied parameters do not match any signature of call target." }, Untyped_function_calls_may_not_accept_type_arguments: { code: 2347, category: ts.DiagnosticCategory.Error, key: "Untyped_function_calls_may_not_accept_type_arguments_2347", message: "Untyped function calls may not accept type arguments." }, Value_of_type_0_is_not_callable_Did_you_mean_to_include_new: { code: 2348, category: ts.DiagnosticCategory.Error, key: "Value_of_type_0_is_not_callable_Did_you_mean_to_include_new_2348", message: "Value of type '{0}' is not callable. Did you mean to include 'new'?" }, - Cannot_invoke_an_expression_whose_type_lacks_a_call_signature: { code: 2349, category: ts.DiagnosticCategory.Error, key: "Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_2349", message: "Cannot invoke an expression whose type lacks a call signature." }, + Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures: { code: 2349, category: ts.DiagnosticCategory.Error, key: "Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatur_2349", message: "Cannot invoke an expression whose type lacks a call signature. Type '{0}' has no compatible call signatures." }, Only_a_void_function_can_be_called_with_the_new_keyword: { code: 2350, category: ts.DiagnosticCategory.Error, key: "Only_a_void_function_can_be_called_with_the_new_keyword_2350", message: "Only a void function can be called with the 'new' keyword." }, Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature: { code: 2351, category: ts.DiagnosticCategory.Error, key: "Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature_2351", message: "Cannot use 'new' with an expression whose type lacks a call or construct signature." }, Type_0_cannot_be_converted_to_type_1: { code: 2352, category: ts.DiagnosticCategory.Error, key: "Type_0_cannot_be_converted_to_type_1_2352", message: "Type '{0}' cannot be converted to type '{1}'." }, Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1: { code: 2353, category: ts.DiagnosticCategory.Error, key: "Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1_2353", message: "Object literal may only specify known properties, and '{0}' does not exist in type '{1}'." }, - No_best_common_type_exists_among_return_expressions: { code: 2354, category: ts.DiagnosticCategory.Error, key: "No_best_common_type_exists_among_return_expressions_2354", message: "No best common type exists among return expressions." }, A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value: { code: 2355, category: ts.DiagnosticCategory.Error, key: "A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value_2355", message: "A function whose declared type is neither 'void' nor 'any' must return a value." }, An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type: { code: 2356, category: ts.DiagnosticCategory.Error, key: "An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type_2356", message: "An arithmetic operand must be of type 'any', 'number' or an enum type." }, The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer: { code: 2357, category: ts.DiagnosticCategory.Error, key: "The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer_2357", message: "The operand of an increment or decrement operator must be a variable, property or indexer." }, @@ -6146,7 +7955,7 @@ var ts; The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter: { code: 2407, category: ts.DiagnosticCategory.Error, key: "The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter_2407", message: "The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter." }, Setters_cannot_return_a_value: { code: 2408, category: ts.DiagnosticCategory.Error, key: "Setters_cannot_return_a_value_2408", message: "Setters cannot return a value." }, Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class: { code: 2409, category: ts.DiagnosticCategory.Error, key: "Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class_2409", message: "Return type of constructor signature must be assignable to the instance type of the class" }, - All_symbols_within_a_with_block_will_be_resolved_to_any: { code: 2410, category: ts.DiagnosticCategory.Error, key: "All_symbols_within_a_with_block_will_be_resolved_to_any_2410", message: "All symbols within a 'with' block will be resolved to 'any'." }, + The_with_statement_is_not_supported_All_symbols_in_a_with_block_will_have_type_any: { code: 2410, category: ts.DiagnosticCategory.Error, key: "The_with_statement_is_not_supported_All_symbols_in_a_with_block_will_have_type_any_2410", message: "The 'with' statement is not supported. All symbols in a 'with' block will have type 'any'." }, Property_0_of_type_1_is_not_assignable_to_string_index_type_2: { code: 2411, category: ts.DiagnosticCategory.Error, key: "Property_0_of_type_1_is_not_assignable_to_string_index_type_2_2411", message: "Property '{0}' of type '{1}' is not assignable to string index type '{2}'." }, Property_0_of_type_1_is_not_assignable_to_numeric_index_type_2: { code: 2412, category: ts.DiagnosticCategory.Error, key: "Property_0_of_type_1_is_not_assignable_to_numeric_index_type_2_2412", message: "Property '{0}' of type '{1}' is not assignable to numeric index type '{2}'." }, Numeric_index_type_0_is_not_assignable_to_string_index_type_1: { code: 2413, category: ts.DiagnosticCategory.Error, key: "Numeric_index_type_0_is_not_assignable_to_string_index_type_1_2413", message: "Numeric index type '{0}' is not assignable to string index type '{1}'." }, @@ -6234,7 +8043,6 @@ var ts; A_rest_element_cannot_contain_a_binding_pattern: { code: 2501, category: ts.DiagnosticCategory.Error, key: "A_rest_element_cannot_contain_a_binding_pattern_2501", message: "A rest element cannot contain a binding pattern." }, _0_is_referenced_directly_or_indirectly_in_its_own_type_annotation: { code: 2502, category: ts.DiagnosticCategory.Error, key: "_0_is_referenced_directly_or_indirectly_in_its_own_type_annotation_2502", message: "'{0}' is referenced directly or indirectly in its own type annotation." }, Cannot_find_namespace_0: { code: 2503, category: ts.DiagnosticCategory.Error, key: "Cannot_find_namespace_0_2503", message: "Cannot find namespace '{0}'." }, - No_best_common_type_exists_among_yield_expressions: { code: 2504, category: ts.DiagnosticCategory.Error, key: "No_best_common_type_exists_among_yield_expressions_2504", message: "No best common type exists among yield expressions." }, A_generator_cannot_have_a_void_type_annotation: { code: 2505, category: ts.DiagnosticCategory.Error, key: "A_generator_cannot_have_a_void_type_annotation_2505", message: "A generator cannot have a 'void' type annotation." }, _0_is_referenced_directly_or_indirectly_in_its_own_base_expression: { code: 2506, category: ts.DiagnosticCategory.Error, key: "_0_is_referenced_directly_or_indirectly_in_its_own_base_expression_2506", message: "'{0}' is referenced directly or indirectly in its own base expression." }, Type_0_is_not_a_constructor_function_type: { code: 2507, category: ts.DiagnosticCategory.Error, key: "Type_0_is_not_a_constructor_function_type_2507", message: "Type '{0}' is not a constructor function type." }, @@ -6251,7 +8059,7 @@ var ts; A_this_based_type_guard_is_not_compatible_with_a_parameter_based_type_guard: { code: 2518, category: ts.DiagnosticCategory.Error, key: "A_this_based_type_guard_is_not_compatible_with_a_parameter_based_type_guard_2518", message: "A 'this'-based type guard is not compatible with a parameter-based type guard." }, Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions: { code: 2520, category: ts.DiagnosticCategory.Error, key: "Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions_2520", message: "Duplicate identifier '{0}'. Compiler uses declaration '{1}' to support async functions." }, Expression_resolves_to_variable_declaration_0_that_compiler_uses_to_support_async_functions: { code: 2521, category: ts.DiagnosticCategory.Error, key: "Expression_resolves_to_variable_declaration_0_that_compiler_uses_to_support_async_functions_2521", message: "Expression resolves to variable declaration '{0}' that compiler uses to support async functions." }, - The_arguments_object_cannot_be_referenced_in_an_async_arrow_function_Consider_using_a_standard_async_function_expression: { code: 2522, category: ts.DiagnosticCategory.Error, key: "The_arguments_object_cannot_be_referenced_in_an_async_arrow_function_Consider_using_a_standard_async_2522", message: "The 'arguments' object cannot be referenced in an async arrow function. Consider using a standard async function expression." }, + The_arguments_object_cannot_be_referenced_in_an_async_function_or_method_in_ES3_and_ES5_Consider_using_a_standard_function_or_method: { code: 2522, category: ts.DiagnosticCategory.Error, key: "The_arguments_object_cannot_be_referenced_in_an_async_function_or_method_in_ES3_and_ES5_Consider_usi_2522", message: "The 'arguments' object cannot be referenced in an async function or method in ES3 and ES5. Consider using a standard function or method." }, yield_expressions_cannot_be_used_in_a_parameter_initializer: { code: 2523, category: ts.DiagnosticCategory.Error, key: "yield_expressions_cannot_be_used_in_a_parameter_initializer_2523", message: "'yield' expressions cannot be used in a parameter initializer." }, await_expressions_cannot_be_used_in_a_parameter_initializer: { code: 2524, category: ts.DiagnosticCategory.Error, key: "await_expressions_cannot_be_used_in_a_parameter_initializer_2524", message: "'await' expressions cannot be used in a parameter initializer." }, Initializer_provides_no_value_for_this_binding_element_and_the_binding_element_has_no_default_value: { code: 2525, category: ts.DiagnosticCategory.Error, key: "Initializer_provides_no_value_for_this_binding_element_and_the_binding_element_has_no_default_value_2525", message: "Initializer provides no value for this binding element and the binding element has no default value." }, @@ -6315,6 +8123,10 @@ var ts; A_class_must_be_declared_after_its_base_class: { code: 2690, category: ts.DiagnosticCategory.Error, key: "A_class_must_be_declared_after_its_base_class_2690", message: "A class must be declared after its base class." }, An_import_path_cannot_end_with_a_0_extension_Consider_importing_1_instead: { code: 2691, category: ts.DiagnosticCategory.Error, key: "An_import_path_cannot_end_with_a_0_extension_Consider_importing_1_instead_2691", message: "An import path cannot end with a '{0}' extension. Consider importing '{1}' instead." }, _0_is_a_primitive_but_1_is_a_wrapper_object_Prefer_using_0_when_possible: { code: 2692, category: ts.DiagnosticCategory.Error, key: "_0_is_a_primitive_but_1_is_a_wrapper_object_Prefer_using_0_when_possible_2692", message: "'{0}' is a primitive, but '{1}' is a wrapper object. Prefer using '{0}' when possible." }, + _0_only_refers_to_a_type_but_is_being_used_as_a_value_here: { code: 2693, category: ts.DiagnosticCategory.Error, key: "_0_only_refers_to_a_type_but_is_being_used_as_a_value_here_2693", message: "'{0}' only refers to a type, but is being used as a value here." }, + Namespace_0_has_no_exported_member_1: { code: 2694, category: ts.DiagnosticCategory.Error, key: "Namespace_0_has_no_exported_member_1_2694", message: "Namespace '{0}' has no exported member '{1}'." }, + Left_side_of_comma_operator_is_unused_and_has_no_side_effects: { code: 2695, category: ts.DiagnosticCategory.Error, key: "Left_side_of_comma_operator_is_unused_and_has_no_side_effects_2695", message: "Left side of comma operator is unused and has no side effects." }, + The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead: { code: 2696, category: ts.DiagnosticCategory.Error, key: "The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead_2696", message: "The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead?" }, Import_declaration_0_is_using_private_name_1: { code: 4000, category: ts.DiagnosticCategory.Error, key: "Import_declaration_0_is_using_private_name_1_4000", message: "Import declaration '{0}' is using private name '{1}'." }, Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: ts.DiagnosticCategory.Error, key: "Type_parameter_0_of_exported_class_has_or_is_using_private_name_1_4002", message: "Type parameter '{0}' of exported class has or is using private name '{1}'." }, Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4004, category: ts.DiagnosticCategory.Error, key: "Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1_4004", message: "Type parameter '{0}' of exported interface has or is using private name '{1}'." }, @@ -6444,6 +8256,7 @@ var ts; VERSION: { code: 6036, category: ts.DiagnosticCategory.Message, key: "VERSION_6036", message: "VERSION" }, LOCATION: { code: 6037, category: ts.DiagnosticCategory.Message, key: "LOCATION_6037", message: "LOCATION" }, DIRECTORY: { code: 6038, category: ts.DiagnosticCategory.Message, key: "DIRECTORY_6038", message: "DIRECTORY" }, + STRATEGY: { code: 6039, category: ts.DiagnosticCategory.Message, key: "STRATEGY_6039", message: "STRATEGY" }, Compilation_complete_Watching_for_file_changes: { code: 6042, category: ts.DiagnosticCategory.Message, key: "Compilation_complete_Watching_for_file_changes_6042", message: "Compilation complete. Watching for file changes." }, Generates_corresponding_map_file: { code: 6043, category: ts.DiagnosticCategory.Message, key: "Generates_corresponding_map_file_6043", message: "Generates corresponding '.map' file." }, Compiler_option_0_expects_an_argument: { code: 6044, category: ts.DiagnosticCategory.Error, key: "Compiler_option_0_expects_an_argument_6044", message: "Compiler option '{0}' expects an argument." }, @@ -6535,6 +8348,8 @@ var ts; The_maximum_dependency_depth_to_search_under_node_modules_and_load_JavaScript_files: { code: 6136, category: ts.DiagnosticCategory.Message, key: "The_maximum_dependency_depth_to_search_under_node_modules_and_load_JavaScript_files_6136", message: "The maximum dependency depth to search under node_modules and load JavaScript files" }, No_types_specified_in_package_json_but_allowJs_is_set_so_returning_main_value_of_0: { code: 6137, category: ts.DiagnosticCategory.Message, key: "No_types_specified_in_package_json_but_allowJs_is_set_so_returning_main_value_of_0_6137", message: "No types specified in 'package.json' but 'allowJs' is set, so returning 'main' value of '{0}'" }, Property_0_is_declared_but_never_used: { code: 6138, category: ts.DiagnosticCategory.Error, key: "Property_0_is_declared_but_never_used_6138", message: "Property '{0}' is declared but never used." }, + Import_emit_helpers_from_tslib: { code: 6139, category: ts.DiagnosticCategory.Message, key: "Import_emit_helpers_from_tslib_6139", message: "Import emit helpers from 'tslib'." }, + Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using_cache_location_2: { code: 6140, category: ts.DiagnosticCategory.Error, key: "Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using__6140", message: "Auto discovery for typings is enabled in project '{0}'. Running extra resolution pass for module '{1}' using cache location '{2}'." }, Variable_0_implicitly_has_an_1_type: { code: 7005, category: ts.DiagnosticCategory.Error, key: "Variable_0_implicitly_has_an_1_type_7005", message: "Variable '{0}' implicitly has an '{1}' type." }, Parameter_0_implicitly_has_an_1_type: { code: 7006, category: ts.DiagnosticCategory.Error, key: "Parameter_0_implicitly_has_an_1_type_7006", message: "Parameter '{0}' implicitly has an '{1}' type." }, Member_0_implicitly_has_an_1_type: { code: 7008, category: ts.DiagnosticCategory.Error, key: "Member_0_implicitly_has_an_1_type_7008", message: "Member '{0}' implicitly has an '{1}' type." }, @@ -6587,6 +8402,8 @@ var ts; JSX_element_0_has_no_corresponding_closing_tag: { code: 17008, category: ts.DiagnosticCategory.Error, key: "JSX_element_0_has_no_corresponding_closing_tag_17008", message: "JSX element '{0}' has no corresponding closing tag." }, super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class: { code: 17009, category: ts.DiagnosticCategory.Error, key: "super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class_17009", message: "'super' must be called before accessing 'this' in the constructor of a derived class." }, Unknown_typing_option_0: { code: 17010, category: ts.DiagnosticCategory.Error, key: "Unknown_typing_option_0_17010", message: "Unknown typing option '{0}'." }, + Circularity_detected_while_resolving_configuration_Colon_0: { code: 18000, category: ts.DiagnosticCategory.Error, key: "Circularity_detected_while_resolving_configuration_Colon_0_18000", message: "Circularity detected while resolving configuration: {0}" }, + The_path_in_an_extends_options_must_be_relative_or_rooted: { code: 18001, category: ts.DiagnosticCategory.Error, key: "The_path_in_an_extends_options_must_be_relative_or_rooted_18001", message: "The path in an 'extends' options must be relative or rooted." }, }; })(ts || (ts = {})); /// @@ -6807,8 +8624,8 @@ var ts; } function makeReverseMap(source) { var result = []; - for (var name_6 in source) { - result[source[name_6]] = name_6; + for (var name_8 in source) { + result[source[name_8]] = name_8; } return result; } @@ -6969,9 +8786,7 @@ var ts; /* @internal */ function skipTrivia(text, pos, stopAfterLineBreak, stopAtComments) { if (stopAtComments === void 0) { stopAtComments = false; } - // Using ! with a greater than test is a fast way of testing the following conditions: - // pos === undefined || pos === null || isNaN(pos) || pos < 0; - if (!(pos >= 0)) { + if (ts.positionIsSynthesized(pos)) { return pos; } // Keep in sync with couldStartTrivia @@ -7102,20 +8917,34 @@ var ts; return pos; } /** - * Extract comments from text prefixing the token closest following `pos`. - * The return value is an array containing a TextRange for each comment. - * Single-line comment ranges include the beginning '//' characters but not the ending line break. - * Multi - line comment ranges include the beginning '/* and ending '/' characters. - * The return value is undefined if no comments were found. - * @param trailing - * If false, whitespace is skipped until the first line break and comments between that location - * and the next token are returned. - * If true, comments occurring between the given position and the next line break are returned. + * Invokes a callback for each comment range following the provided position. + * + * Single-line comment ranges include the leading double-slash characters but not the ending + * line break. Multi-line comment ranges include the leading slash-asterisk and trailing + * asterisk-slash characters. + * + * @param reduce If true, accumulates the result of calling the callback in a fashion similar + * to reduceLeft. If false, iteration stops when the callback returns a truthy value. + * @param text The source text to scan. + * @param pos The position at which to start scanning. + * @param trailing If false, whitespace is skipped until the first line break and comments + * between that location and the next token are returned. If true, comments occurring + * between the given position and the next line break are returned. + * @param cb The callback to execute as each comment range is encountered. + * @param state A state value to pass to each iteration of the callback. + * @param initial An initial value to pass when accumulating results (when "reduce" is true). + * @returns If "reduce" is true, the accumulated value. If "reduce" is false, the first truthy + * return value of the callback. */ - function getCommentRanges(text, pos, trailing) { - var result; + function iterateCommentRanges(reduce, text, pos, trailing, cb, state, initial) { + var pendingPos; + var pendingEnd; + var pendingKind; + var pendingHasTrailingNewLine; + var hasPendingCommentRange = false; var collecting = trailing || pos === 0; - while (pos < text.length) { + var accumulator = initial; + scan: while (pos >= 0 && pos < text.length) { var ch = text.charCodeAt(pos); switch (ch) { case 13 /* carriageReturn */: @@ -7125,11 +8954,11 @@ var ts; case 10 /* lineFeed */: pos++; if (trailing) { - return result; + break scan; } collecting = true; - if (result && result.length) { - ts.lastOrUndefined(result).hasTrailingNewLine = true; + if (hasPendingCommentRange) { + pendingHasTrailingNewLine = true; } continue; case 9 /* tab */: @@ -7164,34 +8993,68 @@ var ts; } } if (collecting) { - if (!result) { - result = []; + if (hasPendingCommentRange) { + accumulator = cb(pendingPos, pendingEnd, pendingKind, pendingHasTrailingNewLine, state, accumulator); + if (!reduce && accumulator) { + // If we are not reducing and we have a truthy result, return it. + return accumulator; + } + hasPendingCommentRange = false; } - result.push({ pos: startPos, end: pos, hasTrailingNewLine: hasTrailingNewLine, kind: kind }); + pendingPos = startPos; + pendingEnd = pos; + pendingKind = kind; + pendingHasTrailingNewLine = hasTrailingNewLine; + hasPendingCommentRange = true; } continue; } - break; + break scan; default: if (ch > 127 /* maxAsciiCharacter */ && (isWhiteSpace(ch))) { - if (result && result.length && isLineBreak(ch)) { - ts.lastOrUndefined(result).hasTrailingNewLine = true; + if (hasPendingCommentRange && isLineBreak(ch)) { + pendingHasTrailingNewLine = true; } pos++; continue; } - break; + break scan; } - return result; } - return result; + if (hasPendingCommentRange) { + accumulator = cb(pendingPos, pendingEnd, pendingKind, pendingHasTrailingNewLine, state, accumulator); + } + return accumulator; + } + function forEachLeadingCommentRange(text, pos, cb, state) { + return iterateCommentRanges(/*reduce*/ false, text, pos, /*trailing*/ false, cb, state); + } + ts.forEachLeadingCommentRange = forEachLeadingCommentRange; + function forEachTrailingCommentRange(text, pos, cb, state) { + return iterateCommentRanges(/*reduce*/ false, text, pos, /*trailing*/ true, cb, state); + } + ts.forEachTrailingCommentRange = forEachTrailingCommentRange; + function reduceEachLeadingCommentRange(text, pos, cb, state, initial) { + return iterateCommentRanges(/*reduce*/ true, text, pos, /*trailing*/ false, cb, state, initial); + } + ts.reduceEachLeadingCommentRange = reduceEachLeadingCommentRange; + function reduceEachTrailingCommentRange(text, pos, cb, state, initial) { + return iterateCommentRanges(/*reduce*/ true, text, pos, /*trailing*/ true, cb, state, initial); + } + ts.reduceEachTrailingCommentRange = reduceEachTrailingCommentRange; + function appendCommentRange(pos, end, kind, hasTrailingNewLine, state, comments) { + if (!comments) { + comments = []; + } + comments.push({ pos: pos, end: end, hasTrailingNewLine: hasTrailingNewLine, kind: kind }); + return comments; } function getLeadingCommentRanges(text, pos) { - return getCommentRanges(text, pos, /*trailing*/ false); + return reduceEachLeadingCommentRange(text, pos, appendCommentRange, undefined, undefined); } ts.getLeadingCommentRanges = getLeadingCommentRanges; function getTrailingCommentRanges(text, pos) { - return getCommentRanges(text, pos, /*trailing*/ true); + return reduceEachTrailingCommentRange(text, pos, appendCommentRange, undefined, undefined); } ts.getTrailingCommentRanges = getTrailingCommentRanges; /** Optionally, get the shebang */ @@ -7214,7 +9077,7 @@ var ts; } ts.isIdentifierPart = isIdentifierPart; /* @internal */ - function isIdentifier(name, languageVersion) { + function isIdentifierText(name, languageVersion) { if (!isIdentifierStart(name.charCodeAt(0), languageVersion)) { return false; } @@ -7225,7 +9088,7 @@ var ts; } return true; } - ts.isIdentifier = isIdentifier; + ts.isIdentifierText = isIdentifierText; // Creates a scanner over a (possibly unspecified) range of a piece of text. function createScanner(languageVersion, skipTrivia, languageVariant, text, onError, start, length) { if (languageVariant === void 0) { languageVariant = 0 /* Standard */; } @@ -7259,6 +9122,7 @@ var ts; reScanSlashToken: reScanSlashToken, reScanTemplateToken: reScanTemplateToken, scanJsxIdentifier: scanJsxIdentifier, + scanJsxAttributeValue: scanJsxAttributeValue, reScanJsxToken: reScanJsxToken, scanJsxToken: scanJsxToken, scanJSDocToken: scanJSDocToken, @@ -7350,7 +9214,8 @@ var ts; } return value; } - function scanString() { + function scanString(allowEscapes) { + if (allowEscapes === void 0) { allowEscapes = true; } var quote = text.charCodeAt(pos); pos++; var result = ""; @@ -7368,7 +9233,7 @@ var ts; pos++; break; } - if (ch === 92 /* backslash */) { + if (ch === 92 /* backslash */ && allowEscapes) { result += text.substring(start, pos); result += scanEscapeSequence(); start = pos; @@ -8113,43 +9978,62 @@ var ts; } return token; } + function scanJsxAttributeValue() { + startPos = pos; + switch (text.charCodeAt(pos)) { + case 34 /* doubleQuote */: + case 39 /* singleQuote */: + tokenValue = scanString(/*allowEscapes*/ false); + return token = 9 /* StringLiteral */; + default: + // If this scans anything other than `{`, it's a parse error. + return scan(); + } + } function scanJSDocToken() { if (pos >= end) { return token = 1 /* EndOfFileToken */; } startPos = pos; - // Eat leading whitespace - var ch = text.charCodeAt(pos); - while (pos < end) { - ch = text.charCodeAt(pos); - if (isWhiteSpaceSingleLine(ch)) { - pos++; - } - else { - break; - } - } tokenPos = pos; + var ch = text.charCodeAt(pos); switch (ch) { + case 9 /* tab */: + case 11 /* verticalTab */: + case 12 /* formFeed */: + case 32 /* space */: + while (pos < end && isWhiteSpaceSingleLine(text.charCodeAt(pos))) { + pos++; + } + return token = 5 /* WhitespaceTrivia */; case 64 /* at */: - return pos += 1, token = 55 /* AtToken */; + pos++; + return token = 55 /* AtToken */; case 10 /* lineFeed */: case 13 /* carriageReturn */: - return pos += 1, token = 4 /* NewLineTrivia */; + pos++; + return token = 4 /* NewLineTrivia */; case 42 /* asterisk */: - return pos += 1, token = 37 /* AsteriskToken */; + pos++; + return token = 37 /* AsteriskToken */; case 123 /* openBrace */: - return pos += 1, token = 15 /* OpenBraceToken */; + pos++; + return token = 15 /* OpenBraceToken */; case 125 /* closeBrace */: - return pos += 1, token = 16 /* CloseBraceToken */; + pos++; + return token = 16 /* CloseBraceToken */; case 91 /* openBracket */: - return pos += 1, token = 19 /* OpenBracketToken */; + pos++; + return token = 19 /* OpenBracketToken */; case 93 /* closeBracket */: - return pos += 1, token = 20 /* CloseBracketToken */; + pos++; + return token = 20 /* CloseBracketToken */; case 61 /* equals */: - return pos += 1, token = 56 /* EqualsToken */; + pos++; + return token = 56 /* EqualsToken */; case 44 /* comma */: - return pos += 1, token = 24 /* CommaToken */; + pos++; + return token = 24 /* CommaToken */; } if (isIdentifierStart(ch, 2 /* Latest */)) { pos++; @@ -8242,2025 +10126,4656 @@ var ts; } ts.createScanner = createScanner; })(ts || (ts = {})); +/// /// -/// +/* @internal */ var ts; (function (ts) { var NodeConstructor; - var TokenConstructor; - var IdentifierConstructor; var SourceFileConstructor; - function createNode(kind, pos, end) { - if (kind === 256 /* SourceFile */) { - return new (SourceFileConstructor || (SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor()))(kind, pos, end); + function createNode(kind, location, flags) { + var ConstructorForKind = kind === 256 /* SourceFile */ + ? (SourceFileConstructor || (SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor())) + : (NodeConstructor || (NodeConstructor = ts.objectAllocator.getNodeConstructor())); + var node = location + ? new ConstructorForKind(kind, location.pos, location.end) + : new ConstructorForKind(kind, /*pos*/ -1, /*end*/ -1); + node.flags = flags | 8 /* Synthesized */; + return node; + } + function updateNode(updated, original) { + if (updated !== original) { + setOriginalNode(updated, original); + if (original.startsOnNewLine) { + updated.startsOnNewLine = true; + } + ts.aggregateTransformFlags(updated); } - else if (kind === 69 /* Identifier */) { - return new (IdentifierConstructor || (IdentifierConstructor = ts.objectAllocator.getIdentifierConstructor()))(kind, pos, end); + return updated; + } + ts.updateNode = updateNode; + function createNodeArray(elements, location, hasTrailingComma) { + if (elements) { + if (ts.isNodeArray(elements)) { + return elements; + } } - else if (kind < 139 /* FirstNode */) { - return new (TokenConstructor || (TokenConstructor = ts.objectAllocator.getTokenConstructor()))(kind, pos, end); + else { + elements = []; + } + var array = elements; + if (location) { + array.pos = location.pos; + array.end = location.end; } else { - return new (NodeConstructor || (NodeConstructor = ts.objectAllocator.getNodeConstructor()))(kind, pos, end); + array.pos = -1; + array.end = -1; } + if (hasTrailingComma) { + array.hasTrailingComma = true; + } + return array; } - ts.createNode = createNode; - function visitNode(cbNode, node) { - if (node) { - return cbNode(node); + ts.createNodeArray = createNodeArray; + function createSynthesizedNode(kind, startsOnNewLine) { + var node = createNode(kind, /*location*/ undefined); + node.startsOnNewLine = startsOnNewLine; + return node; + } + ts.createSynthesizedNode = createSynthesizedNode; + function createSynthesizedNodeArray(elements) { + return createNodeArray(elements, /*location*/ undefined); + } + ts.createSynthesizedNodeArray = createSynthesizedNodeArray; + /** + * Creates a shallow, memberwise clone of a node with no source map location. + */ + function getSynthesizedClone(node) { + // We don't use "clone" from core.ts here, as we need to preserve the prototype chain of + // the original node. We also need to exclude specific properties and only include own- + // properties (to skip members already defined on the shared prototype). + var clone = createNode(node.kind, /*location*/ undefined, node.flags); + setOriginalNode(clone, node); + for (var key in node) { + if (clone.hasOwnProperty(key) || !node.hasOwnProperty(key)) { + continue; + } + clone[key] = node[key]; } + return clone; } - function visitNodeArray(cbNodes, nodes) { - if (nodes) { - return cbNodes(nodes); + ts.getSynthesizedClone = getSynthesizedClone; + /** + * Creates a shallow, memberwise clone of a node for mutation. + */ + function getMutableClone(node) { + var clone = getSynthesizedClone(node); + clone.pos = node.pos; + clone.end = node.end; + clone.parent = node.parent; + return clone; + } + ts.getMutableClone = getMutableClone; + function createLiteral(value, location) { + if (typeof value === "number") { + var node = createNode(8 /* NumericLiteral */, location, /*flags*/ undefined); + node.text = value.toString(); + return node; + } + else if (typeof value === "boolean") { + return createNode(value ? 99 /* TrueKeyword */ : 84 /* FalseKeyword */, location, /*flags*/ undefined); + } + else if (typeof value === "string") { + var node = createNode(9 /* StringLiteral */, location, /*flags*/ undefined); + node.text = value; + return node; + } + else { + var node = createNode(9 /* StringLiteral */, location, /*flags*/ undefined); + node.textSourceNode = value; + node.text = value.text; + return node; } } - function visitEachNode(cbNode, nodes) { - if (nodes) { - for (var _i = 0, nodes_1 = nodes; _i < nodes_1.length; _i++) { - var node = nodes_1[_i]; - var result = cbNode(node); - if (result) { - return result; - } - } + ts.createLiteral = createLiteral; + // Identifiers + var nextAutoGenerateId = 0; + function createIdentifier(text, location) { + var node = createNode(69 /* Identifier */, location); + node.text = ts.escapeIdentifier(text); + node.originalKeywordKind = ts.stringToToken(text); + node.autoGenerateKind = 0 /* None */; + node.autoGenerateId = 0; + return node; + } + ts.createIdentifier = createIdentifier; + function createTempVariable(recordTempVariable, location) { + var name = createNode(69 /* Identifier */, location); + name.text = ""; + name.originalKeywordKind = 0 /* Unknown */; + name.autoGenerateKind = 1 /* Auto */; + name.autoGenerateId = nextAutoGenerateId; + nextAutoGenerateId++; + if (recordTempVariable) { + recordTempVariable(name); } + return name; } - // Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes - // stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise, - // embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns - // a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned. - function forEachChild(node, cbNode, cbNodeArray) { - if (!node) { - return; - } - // The visitXXX functions could be written as local functions that close over the cbNode and cbNodeArray - // callback parameters, but that causes a closure allocation for each invocation with noticeable effects - // on performance. - var visitNodes = cbNodeArray ? visitNodeArray : visitEachNode; - var cbNodes = cbNodeArray || cbNode; - switch (node.kind) { - case 139 /* QualifiedName */: - return visitNode(cbNode, node.left) || - visitNode(cbNode, node.right); - case 141 /* TypeParameter */: - return visitNode(cbNode, node.name) || - visitNode(cbNode, node.constraint) || - visitNode(cbNode, node.expression); - case 254 /* ShorthandPropertyAssignment */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.questionToken) || - visitNode(cbNode, node.equalsToken) || - visitNode(cbNode, node.objectAssignmentInitializer); - case 142 /* Parameter */: - case 145 /* PropertyDeclaration */: - case 144 /* PropertySignature */: - case 253 /* PropertyAssignment */: - case 218 /* VariableDeclaration */: - case 169 /* BindingElement */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.propertyName) || - visitNode(cbNode, node.dotDotDotToken) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.questionToken) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.initializer); - case 156 /* FunctionType */: - case 157 /* ConstructorType */: - case 151 /* CallSignature */: - case 152 /* ConstructSignature */: - case 153 /* IndexSignature */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNodes(cbNodes, node.typeParameters) || - visitNodes(cbNodes, node.parameters) || - visitNode(cbNode, node.type); - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - case 148 /* Constructor */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 179 /* FunctionExpression */: - case 220 /* FunctionDeclaration */: - case 180 /* ArrowFunction */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.asteriskToken) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.questionToken) || - visitNodes(cbNodes, node.typeParameters) || - visitNodes(cbNodes, node.parameters) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.equalsGreaterThanToken) || - visitNode(cbNode, node.body); - case 155 /* TypeReference */: - return visitNode(cbNode, node.typeName) || - visitNodes(cbNodes, node.typeArguments); - case 154 /* TypePredicate */: - return visitNode(cbNode, node.parameterName) || - visitNode(cbNode, node.type); - case 158 /* TypeQuery */: - return visitNode(cbNode, node.exprName); - case 159 /* TypeLiteral */: - return visitNodes(cbNodes, node.members); - case 160 /* ArrayType */: - return visitNode(cbNode, node.elementType); - case 161 /* TupleType */: - return visitNodes(cbNodes, node.elementTypes); - case 162 /* UnionType */: - case 163 /* IntersectionType */: - return visitNodes(cbNodes, node.types); - case 164 /* ParenthesizedType */: - return visitNode(cbNode, node.type); - case 166 /* LiteralType */: - return visitNode(cbNode, node.literal); - case 167 /* ObjectBindingPattern */: - case 168 /* ArrayBindingPattern */: - return visitNodes(cbNodes, node.elements); - case 170 /* ArrayLiteralExpression */: - return visitNodes(cbNodes, node.elements); - case 171 /* ObjectLiteralExpression */: - return visitNodes(cbNodes, node.properties); - case 172 /* PropertyAccessExpression */: - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.name); - case 173 /* ElementAccessExpression */: - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.argumentExpression); - case 174 /* CallExpression */: - case 175 /* NewExpression */: - return visitNode(cbNode, node.expression) || - visitNodes(cbNodes, node.typeArguments) || - visitNodes(cbNodes, node.arguments); - case 176 /* TaggedTemplateExpression */: - return visitNode(cbNode, node.tag) || - visitNode(cbNode, node.template); - case 177 /* TypeAssertionExpression */: - return visitNode(cbNode, node.type) || - visitNode(cbNode, node.expression); - case 178 /* ParenthesizedExpression */: - return visitNode(cbNode, node.expression); - case 181 /* DeleteExpression */: - return visitNode(cbNode, node.expression); - case 182 /* TypeOfExpression */: - return visitNode(cbNode, node.expression); - case 183 /* VoidExpression */: - return visitNode(cbNode, node.expression); - case 185 /* PrefixUnaryExpression */: - return visitNode(cbNode, node.operand); - case 190 /* YieldExpression */: - return visitNode(cbNode, node.asteriskToken) || - visitNode(cbNode, node.expression); - case 184 /* AwaitExpression */: - return visitNode(cbNode, node.expression); - case 186 /* PostfixUnaryExpression */: - return visitNode(cbNode, node.operand); - case 187 /* BinaryExpression */: - return visitNode(cbNode, node.left) || - visitNode(cbNode, node.operatorToken) || - visitNode(cbNode, node.right); - case 195 /* AsExpression */: - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.type); - case 196 /* NonNullExpression */: - return visitNode(cbNode, node.expression); - case 188 /* ConditionalExpression */: - return visitNode(cbNode, node.condition) || - visitNode(cbNode, node.questionToken) || - visitNode(cbNode, node.whenTrue) || - visitNode(cbNode, node.colonToken) || - visitNode(cbNode, node.whenFalse); - case 191 /* SpreadElementExpression */: - return visitNode(cbNode, node.expression); - case 199 /* Block */: - case 226 /* ModuleBlock */: - return visitNodes(cbNodes, node.statements); - case 256 /* SourceFile */: - return visitNodes(cbNodes, node.statements) || - visitNode(cbNode, node.endOfFileToken); - case 200 /* VariableStatement */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.declarationList); - case 219 /* VariableDeclarationList */: - return visitNodes(cbNodes, node.declarations); - case 202 /* ExpressionStatement */: - return visitNode(cbNode, node.expression); - case 203 /* IfStatement */: - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.thenStatement) || - visitNode(cbNode, node.elseStatement); - case 204 /* DoStatement */: - return visitNode(cbNode, node.statement) || - visitNode(cbNode, node.expression); - case 205 /* WhileStatement */: - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.statement); - case 206 /* ForStatement */: - return visitNode(cbNode, node.initializer) || - visitNode(cbNode, node.condition) || - visitNode(cbNode, node.incrementor) || - visitNode(cbNode, node.statement); - case 207 /* ForInStatement */: - return visitNode(cbNode, node.initializer) || - visitNode(cbNode, node.expression) || - visitNode(cbNode, node.statement); - case 208 /* ForOfStatement */: - return visitNode(cbNode, node.initializer) || - visitNode(cbNode, node.expression) || - visitNode(cbNode, node.statement); - case 209 /* ContinueStatement */: - case 210 /* BreakStatement */: - return visitNode(cbNode, node.label); - case 211 /* ReturnStatement */: - return visitNode(cbNode, node.expression); - case 212 /* WithStatement */: - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.statement); - case 213 /* SwitchStatement */: - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.caseBlock); - case 227 /* CaseBlock */: - return visitNodes(cbNodes, node.clauses); - case 249 /* CaseClause */: - return visitNode(cbNode, node.expression) || - visitNodes(cbNodes, node.statements); - case 250 /* DefaultClause */: - return visitNodes(cbNodes, node.statements); - case 214 /* LabeledStatement */: - return visitNode(cbNode, node.label) || - visitNode(cbNode, node.statement); - case 215 /* ThrowStatement */: - return visitNode(cbNode, node.expression); - case 216 /* TryStatement */: - return visitNode(cbNode, node.tryBlock) || - visitNode(cbNode, node.catchClause) || - visitNode(cbNode, node.finallyBlock); - case 252 /* CatchClause */: - return visitNode(cbNode, node.variableDeclaration) || - visitNode(cbNode, node.block); - case 143 /* Decorator */: - return visitNode(cbNode, node.expression); - case 221 /* ClassDeclaration */: - case 192 /* ClassExpression */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNodes(cbNodes, node.typeParameters) || - visitNodes(cbNodes, node.heritageClauses) || - visitNodes(cbNodes, node.members); - case 222 /* InterfaceDeclaration */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNodes(cbNodes, node.typeParameters) || - visitNodes(cbNodes, node.heritageClauses) || - visitNodes(cbNodes, node.members); - case 223 /* TypeAliasDeclaration */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNodes(cbNodes, node.typeParameters) || - visitNode(cbNode, node.type); - case 224 /* EnumDeclaration */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNodes(cbNodes, node.members); - case 255 /* EnumMember */: - return visitNode(cbNode, node.name) || - visitNode(cbNode, node.initializer); - case 225 /* ModuleDeclaration */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.body); - case 229 /* ImportEqualsDeclaration */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.moduleReference); - case 230 /* ImportDeclaration */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.importClause) || - visitNode(cbNode, node.moduleSpecifier); - case 231 /* ImportClause */: - return visitNode(cbNode, node.name) || - visitNode(cbNode, node.namedBindings); - case 228 /* NamespaceExportDeclaration */: - return visitNode(cbNode, node.name); - case 232 /* NamespaceImport */: - return visitNode(cbNode, node.name); - case 233 /* NamedImports */: - case 237 /* NamedExports */: - return visitNodes(cbNodes, node.elements); - case 236 /* ExportDeclaration */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.exportClause) || - visitNode(cbNode, node.moduleSpecifier); - case 234 /* ImportSpecifier */: - case 238 /* ExportSpecifier */: - return visitNode(cbNode, node.propertyName) || - visitNode(cbNode, node.name); - case 235 /* ExportAssignment */: - return visitNodes(cbNodes, node.decorators) || - visitNodes(cbNodes, node.modifiers) || - visitNode(cbNode, node.expression); - case 189 /* TemplateExpression */: - return visitNode(cbNode, node.head) || visitNodes(cbNodes, node.templateSpans); - case 197 /* TemplateSpan */: - return visitNode(cbNode, node.expression) || visitNode(cbNode, node.literal); - case 140 /* ComputedPropertyName */: - return visitNode(cbNode, node.expression); - case 251 /* HeritageClause */: - return visitNodes(cbNodes, node.types); - case 194 /* ExpressionWithTypeArguments */: - return visitNode(cbNode, node.expression) || - visitNodes(cbNodes, node.typeArguments); - case 240 /* ExternalModuleReference */: - return visitNode(cbNode, node.expression); - case 239 /* MissingDeclaration */: - return visitNodes(cbNodes, node.decorators); - case 241 /* JsxElement */: - return visitNode(cbNode, node.openingElement) || - visitNodes(cbNodes, node.children) || - visitNode(cbNode, node.closingElement); - case 242 /* JsxSelfClosingElement */: - case 243 /* JsxOpeningElement */: - return visitNode(cbNode, node.tagName) || - visitNodes(cbNodes, node.attributes); - case 246 /* JsxAttribute */: - return visitNode(cbNode, node.name) || - visitNode(cbNode, node.initializer); - case 247 /* JsxSpreadAttribute */: - return visitNode(cbNode, node.expression); - case 248 /* JsxExpression */: - return visitNode(cbNode, node.expression); - case 245 /* JsxClosingElement */: - return visitNode(cbNode, node.tagName); - case 257 /* JSDocTypeExpression */: - return visitNode(cbNode, node.type); - case 261 /* JSDocUnionType */: - return visitNodes(cbNodes, node.types); - case 262 /* JSDocTupleType */: - return visitNodes(cbNodes, node.types); - case 260 /* JSDocArrayType */: - return visitNode(cbNode, node.elementType); - case 264 /* JSDocNonNullableType */: - return visitNode(cbNode, node.type); - case 263 /* JSDocNullableType */: - return visitNode(cbNode, node.type); - case 265 /* JSDocRecordType */: - return visitNodes(cbNodes, node.members); - case 267 /* JSDocTypeReference */: - return visitNode(cbNode, node.name) || - visitNodes(cbNodes, node.typeArguments); - case 268 /* JSDocOptionalType */: - return visitNode(cbNode, node.type); - case 269 /* JSDocFunctionType */: - return visitNodes(cbNodes, node.parameters) || - visitNode(cbNode, node.type); - case 270 /* JSDocVariadicType */: - return visitNode(cbNode, node.type); - case 271 /* JSDocConstructorType */: - return visitNode(cbNode, node.type); - case 272 /* JSDocThisType */: - return visitNode(cbNode, node.type); - case 266 /* JSDocRecordMember */: - return visitNode(cbNode, node.name) || - visitNode(cbNode, node.type); - case 273 /* JSDocComment */: - return visitNodes(cbNodes, node.tags); - case 275 /* JSDocParameterTag */: - return visitNode(cbNode, node.preParameterName) || - visitNode(cbNode, node.typeExpression) || - visitNode(cbNode, node.postParameterName); - case 276 /* JSDocReturnTag */: - return visitNode(cbNode, node.typeExpression); - case 277 /* JSDocTypeTag */: - return visitNode(cbNode, node.typeExpression); - case 278 /* JSDocTemplateTag */: - return visitNodes(cbNodes, node.typeParameters); - case 279 /* JSDocTypedefTag */: - return visitNode(cbNode, node.typeExpression) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.jsDocTypeLiteral); - case 281 /* JSDocTypeLiteral */: - return visitNodes(cbNodes, node.jsDocPropertyTags); - case 280 /* JSDocPropertyTag */: - return visitNode(cbNode, node.typeExpression) || - visitNode(cbNode, node.name); - case 282 /* JSDocLiteralType */: - return visitNode(cbNode, node.literal); + ts.createTempVariable = createTempVariable; + function createLoopVariable(location) { + var name = createNode(69 /* Identifier */, location); + name.text = ""; + name.originalKeywordKind = 0 /* Unknown */; + name.autoGenerateKind = 2 /* Loop */; + name.autoGenerateId = nextAutoGenerateId; + nextAutoGenerateId++; + return name; + } + ts.createLoopVariable = createLoopVariable; + function createUniqueName(text, location) { + var name = createNode(69 /* Identifier */, location); + name.text = text; + name.originalKeywordKind = 0 /* Unknown */; + name.autoGenerateKind = 3 /* Unique */; + name.autoGenerateId = nextAutoGenerateId; + nextAutoGenerateId++; + return name; + } + ts.createUniqueName = createUniqueName; + function getGeneratedNameForNode(node, location) { + var name = createNode(69 /* Identifier */, location); + name.original = node; + name.text = ""; + name.originalKeywordKind = 0 /* Unknown */; + name.autoGenerateKind = 4 /* Node */; + name.autoGenerateId = nextAutoGenerateId; + nextAutoGenerateId++; + return name; + } + ts.getGeneratedNameForNode = getGeneratedNameForNode; + // Punctuation + function createToken(token) { + return createNode(token); + } + ts.createToken = createToken; + // Reserved words + function createSuper() { + var node = createNode(95 /* SuperKeyword */); + return node; + } + ts.createSuper = createSuper; + function createThis(location) { + var node = createNode(97 /* ThisKeyword */, location); + return node; + } + ts.createThis = createThis; + function createNull() { + var node = createNode(93 /* NullKeyword */); + return node; + } + ts.createNull = createNull; + // Names + function createComputedPropertyName(expression, location) { + var node = createNode(140 /* ComputedPropertyName */, location); + node.expression = expression; + return node; + } + ts.createComputedPropertyName = createComputedPropertyName; + function updateComputedPropertyName(node, expression) { + if (node.expression !== expression) { + return updateNode(createComputedPropertyName(expression, node), node); } + return node; } - ts.forEachChild = forEachChild; - function createSourceFile(fileName, sourceText, languageVersion, setParentNodes, scriptKind) { - if (setParentNodes === void 0) { setParentNodes = false; } - ts.performance.mark("beforeParse"); - var result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind); - ts.performance.mark("afterParse"); - ts.performance.measure("Parse", "beforeParse", "afterParse"); - return result; + ts.updateComputedPropertyName = updateComputedPropertyName; + // Signature elements + function createParameter(name, initializer, location) { + return createParameterDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, name, + /*questionToken*/ undefined, + /*type*/ undefined, initializer, location); + } + ts.createParameter = createParameter; + function createParameterDeclaration(decorators, modifiers, dotDotDotToken, name, questionToken, type, initializer, location, flags) { + var node = createNode(142 /* Parameter */, location, flags); + node.decorators = decorators ? createNodeArray(decorators) : undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.dotDotDotToken = dotDotDotToken; + node.name = typeof name === "string" ? createIdentifier(name) : name; + node.questionToken = questionToken; + node.type = type; + node.initializer = initializer ? parenthesizeExpressionForList(initializer) : undefined; + return node; } - ts.createSourceFile = createSourceFile; - function isExternalModule(file) { - return file.externalModuleIndicator !== undefined; + ts.createParameterDeclaration = createParameterDeclaration; + function updateParameterDeclaration(node, decorators, modifiers, name, type, initializer) { + if (node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name || node.type !== type || node.initializer !== initializer) { + return updateNode(createParameterDeclaration(decorators, modifiers, node.dotDotDotToken, name, node.questionToken, type, initializer, /*location*/ node, /*flags*/ node.flags), node); + } + return node; } - ts.isExternalModule = isExternalModule; - // Produces a new SourceFile for the 'newText' provided. The 'textChangeRange' parameter - // indicates what changed between the 'text' that this SourceFile has and the 'newText'. - // The SourceFile will be created with the compiler attempting to reuse as many nodes from - // this file as possible. - // - // Note: this function mutates nodes from this SourceFile. That means any existing nodes - // from this SourceFile that are being held onto may change as a result (including - // becoming detached from any SourceFile). It is recommended that this SourceFile not - // be used once 'update' is called on it. - function updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks) { - return IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); + ts.updateParameterDeclaration = updateParameterDeclaration; + // Type members + function createProperty(decorators, modifiers, name, questionToken, type, initializer, location) { + var node = createNode(145 /* PropertyDeclaration */, location); + node.decorators = decorators ? createNodeArray(decorators) : undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.name = typeof name === "string" ? createIdentifier(name) : name; + node.questionToken = questionToken; + node.type = type; + node.initializer = initializer; + return node; } - ts.updateSourceFile = updateSourceFile; - /* @internal */ - function parseIsolatedJSDocComment(content, start, length) { - var result = Parser.JSDocParser.parseIsolatedJSDocComment(content, start, length); - if (result && result.jsDocComment) { - // because the jsDocComment was parsed out of the source file, it might - // not be covered by the fixupParentReferences. - Parser.fixupParentReferences(result.jsDocComment); + ts.createProperty = createProperty; + function updateProperty(node, decorators, modifiers, name, type, initializer) { + if (node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name || node.type !== type || node.initializer !== initializer) { + return updateNode(createProperty(decorators, modifiers, name, node.questionToken, type, initializer, node), node); } - return result; + return node; } - ts.parseIsolatedJSDocComment = parseIsolatedJSDocComment; - /* @internal */ - // Exposed only for testing. - function parseJSDocTypeExpressionForTests(content, start, length) { - return Parser.JSDocParser.parseJSDocTypeExpressionForTests(content, start, length); + ts.updateProperty = updateProperty; + function createMethod(decorators, modifiers, asteriskToken, name, typeParameters, parameters, type, body, location, flags) { + var node = createNode(147 /* MethodDeclaration */, location, flags); + node.decorators = decorators ? createNodeArray(decorators) : undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.asteriskToken = asteriskToken; + node.name = typeof name === "string" ? createIdentifier(name) : name; + node.typeParameters = typeParameters ? createNodeArray(typeParameters) : undefined; + node.parameters = createNodeArray(parameters); + node.type = type; + node.body = body; + return node; } - ts.parseJSDocTypeExpressionForTests = parseJSDocTypeExpressionForTests; - // Implement the parser as a singleton module. We do this for perf reasons because creating - // parser instances can actually be expensive enough to impact us on projects with many source - // files. - var Parser; - (function (Parser) { - // Share a single scanner across all calls to parse a source file. This helps speed things - // up by avoiding the cost of creating/compiling scanners over and over again. - var scanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ true); - var disallowInAndDecoratorContext = 4194304 /* DisallowInContext */ | 16777216 /* DecoratorContext */; - // capture constructors in 'initializeState' to avoid null checks - var NodeConstructor; - var TokenConstructor; - var IdentifierConstructor; - var SourceFileConstructor; - var sourceFile; - var parseDiagnostics; - var syntaxCursor; - var currentToken; - var sourceText; - var nodeCount; - var identifiers; - var identifierCount; - var parsingContext; - // Flags that dictate what parsing context we're in. For example: - // Whether or not we are in strict parsing mode. All that changes in strict parsing mode is - // that some tokens that would be considered identifiers may be considered keywords. - // - // When adding more parser context flags, consider which is the more common case that the - // flag will be in. This should be the 'false' state for that flag. The reason for this is - // that we don't store data in our nodes unless the value is in the *non-default* state. So, - // for example, more often than code 'allows-in' (or doesn't 'disallow-in'). We opt for - // 'disallow-in' set to 'false'. Otherwise, if we had 'allowsIn' set to 'true', then almost - // all nodes would need extra state on them to store this info. - // - // Note: 'allowIn' and 'allowYield' track 1:1 with the [in] and [yield] concepts in the ES6 - // grammar specification. - // - // An important thing about these context concepts. By default they are effectively inherited - // while parsing through every grammar production. i.e. if you don't change them, then when - // you parse a sub-production, it will have the same context values as the parent production. - // This is great most of the time. After all, consider all the 'expression' grammar productions - // and how nearly all of them pass along the 'in' and 'yield' context values: - // - // EqualityExpression[In, Yield] : - // RelationalExpression[?In, ?Yield] - // EqualityExpression[?In, ?Yield] == RelationalExpression[?In, ?Yield] - // EqualityExpression[?In, ?Yield] != RelationalExpression[?In, ?Yield] - // EqualityExpression[?In, ?Yield] === RelationalExpression[?In, ?Yield] - // EqualityExpression[?In, ?Yield] !== RelationalExpression[?In, ?Yield] - // - // Where you have to be careful is then understanding what the points are in the grammar - // where the values are *not* passed along. For example: - // - // SingleNameBinding[Yield,GeneratorParameter] - // [+GeneratorParameter]BindingIdentifier[Yield] Initializer[In]opt - // [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt - // - // Here this is saying that if the GeneratorParameter context flag is set, that we should - // explicitly set the 'yield' context flag to false before calling into the BindingIdentifier - // and we should explicitly unset the 'yield' context flag before calling into the Initializer. - // production. Conversely, if the GeneratorParameter context flag is not set, then we - // should leave the 'yield' context flag alone. - // - // Getting this all correct is tricky and requires careful reading of the grammar to - // understand when these values should be changed versus when they should be inherited. - // - // Note: it should not be necessary to save/restore these flags during speculative/lookahead - // parsing. These context flags are naturally stored and restored through normal recursive - // descent parsing and unwinding. - var contextFlags; - // Whether or not we've had a parse error since creating the last AST node. If we have - // encountered an error, it will be stored on the next AST node we create. Parse errors - // can be broken down into three categories: - // - // 1) An error that occurred during scanning. For example, an unterminated literal, or a - // character that was completely not understood. - // - // 2) A token was expected, but was not present. This type of error is commonly produced - // by the 'parseExpected' function. - // - // 3) A token was present that no parsing function was able to consume. This type of error - // only occurs in the 'abortParsingListOrMoveToNextToken' function when the parser - // decides to skip the token. - // - // In all of these cases, we want to mark the next node as having had an error before it. - // With this mark, we can know in incremental settings if this node can be reused, or if - // we have to reparse it. If we don't keep this information around, we may just reuse the - // node. in that event we would then not produce the same errors as we did before, causing - // significant confusion problems. - // - // Note: it is necessary that this value be saved/restored during speculative/lookahead - // parsing. During lookahead parsing, we will often create a node. That node will have - // this value attached, and then this value will be set back to 'false'. If we decide to - // rewind, we must get back to the same value we had prior to the lookahead. - // - // Note: any errors at the end of the file that do not precede a regular node, should get - // attached to the EOF token. - var parseErrorBeforeNextFinishedNode = false; - function parseSourceFile(fileName, _sourceText, languageVersion, _syntaxCursor, setParentNodes, scriptKind) { - scriptKind = ts.ensureScriptKind(fileName, scriptKind); - initializeState(fileName, _sourceText, languageVersion, _syntaxCursor, scriptKind); - var result = parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind); - clearState(); - return result; + ts.createMethod = createMethod; + function updateMethod(node, decorators, modifiers, name, typeParameters, parameters, type, body) { + if (node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name || node.typeParameters !== typeParameters || node.parameters !== parameters || node.type !== type || node.body !== body) { + return updateNode(createMethod(decorators, modifiers, node.asteriskToken, name, typeParameters, parameters, type, body, /*location*/ node, node.flags), node); } - Parser.parseSourceFile = parseSourceFile; - function getLanguageVariant(scriptKind) { - // .tsx and .jsx files are treated as jsx language variant. - return scriptKind === 4 /* TSX */ || scriptKind === 2 /* JSX */ || scriptKind === 1 /* JS */ ? 1 /* JSX */ : 0 /* Standard */; + return node; + } + ts.updateMethod = updateMethod; + function createConstructor(decorators, modifiers, parameters, body, location, flags) { + var node = createNode(148 /* Constructor */, location, flags); + node.decorators = decorators ? createNodeArray(decorators) : undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.typeParameters = undefined; + node.parameters = createNodeArray(parameters); + node.type = undefined; + node.body = body; + return node; + } + ts.createConstructor = createConstructor; + function updateConstructor(node, decorators, modifiers, parameters, body) { + if (node.decorators !== decorators || node.modifiers !== modifiers || node.parameters !== parameters || node.body !== body) { + return updateNode(createConstructor(decorators, modifiers, parameters, body, /*location*/ node, node.flags), node); } - function initializeState(fileName, _sourceText, languageVersion, _syntaxCursor, scriptKind) { - NodeConstructor = ts.objectAllocator.getNodeConstructor(); - TokenConstructor = ts.objectAllocator.getTokenConstructor(); - IdentifierConstructor = ts.objectAllocator.getIdentifierConstructor(); - SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor(); - sourceText = _sourceText; - syntaxCursor = _syntaxCursor; - parseDiagnostics = []; - parsingContext = 0; - identifiers = ts.createMap(); - identifierCount = 0; - nodeCount = 0; - contextFlags = scriptKind === 1 /* JS */ || scriptKind === 2 /* JSX */ ? 134217728 /* JavaScriptFile */ : 0 /* None */; - parseErrorBeforeNextFinishedNode = false; - // Initialize and prime the scanner before parsing the source elements. - scanner.setText(sourceText); - scanner.setOnError(scanError); - scanner.setScriptTarget(languageVersion); - scanner.setLanguageVariant(getLanguageVariant(scriptKind)); + return node; + } + ts.updateConstructor = updateConstructor; + function createGetAccessor(decorators, modifiers, name, parameters, type, body, location, flags) { + var node = createNode(149 /* GetAccessor */, location, flags); + node.decorators = decorators ? createNodeArray(decorators) : undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.name = typeof name === "string" ? createIdentifier(name) : name; + node.typeParameters = undefined; + node.parameters = createNodeArray(parameters); + node.type = type; + node.body = body; + return node; + } + ts.createGetAccessor = createGetAccessor; + function updateGetAccessor(node, decorators, modifiers, name, parameters, type, body) { + if (node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name || node.parameters !== parameters || node.type !== type || node.body !== body) { + return updateNode(createGetAccessor(decorators, modifiers, name, parameters, type, body, /*location*/ node, node.flags), node); } - function clearState() { - // Clear out the text the scanner is pointing at, so it doesn't keep anything alive unnecessarily. - scanner.setText(""); - scanner.setOnError(undefined); - // Clear any data. We don't want to accidentally hold onto it for too long. - parseDiagnostics = undefined; - sourceFile = undefined; - identifiers = undefined; - syntaxCursor = undefined; - sourceText = undefined; + return node; + } + ts.updateGetAccessor = updateGetAccessor; + function createSetAccessor(decorators, modifiers, name, parameters, body, location, flags) { + var node = createNode(150 /* SetAccessor */, location, flags); + node.decorators = decorators ? createNodeArray(decorators) : undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.name = typeof name === "string" ? createIdentifier(name) : name; + node.typeParameters = undefined; + node.parameters = createNodeArray(parameters); + node.body = body; + return node; + } + ts.createSetAccessor = createSetAccessor; + function updateSetAccessor(node, decorators, modifiers, name, parameters, body) { + if (node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name || node.parameters !== parameters || node.body !== body) { + return updateNode(createSetAccessor(decorators, modifiers, name, parameters, body, /*location*/ node, node.flags), node); } - function parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind) { - sourceFile = createSourceFile(fileName, languageVersion, scriptKind); - sourceFile.flags = contextFlags; - // Prime the scanner. - nextToken(); - processReferenceComments(sourceFile); - sourceFile.statements = parseList(0 /* SourceElements */, parseStatement); - ts.Debug.assert(token() === 1 /* EndOfFileToken */); - sourceFile.endOfFileToken = parseTokenNode(); - setExternalModuleIndicator(sourceFile); - sourceFile.nodeCount = nodeCount; - sourceFile.identifierCount = identifierCount; - sourceFile.identifiers = identifiers; - sourceFile.parseDiagnostics = parseDiagnostics; - if (setParentNodes) { - fixupParentReferences(sourceFile); - } - return sourceFile; + return node; + } + ts.updateSetAccessor = updateSetAccessor; + // Binding Patterns + function createObjectBindingPattern(elements, location) { + var node = createNode(167 /* ObjectBindingPattern */, location); + node.elements = createNodeArray(elements); + return node; + } + ts.createObjectBindingPattern = createObjectBindingPattern; + function updateObjectBindingPattern(node, elements) { + if (node.elements !== elements) { + return updateNode(createObjectBindingPattern(elements, node), node); } - function addJSDocComment(node) { - if (contextFlags & 134217728 /* JavaScriptFile */) { - var comments = ts.getLeadingCommentRangesOfNode(node, sourceFile); - if (comments) { - for (var _i = 0, comments_1 = comments; _i < comments_1.length; _i++) { - var comment = comments_1[_i]; - var jsDocComment = JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos); - if (!jsDocComment) { - continue; - } - if (!node.jsDocComments) { - node.jsDocComments = []; - } - node.jsDocComments.push(jsDocComment); - } - } - } - return node; + return node; + } + ts.updateObjectBindingPattern = updateObjectBindingPattern; + function createArrayBindingPattern(elements, location) { + var node = createNode(168 /* ArrayBindingPattern */, location); + node.elements = createNodeArray(elements); + return node; + } + ts.createArrayBindingPattern = createArrayBindingPattern; + function updateArrayBindingPattern(node, elements) { + if (node.elements !== elements) { + return updateNode(createArrayBindingPattern(elements, node), node); } - function fixupParentReferences(rootNode) { - // normally parent references are set during binding. However, for clients that only need - // a syntax tree, and no semantic features, then the binding process is an unnecessary - // overhead. This functions allows us to set all the parents, without all the expense of - // binding. - var parent = rootNode; - forEachChild(rootNode, visitNode); - return; - function visitNode(n) { - // walk down setting parents that differ from the parent we think it should be. This - // allows us to quickly bail out of setting parents for subtrees during incremental - // parsing - if (n.parent !== parent) { - n.parent = parent; - var saveParent = parent; - parent = n; - forEachChild(n, visitNode); - if (n.jsDocComments) { - for (var _i = 0, _a = n.jsDocComments; _i < _a.length; _i++) { - var jsDocComment = _a[_i]; - jsDocComment.parent = n; - parent = jsDocComment; - forEachChild(jsDocComment, visitNode); - } - } - parent = saveParent; - } - } + return node; + } + ts.updateArrayBindingPattern = updateArrayBindingPattern; + function createBindingElement(propertyName, dotDotDotToken, name, initializer, location) { + var node = createNode(169 /* BindingElement */, location); + node.propertyName = typeof propertyName === "string" ? createIdentifier(propertyName) : propertyName; + node.dotDotDotToken = dotDotDotToken; + node.name = typeof name === "string" ? createIdentifier(name) : name; + node.initializer = initializer; + return node; + } + ts.createBindingElement = createBindingElement; + function updateBindingElement(node, propertyName, name, initializer) { + if (node.propertyName !== propertyName || node.name !== name || node.initializer !== initializer) { + return updateNode(createBindingElement(propertyName, node.dotDotDotToken, name, initializer, node), node); } - Parser.fixupParentReferences = fixupParentReferences; - function createSourceFile(fileName, languageVersion, scriptKind) { - // code from createNode is inlined here so createNode won't have to deal with special case of creating source files - // this is quite rare comparing to other nodes and createNode should be as fast as possible - var sourceFile = new SourceFileConstructor(256 /* SourceFile */, /*pos*/ 0, /* end */ sourceText.length); - nodeCount++; - sourceFile.text = sourceText; - sourceFile.bindDiagnostics = []; - sourceFile.languageVersion = languageVersion; - sourceFile.fileName = ts.normalizePath(fileName); - sourceFile.languageVariant = getLanguageVariant(scriptKind); - sourceFile.isDeclarationFile = ts.fileExtensionIs(sourceFile.fileName, ".d.ts"); - sourceFile.scriptKind = scriptKind; - return sourceFile; + return node; + } + ts.updateBindingElement = updateBindingElement; + // Expression + function createArrayLiteral(elements, location, multiLine) { + var node = createNode(170 /* ArrayLiteralExpression */, location); + node.elements = parenthesizeListElements(createNodeArray(elements)); + if (multiLine) { + node.multiLine = true; } - function setContextFlag(val, flag) { - if (val) { - contextFlags |= flag; - } - else { - contextFlags &= ~flag; - } + return node; + } + ts.createArrayLiteral = createArrayLiteral; + function updateArrayLiteral(node, elements) { + if (node.elements !== elements) { + return updateNode(createArrayLiteral(elements, node, node.multiLine), node); } - function setDisallowInContext(val) { - setContextFlag(val, 4194304 /* DisallowInContext */); + return node; + } + ts.updateArrayLiteral = updateArrayLiteral; + function createObjectLiteral(properties, location, multiLine) { + var node = createNode(171 /* ObjectLiteralExpression */, location); + node.properties = createNodeArray(properties); + if (multiLine) { + node.multiLine = true; } - function setYieldContext(val) { - setContextFlag(val, 8388608 /* YieldContext */); + return node; + } + ts.createObjectLiteral = createObjectLiteral; + function updateObjectLiteral(node, properties) { + if (node.properties !== properties) { + return updateNode(createObjectLiteral(properties, node, node.multiLine), node); } - function setDecoratorContext(val) { - setContextFlag(val, 16777216 /* DecoratorContext */); + return node; + } + ts.updateObjectLiteral = updateObjectLiteral; + function createPropertyAccess(expression, name, location, flags) { + var node = createNode(172 /* PropertyAccessExpression */, location, flags); + node.expression = parenthesizeForAccess(expression); + (node.emitNode || (node.emitNode = {})).flags |= 1048576 /* NoIndentation */; + node.name = typeof name === "string" ? createIdentifier(name) : name; + return node; + } + ts.createPropertyAccess = createPropertyAccess; + function updatePropertyAccess(node, expression, name) { + if (node.expression !== expression || node.name !== name) { + var propertyAccess = createPropertyAccess(expression, name, /*location*/ node, node.flags); + // Because we are updating existed propertyAccess we want to inherit its emitFlags instead of using default from createPropertyAccess + (propertyAccess.emitNode || (propertyAccess.emitNode = {})).flags = getEmitFlags(node); + return updateNode(propertyAccess, node); } - function setAwaitContext(val) { - setContextFlag(val, 33554432 /* AwaitContext */); + return node; + } + ts.updatePropertyAccess = updatePropertyAccess; + function createElementAccess(expression, index, location) { + var node = createNode(173 /* ElementAccessExpression */, location); + node.expression = parenthesizeForAccess(expression); + node.argumentExpression = typeof index === "number" ? createLiteral(index) : index; + return node; + } + ts.createElementAccess = createElementAccess; + function updateElementAccess(node, expression, argumentExpression) { + if (node.expression !== expression || node.argumentExpression !== argumentExpression) { + return updateNode(createElementAccess(expression, argumentExpression, node), node); } - function doOutsideOfContext(context, func) { - // contextFlagsToClear will contain only the context flags that are - // currently set that we need to temporarily clear - // We don't just blindly reset to the previous flags to ensure - // that we do not mutate cached flags for the incremental - // parser (ThisNodeHasError, ThisNodeOrAnySubNodesHasError, and - // HasAggregatedChildData). - var contextFlagsToClear = context & contextFlags; - if (contextFlagsToClear) { - // clear the requested context flags - setContextFlag(/*val*/ false, contextFlagsToClear); - var result = func(); - // restore the context flags we just cleared - setContextFlag(/*val*/ true, contextFlagsToClear); - return result; - } - // no need to do anything special as we are not in any of the requested contexts - return func(); + return node; + } + ts.updateElementAccess = updateElementAccess; + function createCall(expression, typeArguments, argumentsArray, location, flags) { + var node = createNode(174 /* CallExpression */, location, flags); + node.expression = parenthesizeForAccess(expression); + if (typeArguments) { + node.typeArguments = createNodeArray(typeArguments); } - function doInsideOfContext(context, func) { - // contextFlagsToSet will contain only the context flags that - // are not currently set that we need to temporarily enable. - // We don't just blindly reset to the previous flags to ensure - // that we do not mutate cached flags for the incremental - // parser (ThisNodeHasError, ThisNodeOrAnySubNodesHasError, and - // HasAggregatedChildData). - var contextFlagsToSet = context & ~contextFlags; - if (contextFlagsToSet) { - // set the requested context flags - setContextFlag(/*val*/ true, contextFlagsToSet); - var result = func(); - // reset the context flags we just set - setContextFlag(/*val*/ false, contextFlagsToSet); - return result; - } - // no need to do anything special as we are already in all of the requested contexts - return func(); + node.arguments = parenthesizeListElements(createNodeArray(argumentsArray)); + return node; + } + ts.createCall = createCall; + function updateCall(node, expression, typeArguments, argumentsArray) { + if (expression !== node.expression || typeArguments !== node.typeArguments || argumentsArray !== node.arguments) { + return updateNode(createCall(expression, typeArguments, argumentsArray, /*location*/ node, node.flags), node); } - function allowInAnd(func) { - return doOutsideOfContext(4194304 /* DisallowInContext */, func); + return node; + } + ts.updateCall = updateCall; + function createNew(expression, typeArguments, argumentsArray, location, flags) { + var node = createNode(175 /* NewExpression */, location, flags); + node.expression = parenthesizeForNew(expression); + node.typeArguments = typeArguments ? createNodeArray(typeArguments) : undefined; + node.arguments = argumentsArray ? parenthesizeListElements(createNodeArray(argumentsArray)) : undefined; + return node; + } + ts.createNew = createNew; + function updateNew(node, expression, typeArguments, argumentsArray) { + if (node.expression !== expression || node.typeArguments !== typeArguments || node.arguments !== argumentsArray) { + return updateNode(createNew(expression, typeArguments, argumentsArray, /*location*/ node, node.flags), node); } - function disallowInAnd(func) { - return doInsideOfContext(4194304 /* DisallowInContext */, func); + return node; + } + ts.updateNew = updateNew; + function createTaggedTemplate(tag, template, location) { + var node = createNode(176 /* TaggedTemplateExpression */, location); + node.tag = parenthesizeForAccess(tag); + node.template = template; + return node; + } + ts.createTaggedTemplate = createTaggedTemplate; + function updateTaggedTemplate(node, tag, template) { + if (node.tag !== tag || node.template !== template) { + return updateNode(createTaggedTemplate(tag, template, node), node); } - function doInYieldContext(func) { - return doInsideOfContext(8388608 /* YieldContext */, func); + return node; + } + ts.updateTaggedTemplate = updateTaggedTemplate; + function createParen(expression, location) { + var node = createNode(178 /* ParenthesizedExpression */, location); + node.expression = expression; + return node; + } + ts.createParen = createParen; + function updateParen(node, expression) { + if (node.expression !== expression) { + return updateNode(createParen(expression, node), node); } - function doInDecoratorContext(func) { - return doInsideOfContext(16777216 /* DecoratorContext */, func); + return node; + } + ts.updateParen = updateParen; + function createFunctionExpression(asteriskToken, name, typeParameters, parameters, type, body, location, flags) { + var node = createNode(179 /* FunctionExpression */, location, flags); + node.modifiers = undefined; + node.asteriskToken = asteriskToken; + node.name = typeof name === "string" ? createIdentifier(name) : name; + node.typeParameters = typeParameters ? createNodeArray(typeParameters) : undefined; + node.parameters = createNodeArray(parameters); + node.type = type; + node.body = body; + return node; + } + ts.createFunctionExpression = createFunctionExpression; + function updateFunctionExpression(node, name, typeParameters, parameters, type, body) { + if (node.name !== name || node.typeParameters !== typeParameters || node.parameters !== parameters || node.type !== type || node.body !== body) { + return updateNode(createFunctionExpression(node.asteriskToken, name, typeParameters, parameters, type, body, /*location*/ node, node.flags), node); } - function doInAwaitContext(func) { - return doInsideOfContext(33554432 /* AwaitContext */, func); + return node; + } + ts.updateFunctionExpression = updateFunctionExpression; + function createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanToken, body, location, flags) { + var node = createNode(180 /* ArrowFunction */, location, flags); + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.typeParameters = typeParameters ? createNodeArray(typeParameters) : undefined; + node.parameters = createNodeArray(parameters); + node.type = type; + node.equalsGreaterThanToken = equalsGreaterThanToken || createNode(34 /* EqualsGreaterThanToken */); + node.body = parenthesizeConciseBody(body); + return node; + } + ts.createArrowFunction = createArrowFunction; + function updateArrowFunction(node, modifiers, typeParameters, parameters, type, body) { + if (node.modifiers !== modifiers || node.typeParameters !== typeParameters || node.parameters !== parameters || node.type !== type || node.body !== body) { + return updateNode(createArrowFunction(modifiers, typeParameters, parameters, type, node.equalsGreaterThanToken, body, /*location*/ node, node.flags), node); } - function doOutsideOfAwaitContext(func) { - return doOutsideOfContext(33554432 /* AwaitContext */, func); + return node; + } + ts.updateArrowFunction = updateArrowFunction; + function createDelete(expression, location) { + var node = createNode(181 /* DeleteExpression */, location); + node.expression = parenthesizePrefixOperand(expression); + return node; + } + ts.createDelete = createDelete; + function updateDelete(node, expression) { + if (node.expression !== expression) { + return updateNode(createDelete(expression, node), expression); } - function doInYieldAndAwaitContext(func) { - return doInsideOfContext(8388608 /* YieldContext */ | 33554432 /* AwaitContext */, func); + return node; + } + ts.updateDelete = updateDelete; + function createTypeOf(expression, location) { + var node = createNode(182 /* TypeOfExpression */, location); + node.expression = parenthesizePrefixOperand(expression); + return node; + } + ts.createTypeOf = createTypeOf; + function updateTypeOf(node, expression) { + if (node.expression !== expression) { + return updateNode(createTypeOf(expression, node), expression); } - function inContext(flags) { - return (contextFlags & flags) !== 0; + return node; + } + ts.updateTypeOf = updateTypeOf; + function createVoid(expression, location) { + var node = createNode(183 /* VoidExpression */, location); + node.expression = parenthesizePrefixOperand(expression); + return node; + } + ts.createVoid = createVoid; + function updateVoid(node, expression) { + if (node.expression !== expression) { + return updateNode(createVoid(expression, node), node); } - function inYieldContext() { - return inContext(8388608 /* YieldContext */); + return node; + } + ts.updateVoid = updateVoid; + function createAwait(expression, location) { + var node = createNode(184 /* AwaitExpression */, location); + node.expression = parenthesizePrefixOperand(expression); + return node; + } + ts.createAwait = createAwait; + function updateAwait(node, expression) { + if (node.expression !== expression) { + return updateNode(createAwait(expression, node), node); } - function inDisallowInContext() { - return inContext(4194304 /* DisallowInContext */); + return node; + } + ts.updateAwait = updateAwait; + function createPrefix(operator, operand, location) { + var node = createNode(185 /* PrefixUnaryExpression */, location); + node.operator = operator; + node.operand = parenthesizePrefixOperand(operand); + return node; + } + ts.createPrefix = createPrefix; + function updatePrefix(node, operand) { + if (node.operand !== operand) { + return updateNode(createPrefix(node.operator, operand, node), node); } - function inDecoratorContext() { - return inContext(16777216 /* DecoratorContext */); + return node; + } + ts.updatePrefix = updatePrefix; + function createPostfix(operand, operator, location) { + var node = createNode(186 /* PostfixUnaryExpression */, location); + node.operand = parenthesizePostfixOperand(operand); + node.operator = operator; + return node; + } + ts.createPostfix = createPostfix; + function updatePostfix(node, operand) { + if (node.operand !== operand) { + return updateNode(createPostfix(operand, node.operator, node), node); } - function inAwaitContext() { - return inContext(33554432 /* AwaitContext */); + return node; + } + ts.updatePostfix = updatePostfix; + function createBinary(left, operator, right, location) { + var operatorToken = typeof operator === "number" ? createSynthesizedNode(operator) : operator; + var operatorKind = operatorToken.kind; + var node = createNode(187 /* BinaryExpression */, location); + node.left = parenthesizeBinaryOperand(operatorKind, left, /*isLeftSideOfBinary*/ true, /*leftOperand*/ undefined); + node.operatorToken = operatorToken; + node.right = parenthesizeBinaryOperand(operatorKind, right, /*isLeftSideOfBinary*/ false, node.left); + return node; + } + ts.createBinary = createBinary; + function updateBinary(node, left, right) { + if (node.left !== left || node.right !== right) { + return updateNode(createBinary(left, node.operatorToken, right, /*location*/ node), node); } - function parseErrorAtCurrentToken(message, arg0) { - var start = scanner.getTokenPos(); - var length = scanner.getTextPos() - start; - parseErrorAtPosition(start, length, message, arg0); + return node; + } + ts.updateBinary = updateBinary; + function createConditional(condition, questionToken, whenTrue, colonToken, whenFalse, location) { + var node = createNode(188 /* ConditionalExpression */, location); + node.condition = condition; + node.questionToken = questionToken; + node.whenTrue = whenTrue; + node.colonToken = colonToken; + node.whenFalse = whenFalse; + return node; + } + ts.createConditional = createConditional; + function updateConditional(node, condition, whenTrue, whenFalse) { + if (node.condition !== condition || node.whenTrue !== whenTrue || node.whenFalse !== whenFalse) { + return updateNode(createConditional(condition, node.questionToken, whenTrue, node.colonToken, whenFalse, node), node); } - function parseErrorAtPosition(start, length, message, arg0) { - // Don't report another error if it would just be at the same position as the last error. - var lastError = ts.lastOrUndefined(parseDiagnostics); - if (!lastError || start !== lastError.start) { - parseDiagnostics.push(ts.createFileDiagnostic(sourceFile, start, length, message, arg0)); - } - // Mark that we've encountered an error. We'll set an appropriate bit on the next - // node we finish so that it can't be reused incrementally. - parseErrorBeforeNextFinishedNode = true; + return node; + } + ts.updateConditional = updateConditional; + function createTemplateExpression(head, templateSpans, location) { + var node = createNode(189 /* TemplateExpression */, location); + node.head = head; + node.templateSpans = createNodeArray(templateSpans); + return node; + } + ts.createTemplateExpression = createTemplateExpression; + function updateTemplateExpression(node, head, templateSpans) { + if (node.head !== head || node.templateSpans !== templateSpans) { + return updateNode(createTemplateExpression(head, templateSpans, node), node); } - function scanError(message, length) { - var pos = scanner.getTextPos(); - parseErrorAtPosition(pos, length || 0, message); + return node; + } + ts.updateTemplateExpression = updateTemplateExpression; + function createYield(asteriskToken, expression, location) { + var node = createNode(190 /* YieldExpression */, location); + node.asteriskToken = asteriskToken; + node.expression = expression; + return node; + } + ts.createYield = createYield; + function updateYield(node, expression) { + if (node.expression !== expression) { + return updateNode(createYield(node.asteriskToken, expression, node), node); } - function getNodePos() { - return scanner.getStartPos(); + return node; + } + ts.updateYield = updateYield; + function createSpread(expression, location) { + var node = createNode(191 /* SpreadElementExpression */, location); + node.expression = parenthesizeExpressionForList(expression); + return node; + } + ts.createSpread = createSpread; + function updateSpread(node, expression) { + if (node.expression !== expression) { + return updateNode(createSpread(expression, node), node); } - function getNodeEnd() { - return scanner.getStartPos(); + return node; + } + ts.updateSpread = updateSpread; + function createClassExpression(modifiers, name, typeParameters, heritageClauses, members, location) { + var node = createNode(192 /* ClassExpression */, location); + node.decorators = undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.name = name; + node.typeParameters = typeParameters ? createNodeArray(typeParameters) : undefined; + node.heritageClauses = createNodeArray(heritageClauses); + node.members = createNodeArray(members); + return node; + } + ts.createClassExpression = createClassExpression; + function updateClassExpression(node, modifiers, name, typeParameters, heritageClauses, members) { + if (node.modifiers !== modifiers || node.name !== name || node.typeParameters !== typeParameters || node.heritageClauses !== heritageClauses || node.members !== members) { + return updateNode(createClassExpression(modifiers, name, typeParameters, heritageClauses, members, node), node); } - // Use this function to access the current token instead of reading the currentToken - // variable. Since function results aren't narrowed in control flow analysis, this ensures - // that the type checker doesn't make wrong assumptions about the type of the current - // token (e.g. a call to nextToken() changes the current token but the checker doesn't - // reason about this side effect). Mainstream VMs inline simple functions like this, so - // there is no performance penalty. - function token() { - return currentToken; + return node; + } + ts.updateClassExpression = updateClassExpression; + function createOmittedExpression(location) { + var node = createNode(193 /* OmittedExpression */, location); + return node; + } + ts.createOmittedExpression = createOmittedExpression; + function createExpressionWithTypeArguments(typeArguments, expression, location) { + var node = createNode(194 /* ExpressionWithTypeArguments */, location); + node.typeArguments = typeArguments ? createNodeArray(typeArguments) : undefined; + node.expression = parenthesizeForAccess(expression); + return node; + } + ts.createExpressionWithTypeArguments = createExpressionWithTypeArguments; + function updateExpressionWithTypeArguments(node, typeArguments, expression) { + if (node.typeArguments !== typeArguments || node.expression !== expression) { + return updateNode(createExpressionWithTypeArguments(typeArguments, expression, node), node); } - function nextToken() { - return currentToken = scanner.scan(); + return node; + } + ts.updateExpressionWithTypeArguments = updateExpressionWithTypeArguments; + // Misc + function createTemplateSpan(expression, literal, location) { + var node = createNode(197 /* TemplateSpan */, location); + node.expression = expression; + node.literal = literal; + return node; + } + ts.createTemplateSpan = createTemplateSpan; + function updateTemplateSpan(node, expression, literal) { + if (node.expression !== expression || node.literal !== literal) { + return updateNode(createTemplateSpan(expression, literal, node), node); } - function reScanGreaterToken() { - return currentToken = scanner.reScanGreaterToken(); + return node; + } + ts.updateTemplateSpan = updateTemplateSpan; + // Element + function createBlock(statements, location, multiLine, flags) { + var block = createNode(199 /* Block */, location, flags); + block.statements = createNodeArray(statements); + if (multiLine) { + block.multiLine = true; } - function reScanSlashToken() { - return currentToken = scanner.reScanSlashToken(); + return block; + } + ts.createBlock = createBlock; + function updateBlock(node, statements) { + if (statements !== node.statements) { + return updateNode(createBlock(statements, /*location*/ node, node.multiLine, node.flags), node); } - function reScanTemplateToken() { - return currentToken = scanner.reScanTemplateToken(); + return node; + } + ts.updateBlock = updateBlock; + function createVariableStatement(modifiers, declarationList, location, flags) { + var node = createNode(200 /* VariableStatement */, location, flags); + node.decorators = undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.declarationList = ts.isArray(declarationList) ? createVariableDeclarationList(declarationList) : declarationList; + return node; + } + ts.createVariableStatement = createVariableStatement; + function updateVariableStatement(node, modifiers, declarationList) { + if (node.modifiers !== modifiers || node.declarationList !== declarationList) { + return updateNode(createVariableStatement(modifiers, declarationList, /*location*/ node, node.flags), node); } - function scanJsxIdentifier() { - return currentToken = scanner.scanJsxIdentifier(); + return node; + } + ts.updateVariableStatement = updateVariableStatement; + function createVariableDeclarationList(declarations, location, flags) { + var node = createNode(219 /* VariableDeclarationList */, location, flags); + node.declarations = createNodeArray(declarations); + return node; + } + ts.createVariableDeclarationList = createVariableDeclarationList; + function updateVariableDeclarationList(node, declarations) { + if (node.declarations !== declarations) { + return updateNode(createVariableDeclarationList(declarations, /*location*/ node, node.flags), node); } - function scanJsxText() { - return currentToken = scanner.scanJsxToken(); + return node; + } + ts.updateVariableDeclarationList = updateVariableDeclarationList; + function createVariableDeclaration(name, type, initializer, location, flags) { + var node = createNode(218 /* VariableDeclaration */, location, flags); + node.name = typeof name === "string" ? createIdentifier(name) : name; + node.type = type; + node.initializer = initializer !== undefined ? parenthesizeExpressionForList(initializer) : undefined; + return node; + } + ts.createVariableDeclaration = createVariableDeclaration; + function updateVariableDeclaration(node, name, type, initializer) { + if (node.name !== name || node.type !== type || node.initializer !== initializer) { + return updateNode(createVariableDeclaration(name, type, initializer, /*location*/ node, node.flags), node); } - function speculationHelper(callback, isLookAhead) { - // Keep track of the state we'll need to rollback to if lookahead fails (or if the - // caller asked us to always reset our state). - var saveToken = currentToken; - var saveParseDiagnosticsLength = parseDiagnostics.length; - var saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode; - // Note: it is not actually necessary to save/restore the context flags here. That's - // because the saving/restoring of these flags happens naturally through the recursive - // descent nature of our parser. However, we still store this here just so we can - // assert that invariant holds. - var saveContextFlags = contextFlags; - // If we're only looking ahead, then tell the scanner to only lookahead as well. - // Otherwise, if we're actually speculatively parsing, then tell the scanner to do the - // same. - var result = isLookAhead - ? scanner.lookAhead(callback) - : scanner.tryScan(callback); - ts.Debug.assert(saveContextFlags === contextFlags); - // If our callback returned something 'falsy' or we're just looking ahead, - // then unconditionally restore us to where we were. - if (!result || isLookAhead) { - currentToken = saveToken; - parseDiagnostics.length = saveParseDiagnosticsLength; - parseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode; - } - return result; + return node; + } + ts.updateVariableDeclaration = updateVariableDeclaration; + function createEmptyStatement(location) { + return createNode(201 /* EmptyStatement */, location); + } + ts.createEmptyStatement = createEmptyStatement; + function createStatement(expression, location, flags) { + var node = createNode(202 /* ExpressionStatement */, location, flags); + node.expression = parenthesizeExpressionForExpressionStatement(expression); + return node; + } + ts.createStatement = createStatement; + function updateStatement(node, expression) { + if (node.expression !== expression) { + return updateNode(createStatement(expression, /*location*/ node, node.flags), node); } - /** Invokes the provided callback then unconditionally restores the parser to the state it - * was in immediately prior to invoking the callback. The result of invoking the callback - * is returned from this function. - */ - function lookAhead(callback) { - return speculationHelper(callback, /*isLookAhead*/ true); + return node; + } + ts.updateStatement = updateStatement; + function createIf(expression, thenStatement, elseStatement, location) { + var node = createNode(203 /* IfStatement */, location); + node.expression = expression; + node.thenStatement = thenStatement; + node.elseStatement = elseStatement; + return node; + } + ts.createIf = createIf; + function updateIf(node, expression, thenStatement, elseStatement) { + if (node.expression !== expression || node.thenStatement !== thenStatement || node.elseStatement !== elseStatement) { + return updateNode(createIf(expression, thenStatement, elseStatement, /*location*/ node), node); } - /** Invokes the provided callback. If the callback returns something falsy, then it restores - * the parser to the state it was in immediately prior to invoking the callback. If the - * callback returns something truthy, then the parser state is not rolled back. The result - * of invoking the callback is returned from this function. - */ - function tryParse(callback) { - return speculationHelper(callback, /*isLookAhead*/ false); + return node; + } + ts.updateIf = updateIf; + function createDo(statement, expression, location) { + var node = createNode(204 /* DoStatement */, location); + node.statement = statement; + node.expression = expression; + return node; + } + ts.createDo = createDo; + function updateDo(node, statement, expression) { + if (node.statement !== statement || node.expression !== expression) { + return updateNode(createDo(statement, expression, node), node); } - // Ignore strict mode flag because we will report an error in type checker instead. - function isIdentifier() { - if (token() === 69 /* Identifier */) { - return true; - } - // If we have a 'yield' keyword, and we're in the [yield] context, then 'yield' is - // considered a keyword and is not an identifier. - if (token() === 114 /* YieldKeyword */ && inYieldContext()) { - return false; - } - // If we have a 'await' keyword, and we're in the [Await] context, then 'await' is - // considered a keyword and is not an identifier. - if (token() === 119 /* AwaitKeyword */ && inAwaitContext()) { - return false; - } - return token() > 105 /* LastReservedWord */; + return node; + } + ts.updateDo = updateDo; + function createWhile(expression, statement, location) { + var node = createNode(205 /* WhileStatement */, location); + node.expression = expression; + node.statement = statement; + return node; + } + ts.createWhile = createWhile; + function updateWhile(node, expression, statement) { + if (node.expression !== expression || node.statement !== statement) { + return updateNode(createWhile(expression, statement, node), node); } - function parseExpected(kind, diagnosticMessage, shouldAdvance) { - if (shouldAdvance === void 0) { shouldAdvance = true; } - if (token() === kind) { - if (shouldAdvance) { - nextToken(); - } - return true; - } - // Report specific message if provided with one. Otherwise, report generic fallback message. - if (diagnosticMessage) { - parseErrorAtCurrentToken(diagnosticMessage); - } - else { - parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(kind)); - } - return false; + return node; + } + ts.updateWhile = updateWhile; + function createFor(initializer, condition, incrementor, statement, location) { + var node = createNode(206 /* ForStatement */, location, /*flags*/ undefined); + node.initializer = initializer; + node.condition = condition; + node.incrementor = incrementor; + node.statement = statement; + return node; + } + ts.createFor = createFor; + function updateFor(node, initializer, condition, incrementor, statement) { + if (node.initializer !== initializer || node.condition !== condition || node.incrementor !== incrementor || node.statement !== statement) { + return updateNode(createFor(initializer, condition, incrementor, statement, node), node); } - function parseOptional(t) { - if (token() === t) { - nextToken(); - return true; - } - return false; + return node; + } + ts.updateFor = updateFor; + function createForIn(initializer, expression, statement, location) { + var node = createNode(207 /* ForInStatement */, location); + node.initializer = initializer; + node.expression = expression; + node.statement = statement; + return node; + } + ts.createForIn = createForIn; + function updateForIn(node, initializer, expression, statement) { + if (node.initializer !== initializer || node.expression !== expression || node.statement !== statement) { + return updateNode(createForIn(initializer, expression, statement, node), node); } - function parseOptionalToken(t) { - if (token() === t) { - return parseTokenNode(); - } - return undefined; + return node; + } + ts.updateForIn = updateForIn; + function createForOf(initializer, expression, statement, location) { + var node = createNode(208 /* ForOfStatement */, location); + node.initializer = initializer; + node.expression = expression; + node.statement = statement; + return node; + } + ts.createForOf = createForOf; + function updateForOf(node, initializer, expression, statement) { + if (node.initializer !== initializer || node.expression !== expression || node.statement !== statement) { + return updateNode(createForOf(initializer, expression, statement, node), node); } - function parseExpectedToken(t, reportAtCurrentPosition, diagnosticMessage, arg0) { - return parseOptionalToken(t) || - createMissingNode(t, reportAtCurrentPosition, diagnosticMessage, arg0); + return node; + } + ts.updateForOf = updateForOf; + function createContinue(label, location) { + var node = createNode(209 /* ContinueStatement */, location); + if (label) { + node.label = label; } - function parseTokenNode() { - var node = createNode(token()); - nextToken(); - return finishNode(node); + return node; + } + ts.createContinue = createContinue; + function updateContinue(node, label) { + if (node.label !== label) { + return updateNode(createContinue(label, node), node); } - function canParseSemicolon() { - // If there's a real semicolon, then we can always parse it out. - if (token() === 23 /* SemicolonToken */) { - return true; - } - // We can parse out an optional semicolon in ASI cases in the following cases. - return token() === 16 /* CloseBraceToken */ || token() === 1 /* EndOfFileToken */ || scanner.hasPrecedingLineBreak(); + return node; + } + ts.updateContinue = updateContinue; + function createBreak(label, location) { + var node = createNode(210 /* BreakStatement */, location); + if (label) { + node.label = label; } - function parseSemicolon() { - if (canParseSemicolon()) { - if (token() === 23 /* SemicolonToken */) { - // consume the semicolon if it was explicitly provided. - nextToken(); - } - return true; - } - else { - return parseExpected(23 /* SemicolonToken */); - } + return node; + } + ts.createBreak = createBreak; + function updateBreak(node, label) { + if (node.label !== label) { + return updateNode(createBreak(label, node), node); } - // note: this function creates only node - function createNode(kind, pos) { - nodeCount++; - if (!(pos >= 0)) { - pos = scanner.getStartPos(); - } - return kind >= 139 /* FirstNode */ ? new NodeConstructor(kind, pos, pos) : - kind === 69 /* Identifier */ ? new IdentifierConstructor(kind, pos, pos) : - new TokenConstructor(kind, pos, pos); + return node; + } + ts.updateBreak = updateBreak; + function createReturn(expression, location) { + var node = createNode(211 /* ReturnStatement */, location); + node.expression = expression; + return node; + } + ts.createReturn = createReturn; + function updateReturn(node, expression) { + if (node.expression !== expression) { + return updateNode(createReturn(expression, /*location*/ node), node); } - function finishNode(node, end) { - node.end = end === undefined ? scanner.getStartPos() : end; - if (contextFlags) { - node.flags |= contextFlags; - } - // Keep track on the node if we encountered an error while parsing it. If we did, then - // we cannot reuse the node incrementally. Once we've marked this node, clear out the - // flag so that we don't mark any subsequent nodes. - if (parseErrorBeforeNextFinishedNode) { - parseErrorBeforeNextFinishedNode = false; - node.flags |= 67108864 /* ThisNodeHasError */; - } - return node; + return node; + } + ts.updateReturn = updateReturn; + function createWith(expression, statement, location) { + var node = createNode(212 /* WithStatement */, location); + node.expression = expression; + node.statement = statement; + return node; + } + ts.createWith = createWith; + function updateWith(node, expression, statement) { + if (node.expression !== expression || node.statement !== statement) { + return updateNode(createWith(expression, statement, node), node); } - function createMissingNode(kind, reportAtCurrentPosition, diagnosticMessage, arg0) { - if (reportAtCurrentPosition) { - parseErrorAtPosition(scanner.getStartPos(), 0, diagnosticMessage, arg0); - } - else { - parseErrorAtCurrentToken(diagnosticMessage, arg0); - } - var result = createNode(kind, scanner.getStartPos()); - result.text = ""; - return finishNode(result); + return node; + } + ts.updateWith = updateWith; + function createSwitch(expression, caseBlock, location) { + var node = createNode(213 /* SwitchStatement */, location); + node.expression = parenthesizeExpressionForList(expression); + node.caseBlock = caseBlock; + return node; + } + ts.createSwitch = createSwitch; + function updateSwitch(node, expression, caseBlock) { + if (node.expression !== expression || node.caseBlock !== caseBlock) { + return updateNode(createSwitch(expression, caseBlock, node), node); } - function internIdentifier(text) { - text = ts.escapeIdentifier(text); - return identifiers[text] || (identifiers[text] = text); + return node; + } + ts.updateSwitch = updateSwitch; + function createLabel(label, statement, location) { + var node = createNode(214 /* LabeledStatement */, location); + node.label = typeof label === "string" ? createIdentifier(label) : label; + node.statement = statement; + return node; + } + ts.createLabel = createLabel; + function updateLabel(node, label, statement) { + if (node.label !== label || node.statement !== statement) { + return updateNode(createLabel(label, statement, node), node); } - // An identifier that starts with two underscores has an extra underscore character prepended to it to avoid issues - // with magic property names like '__proto__'. The 'identifiers' object is used to share a single string instance for - // each identifier in order to reduce memory consumption. - function createIdentifier(isIdentifier, diagnosticMessage) { - identifierCount++; - if (isIdentifier) { - var node = createNode(69 /* Identifier */); - // Store original token kind if it is not just an Identifier so we can report appropriate error later in type checker - if (token() !== 69 /* Identifier */) { - node.originalKeywordKind = token(); - } - node.text = internIdentifier(scanner.getTokenValue()); - nextToken(); - return finishNode(node); - } - return createMissingNode(69 /* Identifier */, /*reportAtCurrentPosition*/ false, diagnosticMessage || ts.Diagnostics.Identifier_expected); + return node; + } + ts.updateLabel = updateLabel; + function createThrow(expression, location) { + var node = createNode(215 /* ThrowStatement */, location); + node.expression = expression; + return node; + } + ts.createThrow = createThrow; + function updateThrow(node, expression) { + if (node.expression !== expression) { + return updateNode(createThrow(expression, node), node); } - function parseIdentifier(diagnosticMessage) { - return createIdentifier(isIdentifier(), diagnosticMessage); + return node; + } + ts.updateThrow = updateThrow; + function createTry(tryBlock, catchClause, finallyBlock, location) { + var node = createNode(216 /* TryStatement */, location); + node.tryBlock = tryBlock; + node.catchClause = catchClause; + node.finallyBlock = finallyBlock; + return node; + } + ts.createTry = createTry; + function updateTry(node, tryBlock, catchClause, finallyBlock) { + if (node.tryBlock !== tryBlock || node.catchClause !== catchClause || node.finallyBlock !== finallyBlock) { + return updateNode(createTry(tryBlock, catchClause, finallyBlock, node), node); } - function parseIdentifierName() { - return createIdentifier(ts.tokenIsIdentifierOrKeyword(token())); + return node; + } + ts.updateTry = updateTry; + function createCaseBlock(clauses, location) { + var node = createNode(227 /* CaseBlock */, location); + node.clauses = createNodeArray(clauses); + return node; + } + ts.createCaseBlock = createCaseBlock; + function updateCaseBlock(node, clauses) { + if (node.clauses !== clauses) { + return updateNode(createCaseBlock(clauses, node), node); } - function isLiteralPropertyName() { - return ts.tokenIsIdentifierOrKeyword(token()) || - token() === 9 /* StringLiteral */ || - token() === 8 /* NumericLiteral */; + return node; + } + ts.updateCaseBlock = updateCaseBlock; + function createFunctionDeclaration(decorators, modifiers, asteriskToken, name, typeParameters, parameters, type, body, location, flags) { + var node = createNode(220 /* FunctionDeclaration */, location, flags); + node.decorators = decorators ? createNodeArray(decorators) : undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.asteriskToken = asteriskToken; + node.name = typeof name === "string" ? createIdentifier(name) : name; + node.typeParameters = typeParameters ? createNodeArray(typeParameters) : undefined; + node.parameters = createNodeArray(parameters); + node.type = type; + node.body = body; + return node; + } + ts.createFunctionDeclaration = createFunctionDeclaration; + function updateFunctionDeclaration(node, decorators, modifiers, name, typeParameters, parameters, type, body) { + if (node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name || node.typeParameters !== typeParameters || node.parameters !== parameters || node.type !== type || node.body !== body) { + return updateNode(createFunctionDeclaration(decorators, modifiers, node.asteriskToken, name, typeParameters, parameters, type, body, /*location*/ node, node.flags), node); } - function parsePropertyNameWorker(allowComputedPropertyNames) { - if (token() === 9 /* StringLiteral */ || token() === 8 /* NumericLiteral */) { - return parseLiteralNode(/*internName*/ true); - } - if (allowComputedPropertyNames && token() === 19 /* OpenBracketToken */) { - return parseComputedPropertyName(); - } - return parseIdentifierName(); + return node; + } + ts.updateFunctionDeclaration = updateFunctionDeclaration; + function createClassDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members, location) { + var node = createNode(221 /* ClassDeclaration */, location); + node.decorators = decorators ? createNodeArray(decorators) : undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.name = name; + node.typeParameters = typeParameters ? createNodeArray(typeParameters) : undefined; + node.heritageClauses = createNodeArray(heritageClauses); + node.members = createNodeArray(members); + return node; + } + ts.createClassDeclaration = createClassDeclaration; + function updateClassDeclaration(node, decorators, modifiers, name, typeParameters, heritageClauses, members) { + if (node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name || node.typeParameters !== typeParameters || node.heritageClauses !== heritageClauses || node.members !== members) { + return updateNode(createClassDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members, node), node); } - function parsePropertyName() { - return parsePropertyNameWorker(/*allowComputedPropertyNames*/ true); + return node; + } + ts.updateClassDeclaration = updateClassDeclaration; + function createImportDeclaration(decorators, modifiers, importClause, moduleSpecifier, location) { + var node = createNode(230 /* ImportDeclaration */, location); + node.decorators = decorators ? createNodeArray(decorators) : undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.importClause = importClause; + node.moduleSpecifier = moduleSpecifier; + return node; + } + ts.createImportDeclaration = createImportDeclaration; + function updateImportDeclaration(node, decorators, modifiers, importClause, moduleSpecifier) { + if (node.decorators !== decorators || node.modifiers !== modifiers || node.importClause !== importClause || node.moduleSpecifier !== moduleSpecifier) { + return updateNode(createImportDeclaration(decorators, modifiers, importClause, moduleSpecifier, node), node); } - function parseSimplePropertyName() { - return parsePropertyNameWorker(/*allowComputedPropertyNames*/ false); + return node; + } + ts.updateImportDeclaration = updateImportDeclaration; + function createImportClause(name, namedBindings, location) { + var node = createNode(231 /* ImportClause */, location); + node.name = name; + node.namedBindings = namedBindings; + return node; + } + ts.createImportClause = createImportClause; + function updateImportClause(node, name, namedBindings) { + if (node.name !== name || node.namedBindings !== namedBindings) { + return updateNode(createImportClause(name, namedBindings, node), node); } - function isSimplePropertyName() { - return token() === 9 /* StringLiteral */ || token() === 8 /* NumericLiteral */ || ts.tokenIsIdentifierOrKeyword(token()); + return node; + } + ts.updateImportClause = updateImportClause; + function createNamespaceImport(name, location) { + var node = createNode(232 /* NamespaceImport */, location); + node.name = name; + return node; + } + ts.createNamespaceImport = createNamespaceImport; + function updateNamespaceImport(node, name) { + if (node.name !== name) { + return updateNode(createNamespaceImport(name, node), node); } - function parseComputedPropertyName() { - // PropertyName [Yield]: - // LiteralPropertyName - // ComputedPropertyName[?Yield] - var node = createNode(140 /* ComputedPropertyName */); - parseExpected(19 /* OpenBracketToken */); - // We parse any expression (including a comma expression). But the grammar - // says that only an assignment expression is allowed, so the grammar checker - // will error if it sees a comma expression. - node.expression = allowInAnd(parseExpression); - parseExpected(20 /* CloseBracketToken */); - return finishNode(node); + return node; + } + ts.updateNamespaceImport = updateNamespaceImport; + function createNamedImports(elements, location) { + var node = createNode(233 /* NamedImports */, location); + node.elements = createNodeArray(elements); + return node; + } + ts.createNamedImports = createNamedImports; + function updateNamedImports(node, elements) { + if (node.elements !== elements) { + return updateNode(createNamedImports(elements, node), node); } - function parseContextualModifier(t) { - return token() === t && tryParse(nextTokenCanFollowModifier); + return node; + } + ts.updateNamedImports = updateNamedImports; + function createImportSpecifier(propertyName, name, location) { + var node = createNode(234 /* ImportSpecifier */, location); + node.propertyName = propertyName; + node.name = name; + return node; + } + ts.createImportSpecifier = createImportSpecifier; + function updateImportSpecifier(node, propertyName, name) { + if (node.propertyName !== propertyName || node.name !== name) { + return updateNode(createImportSpecifier(propertyName, name, node), node); } - function nextTokenIsOnSameLineAndCanFollowModifier() { - nextToken(); - if (scanner.hasPrecedingLineBreak()) { - return false; - } - return canFollowModifier(); + return node; + } + ts.updateImportSpecifier = updateImportSpecifier; + function createExportAssignment(decorators, modifiers, isExportEquals, expression, location) { + var node = createNode(235 /* ExportAssignment */, location); + node.decorators = decorators ? createNodeArray(decorators) : undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.isExportEquals = isExportEquals; + node.expression = expression; + return node; + } + ts.createExportAssignment = createExportAssignment; + function updateExportAssignment(node, decorators, modifiers, expression) { + if (node.decorators !== decorators || node.modifiers !== modifiers || node.expression !== expression) { + return updateNode(createExportAssignment(decorators, modifiers, node.isExportEquals, expression, node), node); } - function nextTokenCanFollowModifier() { - if (token() === 74 /* ConstKeyword */) { - // 'const' is only a modifier if followed by 'enum'. - return nextToken() === 81 /* EnumKeyword */; - } - if (token() === 82 /* ExportKeyword */) { - nextToken(); - if (token() === 77 /* DefaultKeyword */) { - return lookAhead(nextTokenIsClassOrFunctionOrAsync); - } - return token() !== 37 /* AsteriskToken */ && token() !== 116 /* AsKeyword */ && token() !== 15 /* OpenBraceToken */ && canFollowModifier(); - } - if (token() === 77 /* DefaultKeyword */) { - return nextTokenIsClassOrFunctionOrAsync(); - } - if (token() === 113 /* StaticKeyword */) { - nextToken(); - return canFollowModifier(); - } - return nextTokenIsOnSameLineAndCanFollowModifier(); + return node; + } + ts.updateExportAssignment = updateExportAssignment; + function createExportDeclaration(decorators, modifiers, exportClause, moduleSpecifier, location) { + var node = createNode(236 /* ExportDeclaration */, location); + node.decorators = decorators ? createNodeArray(decorators) : undefined; + node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.exportClause = exportClause; + node.moduleSpecifier = moduleSpecifier; + return node; + } + ts.createExportDeclaration = createExportDeclaration; + function updateExportDeclaration(node, decorators, modifiers, exportClause, moduleSpecifier) { + if (node.decorators !== decorators || node.modifiers !== modifiers || node.exportClause !== exportClause || node.moduleSpecifier !== moduleSpecifier) { + return updateNode(createExportDeclaration(decorators, modifiers, exportClause, moduleSpecifier, node), node); } - function parseAnyContextualModifier() { - return ts.isModifierKind(token()) && tryParse(nextTokenCanFollowModifier); + return node; + } + ts.updateExportDeclaration = updateExportDeclaration; + function createNamedExports(elements, location) { + var node = createNode(237 /* NamedExports */, location); + node.elements = createNodeArray(elements); + return node; + } + ts.createNamedExports = createNamedExports; + function updateNamedExports(node, elements) { + if (node.elements !== elements) { + return updateNode(createNamedExports(elements, node), node); } - function canFollowModifier() { - return token() === 19 /* OpenBracketToken */ - || token() === 15 /* OpenBraceToken */ - || token() === 37 /* AsteriskToken */ - || token() === 22 /* DotDotDotToken */ - || isLiteralPropertyName(); + return node; + } + ts.updateNamedExports = updateNamedExports; + function createExportSpecifier(name, propertyName, location) { + var node = createNode(238 /* ExportSpecifier */, location); + node.name = typeof name === "string" ? createIdentifier(name) : name; + node.propertyName = typeof propertyName === "string" ? createIdentifier(propertyName) : propertyName; + return node; + } + ts.createExportSpecifier = createExportSpecifier; + function updateExportSpecifier(node, name, propertyName) { + if (node.name !== name || node.propertyName !== propertyName) { + return updateNode(createExportSpecifier(name, propertyName, node), node); } - function nextTokenIsClassOrFunctionOrAsync() { - nextToken(); - return token() === 73 /* ClassKeyword */ || token() === 87 /* FunctionKeyword */ || - (token() === 118 /* AsyncKeyword */ && lookAhead(nextTokenIsFunctionKeywordOnSameLine)); + return node; + } + ts.updateExportSpecifier = updateExportSpecifier; + // JSX + function createJsxElement(openingElement, children, closingElement, location) { + var node = createNode(241 /* JsxElement */, location); + node.openingElement = openingElement; + node.children = createNodeArray(children); + node.closingElement = closingElement; + return node; + } + ts.createJsxElement = createJsxElement; + function updateJsxElement(node, openingElement, children, closingElement) { + if (node.openingElement !== openingElement || node.children !== children || node.closingElement !== closingElement) { + return updateNode(createJsxElement(openingElement, children, closingElement, node), node); } - // True if positioned at the start of a list element - function isListElement(parsingContext, inErrorRecovery) { - var node = currentNode(parsingContext); - if (node) { - return true; - } - switch (parsingContext) { - case 0 /* SourceElements */: - case 1 /* BlockStatements */: - case 3 /* SwitchClauseStatements */: - // If we're in error recovery, then we don't want to treat ';' as an empty statement. - // The problem is that ';' can show up in far too many contexts, and if we see one - // and assume it's a statement, then we may bail out inappropriately from whatever - // we're parsing. For example, if we have a semicolon in the middle of a class, then - // we really don't want to assume the class is over and we're on a statement in the - // outer module. We just want to consume and move on. - return !(token() === 23 /* SemicolonToken */ && inErrorRecovery) && isStartOfStatement(); - case 2 /* SwitchClauses */: - return token() === 71 /* CaseKeyword */ || token() === 77 /* DefaultKeyword */; - case 4 /* TypeMembers */: - return lookAhead(isTypeMemberStart); - case 5 /* ClassMembers */: - // We allow semicolons as class elements (as specified by ES6) as long as we're - // not in error recovery. If we're in error recovery, we don't want an errant - // semicolon to be treated as a class member (since they're almost always used - // for statements. - return lookAhead(isClassMemberStart) || (token() === 23 /* SemicolonToken */ && !inErrorRecovery); - case 6 /* EnumMembers */: - // Include open bracket computed properties. This technically also lets in indexers, - // which would be a candidate for improved error reporting. - return token() === 19 /* OpenBracketToken */ || isLiteralPropertyName(); - case 12 /* ObjectLiteralMembers */: - return token() === 19 /* OpenBracketToken */ || token() === 37 /* AsteriskToken */ || isLiteralPropertyName(); - case 9 /* ObjectBindingElements */: - return token() === 19 /* OpenBracketToken */ || isLiteralPropertyName(); - case 7 /* HeritageClauseElement */: - // If we see { } then only consume it as an expression if it is followed by , or { - // That way we won't consume the body of a class in its heritage clause. - if (token() === 15 /* OpenBraceToken */) { - return lookAhead(isValidHeritageClauseObjectLiteral); - } - if (!inErrorRecovery) { - return isStartOfLeftHandSideExpression() && !isHeritageClauseExtendsOrImplementsKeyword(); - } - else { - // If we're in error recovery we tighten up what we're willing to match. - // That way we don't treat something like "this" as a valid heritage clause - // element during recovery. - return isIdentifier() && !isHeritageClauseExtendsOrImplementsKeyword(); - } - case 8 /* VariableDeclarations */: - return isIdentifierOrPattern(); - case 10 /* ArrayBindingElements */: - return token() === 24 /* CommaToken */ || token() === 22 /* DotDotDotToken */ || isIdentifierOrPattern(); - case 17 /* TypeParameters */: - return isIdentifier(); - case 11 /* ArgumentExpressions */: - case 15 /* ArrayLiteralMembers */: - return token() === 24 /* CommaToken */ || token() === 22 /* DotDotDotToken */ || isStartOfExpression(); - case 16 /* Parameters */: - return isStartOfParameter(); - case 18 /* TypeArguments */: - case 19 /* TupleElementTypes */: - return token() === 24 /* CommaToken */ || isStartOfType(); - case 20 /* HeritageClauses */: - return isHeritageClause(); - case 21 /* ImportOrExportSpecifiers */: - return ts.tokenIsIdentifierOrKeyword(token()); - case 13 /* JsxAttributes */: - return ts.tokenIsIdentifierOrKeyword(token()) || token() === 15 /* OpenBraceToken */; - case 14 /* JsxChildren */: - return true; - case 22 /* JSDocFunctionParameters */: - case 23 /* JSDocTypeArguments */: - case 25 /* JSDocTupleTypes */: - return JSDocParser.isJSDocType(); - case 24 /* JSDocRecordMembers */: - return isSimplePropertyName(); - } - ts.Debug.fail("Non-exhaustive case in 'isListElement'."); + return node; + } + ts.updateJsxElement = updateJsxElement; + function createJsxSelfClosingElement(tagName, attributes, location) { + var node = createNode(242 /* JsxSelfClosingElement */, location); + node.tagName = tagName; + node.attributes = createNodeArray(attributes); + return node; + } + ts.createJsxSelfClosingElement = createJsxSelfClosingElement; + function updateJsxSelfClosingElement(node, tagName, attributes) { + if (node.tagName !== tagName || node.attributes !== attributes) { + return updateNode(createJsxSelfClosingElement(tagName, attributes, node), node); } - function isValidHeritageClauseObjectLiteral() { - ts.Debug.assert(token() === 15 /* OpenBraceToken */); - if (nextToken() === 16 /* CloseBraceToken */) { - // if we see "extends {}" then only treat the {} as what we're extending (and not - // the class body) if we have: - // - // extends {} { - // extends {}, - // extends {} extends - // extends {} implements - var next = nextToken(); - return next === 24 /* CommaToken */ || next === 15 /* OpenBraceToken */ || next === 83 /* ExtendsKeyword */ || next === 106 /* ImplementsKeyword */; - } - return true; + return node; + } + ts.updateJsxSelfClosingElement = updateJsxSelfClosingElement; + function createJsxOpeningElement(tagName, attributes, location) { + var node = createNode(243 /* JsxOpeningElement */, location); + node.tagName = tagName; + node.attributes = createNodeArray(attributes); + return node; + } + ts.createJsxOpeningElement = createJsxOpeningElement; + function updateJsxOpeningElement(node, tagName, attributes) { + if (node.tagName !== tagName || node.attributes !== attributes) { + return updateNode(createJsxOpeningElement(tagName, attributes, node), node); } - function nextTokenIsIdentifier() { - nextToken(); - return isIdentifier(); + return node; + } + ts.updateJsxOpeningElement = updateJsxOpeningElement; + function createJsxClosingElement(tagName, location) { + var node = createNode(245 /* JsxClosingElement */, location); + node.tagName = tagName; + return node; + } + ts.createJsxClosingElement = createJsxClosingElement; + function updateJsxClosingElement(node, tagName) { + if (node.tagName !== tagName) { + return updateNode(createJsxClosingElement(tagName, node), node); } - function nextTokenIsIdentifierOrKeyword() { - nextToken(); - return ts.tokenIsIdentifierOrKeyword(token()); + return node; + } + ts.updateJsxClosingElement = updateJsxClosingElement; + function createJsxAttribute(name, initializer, location) { + var node = createNode(246 /* JsxAttribute */, location); + node.name = name; + node.initializer = initializer; + return node; + } + ts.createJsxAttribute = createJsxAttribute; + function updateJsxAttribute(node, name, initializer) { + if (node.name !== name || node.initializer !== initializer) { + return updateNode(createJsxAttribute(name, initializer, node), node); } - function isHeritageClauseExtendsOrImplementsKeyword() { - if (token() === 106 /* ImplementsKeyword */ || - token() === 83 /* ExtendsKeyword */) { - return lookAhead(nextTokenIsStartOfExpression); - } - return false; + return node; + } + ts.updateJsxAttribute = updateJsxAttribute; + function createJsxSpreadAttribute(expression, location) { + var node = createNode(247 /* JsxSpreadAttribute */, location); + node.expression = expression; + return node; + } + ts.createJsxSpreadAttribute = createJsxSpreadAttribute; + function updateJsxSpreadAttribute(node, expression) { + if (node.expression !== expression) { + return updateNode(createJsxSpreadAttribute(expression, node), node); } - function nextTokenIsStartOfExpression() { - nextToken(); - return isStartOfExpression(); + return node; + } + ts.updateJsxSpreadAttribute = updateJsxSpreadAttribute; + function createJsxExpression(expression, location) { + var node = createNode(248 /* JsxExpression */, location); + node.expression = expression; + return node; + } + ts.createJsxExpression = createJsxExpression; + function updateJsxExpression(node, expression) { + if (node.expression !== expression) { + return updateNode(createJsxExpression(expression, node), node); } - // True if positioned at a list terminator - function isListTerminator(kind) { - if (token() === 1 /* EndOfFileToken */) { - // Being at the end of the file ends all lists. - return true; - } - switch (kind) { - case 1 /* BlockStatements */: - case 2 /* SwitchClauses */: - case 4 /* TypeMembers */: - case 5 /* ClassMembers */: - case 6 /* EnumMembers */: - case 12 /* ObjectLiteralMembers */: - case 9 /* ObjectBindingElements */: - case 21 /* ImportOrExportSpecifiers */: - return token() === 16 /* CloseBraceToken */; - case 3 /* SwitchClauseStatements */: - return token() === 16 /* CloseBraceToken */ || token() === 71 /* CaseKeyword */ || token() === 77 /* DefaultKeyword */; - case 7 /* HeritageClauseElement */: - return token() === 15 /* OpenBraceToken */ || token() === 83 /* ExtendsKeyword */ || token() === 106 /* ImplementsKeyword */; - case 8 /* VariableDeclarations */: - return isVariableDeclaratorListTerminator(); - case 17 /* TypeParameters */: - // Tokens other than '>' are here for better error recovery - return token() === 27 /* GreaterThanToken */ || token() === 17 /* OpenParenToken */ || token() === 15 /* OpenBraceToken */ || token() === 83 /* ExtendsKeyword */ || token() === 106 /* ImplementsKeyword */; - case 11 /* ArgumentExpressions */: - // Tokens other than ')' are here for better error recovery - return token() === 18 /* CloseParenToken */ || token() === 23 /* SemicolonToken */; - case 15 /* ArrayLiteralMembers */: - case 19 /* TupleElementTypes */: - case 10 /* ArrayBindingElements */: - return token() === 20 /* CloseBracketToken */; - case 16 /* Parameters */: - // Tokens other than ')' and ']' (the latter for index signatures) are here for better error recovery - return token() === 18 /* CloseParenToken */ || token() === 20 /* CloseBracketToken */ /*|| token === SyntaxKind.OpenBraceToken*/; - case 18 /* TypeArguments */: - // Tokens other than '>' are here for better error recovery - return token() === 27 /* GreaterThanToken */ || token() === 17 /* OpenParenToken */; - case 20 /* HeritageClauses */: - return token() === 15 /* OpenBraceToken */ || token() === 16 /* CloseBraceToken */; - case 13 /* JsxAttributes */: - return token() === 27 /* GreaterThanToken */ || token() === 39 /* SlashToken */; - case 14 /* JsxChildren */: - return token() === 25 /* LessThanToken */ && lookAhead(nextTokenIsSlash); - case 22 /* JSDocFunctionParameters */: - return token() === 18 /* CloseParenToken */ || token() === 54 /* ColonToken */ || token() === 16 /* CloseBraceToken */; - case 23 /* JSDocTypeArguments */: - return token() === 27 /* GreaterThanToken */ || token() === 16 /* CloseBraceToken */; - case 25 /* JSDocTupleTypes */: - return token() === 20 /* CloseBracketToken */ || token() === 16 /* CloseBraceToken */; - case 24 /* JSDocRecordMembers */: - return token() === 16 /* CloseBraceToken */; - } + return node; + } + ts.updateJsxExpression = updateJsxExpression; + // Clauses + function createHeritageClause(token, types, location) { + var node = createNode(251 /* HeritageClause */, location); + node.token = token; + node.types = createNodeArray(types); + return node; + } + ts.createHeritageClause = createHeritageClause; + function updateHeritageClause(node, types) { + if (node.types !== types) { + return updateNode(createHeritageClause(node.token, types, node), node); } - function isVariableDeclaratorListTerminator() { - // If we can consume a semicolon (either explicitly, or with ASI), then consider us done - // with parsing the list of variable declarators. - if (canParseSemicolon()) { - return true; + return node; + } + ts.updateHeritageClause = updateHeritageClause; + function createCaseClause(expression, statements, location) { + var node = createNode(249 /* CaseClause */, location); + node.expression = parenthesizeExpressionForList(expression); + node.statements = createNodeArray(statements); + return node; + } + ts.createCaseClause = createCaseClause; + function updateCaseClause(node, expression, statements) { + if (node.expression !== expression || node.statements !== statements) { + return updateNode(createCaseClause(expression, statements, node), node); + } + return node; + } + ts.updateCaseClause = updateCaseClause; + function createDefaultClause(statements, location) { + var node = createNode(250 /* DefaultClause */, location); + node.statements = createNodeArray(statements); + return node; + } + ts.createDefaultClause = createDefaultClause; + function updateDefaultClause(node, statements) { + if (node.statements !== statements) { + return updateNode(createDefaultClause(statements, node), node); + } + return node; + } + ts.updateDefaultClause = updateDefaultClause; + function createCatchClause(variableDeclaration, block, location) { + var node = createNode(252 /* CatchClause */, location); + node.variableDeclaration = typeof variableDeclaration === "string" ? createVariableDeclaration(variableDeclaration) : variableDeclaration; + node.block = block; + return node; + } + ts.createCatchClause = createCatchClause; + function updateCatchClause(node, variableDeclaration, block) { + if (node.variableDeclaration !== variableDeclaration || node.block !== block) { + return updateNode(createCatchClause(variableDeclaration, block, node), node); + } + return node; + } + ts.updateCatchClause = updateCatchClause; + // Property assignments + function createPropertyAssignment(name, initializer, location) { + var node = createNode(253 /* PropertyAssignment */, location); + node.name = typeof name === "string" ? createIdentifier(name) : name; + node.questionToken = undefined; + node.initializer = initializer !== undefined ? parenthesizeExpressionForList(initializer) : undefined; + return node; + } + ts.createPropertyAssignment = createPropertyAssignment; + function updatePropertyAssignment(node, name, initializer) { + if (node.name !== name || node.initializer !== initializer) { + return updateNode(createPropertyAssignment(name, initializer, node), node); + } + return node; + } + ts.updatePropertyAssignment = updatePropertyAssignment; + function createShorthandPropertyAssignment(name, objectAssignmentInitializer, location) { + var node = createNode(254 /* ShorthandPropertyAssignment */, location); + node.name = typeof name === "string" ? createIdentifier(name) : name; + node.objectAssignmentInitializer = objectAssignmentInitializer !== undefined ? parenthesizeExpressionForList(objectAssignmentInitializer) : undefined; + return node; + } + ts.createShorthandPropertyAssignment = createShorthandPropertyAssignment; + function updateShorthandPropertyAssignment(node, name, objectAssignmentInitializer) { + if (node.name !== name || node.objectAssignmentInitializer !== objectAssignmentInitializer) { + return updateNode(createShorthandPropertyAssignment(name, objectAssignmentInitializer, node), node); + } + return node; + } + ts.updateShorthandPropertyAssignment = updateShorthandPropertyAssignment; + // Top-level nodes + function updateSourceFileNode(node, statements) { + if (node.statements !== statements) { + var updated = createNode(256 /* SourceFile */, /*location*/ node, node.flags); + updated.statements = createNodeArray(statements); + updated.endOfFileToken = node.endOfFileToken; + updated.fileName = node.fileName; + updated.path = node.path; + updated.text = node.text; + if (node.amdDependencies !== undefined) + updated.amdDependencies = node.amdDependencies; + if (node.moduleName !== undefined) + updated.moduleName = node.moduleName; + if (node.referencedFiles !== undefined) + updated.referencedFiles = node.referencedFiles; + if (node.typeReferenceDirectives !== undefined) + updated.typeReferenceDirectives = node.typeReferenceDirectives; + if (node.languageVariant !== undefined) + updated.languageVariant = node.languageVariant; + if (node.isDeclarationFile !== undefined) + updated.isDeclarationFile = node.isDeclarationFile; + if (node.renamedDependencies !== undefined) + updated.renamedDependencies = node.renamedDependencies; + if (node.hasNoDefaultLib !== undefined) + updated.hasNoDefaultLib = node.hasNoDefaultLib; + if (node.languageVersion !== undefined) + updated.languageVersion = node.languageVersion; + if (node.scriptKind !== undefined) + updated.scriptKind = node.scriptKind; + if (node.externalModuleIndicator !== undefined) + updated.externalModuleIndicator = node.externalModuleIndicator; + if (node.commonJsModuleIndicator !== undefined) + updated.commonJsModuleIndicator = node.commonJsModuleIndicator; + if (node.identifiers !== undefined) + updated.identifiers = node.identifiers; + if (node.nodeCount !== undefined) + updated.nodeCount = node.nodeCount; + if (node.identifierCount !== undefined) + updated.identifierCount = node.identifierCount; + if (node.symbolCount !== undefined) + updated.symbolCount = node.symbolCount; + if (node.parseDiagnostics !== undefined) + updated.parseDiagnostics = node.parseDiagnostics; + if (node.bindDiagnostics !== undefined) + updated.bindDiagnostics = node.bindDiagnostics; + if (node.lineMap !== undefined) + updated.lineMap = node.lineMap; + if (node.classifiableNames !== undefined) + updated.classifiableNames = node.classifiableNames; + if (node.resolvedModules !== undefined) + updated.resolvedModules = node.resolvedModules; + if (node.resolvedTypeReferenceDirectiveNames !== undefined) + updated.resolvedTypeReferenceDirectiveNames = node.resolvedTypeReferenceDirectiveNames; + if (node.imports !== undefined) + updated.imports = node.imports; + if (node.moduleAugmentations !== undefined) + updated.moduleAugmentations = node.moduleAugmentations; + if (node.externalHelpersModuleName !== undefined) + updated.externalHelpersModuleName = node.externalHelpersModuleName; + return updateNode(updated, node); + } + return node; + } + ts.updateSourceFileNode = updateSourceFileNode; + // Transformation nodes + /** + * Creates a synthetic statement to act as a placeholder for a not-emitted statement in + * order to preserve comments. + * + * @param original The original statement. + */ + function createNotEmittedStatement(original) { + var node = createNode(287 /* NotEmittedStatement */, /*location*/ original); + node.original = original; + return node; + } + ts.createNotEmittedStatement = createNotEmittedStatement; + /** + * Creates a synthetic expression to act as a placeholder for a not-emitted expression in + * order to preserve comments or sourcemap positions. + * + * @param expression The inner expression to emit. + * @param original The original outer expression. + * @param location The location for the expression. Defaults to the positions from "original" if provided. + */ + function createPartiallyEmittedExpression(expression, original, location) { + var node = createNode(288 /* PartiallyEmittedExpression */, /*location*/ location || original); + node.expression = expression; + node.original = original; + return node; + } + ts.createPartiallyEmittedExpression = createPartiallyEmittedExpression; + function updatePartiallyEmittedExpression(node, expression) { + if (node.expression !== expression) { + return updateNode(createPartiallyEmittedExpression(expression, node.original, node), node); + } + return node; + } + ts.updatePartiallyEmittedExpression = updatePartiallyEmittedExpression; + // Compound nodes + function createComma(left, right) { + return createBinary(left, 24 /* CommaToken */, right); + } + ts.createComma = createComma; + function createLessThan(left, right, location) { + return createBinary(left, 25 /* LessThanToken */, right, location); + } + ts.createLessThan = createLessThan; + function createAssignment(left, right, location) { + return createBinary(left, 56 /* EqualsToken */, right, location); + } + ts.createAssignment = createAssignment; + function createStrictEquality(left, right) { + return createBinary(left, 32 /* EqualsEqualsEqualsToken */, right); + } + ts.createStrictEquality = createStrictEquality; + function createStrictInequality(left, right) { + return createBinary(left, 33 /* ExclamationEqualsEqualsToken */, right); + } + ts.createStrictInequality = createStrictInequality; + function createAdd(left, right) { + return createBinary(left, 35 /* PlusToken */, right); + } + ts.createAdd = createAdd; + function createSubtract(left, right) { + return createBinary(left, 36 /* MinusToken */, right); + } + ts.createSubtract = createSubtract; + function createPostfixIncrement(operand, location) { + return createPostfix(operand, 41 /* PlusPlusToken */, location); + } + ts.createPostfixIncrement = createPostfixIncrement; + function createLogicalAnd(left, right) { + return createBinary(left, 51 /* AmpersandAmpersandToken */, right); + } + ts.createLogicalAnd = createLogicalAnd; + function createLogicalOr(left, right) { + return createBinary(left, 52 /* BarBarToken */, right); + } + ts.createLogicalOr = createLogicalOr; + function createLogicalNot(operand) { + return createPrefix(49 /* ExclamationToken */, operand); + } + ts.createLogicalNot = createLogicalNot; + function createVoidZero() { + return createVoid(createLiteral(0)); + } + ts.createVoidZero = createVoidZero; + function createMemberAccessForPropertyName(target, memberName, location) { + if (ts.isComputedPropertyName(memberName)) { + return createElementAccess(target, memberName.expression, location); + } + else { + var expression = ts.isIdentifier(memberName) ? createPropertyAccess(target, memberName, location) : createElementAccess(target, memberName, location); + (expression.emitNode || (expression.emitNode = {})).flags |= 2048 /* NoNestedSourceMaps */; + return expression; + } + } + ts.createMemberAccessForPropertyName = createMemberAccessForPropertyName; + function createRestParameter(name) { + return createParameterDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, createSynthesizedNode(22 /* DotDotDotToken */), name, + /*questionToken*/ undefined, + /*type*/ undefined, + /*initializer*/ undefined); + } + ts.createRestParameter = createRestParameter; + function createFunctionCall(func, thisArg, argumentsList, location) { + return createCall(createPropertyAccess(func, "call"), + /*typeArguments*/ undefined, [ + thisArg + ].concat(argumentsList), location); + } + ts.createFunctionCall = createFunctionCall; + function createFunctionApply(func, thisArg, argumentsExpression, location) { + return createCall(createPropertyAccess(func, "apply"), + /*typeArguments*/ undefined, [ + thisArg, + argumentsExpression + ], location); + } + ts.createFunctionApply = createFunctionApply; + function createArraySlice(array, start) { + var argumentsList = []; + if (start !== undefined) { + argumentsList.push(typeof start === "number" ? createLiteral(start) : start); + } + return createCall(createPropertyAccess(array, "slice"), /*typeArguments*/ undefined, argumentsList); + } + ts.createArraySlice = createArraySlice; + function createArrayConcat(array, values) { + return createCall(createPropertyAccess(array, "concat"), + /*typeArguments*/ undefined, values); + } + ts.createArrayConcat = createArrayConcat; + function createMathPow(left, right, location) { + return createCall(createPropertyAccess(createIdentifier("Math"), "pow"), + /*typeArguments*/ undefined, [left, right], location); + } + ts.createMathPow = createMathPow; + function createReactNamespace(reactNamespace, parent) { + // To ensure the emit resolver can properly resolve the namespace, we need to + // treat this identifier as if it were a source tree node by clearing the `Synthesized` + // flag and setting a parent node. + var react = createIdentifier(reactNamespace || "React"); + react.flags &= ~8 /* Synthesized */; + react.parent = parent; + return react; + } + function createReactCreateElement(reactNamespace, tagName, props, children, parentElement, location) { + var argumentsList = [tagName]; + if (props) { + argumentsList.push(props); + } + if (children && children.length > 0) { + if (!props) { + argumentsList.push(createNull()); } - // in the case where we're parsing the variable declarator of a 'for-in' statement, we - // are done if we see an 'in' keyword in front of us. Same with for-of - if (isInOrOfKeyword(token())) { - return true; + if (children.length > 1) { + for (var _i = 0, children_1 = children; _i < children_1.length; _i++) { + var child = children_1[_i]; + child.startsOnNewLine = true; + argumentsList.push(child); + } } - // ERROR RECOVERY TWEAK: - // For better error recovery, if we see an '=>' then we just stop immediately. We've got an - // arrow function here and it's going to be very unlikely that we'll resynchronize and get - // another variable declaration. - if (token() === 34 /* EqualsGreaterThanToken */) { + else { + argumentsList.push(children[0]); + } + } + return createCall(createPropertyAccess(createReactNamespace(reactNamespace, parentElement), "createElement"), + /*typeArguments*/ undefined, argumentsList, location); + } + ts.createReactCreateElement = createReactCreateElement; + function createLetDeclarationList(declarations, location) { + return createVariableDeclarationList(declarations, location, 1 /* Let */); + } + ts.createLetDeclarationList = createLetDeclarationList; + function createConstDeclarationList(declarations, location) { + return createVariableDeclarationList(declarations, location, 2 /* Const */); + } + ts.createConstDeclarationList = createConstDeclarationList; + // Helpers + function createHelperName(externalHelpersModuleName, name) { + return externalHelpersModuleName + ? createPropertyAccess(externalHelpersModuleName, name) + : createIdentifier(name); + } + ts.createHelperName = createHelperName; + function createExtendsHelper(externalHelpersModuleName, name) { + return createCall(createHelperName(externalHelpersModuleName, "__extends"), + /*typeArguments*/ undefined, [ + name, + createIdentifier("_super") + ]); + } + ts.createExtendsHelper = createExtendsHelper; + function createAssignHelper(externalHelpersModuleName, attributesSegments) { + return createCall(createHelperName(externalHelpersModuleName, "__assign"), + /*typeArguments*/ undefined, attributesSegments); + } + ts.createAssignHelper = createAssignHelper; + function createParamHelper(externalHelpersModuleName, expression, parameterOffset, location) { + return createCall(createHelperName(externalHelpersModuleName, "__param"), + /*typeArguments*/ undefined, [ + createLiteral(parameterOffset), + expression + ], location); + } + ts.createParamHelper = createParamHelper; + function createMetadataHelper(externalHelpersModuleName, metadataKey, metadataValue) { + return createCall(createHelperName(externalHelpersModuleName, "__metadata"), + /*typeArguments*/ undefined, [ + createLiteral(metadataKey), + metadataValue + ]); + } + ts.createMetadataHelper = createMetadataHelper; + function createDecorateHelper(externalHelpersModuleName, decoratorExpressions, target, memberName, descriptor, location) { + var argumentsArray = []; + argumentsArray.push(createArrayLiteral(decoratorExpressions, /*location*/ undefined, /*multiLine*/ true)); + argumentsArray.push(target); + if (memberName) { + argumentsArray.push(memberName); + if (descriptor) { + argumentsArray.push(descriptor); + } + } + return createCall(createHelperName(externalHelpersModuleName, "__decorate"), /*typeArguments*/ undefined, argumentsArray, location); + } + ts.createDecorateHelper = createDecorateHelper; + function createAwaiterHelper(externalHelpersModuleName, hasLexicalArguments, promiseConstructor, body) { + var generatorFunc = createFunctionExpression(createNode(37 /* AsteriskToken */), + /*name*/ undefined, + /*typeParameters*/ undefined, + /*parameters*/ [], + /*type*/ undefined, body); + // Mark this node as originally an async function + (generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= 2097152 /* AsyncFunctionBody */; + return createCall(createHelperName(externalHelpersModuleName, "__awaiter"), + /*typeArguments*/ undefined, [ + createThis(), + hasLexicalArguments ? createIdentifier("arguments") : createVoidZero(), + promiseConstructor ? createExpressionFromEntityName(promiseConstructor) : createVoidZero(), + generatorFunc + ]); + } + ts.createAwaiterHelper = createAwaiterHelper; + function createHasOwnProperty(target, propertyName) { + return createCall(createPropertyAccess(target, "hasOwnProperty"), + /*typeArguments*/ undefined, [propertyName]); + } + ts.createHasOwnProperty = createHasOwnProperty; + function createObjectCreate(prototype) { + return createCall(createPropertyAccess(createIdentifier("Object"), "create"), + /*typeArguments*/ undefined, [prototype]); + } + function createGeti(target) { + // name => super[name] + return createArrowFunction( + /*modifiers*/ undefined, + /*typeParameters*/ undefined, [createParameter("name")], + /*type*/ undefined, + /*equalsGreaterThanToken*/ undefined, createElementAccess(target, createIdentifier("name"))); + } + function createSeti(target) { + // (name, value) => super[name] = value + return createArrowFunction( + /*modifiers*/ undefined, + /*typeParameters*/ undefined, [ + createParameter("name"), + createParameter("value") + ], + /*type*/ undefined, + /*equalsGreaterThanToken*/ undefined, createAssignment(createElementAccess(target, createIdentifier("name")), createIdentifier("value"))); + } + function createAdvancedAsyncSuperHelper() { + // const _super = (function (geti, seti) { + // const cache = Object.create(null); + // return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } }); + // })(name => super[name], (name, value) => super[name] = value); + // const cache = Object.create(null); + var createCache = createVariableStatement( + /*modifiers*/ undefined, createConstDeclarationList([ + createVariableDeclaration("cache", + /*type*/ undefined, createObjectCreate(createNull())) + ])); + // get value() { return geti(name); } + var getter = createGetAccessor( + /*decorators*/ undefined, + /*modifiers*/ undefined, "value", + /*parameters*/ [], + /*type*/ undefined, createBlock([ + createReturn(createCall(createIdentifier("geti"), + /*typeArguments*/ undefined, [createIdentifier("name")])) + ])); + // set value(v) { seti(name, v); } + var setter = createSetAccessor( + /*decorators*/ undefined, + /*modifiers*/ undefined, "value", [createParameter("v")], createBlock([ + createStatement(createCall(createIdentifier("seti"), + /*typeArguments*/ undefined, [ + createIdentifier("name"), + createIdentifier("v") + ])) + ])); + // return name => cache[name] || ... + var getOrCreateAccessorsForName = createReturn(createArrowFunction( + /*modifiers*/ undefined, + /*typeParameters*/ undefined, [createParameter("name")], + /*type*/ undefined, + /*equalsGreaterThanToken*/ undefined, createLogicalOr(createElementAccess(createIdentifier("cache"), createIdentifier("name")), createParen(createAssignment(createElementAccess(createIdentifier("cache"), createIdentifier("name")), createObjectLiteral([ + getter, + setter + ])))))); + // const _super = (function (geti, seti) { + // const cache = Object.create(null); + // return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } }); + // })(name => super[name], (name, value) => super[name] = value); + return createVariableStatement( + /*modifiers*/ undefined, createConstDeclarationList([ + createVariableDeclaration("_super", + /*type*/ undefined, createCall(createParen(createFunctionExpression( + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ + createParameter("geti"), + createParameter("seti") + ], + /*type*/ undefined, createBlock([ + createCache, + getOrCreateAccessorsForName + ]))), + /*typeArguments*/ undefined, [ + createGeti(createSuper()), + createSeti(createSuper()) + ])) + ])); + } + ts.createAdvancedAsyncSuperHelper = createAdvancedAsyncSuperHelper; + function createSimpleAsyncSuperHelper() { + return createVariableStatement( + /*modifiers*/ undefined, createConstDeclarationList([ + createVariableDeclaration("_super", + /*type*/ undefined, createGeti(createSuper())) + ])); + } + ts.createSimpleAsyncSuperHelper = createSimpleAsyncSuperHelper; + function shouldBeCapturedInTempVariable(node, cacheIdentifiers) { + var target = skipParentheses(node); + switch (target.kind) { + case 69 /* Identifier */: + return cacheIdentifiers; + case 97 /* ThisKeyword */: + case 8 /* NumericLiteral */: + case 9 /* StringLiteral */: + return false; + case 170 /* ArrayLiteralExpression */: + var elements = target.elements; + if (elements.length === 0) { + return false; + } + return true; + case 171 /* ObjectLiteralExpression */: + return target.properties.length > 0; + default: return true; - } - // Keep trying to parse out variable declarators. - return false; } - // True if positioned at element or terminator of the current list or any enclosing list - function isInSomeParsingContext() { - for (var kind = 0; kind < 26 /* Count */; kind++) { - if (parsingContext & (1 << kind)) { - if (isListElement(kind, /*inErrorRecovery*/ true) || isListTerminator(kind)) { - return true; + } + function createCallBinding(expression, recordTempVariable, languageVersion, cacheIdentifiers) { + var callee = skipOuterExpressions(expression, 7 /* All */); + var thisArg; + var target; + if (ts.isSuperProperty(callee)) { + thisArg = createThis(); + target = callee; + } + else if (callee.kind === 95 /* SuperKeyword */) { + thisArg = createThis(); + target = languageVersion < 2 /* ES6 */ ? createIdentifier("_super", /*location*/ callee) : callee; + } + else { + switch (callee.kind) { + case 172 /* PropertyAccessExpression */: { + if (shouldBeCapturedInTempVariable(callee.expression, cacheIdentifiers)) { + // for `a.b()` target is `(_a = a).b` and thisArg is `_a` + thisArg = createTempVariable(recordTempVariable); + target = createPropertyAccess(createAssignment(thisArg, callee.expression, + /*location*/ callee.expression), callee.name, + /*location*/ callee); } + else { + thisArg = callee.expression; + target = callee; + } + break; } - } - return false; - } - // Parses a list of elements - function parseList(kind, parseElement) { - var saveParsingContext = parsingContext; - parsingContext |= 1 << kind; - var result = []; - result.pos = getNodePos(); - while (!isListTerminator(kind)) { - if (isListElement(kind, /*inErrorRecovery*/ false)) { - var element = parseListElement(kind, parseElement); - result.push(element); - continue; + case 173 /* ElementAccessExpression */: { + if (shouldBeCapturedInTempVariable(callee.expression, cacheIdentifiers)) { + // for `a[b]()` target is `(_a = a)[b]` and thisArg is `_a` + thisArg = createTempVariable(recordTempVariable); + target = createElementAccess(createAssignment(thisArg, callee.expression, + /*location*/ callee.expression), callee.argumentExpression, + /*location*/ callee); + } + else { + thisArg = callee.expression; + target = callee; + } + break; } - if (abortParsingListOrMoveToNextToken(kind)) { + default: { + // for `a()` target is `a` and thisArg is `void 0` + thisArg = createVoidZero(); + target = parenthesizeForAccess(expression); break; } } - result.end = getNodeEnd(); - parsingContext = saveParsingContext; - return result; } - function parseListElement(parsingContext, parseElement) { - var node = currentNode(parsingContext); - if (node) { - return consumeNode(node); - } - return parseElement(); + return { target: target, thisArg: thisArg }; + } + ts.createCallBinding = createCallBinding; + function inlineExpressions(expressions) { + return ts.reduceLeft(expressions, createComma); + } + ts.inlineExpressions = inlineExpressions; + function createExpressionFromEntityName(node) { + if (ts.isQualifiedName(node)) { + var left = createExpressionFromEntityName(node.left); + var right = getMutableClone(node.right); + return createPropertyAccess(left, right, /*location*/ node); } - function currentNode(parsingContext) { - // If there is an outstanding parse error that we've encountered, but not attached to - // some node, then we cannot get a node from the old source tree. This is because we - // want to mark the next node we encounter as being unusable. - // - // Note: This may be too conservative. Perhaps we could reuse the node and set the bit - // on it (or its leftmost child) as having the error. For now though, being conservative - // is nice and likely won't ever affect perf. - if (parseErrorBeforeNextFinishedNode) { - return undefined; - } - if (!syntaxCursor) { - // if we don't have a cursor, we could never return a node from the old tree. - return undefined; - } - var node = syntaxCursor.currentNode(scanner.getStartPos()); - // Can't reuse a missing node. - if (ts.nodeIsMissing(node)) { - return undefined; - } - // Can't reuse a node that intersected the change range. - if (node.intersectsChange) { - return undefined; - } - // Can't reuse a node that contains a parse error. This is necessary so that we - // produce the same set of errors again. - if (ts.containsParseError(node)) { - return undefined; - } - // We can only reuse a node if it was parsed under the same strict mode that we're - // currently in. i.e. if we originally parsed a node in non-strict mode, but then - // the user added 'using strict' at the top of the file, then we can't use that node - // again as the presence of strict mode may cause us to parse the tokens in the file - // differently. - // - // Note: we *can* reuse tokens when the strict mode changes. That's because tokens - // are unaffected by strict mode. It's just the parser will decide what to do with it - // differently depending on what mode it is in. - // - // This also applies to all our other context flags as well. - var nodeContextFlags = node.flags & 197132288 /* ContextFlags */; - if (nodeContextFlags !== contextFlags) { - return undefined; - } - // Ok, we have a node that looks like it could be reused. Now verify that it is valid - // in the current list parsing context that we're currently at. - if (!canReuseNode(node, parsingContext)) { - return undefined; - } - return node; + else { + return getMutableClone(node); } - function consumeNode(node) { - // Move the scanner so it is after the node we just consumed. - scanner.setTextPos(node.end); - nextToken(); - return node; + } + ts.createExpressionFromEntityName = createExpressionFromEntityName; + function createExpressionForPropertyName(memberName) { + if (ts.isIdentifier(memberName)) { + return createLiteral(memberName, /*location*/ undefined); } - function canReuseNode(node, parsingContext) { - switch (parsingContext) { - case 5 /* ClassMembers */: - return isReusableClassMember(node); - case 2 /* SwitchClauses */: - return isReusableSwitchClause(node); - case 0 /* SourceElements */: - case 1 /* BlockStatements */: - case 3 /* SwitchClauseStatements */: - return isReusableStatement(node); - case 6 /* EnumMembers */: - return isReusableEnumMember(node); - case 4 /* TypeMembers */: - return isReusableTypeMember(node); - case 8 /* VariableDeclarations */: - return isReusableVariableDeclaration(node); - case 16 /* Parameters */: - return isReusableParameter(node); - // Any other lists we do not care about reusing nodes in. But feel free to add if - // you can do so safely. Danger areas involve nodes that may involve speculative - // parsing. If speculative parsing is involved with the node, then the range the - // parser reached while looking ahead might be in the edited range (see the example - // in canReuseVariableDeclaratorNode for a good case of this). - case 20 /* HeritageClauses */: - // This would probably be safe to reuse. There is no speculative parsing with - // heritage clauses. - case 17 /* TypeParameters */: - // This would probably be safe to reuse. There is no speculative parsing with - // type parameters. Note that that's because type *parameters* only occur in - // unambiguous *type* contexts. While type *arguments* occur in very ambiguous - // *expression* contexts. - case 19 /* TupleElementTypes */: - // This would probably be safe to reuse. There is no speculative parsing with - // tuple types. - // Technically, type argument list types are probably safe to reuse. While - // speculative parsing is involved with them (since type argument lists are only - // produced from speculative parsing a < as a type argument list), we only have - // the types because speculative parsing succeeded. Thus, the lookahead never - // went past the end of the list and rewound. - case 18 /* TypeArguments */: - // Note: these are almost certainly not safe to ever reuse. Expressions commonly - // need a large amount of lookahead, and we should not reuse them as they may - // have actually intersected the edit. - case 11 /* ArgumentExpressions */: - // This is not safe to reuse for the same reason as the 'AssignmentExpression' - // cases. i.e. a property assignment may end with an expression, and thus might - // have lookahead far beyond it's old node. - case 12 /* ObjectLiteralMembers */: - // This is probably not safe to reuse. There can be speculative parsing with - // type names in a heritage clause. There can be generic names in the type - // name list, and there can be left hand side expressions (which can have type - // arguments.) - case 7 /* HeritageClauseElement */: - // Perhaps safe to reuse, but it's unlikely we'd see more than a dozen attributes - // on any given element. Same for children. - case 13 /* JsxAttributes */: - case 14 /* JsxChildren */: - } - return false; + else if (ts.isComputedPropertyName(memberName)) { + return getMutableClone(memberName.expression); } - function isReusableClassMember(node) { - if (node) { - switch (node.kind) { - case 148 /* Constructor */: - case 153 /* IndexSignature */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 145 /* PropertyDeclaration */: - case 198 /* SemicolonClassElement */: - return true; - case 147 /* MethodDeclaration */: - // Method declarations are not necessarily reusable. An object-literal - // may have a method calls "constructor(...)" and we must reparse that - // into an actual .ConstructorDeclaration. - var methodDeclaration = node; - var nameIsConstructor = methodDeclaration.name.kind === 69 /* Identifier */ && - methodDeclaration.name.originalKeywordKind === 121 /* ConstructorKeyword */; - return !nameIsConstructor; + else { + return getMutableClone(memberName); + } + } + ts.createExpressionForPropertyName = createExpressionForPropertyName; + function createExpressionForObjectLiteralElementLike(node, property, receiver) { + switch (property.kind) { + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + return createExpressionForAccessorDeclaration(node.properties, property, receiver, node.multiLine); + case 253 /* PropertyAssignment */: + return createExpressionForPropertyAssignment(property, receiver); + case 254 /* ShorthandPropertyAssignment */: + return createExpressionForShorthandPropertyAssignment(property, receiver); + case 147 /* MethodDeclaration */: + return createExpressionForMethodDeclaration(property, receiver); + } + } + ts.createExpressionForObjectLiteralElementLike = createExpressionForObjectLiteralElementLike; + function createExpressionForAccessorDeclaration(properties, property, receiver, multiLine) { + var _a = ts.getAllAccessorDeclarations(properties, property), firstAccessor = _a.firstAccessor, getAccessor = _a.getAccessor, setAccessor = _a.setAccessor; + if (property === firstAccessor) { + var properties_1 = []; + if (getAccessor) { + var getterFunction = createFunctionExpression( + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, getAccessor.parameters, + /*type*/ undefined, getAccessor.body, + /*location*/ getAccessor); + setOriginalNode(getterFunction, getAccessor); + var getter = createPropertyAssignment("get", getterFunction); + properties_1.push(getter); + } + if (setAccessor) { + var setterFunction = createFunctionExpression( + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, setAccessor.parameters, + /*type*/ undefined, setAccessor.body, + /*location*/ setAccessor); + setOriginalNode(setterFunction, setAccessor); + var setter = createPropertyAssignment("set", setterFunction); + properties_1.push(setter); + } + properties_1.push(createPropertyAssignment("enumerable", createLiteral(true))); + properties_1.push(createPropertyAssignment("configurable", createLiteral(true))); + var expression = createCall(createPropertyAccess(createIdentifier("Object"), "defineProperty"), + /*typeArguments*/ undefined, [ + receiver, + createExpressionForPropertyName(property.name), + createObjectLiteral(properties_1, /*location*/ undefined, multiLine) + ], + /*location*/ firstAccessor); + return ts.aggregateTransformFlags(expression); + } + return undefined; + } + function createExpressionForPropertyAssignment(property, receiver) { + return ts.aggregateTransformFlags(setOriginalNode(createAssignment(createMemberAccessForPropertyName(receiver, property.name, /*location*/ property.name), property.initializer, + /*location*/ property), + /*original*/ property)); + } + function createExpressionForShorthandPropertyAssignment(property, receiver) { + return ts.aggregateTransformFlags(setOriginalNode(createAssignment(createMemberAccessForPropertyName(receiver, property.name, /*location*/ property.name), getSynthesizedClone(property.name), + /*location*/ property), + /*original*/ property)); + } + function createExpressionForMethodDeclaration(method, receiver) { + return ts.aggregateTransformFlags(setOriginalNode(createAssignment(createMemberAccessForPropertyName(receiver, method.name, /*location*/ method.name), setOriginalNode(createFunctionExpression(method.asteriskToken, + /*name*/ undefined, + /*typeParameters*/ undefined, method.parameters, + /*type*/ undefined, method.body, + /*location*/ method), + /*original*/ method), + /*location*/ method), + /*original*/ method)); + } + // Utilities + function isUseStrictPrologue(node) { + return node.expression.text === "use strict"; + } + /** + * Add any necessary prologue-directives into target statement-array. + * The function needs to be called during each transformation step. + * This function needs to be called whenever we transform the statement + * list of a source file, namespace, or function-like body. + * + * @param target: result statements array + * @param source: origin statements array + * @param ensureUseStrict: boolean determining whether the function need to add prologue-directives + * @param visitor: Optional callback used to visit any custom prologue directives. + */ + function addPrologueDirectives(target, source, ensureUseStrict, visitor) { + ts.Debug.assert(target.length === 0, "PrologueDirectives should be at the first statement in the target statements array"); + var foundUseStrict = false; + var statementOffset = 0; + var numStatements = source.length; + while (statementOffset < numStatements) { + var statement = source[statementOffset]; + if (ts.isPrologueDirective(statement)) { + if (isUseStrictPrologue(statement)) { + foundUseStrict = true; + } + target.push(statement); + } + else { + if (ensureUseStrict && !foundUseStrict) { + target.push(startOnNewLine(createStatement(createLiteral("use strict")))); + foundUseStrict = true; + } + if (getEmitFlags(statement) & 8388608 /* CustomPrologue */) { + target.push(visitor ? ts.visitNode(statement, visitor, ts.isStatement) : statement); + } + else { + break; } } - return false; + statementOffset++; } - function isReusableSwitchClause(node) { - if (node) { - switch (node.kind) { - case 249 /* CaseClause */: - case 250 /* DefaultClause */: - return true; + return statementOffset; + } + ts.addPrologueDirectives = addPrologueDirectives; + /** + * Wraps the operand to a BinaryExpression in parentheses if they are needed to preserve the intended + * order of operations. + * + * @param binaryOperator The operator for the BinaryExpression. + * @param operand The operand for the BinaryExpression. + * @param isLeftSideOfBinary A value indicating whether the operand is the left side of the + * BinaryExpression. + */ + function parenthesizeBinaryOperand(binaryOperator, operand, isLeftSideOfBinary, leftOperand) { + var skipped = skipPartiallyEmittedExpressions(operand); + // If the resulting expression is already parenthesized, we do not need to do any further processing. + if (skipped.kind === 178 /* ParenthesizedExpression */) { + return operand; + } + return binaryOperandNeedsParentheses(binaryOperator, operand, isLeftSideOfBinary, leftOperand) + ? createParen(operand) + : operand; + } + ts.parenthesizeBinaryOperand = parenthesizeBinaryOperand; + /** + * Determines whether the operand to a BinaryExpression needs to be parenthesized. + * + * @param binaryOperator The operator for the BinaryExpression. + * @param operand The operand for the BinaryExpression. + * @param isLeftSideOfBinary A value indicating whether the operand is the left side of the + * BinaryExpression. + */ + function binaryOperandNeedsParentheses(binaryOperator, operand, isLeftSideOfBinary, leftOperand) { + // If the operand has lower precedence, then it needs to be parenthesized to preserve the + // intent of the expression. For example, if the operand is `a + b` and the operator is + // `*`, then we need to parenthesize the operand to preserve the intended order of + // operations: `(a + b) * x`. + // + // If the operand has higher precedence, then it does not need to be parenthesized. For + // example, if the operand is `a * b` and the operator is `+`, then we do not need to + // parenthesize to preserve the intended order of operations: `a * b + x`. + // + // If the operand has the same precedence, then we need to check the associativity of + // the operator based on whether this is the left or right operand of the expression. + // + // For example, if `a / d` is on the right of operator `*`, we need to parenthesize + // to preserve the intended order of operations: `x * (a / d)` + // + // If `a ** d` is on the left of operator `**`, we need to parenthesize to preserve + // the intended order of operations: `(a ** b) ** c` + var binaryOperatorPrecedence = ts.getOperatorPrecedence(187 /* BinaryExpression */, binaryOperator); + var binaryOperatorAssociativity = ts.getOperatorAssociativity(187 /* BinaryExpression */, binaryOperator); + var emittedOperand = skipPartiallyEmittedExpressions(operand); + var operandPrecedence = ts.getExpressionPrecedence(emittedOperand); + switch (ts.compareValues(operandPrecedence, binaryOperatorPrecedence)) { + case -1 /* LessThan */: + // If the operand is the right side of a right-associative binary operation + // and is a yield expression, then we do not need parentheses. + if (!isLeftSideOfBinary + && binaryOperatorAssociativity === 1 /* Right */ + && operand.kind === 190 /* YieldExpression */) { + return false; + } + return true; + case 1 /* GreaterThan */: + return false; + case 0 /* EqualTo */: + if (isLeftSideOfBinary) { + // No need to parenthesize the left operand when the binary operator is + // left associative: + // (a*b)/x -> a*b/x + // (a**b)/x -> a**b/x + // + // Parentheses are needed for the left operand when the binary operator is + // right associative: + // (a/b)**x -> (a/b)**x + // (a**b)**x -> (a**b)**x + return binaryOperatorAssociativity === 1 /* Right */; + } + else { + if (ts.isBinaryExpression(emittedOperand) + && emittedOperand.operatorToken.kind === binaryOperator) { + // No need to parenthesize the right operand when the binary operator and + // operand are the same and one of the following: + // x*(a*b) => x*a*b + // x|(a|b) => x|a|b + // x&(a&b) => x&a&b + // x^(a^b) => x^a^b + if (operatorHasAssociativeProperty(binaryOperator)) { + return false; + } + // No need to parenthesize the right operand when the binary operator + // is plus (+) if both the left and right operands consist solely of either + // literals of the same kind or binary plus (+) expressions for literals of + // the same kind (recursively). + // "a"+(1+2) => "a"+(1+2) + // "a"+("b"+"c") => "a"+"b"+"c" + if (binaryOperator === 35 /* PlusToken */) { + var leftKind = leftOperand ? getLiteralKindOfBinaryPlusOperand(leftOperand) : 0 /* Unknown */; + if (ts.isLiteralKind(leftKind) && leftKind === getLiteralKindOfBinaryPlusOperand(emittedOperand)) { + return false; + } + } + } + // No need to parenthesize the right operand when the operand is right + // associative: + // x/(a**b) -> x/a**b + // x**(a**b) -> x**a**b + // + // Parentheses are needed for the right operand when the operand is left + // associative: + // x/(a*b) -> x/(a*b) + // x**(a/b) -> x**(a/b) + var operandAssociativity = ts.getExpressionAssociativity(emittedOperand); + return operandAssociativity === 0 /* Left */; } + } + } + /** + * Determines whether a binary operator is mathematically associative. + * + * @param binaryOperator The binary operator. + */ + function operatorHasAssociativeProperty(binaryOperator) { + // The following operators are associative in JavaScript: + // (a*b)*c -> a*(b*c) -> a*b*c + // (a|b)|c -> a|(b|c) -> a|b|c + // (a&b)&c -> a&(b&c) -> a&b&c + // (a^b)^c -> a^(b^c) -> a^b^c + // + // While addition is associative in mathematics, JavaScript's `+` is not + // guaranteed to be associative as it is overloaded with string concatenation. + return binaryOperator === 37 /* AsteriskToken */ + || binaryOperator === 47 /* BarToken */ + || binaryOperator === 46 /* AmpersandToken */ + || binaryOperator === 48 /* CaretToken */; + } + /** + * This function determines whether an expression consists of a homogeneous set of + * literal expressions or binary plus expressions that all share the same literal kind. + * It is used to determine whether the right-hand operand of a binary plus expression can be + * emitted without parentheses. + */ + function getLiteralKindOfBinaryPlusOperand(node) { + node = skipPartiallyEmittedExpressions(node); + if (ts.isLiteralKind(node.kind)) { + return node.kind; + } + if (node.kind === 187 /* BinaryExpression */ && node.operatorToken.kind === 35 /* PlusToken */) { + if (node.cachedLiteralKind !== undefined) { + return node.cachedLiteralKind; } - return false; + var leftKind = getLiteralKindOfBinaryPlusOperand(node.left); + var literalKind = ts.isLiteralKind(leftKind) + && leftKind === getLiteralKindOfBinaryPlusOperand(node.right) + ? leftKind + : 0 /* Unknown */; + node.cachedLiteralKind = literalKind; + return literalKind; } - function isReusableStatement(node) { - if (node) { - switch (node.kind) { - case 220 /* FunctionDeclaration */: - case 200 /* VariableStatement */: - case 199 /* Block */: - case 203 /* IfStatement */: - case 202 /* ExpressionStatement */: - case 215 /* ThrowStatement */: - case 211 /* ReturnStatement */: - case 213 /* SwitchStatement */: - case 210 /* BreakStatement */: - case 209 /* ContinueStatement */: - case 207 /* ForInStatement */: - case 208 /* ForOfStatement */: - case 206 /* ForStatement */: - case 205 /* WhileStatement */: - case 212 /* WithStatement */: - case 201 /* EmptyStatement */: - case 216 /* TryStatement */: - case 214 /* LabeledStatement */: - case 204 /* DoStatement */: - case 217 /* DebuggerStatement */: - case 230 /* ImportDeclaration */: - case 229 /* ImportEqualsDeclaration */: - case 236 /* ExportDeclaration */: - case 235 /* ExportAssignment */: - case 225 /* ModuleDeclaration */: - case 221 /* ClassDeclaration */: - case 222 /* InterfaceDeclaration */: - case 224 /* EnumDeclaration */: - case 223 /* TypeAliasDeclaration */: - return true; + return 0 /* Unknown */; + } + /** + * Wraps an expression in parentheses if it is needed in order to use the expression + * as the expression of a NewExpression node. + * + * @param expression The Expression node. + */ + function parenthesizeForNew(expression) { + var emittedExpression = skipPartiallyEmittedExpressions(expression); + switch (emittedExpression.kind) { + case 174 /* CallExpression */: + return createParen(expression); + case 175 /* NewExpression */: + return emittedExpression.arguments + ? expression + : createParen(expression); + } + return parenthesizeForAccess(expression); + } + ts.parenthesizeForNew = parenthesizeForNew; + /** + * Wraps an expression in parentheses if it is needed in order to use the expression for + * property or element access. + * + * @param expr The expression node. + */ + function parenthesizeForAccess(expression) { + // isLeftHandSideExpression is almost the correct criterion for when it is not necessary + // to parenthesize the expression before a dot. The known exceptions are: + // + // NewExpression: + // new C.x -> not the same as (new C).x + // NumericLiteral + // 1.x -> not the same as (1).x + // + var emittedExpression = skipPartiallyEmittedExpressions(expression); + if (ts.isLeftHandSideExpression(emittedExpression) + && (emittedExpression.kind !== 175 /* NewExpression */ || emittedExpression.arguments) + && emittedExpression.kind !== 8 /* NumericLiteral */) { + return expression; + } + return createParen(expression, /*location*/ expression); + } + ts.parenthesizeForAccess = parenthesizeForAccess; + function parenthesizePostfixOperand(operand) { + return ts.isLeftHandSideExpression(operand) + ? operand + : createParen(operand, /*location*/ operand); + } + ts.parenthesizePostfixOperand = parenthesizePostfixOperand; + function parenthesizePrefixOperand(operand) { + return ts.isUnaryExpression(operand) + ? operand + : createParen(operand, /*location*/ operand); + } + ts.parenthesizePrefixOperand = parenthesizePrefixOperand; + function parenthesizeListElements(elements) { + var result; + for (var i = 0; i < elements.length; i++) { + var element = parenthesizeExpressionForList(elements[i]); + if (result !== undefined || element !== elements[i]) { + if (result === undefined) { + result = elements.slice(0, i); } + result.push(element); } - return false; } - function isReusableEnumMember(node) { - return node.kind === 255 /* EnumMember */; + if (result !== undefined) { + return createNodeArray(result, elements, elements.hasTrailingComma); } - function isReusableTypeMember(node) { - if (node) { - switch (node.kind) { - case 152 /* ConstructSignature */: - case 146 /* MethodSignature */: - case 153 /* IndexSignature */: - case 144 /* PropertySignature */: - case 151 /* CallSignature */: - return true; - } + return elements; + } + function parenthesizeExpressionForList(expression) { + var emittedExpression = skipPartiallyEmittedExpressions(expression); + var expressionPrecedence = ts.getExpressionPrecedence(emittedExpression); + var commaPrecedence = ts.getOperatorPrecedence(187 /* BinaryExpression */, 24 /* CommaToken */); + return expressionPrecedence > commaPrecedence + ? expression + : createParen(expression, /*location*/ expression); + } + ts.parenthesizeExpressionForList = parenthesizeExpressionForList; + function parenthesizeExpressionForExpressionStatement(expression) { + var emittedExpression = skipPartiallyEmittedExpressions(expression); + if (ts.isCallExpression(emittedExpression)) { + var callee = emittedExpression.expression; + var kind = skipPartiallyEmittedExpressions(callee).kind; + if (kind === 179 /* FunctionExpression */ || kind === 180 /* ArrowFunction */) { + var mutableCall = getMutableClone(emittedExpression); + mutableCall.expression = createParen(callee, /*location*/ callee); + return recreatePartiallyEmittedExpressions(expression, mutableCall); } - return false; } - function isReusableVariableDeclaration(node) { - if (node.kind !== 218 /* VariableDeclaration */) { - return false; + else { + var leftmostExpressionKind = getLeftmostExpression(emittedExpression).kind; + if (leftmostExpressionKind === 171 /* ObjectLiteralExpression */ || leftmostExpressionKind === 179 /* FunctionExpression */) { + return createParen(expression, /*location*/ expression); } - // Very subtle incremental parsing bug. Consider the following code: - // - // let v = new List < A, B - // - // This is actually legal code. It's a list of variable declarators "v = new List() - // - // then we have a problem. "v = new List= 0) { - // Always preserve a trailing comma by marking it on the NodeArray - result.hasTrailingComma = true; - } - result.end = getNodeEnd(); - parsingContext = saveParsingContext; - return result; - } - function createMissingList() { - var pos = getNodePos(); - var result = []; - result.pos = pos; - result.end = pos; - return result; + return node; + } + ts.skipParentheses = skipParentheses; + function skipAssertions(node) { + while (ts.isAssertionExpression(node)) { + node = node.expression; } - function parseBracketedList(kind, parseElement, open, close) { - if (parseExpected(open)) { - var result = parseDelimitedList(kind, parseElement); - parseExpected(close); - return result; - } - return createMissingList(); + return node; + } + ts.skipAssertions = skipAssertions; + function skipPartiallyEmittedExpressions(node) { + while (node.kind === 288 /* PartiallyEmittedExpression */) { + node = node.expression; } - // The allowReservedWords parameter controls whether reserved words are permitted after the first dot - function parseEntityName(allowReservedWords, diagnosticMessage) { - var entity = parseIdentifier(diagnosticMessage); - while (parseOptional(21 /* DotToken */)) { - var node = createNode(139 /* QualifiedName */, entity.pos); // !!! - node.left = entity; - node.right = parseRightSideOfDot(allowReservedWords); - entity = finishNode(node); - } - return entity; + return node; + } + ts.skipPartiallyEmittedExpressions = skipPartiallyEmittedExpressions; + function startOnNewLine(node) { + node.startsOnNewLine = true; + return node; + } + ts.startOnNewLine = startOnNewLine; + function setOriginalNode(node, original) { + node.original = original; + if (original) { + var emitNode = original.emitNode; + if (emitNode) + node.emitNode = mergeEmitNode(emitNode, node.emitNode); } - function parseRightSideOfDot(allowIdentifierNames) { - // Technically a keyword is valid here as all identifiers and keywords are identifier names. - // However, often we'll encounter this in error situations when the identifier or keyword - // is actually starting another valid construct. - // - // So, we check for the following specific case: - // - // name. - // identifierOrKeyword identifierNameOrKeyword - // - // Note: the newlines are important here. For example, if that above code - // were rewritten into: - // - // name.identifierOrKeyword - // identifierNameOrKeyword - // - // Then we would consider it valid. That's because ASI would take effect and - // the code would be implicitly: "name.identifierOrKeyword; identifierNameOrKeyword". - // In the first case though, ASI will not take effect because there is not a - // line terminator after the identifier or keyword. - if (scanner.hasPrecedingLineBreak() && ts.tokenIsIdentifierOrKeyword(token())) { - var matchesPattern = lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine); - if (matchesPattern) { - // Report that we need an identifier. However, report it right after the dot, - // and not on the next token. This is because the next token might actually - // be an identifier and the error would be quite confusing. - return createMissingNode(69 /* Identifier */, /*reportAtCurrentPosition*/ true, ts.Diagnostics.Identifier_expected); + return node; + } + ts.setOriginalNode = setOriginalNode; + function mergeEmitNode(sourceEmitNode, destEmitNode) { + var flags = sourceEmitNode.flags, commentRange = sourceEmitNode.commentRange, sourceMapRange = sourceEmitNode.sourceMapRange, tokenSourceMapRanges = sourceEmitNode.tokenSourceMapRanges; + if (!destEmitNode && (flags || commentRange || sourceMapRange || tokenSourceMapRanges)) + destEmitNode = {}; + if (flags) + destEmitNode.flags = flags; + if (commentRange) + destEmitNode.commentRange = commentRange; + if (sourceMapRange) + destEmitNode.sourceMapRange = sourceMapRange; + if (tokenSourceMapRanges) + destEmitNode.tokenSourceMapRanges = mergeTokenSourceMapRanges(tokenSourceMapRanges, destEmitNode.tokenSourceMapRanges); + return destEmitNode; + } + function mergeTokenSourceMapRanges(sourceRanges, destRanges) { + if (!destRanges) + destRanges = ts.createMap(); + ts.copyProperties(sourceRanges, destRanges); + return destRanges; + } + /** + * Clears any EmitNode entries from parse-tree nodes. + * @param sourceFile A source file. + */ + function disposeEmitNodes(sourceFile) { + // During transformation we may need to annotate a parse tree node with transient + // transformation properties. As parse tree nodes live longer than transformation + // nodes, we need to make sure we reclaim any memory allocated for custom ranges + // from these nodes to ensure we do not hold onto entire subtrees just for position + // information. We also need to reset these nodes to a pre-transformation state + // for incremental parsing scenarios so that we do not impact later emit. + sourceFile = ts.getSourceFileOfNode(ts.getParseTreeNode(sourceFile)); + var emitNode = sourceFile && sourceFile.emitNode; + var annotatedNodes = emitNode && emitNode.annotatedNodes; + if (annotatedNodes) { + for (var _i = 0, annotatedNodes_1 = annotatedNodes; _i < annotatedNodes_1.length; _i++) { + var node = annotatedNodes_1[_i]; + node.emitNode = undefined; + } + } + } + ts.disposeEmitNodes = disposeEmitNodes; + /** + * Associates a node with the current transformation, initializing + * various transient transformation properties. + * + * @param node The node. + */ + function getOrCreateEmitNode(node) { + if (!node.emitNode) { + if (ts.isParseTreeNode(node)) { + // To avoid holding onto transformation artifacts, we keep track of any + // parse tree node we are annotating. This allows us to clean them up after + // all transformations have completed. + if (node.kind === 256 /* SourceFile */) { + return node.emitNode = { annotatedNodes: [node] }; } + var sourceFile = ts.getSourceFileOfNode(node); + getOrCreateEmitNode(sourceFile).annotatedNodes.push(node); } - return allowIdentifierNames ? parseIdentifierName() : parseIdentifier(); - } - function parseTemplateExpression() { - var template = createNode(189 /* TemplateExpression */); - template.head = parseTemplateLiteralFragment(); - ts.Debug.assert(template.head.kind === 12 /* TemplateHead */, "Template head has wrong token kind"); - var templateSpans = []; - templateSpans.pos = getNodePos(); - do { - templateSpans.push(parseTemplateSpan()); - } while (ts.lastOrUndefined(templateSpans).literal.kind === 13 /* TemplateMiddle */); - templateSpans.end = getNodeEnd(); - template.templateSpans = templateSpans; - return finishNode(template); - } - function parseTemplateSpan() { - var span = createNode(197 /* TemplateSpan */); - span.expression = allowInAnd(parseExpression); - var literal; - if (token() === 16 /* CloseBraceToken */) { - reScanTemplateToken(); - literal = parseTemplateLiteralFragment(); - } - else { - literal = parseExpectedToken(14 /* TemplateTail */, /*reportAtCurrentPosition*/ false, ts.Diagnostics._0_expected, ts.tokenToString(16 /* CloseBraceToken */)); - } - span.literal = literal; - return finishNode(span); - } - function parseLiteralNode(internName) { - return parseLiteralLikeNode(token(), internName); - } - function parseTemplateLiteralFragment() { - return parseLiteralLikeNode(token(), /*internName*/ false); - } - function parseLiteralLikeNode(kind, internName) { - var node = createNode(kind); - var text = scanner.getTokenValue(); - node.text = internName ? internIdentifier(text) : text; - if (scanner.hasExtendedUnicodeEscape()) { - node.hasExtendedUnicodeEscape = true; - } - if (scanner.isUnterminated()) { - node.isUnterminated = true; - } - var tokenPos = scanner.getTokenPos(); - nextToken(); - finishNode(node); - // Octal literals are not allowed in strict mode or ES5 - // Note that theoretically the following condition would hold true literals like 009, - // which is not octal.But because of how the scanner separates the tokens, we would - // never get a token like this. Instead, we would get 00 and 9 as two separate tokens. - // We also do not need to check for negatives because any prefix operator would be part of a - // parent unary expression. - if (node.kind === 8 /* NumericLiteral */ - && sourceText.charCodeAt(tokenPos) === 48 /* _0 */ - && ts.isOctalDigit(sourceText.charCodeAt(tokenPos + 1))) { - node.isOctalLiteral = true; - } - return node; + node.emitNode = {}; } - // TYPES - function parseTypeReference() { - var typeName = parseEntityName(/*allowReservedWords*/ false, ts.Diagnostics.Type_expected); - var node = createNode(155 /* TypeReference */, typeName.pos); - node.typeName = typeName; - if (!scanner.hasPrecedingLineBreak() && token() === 25 /* LessThanToken */) { - node.typeArguments = parseBracketedList(18 /* TypeArguments */, parseType, 25 /* LessThanToken */, 27 /* GreaterThanToken */); - } - return finishNode(node); + return node.emitNode; + } + /** + * Gets flags that control emit behavior of a node. + * + * @param node The node. + */ + function getEmitFlags(node) { + var emitNode = node.emitNode; + return emitNode && emitNode.flags; + } + ts.getEmitFlags = getEmitFlags; + /** + * Sets flags that control emit behavior of a node. + * + * @param node The node. + * @param emitFlags The NodeEmitFlags for the node. + */ + function setEmitFlags(node, emitFlags) { + getOrCreateEmitNode(node).flags = emitFlags; + return node; + } + ts.setEmitFlags = setEmitFlags; + /** + * Sets a custom text range to use when emitting source maps. + * + * @param node The node. + * @param range The text range. + */ + function setSourceMapRange(node, range) { + getOrCreateEmitNode(node).sourceMapRange = range; + return node; + } + ts.setSourceMapRange = setSourceMapRange; + /** + * Sets the TextRange to use for source maps for a token of a node. + * + * @param node The node. + * @param token The token. + * @param range The text range. + */ + function setTokenSourceMapRange(node, token, range) { + var emitNode = getOrCreateEmitNode(node); + var tokenSourceMapRanges = emitNode.tokenSourceMapRanges || (emitNode.tokenSourceMapRanges = ts.createMap()); + tokenSourceMapRanges[token] = range; + return node; + } + ts.setTokenSourceMapRange = setTokenSourceMapRange; + /** + * Sets a custom text range to use when emitting comments. + */ + function setCommentRange(node, range) { + getOrCreateEmitNode(node).commentRange = range; + return node; + } + ts.setCommentRange = setCommentRange; + /** + * Gets a custom text range to use when emitting comments. + * + * @param node The node. + */ + function getCommentRange(node) { + var emitNode = node.emitNode; + return (emitNode && emitNode.commentRange) || node; + } + ts.getCommentRange = getCommentRange; + /** + * Gets a custom text range to use when emitting source maps. + * + * @param node The node. + */ + function getSourceMapRange(node) { + var emitNode = node.emitNode; + return (emitNode && emitNode.sourceMapRange) || node; + } + ts.getSourceMapRange = getSourceMapRange; + /** + * Gets the TextRange to use for source maps for a token of a node. + * + * @param node The node. + * @param token The token. + */ + function getTokenSourceMapRange(node, token) { + var emitNode = node.emitNode; + var tokenSourceMapRanges = emitNode && emitNode.tokenSourceMapRanges; + return tokenSourceMapRanges && tokenSourceMapRanges[token]; + } + ts.getTokenSourceMapRange = getTokenSourceMapRange; + /** + * Gets the constant value to emit for an expression. + */ + function getConstantValue(node) { + var emitNode = node.emitNode; + return emitNode && emitNode.constantValue; + } + ts.getConstantValue = getConstantValue; + /** + * Sets the constant value to emit for an expression. + */ + function setConstantValue(node, value) { + var emitNode = getOrCreateEmitNode(node); + emitNode.constantValue = value; + return node; + } + ts.setConstantValue = setConstantValue; + function setTextRange(node, location) { + if (location) { + node.pos = location.pos; + node.end = location.end; } - function parseThisTypePredicate(lhs) { - nextToken(); - var node = createNode(154 /* TypePredicate */, lhs.pos); - node.parameterName = lhs; - node.type = parseType(); - return finishNode(node); + return node; + } + ts.setTextRange = setTextRange; + function setNodeFlags(node, flags) { + node.flags = flags; + return node; + } + ts.setNodeFlags = setNodeFlags; + function setMultiLine(node, multiLine) { + node.multiLine = multiLine; + return node; + } + ts.setMultiLine = setMultiLine; + function setHasTrailingComma(nodes, hasTrailingComma) { + nodes.hasTrailingComma = hasTrailingComma; + return nodes; + } + ts.setHasTrailingComma = setHasTrailingComma; + /** + * Get the name of that target module from an import or export declaration + */ + function getLocalNameForExternalImport(node, sourceFile) { + var namespaceDeclaration = ts.getNamespaceDeclarationNode(node); + if (namespaceDeclaration && !ts.isDefaultImport(node)) { + var name_9 = namespaceDeclaration.name; + return ts.isGeneratedIdentifier(name_9) ? name_9 : createIdentifier(ts.getSourceTextOfNodeFromSourceFile(sourceFile, namespaceDeclaration.name)); } - function parseThisTypeNode() { - var node = createNode(165 /* ThisType */); - nextToken(); - return finishNode(node); + if (node.kind === 230 /* ImportDeclaration */ && node.importClause) { + return getGeneratedNameForNode(node); } - function parseTypeQuery() { - var node = createNode(158 /* TypeQuery */); - parseExpected(101 /* TypeOfKeyword */); - node.exprName = parseEntityName(/*allowReservedWords*/ true); - return finishNode(node); + if (node.kind === 236 /* ExportDeclaration */ && node.moduleSpecifier) { + return getGeneratedNameForNode(node); } - function parseTypeParameter() { - var node = createNode(141 /* TypeParameter */); - node.name = parseIdentifier(); - if (parseOptional(83 /* ExtendsKeyword */)) { - // It's not uncommon for people to write improper constraints to a generic. If the - // user writes a constraint that is an expression and not an actual type, then parse - // it out as an expression (so we can recover well), but report that a type is needed - // instead. - if (isStartOfType() || !isStartOfExpression()) { - node.constraint = parseType(); - } - else { - // It was not a type, and it looked like an expression. Parse out an expression - // here so we recover well. Note: it is important that we call parseUnaryExpression - // and not parseExpression here. If the user has: - // - // - // - // We do *not* want to consume the > as we're consuming the expression for "". - node.expression = parseUnaryExpressionOrHigher(); - } - } - return finishNode(node); + return undefined; + } + ts.getLocalNameForExternalImport = getLocalNameForExternalImport; + /** + * Get the name of a target module from an import/export declaration as should be written in the emitted output. + * The emitted output name can be different from the input if: + * 1. The module has a /// + * 2. --out or --outFile is used, making the name relative to the rootDir + * 3- The containing SourceFile has an entry in renamedDependencies for the import as requested by some module loaders (e.g. System). + * Otherwise, a new StringLiteral node representing the module name will be returned. + */ + function getExternalModuleNameLiteral(importNode, sourceFile, host, resolver, compilerOptions) { + var moduleName = ts.getExternalModuleName(importNode); + if (moduleName.kind === 9 /* StringLiteral */) { + return tryGetModuleNameFromDeclaration(importNode, host, resolver, compilerOptions) + || tryRenameExternalModule(moduleName, sourceFile) + || getSynthesizedClone(moduleName); } - function parseTypeParameters() { - if (token() === 25 /* LessThanToken */) { - return parseBracketedList(17 /* TypeParameters */, parseTypeParameter, 25 /* LessThanToken */, 27 /* GreaterThanToken */); - } + return undefined; + } + ts.getExternalModuleNameLiteral = getExternalModuleNameLiteral; + /** + * Some bundlers (SystemJS builder) sometimes want to rename dependencies. + * Here we check if alternative name was provided for a given moduleName and return it if possible. + */ + function tryRenameExternalModule(moduleName, sourceFile) { + if (sourceFile.renamedDependencies && ts.hasProperty(sourceFile.renamedDependencies, moduleName.text)) { + return createLiteral(sourceFile.renamedDependencies[moduleName.text]); } - function parseParameterType() { - if (parseOptional(54 /* ColonToken */)) { - return parseType(); - } + return undefined; + } + /** + * Get the name of a module as should be written in the emitted output. + * The emitted output name can be different from the input if: + * 1. The module has a /// + * 2. --out or --outFile is used, making the name relative to the rootDir + * Otherwise, a new StringLiteral node representing the module name will be returned. + */ + function tryGetModuleNameFromFile(file, host, options) { + if (!file) { return undefined; } - function isStartOfParameter() { - return token() === 22 /* DotDotDotToken */ || isIdentifierOrPattern() || ts.isModifierKind(token()) || token() === 55 /* AtToken */ || token() === 97 /* ThisKeyword */; - } - function setModifiers(node, modifiers) { - if (modifiers) { - node.flags |= modifiers.flags; - node.modifiers = modifiers; - } - } - function parseParameter() { - var node = createNode(142 /* Parameter */); - if (token() === 97 /* ThisKeyword */) { - node.name = createIdentifier(/*isIdentifier*/ true, undefined); - node.type = parseParameterType(); - return finishNode(node); - } - node.decorators = parseDecorators(); - setModifiers(node, parseModifiers()); - node.dotDotDotToken = parseOptionalToken(22 /* DotDotDotToken */); - // FormalParameter [Yield,Await]: - // BindingElement[?Yield,?Await] - node.name = parseIdentifierOrPattern(); - if (ts.getFullWidth(node.name) === 0 && node.flags === 0 && ts.isModifierKind(token())) { - // in cases like - // 'use strict' - // function foo(static) - // isParameter('static') === true, because of isModifier('static') - // however 'static' is not a legal identifier in a strict mode. - // so result of this function will be ParameterDeclaration (flags = 0, name = missing, type = undefined, initializer = undefined) - // and current token will not change => parsing of the enclosing parameter list will last till the end of time (or OOM) - // to avoid this we'll advance cursor to the next token. - nextToken(); - } - node.questionToken = parseOptionalToken(53 /* QuestionToken */); - node.type = parseParameterType(); - node.initializer = parseBindingElementInitializer(/*inParameter*/ true); - // Do not check for initializers in an ambient context for parameters. This is not - // a grammar error because the grammar allows arbitrary call signatures in - // an ambient context. - // It is actually not necessary for this to be an error at all. The reason is that - // function/constructor implementations are syntactically disallowed in ambient - // contexts. In addition, parameter initializers are semantically disallowed in - // overload signatures. So parameter initializers are transitively disallowed in - // ambient contexts. - return addJSDocComment(finishNode(node)); + if (file.moduleName) { + return createLiteral(file.moduleName); } - function parseBindingElementInitializer(inParameter) { - return inParameter ? parseParameterInitializer() : parseNonParameterInitializer(); + if (!ts.isDeclarationFile(file) && (options.out || options.outFile)) { + return createLiteral(ts.getExternalModuleNameFromPath(host, file.fileName)); } - function parseParameterInitializer() { - return parseInitializer(/*inParameter*/ true); + return undefined; + } + ts.tryGetModuleNameFromFile = tryGetModuleNameFromFile; + function tryGetModuleNameFromDeclaration(declaration, host, resolver, compilerOptions) { + return tryGetModuleNameFromFile(resolver.getExternalModuleFileFromDeclaration(declaration), host, compilerOptions); + } +})(ts || (ts = {})); +/// +/// +/// +var ts; +(function (ts) { + var NodeConstructor; + var TokenConstructor; + var IdentifierConstructor; + var SourceFileConstructor; + function createNode(kind, pos, end) { + if (kind === 256 /* SourceFile */) { + return new (SourceFileConstructor || (SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor()))(kind, pos, end); } - function fillSignature(returnToken, yieldContext, awaitContext, requireCompleteParameterList, signature) { - var returnTokenRequired = returnToken === 34 /* EqualsGreaterThanToken */; - signature.typeParameters = parseTypeParameters(); - signature.parameters = parseParameterList(yieldContext, awaitContext, requireCompleteParameterList); - if (returnTokenRequired) { - parseExpected(returnToken); - signature.type = parseTypeOrTypePredicate(); - } - else if (parseOptional(returnToken)) { - signature.type = parseTypeOrTypePredicate(); - } + else if (kind === 69 /* Identifier */) { + return new (IdentifierConstructor || (IdentifierConstructor = ts.objectAllocator.getIdentifierConstructor()))(kind, pos, end); } - function parseParameterList(yieldContext, awaitContext, requireCompleteParameterList) { - // FormalParameters [Yield,Await]: (modified) - // [empty] - // FormalParameterList[?Yield,Await] - // - // FormalParameter[Yield,Await]: (modified) - // BindingElement[?Yield,Await] - // - // BindingElement [Yield,Await]: (modified) - // SingleNameBinding[?Yield,?Await] - // BindingPattern[?Yield,?Await]Initializer [In, ?Yield,?Await] opt - // - // SingleNameBinding [Yield,Await]: - // BindingIdentifier[?Yield,?Await]Initializer [In, ?Yield,?Await] opt - if (parseExpected(17 /* OpenParenToken */)) { - var savedYieldContext = inYieldContext(); - var savedAwaitContext = inAwaitContext(); - setYieldContext(yieldContext); - setAwaitContext(awaitContext); - var result = parseDelimitedList(16 /* Parameters */, parseParameter); - setYieldContext(savedYieldContext); - setAwaitContext(savedAwaitContext); - if (!parseExpected(18 /* CloseParenToken */) && requireCompleteParameterList) { - // Caller insisted that we had to end with a ) We didn't. So just return - // undefined here. - return undefined; - } - return result; - } - // We didn't even have an open paren. If the caller requires a complete parameter list, - // we definitely can't provide that. However, if they're ok with an incomplete one, - // then just return an empty set of parameters. - return requireCompleteParameterList ? undefined : createMissingList(); + else if (kind < 139 /* FirstNode */) { + return new (TokenConstructor || (TokenConstructor = ts.objectAllocator.getTokenConstructor()))(kind, pos, end); } - function parseTypeMemberSemicolon() { - // We allow type members to be separated by commas or (possibly ASI) semicolons. - // First check if it was a comma. If so, we're done with the member. - if (parseOptional(24 /* CommaToken */)) { - return; - } - // Didn't have a comma. We must have a (possible ASI) semicolon. - parseSemicolon(); + else { + return new (NodeConstructor || (NodeConstructor = ts.objectAllocator.getNodeConstructor()))(kind, pos, end); } - function parseSignatureMember(kind) { - var node = createNode(kind); - if (kind === 152 /* ConstructSignature */) { - parseExpected(92 /* NewKeyword */); - } - fillSignature(54 /* ColonToken */, /*yieldContext*/ false, /*awaitContext*/ false, /*requireCompleteParameterList*/ false, node); - parseTypeMemberSemicolon(); - return finishNode(node); + } + ts.createNode = createNode; + function visitNode(cbNode, node) { + if (node) { + return cbNode(node); } - function isIndexSignature() { - if (token() !== 19 /* OpenBracketToken */) { - return false; - } - return lookAhead(isUnambiguouslyIndexSignature); + } + function visitNodeArray(cbNodes, nodes) { + if (nodes) { + return cbNodes(nodes); } - function isUnambiguouslyIndexSignature() { - // The only allowed sequence is: - // - // [id: - // - // However, for error recovery, we also check the following cases: - // - // [... - // [id, - // [id?, - // [id?: - // [id?] - // [public id - // [private id - // [protected id - // [] - // - nextToken(); - if (token() === 22 /* DotDotDotToken */ || token() === 20 /* CloseBracketToken */) { - return true; - } - if (ts.isModifierKind(token())) { - nextToken(); - if (isIdentifier()) { - return true; + } + function visitEachNode(cbNode, nodes) { + if (nodes) { + for (var _i = 0, nodes_1 = nodes; _i < nodes_1.length; _i++) { + var node = nodes_1[_i]; + var result = cbNode(node); + if (result) { + return result; } } - else if (!isIdentifier()) { - return false; - } - else { - // Skip the identifier - nextToken(); - } - // A colon signifies a well formed indexer - // A comma should be a badly formed indexer because comma expressions are not allowed - // in computed properties. - if (token() === 54 /* ColonToken */ || token() === 24 /* CommaToken */) { - return true; - } - // Question mark could be an indexer with an optional property, - // or it could be a conditional expression in a computed property. - if (token() !== 53 /* QuestionToken */) { - return false; - } - // If any of the following tokens are after the question mark, it cannot - // be a conditional expression, so treat it as an indexer. - nextToken(); - return token() === 54 /* ColonToken */ || token() === 24 /* CommaToken */ || token() === 20 /* CloseBracketToken */; - } - function parseIndexSignatureDeclaration(fullStart, decorators, modifiers) { - var node = createNode(153 /* IndexSignature */, fullStart); - node.decorators = decorators; - setModifiers(node, modifiers); - node.parameters = parseBracketedList(16 /* Parameters */, parseParameter, 19 /* OpenBracketToken */, 20 /* CloseBracketToken */); - node.type = parseTypeAnnotation(); - parseTypeMemberSemicolon(); - return finishNode(node); } - function parsePropertyOrMethodSignature(fullStart, modifiers) { - var name = parsePropertyName(); - var questionToken = parseOptionalToken(53 /* QuestionToken */); - if (token() === 17 /* OpenParenToken */ || token() === 25 /* LessThanToken */) { - var method = createNode(146 /* MethodSignature */, fullStart); - setModifiers(method, modifiers); + } + // Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes + // stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise, + // embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns + // a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned. + function forEachChild(node, cbNode, cbNodeArray) { + if (!node) { + return; + } + // The visitXXX functions could be written as local functions that close over the cbNode and cbNodeArray + // callback parameters, but that causes a closure allocation for each invocation with noticeable effects + // on performance. + var visitNodes = cbNodeArray ? visitNodeArray : visitEachNode; + var cbNodes = cbNodeArray || cbNode; + switch (node.kind) { + case 139 /* QualifiedName */: + return visitNode(cbNode, node.left) || + visitNode(cbNode, node.right); + case 141 /* TypeParameter */: + return visitNode(cbNode, node.name) || + visitNode(cbNode, node.constraint) || + visitNode(cbNode, node.expression); + case 254 /* ShorthandPropertyAssignment */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNode(cbNode, node.questionToken) || + visitNode(cbNode, node.equalsToken) || + visitNode(cbNode, node.objectAssignmentInitializer); + case 142 /* Parameter */: + case 145 /* PropertyDeclaration */: + case 144 /* PropertySignature */: + case 253 /* PropertyAssignment */: + case 218 /* VariableDeclaration */: + case 169 /* BindingElement */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.propertyName) || + visitNode(cbNode, node.dotDotDotToken) || + visitNode(cbNode, node.name) || + visitNode(cbNode, node.questionToken) || + visitNode(cbNode, node.type) || + visitNode(cbNode, node.initializer); + case 156 /* FunctionType */: + case 157 /* ConstructorType */: + case 151 /* CallSignature */: + case 152 /* ConstructSignature */: + case 153 /* IndexSignature */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNodes(cbNodes, node.typeParameters) || + visitNodes(cbNodes, node.parameters) || + visitNode(cbNode, node.type); + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + case 148 /* Constructor */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 179 /* FunctionExpression */: + case 220 /* FunctionDeclaration */: + case 180 /* ArrowFunction */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.asteriskToken) || + visitNode(cbNode, node.name) || + visitNode(cbNode, node.questionToken) || + visitNodes(cbNodes, node.typeParameters) || + visitNodes(cbNodes, node.parameters) || + visitNode(cbNode, node.type) || + visitNode(cbNode, node.equalsGreaterThanToken) || + visitNode(cbNode, node.body); + case 155 /* TypeReference */: + return visitNode(cbNode, node.typeName) || + visitNodes(cbNodes, node.typeArguments); + case 154 /* TypePredicate */: + return visitNode(cbNode, node.parameterName) || + visitNode(cbNode, node.type); + case 158 /* TypeQuery */: + return visitNode(cbNode, node.exprName); + case 159 /* TypeLiteral */: + return visitNodes(cbNodes, node.members); + case 160 /* ArrayType */: + return visitNode(cbNode, node.elementType); + case 161 /* TupleType */: + return visitNodes(cbNodes, node.elementTypes); + case 162 /* UnionType */: + case 163 /* IntersectionType */: + return visitNodes(cbNodes, node.types); + case 164 /* ParenthesizedType */: + return visitNode(cbNode, node.type); + case 166 /* LiteralType */: + return visitNode(cbNode, node.literal); + case 167 /* ObjectBindingPattern */: + case 168 /* ArrayBindingPattern */: + return visitNodes(cbNodes, node.elements); + case 170 /* ArrayLiteralExpression */: + return visitNodes(cbNodes, node.elements); + case 171 /* ObjectLiteralExpression */: + return visitNodes(cbNodes, node.properties); + case 172 /* PropertyAccessExpression */: + return visitNode(cbNode, node.expression) || + visitNode(cbNode, node.name); + case 173 /* ElementAccessExpression */: + return visitNode(cbNode, node.expression) || + visitNode(cbNode, node.argumentExpression); + case 174 /* CallExpression */: + case 175 /* NewExpression */: + return visitNode(cbNode, node.expression) || + visitNodes(cbNodes, node.typeArguments) || + visitNodes(cbNodes, node.arguments); + case 176 /* TaggedTemplateExpression */: + return visitNode(cbNode, node.tag) || + visitNode(cbNode, node.template); + case 177 /* TypeAssertionExpression */: + return visitNode(cbNode, node.type) || + visitNode(cbNode, node.expression); + case 178 /* ParenthesizedExpression */: + return visitNode(cbNode, node.expression); + case 181 /* DeleteExpression */: + return visitNode(cbNode, node.expression); + case 182 /* TypeOfExpression */: + return visitNode(cbNode, node.expression); + case 183 /* VoidExpression */: + return visitNode(cbNode, node.expression); + case 185 /* PrefixUnaryExpression */: + return visitNode(cbNode, node.operand); + case 190 /* YieldExpression */: + return visitNode(cbNode, node.asteriskToken) || + visitNode(cbNode, node.expression); + case 184 /* AwaitExpression */: + return visitNode(cbNode, node.expression); + case 186 /* PostfixUnaryExpression */: + return visitNode(cbNode, node.operand); + case 187 /* BinaryExpression */: + return visitNode(cbNode, node.left) || + visitNode(cbNode, node.operatorToken) || + visitNode(cbNode, node.right); + case 195 /* AsExpression */: + return visitNode(cbNode, node.expression) || + visitNode(cbNode, node.type); + case 196 /* NonNullExpression */: + return visitNode(cbNode, node.expression); + case 188 /* ConditionalExpression */: + return visitNode(cbNode, node.condition) || + visitNode(cbNode, node.questionToken) || + visitNode(cbNode, node.whenTrue) || + visitNode(cbNode, node.colonToken) || + visitNode(cbNode, node.whenFalse); + case 191 /* SpreadElementExpression */: + return visitNode(cbNode, node.expression); + case 199 /* Block */: + case 226 /* ModuleBlock */: + return visitNodes(cbNodes, node.statements); + case 256 /* SourceFile */: + return visitNodes(cbNodes, node.statements) || + visitNode(cbNode, node.endOfFileToken); + case 200 /* VariableStatement */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.declarationList); + case 219 /* VariableDeclarationList */: + return visitNodes(cbNodes, node.declarations); + case 202 /* ExpressionStatement */: + return visitNode(cbNode, node.expression); + case 203 /* IfStatement */: + return visitNode(cbNode, node.expression) || + visitNode(cbNode, node.thenStatement) || + visitNode(cbNode, node.elseStatement); + case 204 /* DoStatement */: + return visitNode(cbNode, node.statement) || + visitNode(cbNode, node.expression); + case 205 /* WhileStatement */: + return visitNode(cbNode, node.expression) || + visitNode(cbNode, node.statement); + case 206 /* ForStatement */: + return visitNode(cbNode, node.initializer) || + visitNode(cbNode, node.condition) || + visitNode(cbNode, node.incrementor) || + visitNode(cbNode, node.statement); + case 207 /* ForInStatement */: + return visitNode(cbNode, node.initializer) || + visitNode(cbNode, node.expression) || + visitNode(cbNode, node.statement); + case 208 /* ForOfStatement */: + return visitNode(cbNode, node.initializer) || + visitNode(cbNode, node.expression) || + visitNode(cbNode, node.statement); + case 209 /* ContinueStatement */: + case 210 /* BreakStatement */: + return visitNode(cbNode, node.label); + case 211 /* ReturnStatement */: + return visitNode(cbNode, node.expression); + case 212 /* WithStatement */: + return visitNode(cbNode, node.expression) || + visitNode(cbNode, node.statement); + case 213 /* SwitchStatement */: + return visitNode(cbNode, node.expression) || + visitNode(cbNode, node.caseBlock); + case 227 /* CaseBlock */: + return visitNodes(cbNodes, node.clauses); + case 249 /* CaseClause */: + return visitNode(cbNode, node.expression) || + visitNodes(cbNodes, node.statements); + case 250 /* DefaultClause */: + return visitNodes(cbNodes, node.statements); + case 214 /* LabeledStatement */: + return visitNode(cbNode, node.label) || + visitNode(cbNode, node.statement); + case 215 /* ThrowStatement */: + return visitNode(cbNode, node.expression); + case 216 /* TryStatement */: + return visitNode(cbNode, node.tryBlock) || + visitNode(cbNode, node.catchClause) || + visitNode(cbNode, node.finallyBlock); + case 252 /* CatchClause */: + return visitNode(cbNode, node.variableDeclaration) || + visitNode(cbNode, node.block); + case 143 /* Decorator */: + return visitNode(cbNode, node.expression); + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNodes(cbNodes, node.typeParameters) || + visitNodes(cbNodes, node.heritageClauses) || + visitNodes(cbNodes, node.members); + case 222 /* InterfaceDeclaration */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNodes(cbNodes, node.typeParameters) || + visitNodes(cbNodes, node.heritageClauses) || + visitNodes(cbNodes, node.members); + case 223 /* TypeAliasDeclaration */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNodes(cbNodes, node.typeParameters) || + visitNode(cbNode, node.type); + case 224 /* EnumDeclaration */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNodes(cbNodes, node.members); + case 255 /* EnumMember */: + return visitNode(cbNode, node.name) || + visitNode(cbNode, node.initializer); + case 225 /* ModuleDeclaration */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNode(cbNode, node.body); + case 229 /* ImportEqualsDeclaration */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNode(cbNode, node.moduleReference); + case 230 /* ImportDeclaration */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.importClause) || + visitNode(cbNode, node.moduleSpecifier); + case 231 /* ImportClause */: + return visitNode(cbNode, node.name) || + visitNode(cbNode, node.namedBindings); + case 228 /* NamespaceExportDeclaration */: + return visitNode(cbNode, node.name); + case 232 /* NamespaceImport */: + return visitNode(cbNode, node.name); + case 233 /* NamedImports */: + case 237 /* NamedExports */: + return visitNodes(cbNodes, node.elements); + case 236 /* ExportDeclaration */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.exportClause) || + visitNode(cbNode, node.moduleSpecifier); + case 234 /* ImportSpecifier */: + case 238 /* ExportSpecifier */: + return visitNode(cbNode, node.propertyName) || + visitNode(cbNode, node.name); + case 235 /* ExportAssignment */: + return visitNodes(cbNodes, node.decorators) || + visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, node.expression); + case 189 /* TemplateExpression */: + return visitNode(cbNode, node.head) || visitNodes(cbNodes, node.templateSpans); + case 197 /* TemplateSpan */: + return visitNode(cbNode, node.expression) || visitNode(cbNode, node.literal); + case 140 /* ComputedPropertyName */: + return visitNode(cbNode, node.expression); + case 251 /* HeritageClause */: + return visitNodes(cbNodes, node.types); + case 194 /* ExpressionWithTypeArguments */: + return visitNode(cbNode, node.expression) || + visitNodes(cbNodes, node.typeArguments); + case 240 /* ExternalModuleReference */: + return visitNode(cbNode, node.expression); + case 239 /* MissingDeclaration */: + return visitNodes(cbNodes, node.decorators); + case 241 /* JsxElement */: + return visitNode(cbNode, node.openingElement) || + visitNodes(cbNodes, node.children) || + visitNode(cbNode, node.closingElement); + case 242 /* JsxSelfClosingElement */: + case 243 /* JsxOpeningElement */: + return visitNode(cbNode, node.tagName) || + visitNodes(cbNodes, node.attributes); + case 246 /* JsxAttribute */: + return visitNode(cbNode, node.name) || + visitNode(cbNode, node.initializer); + case 247 /* JsxSpreadAttribute */: + return visitNode(cbNode, node.expression); + case 248 /* JsxExpression */: + return visitNode(cbNode, node.expression); + case 245 /* JsxClosingElement */: + return visitNode(cbNode, node.tagName); + case 257 /* JSDocTypeExpression */: + return visitNode(cbNode, node.type); + case 261 /* JSDocUnionType */: + return visitNodes(cbNodes, node.types); + case 262 /* JSDocTupleType */: + return visitNodes(cbNodes, node.types); + case 260 /* JSDocArrayType */: + return visitNode(cbNode, node.elementType); + case 264 /* JSDocNonNullableType */: + return visitNode(cbNode, node.type); + case 263 /* JSDocNullableType */: + return visitNode(cbNode, node.type); + case 265 /* JSDocRecordType */: + return visitNode(cbNode, node.literal); + case 267 /* JSDocTypeReference */: + return visitNode(cbNode, node.name) || + visitNodes(cbNodes, node.typeArguments); + case 268 /* JSDocOptionalType */: + return visitNode(cbNode, node.type); + case 269 /* JSDocFunctionType */: + return visitNodes(cbNodes, node.parameters) || + visitNode(cbNode, node.type); + case 270 /* JSDocVariadicType */: + return visitNode(cbNode, node.type); + case 271 /* JSDocConstructorType */: + return visitNode(cbNode, node.type); + case 272 /* JSDocThisType */: + return visitNode(cbNode, node.type); + case 266 /* JSDocRecordMember */: + return visitNode(cbNode, node.name) || + visitNode(cbNode, node.type); + case 273 /* JSDocComment */: + return visitNodes(cbNodes, node.tags); + case 275 /* JSDocParameterTag */: + return visitNode(cbNode, node.preParameterName) || + visitNode(cbNode, node.typeExpression) || + visitNode(cbNode, node.postParameterName); + case 276 /* JSDocReturnTag */: + return visitNode(cbNode, node.typeExpression); + case 277 /* JSDocTypeTag */: + return visitNode(cbNode, node.typeExpression); + case 278 /* JSDocTemplateTag */: + return visitNodes(cbNodes, node.typeParameters); + case 279 /* JSDocTypedefTag */: + return visitNode(cbNode, node.typeExpression) || + visitNode(cbNode, node.name) || + visitNode(cbNode, node.jsDocTypeLiteral); + case 281 /* JSDocTypeLiteral */: + return visitNodes(cbNodes, node.jsDocPropertyTags); + case 280 /* JSDocPropertyTag */: + return visitNode(cbNode, node.typeExpression) || + visitNode(cbNode, node.name); + case 288 /* PartiallyEmittedExpression */: + return visitNode(cbNode, node.expression); + case 282 /* JSDocLiteralType */: + return visitNode(cbNode, node.literal); + } + } + ts.forEachChild = forEachChild; + function createSourceFile(fileName, sourceText, languageVersion, setParentNodes, scriptKind) { + if (setParentNodes === void 0) { setParentNodes = false; } + ts.performance.mark("beforeParse"); + var result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind); + ts.performance.mark("afterParse"); + ts.performance.measure("Parse", "beforeParse", "afterParse"); + return result; + } + ts.createSourceFile = createSourceFile; + function isExternalModule(file) { + return file.externalModuleIndicator !== undefined; + } + ts.isExternalModule = isExternalModule; + // Produces a new SourceFile for the 'newText' provided. The 'textChangeRange' parameter + // indicates what changed between the 'text' that this SourceFile has and the 'newText'. + // The SourceFile will be created with the compiler attempting to reuse as many nodes from + // this file as possible. + // + // Note: this function mutates nodes from this SourceFile. That means any existing nodes + // from this SourceFile that are being held onto may change as a result (including + // becoming detached from any SourceFile). It is recommended that this SourceFile not + // be used once 'update' is called on it. + function updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks) { + return IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); + } + ts.updateSourceFile = updateSourceFile; + /* @internal */ + function parseIsolatedJSDocComment(content, start, length) { + var result = Parser.JSDocParser.parseIsolatedJSDocComment(content, start, length); + if (result && result.jsDoc) { + // because the jsDocComment was parsed out of the source file, it might + // not be covered by the fixupParentReferences. + Parser.fixupParentReferences(result.jsDoc); + } + return result; + } + ts.parseIsolatedJSDocComment = parseIsolatedJSDocComment; + /* @internal */ + // Exposed only for testing. + function parseJSDocTypeExpressionForTests(content, start, length) { + return Parser.JSDocParser.parseJSDocTypeExpressionForTests(content, start, length); + } + ts.parseJSDocTypeExpressionForTests = parseJSDocTypeExpressionForTests; + // Implement the parser as a singleton module. We do this for perf reasons because creating + // parser instances can actually be expensive enough to impact us on projects with many source + // files. + var Parser; + (function (Parser) { + // Share a single scanner across all calls to parse a source file. This helps speed things + // up by avoiding the cost of creating/compiling scanners over and over again. + var scanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ true); + var disallowInAndDecoratorContext = 32768 /* DisallowInContext */ | 131072 /* DecoratorContext */; + // capture constructors in 'initializeState' to avoid null checks + var NodeConstructor; + var TokenConstructor; + var IdentifierConstructor; + var SourceFileConstructor; + var sourceFile; + var parseDiagnostics; + var syntaxCursor; + var currentToken; + var sourceText; + var nodeCount; + var identifiers; + var identifierCount; + var parsingContext; + // Flags that dictate what parsing context we're in. For example: + // Whether or not we are in strict parsing mode. All that changes in strict parsing mode is + // that some tokens that would be considered identifiers may be considered keywords. + // + // When adding more parser context flags, consider which is the more common case that the + // flag will be in. This should be the 'false' state for that flag. The reason for this is + // that we don't store data in our nodes unless the value is in the *non-default* state. So, + // for example, more often than code 'allows-in' (or doesn't 'disallow-in'). We opt for + // 'disallow-in' set to 'false'. Otherwise, if we had 'allowsIn' set to 'true', then almost + // all nodes would need extra state on them to store this info. + // + // Note: 'allowIn' and 'allowYield' track 1:1 with the [in] and [yield] concepts in the ES6 + // grammar specification. + // + // An important thing about these context concepts. By default they are effectively inherited + // while parsing through every grammar production. i.e. if you don't change them, then when + // you parse a sub-production, it will have the same context values as the parent production. + // This is great most of the time. After all, consider all the 'expression' grammar productions + // and how nearly all of them pass along the 'in' and 'yield' context values: + // + // EqualityExpression[In, Yield] : + // RelationalExpression[?In, ?Yield] + // EqualityExpression[?In, ?Yield] == RelationalExpression[?In, ?Yield] + // EqualityExpression[?In, ?Yield] != RelationalExpression[?In, ?Yield] + // EqualityExpression[?In, ?Yield] === RelationalExpression[?In, ?Yield] + // EqualityExpression[?In, ?Yield] !== RelationalExpression[?In, ?Yield] + // + // Where you have to be careful is then understanding what the points are in the grammar + // where the values are *not* passed along. For example: + // + // SingleNameBinding[Yield,GeneratorParameter] + // [+GeneratorParameter]BindingIdentifier[Yield] Initializer[In]opt + // [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt + // + // Here this is saying that if the GeneratorParameter context flag is set, that we should + // explicitly set the 'yield' context flag to false before calling into the BindingIdentifier + // and we should explicitly unset the 'yield' context flag before calling into the Initializer. + // production. Conversely, if the GeneratorParameter context flag is not set, then we + // should leave the 'yield' context flag alone. + // + // Getting this all correct is tricky and requires careful reading of the grammar to + // understand when these values should be changed versus when they should be inherited. + // + // Note: it should not be necessary to save/restore these flags during speculative/lookahead + // parsing. These context flags are naturally stored and restored through normal recursive + // descent parsing and unwinding. + var contextFlags; + // Whether or not we've had a parse error since creating the last AST node. If we have + // encountered an error, it will be stored on the next AST node we create. Parse errors + // can be broken down into three categories: + // + // 1) An error that occurred during scanning. For example, an unterminated literal, or a + // character that was completely not understood. + // + // 2) A token was expected, but was not present. This type of error is commonly produced + // by the 'parseExpected' function. + // + // 3) A token was present that no parsing function was able to consume. This type of error + // only occurs in the 'abortParsingListOrMoveToNextToken' function when the parser + // decides to skip the token. + // + // In all of these cases, we want to mark the next node as having had an error before it. + // With this mark, we can know in incremental settings if this node can be reused, or if + // we have to reparse it. If we don't keep this information around, we may just reuse the + // node. in that event we would then not produce the same errors as we did before, causing + // significant confusion problems. + // + // Note: it is necessary that this value be saved/restored during speculative/lookahead + // parsing. During lookahead parsing, we will often create a node. That node will have + // this value attached, and then this value will be set back to 'false'. If we decide to + // rewind, we must get back to the same value we had prior to the lookahead. + // + // Note: any errors at the end of the file that do not precede a regular node, should get + // attached to the EOF token. + var parseErrorBeforeNextFinishedNode = false; + function parseSourceFile(fileName, _sourceText, languageVersion, _syntaxCursor, setParentNodes, scriptKind) { + scriptKind = ts.ensureScriptKind(fileName, scriptKind); + initializeState(fileName, _sourceText, languageVersion, _syntaxCursor, scriptKind); + var result = parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind); + clearState(); + return result; + } + Parser.parseSourceFile = parseSourceFile; + function getLanguageVariant(scriptKind) { + // .tsx and .jsx files are treated as jsx language variant. + return scriptKind === 4 /* TSX */ || scriptKind === 2 /* JSX */ || scriptKind === 1 /* JS */ ? 1 /* JSX */ : 0 /* Standard */; + } + function initializeState(fileName, _sourceText, languageVersion, _syntaxCursor, scriptKind) { + NodeConstructor = ts.objectAllocator.getNodeConstructor(); + TokenConstructor = ts.objectAllocator.getTokenConstructor(); + IdentifierConstructor = ts.objectAllocator.getIdentifierConstructor(); + SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor(); + sourceText = _sourceText; + syntaxCursor = _syntaxCursor; + parseDiagnostics = []; + parsingContext = 0; + identifiers = ts.createMap(); + identifierCount = 0; + nodeCount = 0; + contextFlags = scriptKind === 1 /* JS */ || scriptKind === 2 /* JSX */ ? 1048576 /* JavaScriptFile */ : 0 /* None */; + parseErrorBeforeNextFinishedNode = false; + // Initialize and prime the scanner before parsing the source elements. + scanner.setText(sourceText); + scanner.setOnError(scanError); + scanner.setScriptTarget(languageVersion); + scanner.setLanguageVariant(getLanguageVariant(scriptKind)); + } + function clearState() { + // Clear out the text the scanner is pointing at, so it doesn't keep anything alive unnecessarily. + scanner.setText(""); + scanner.setOnError(undefined); + // Clear any data. We don't want to accidentally hold onto it for too long. + parseDiagnostics = undefined; + sourceFile = undefined; + identifiers = undefined; + syntaxCursor = undefined; + sourceText = undefined; + } + function parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind) { + sourceFile = createSourceFile(fileName, languageVersion, scriptKind); + sourceFile.flags = contextFlags; + // Prime the scanner. + nextToken(); + processReferenceComments(sourceFile); + sourceFile.statements = parseList(0 /* SourceElements */, parseStatement); + ts.Debug.assert(token() === 1 /* EndOfFileToken */); + sourceFile.endOfFileToken = parseTokenNode(); + setExternalModuleIndicator(sourceFile); + sourceFile.nodeCount = nodeCount; + sourceFile.identifierCount = identifierCount; + sourceFile.identifiers = identifiers; + sourceFile.parseDiagnostics = parseDiagnostics; + if (setParentNodes) { + fixupParentReferences(sourceFile); + } + return sourceFile; + } + function addJSDocComment(node) { + var comments = ts.getJsDocCommentsFromText(node, sourceFile.text); + if (comments) { + for (var _i = 0, comments_2 = comments; _i < comments_2.length; _i++) { + var comment = comments_2[_i]; + var jsDoc = JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos); + if (!jsDoc) { + continue; + } + if (!node.jsDocComments) { + node.jsDocComments = []; + } + node.jsDocComments.push(jsDoc); + } + } + return node; + } + function fixupParentReferences(rootNode) { + // normally parent references are set during binding. However, for clients that only need + // a syntax tree, and no semantic features, then the binding process is an unnecessary + // overhead. This functions allows us to set all the parents, without all the expense of + // binding. + var parent = rootNode; + forEachChild(rootNode, visitNode); + return; + function visitNode(n) { + // walk down setting parents that differ from the parent we think it should be. This + // allows us to quickly bail out of setting parents for subtrees during incremental + // parsing + if (n.parent !== parent) { + n.parent = parent; + var saveParent = parent; + parent = n; + forEachChild(n, visitNode); + if (n.jsDocComments) { + for (var _i = 0, _a = n.jsDocComments; _i < _a.length; _i++) { + var jsDocComment = _a[_i]; + jsDocComment.parent = n; + parent = jsDocComment; + forEachChild(jsDocComment, visitNode); + } + } + parent = saveParent; + } + } + } + Parser.fixupParentReferences = fixupParentReferences; + function createSourceFile(fileName, languageVersion, scriptKind) { + // code from createNode is inlined here so createNode won't have to deal with special case of creating source files + // this is quite rare comparing to other nodes and createNode should be as fast as possible + var sourceFile = new SourceFileConstructor(256 /* SourceFile */, /*pos*/ 0, /* end */ sourceText.length); + nodeCount++; + sourceFile.text = sourceText; + sourceFile.bindDiagnostics = []; + sourceFile.languageVersion = languageVersion; + sourceFile.fileName = ts.normalizePath(fileName); + sourceFile.languageVariant = getLanguageVariant(scriptKind); + sourceFile.isDeclarationFile = ts.fileExtensionIs(sourceFile.fileName, ".d.ts"); + sourceFile.scriptKind = scriptKind; + return sourceFile; + } + function setContextFlag(val, flag) { + if (val) { + contextFlags |= flag; + } + else { + contextFlags &= ~flag; + } + } + function setDisallowInContext(val) { + setContextFlag(val, 32768 /* DisallowInContext */); + } + function setYieldContext(val) { + setContextFlag(val, 65536 /* YieldContext */); + } + function setDecoratorContext(val) { + setContextFlag(val, 131072 /* DecoratorContext */); + } + function setAwaitContext(val) { + setContextFlag(val, 262144 /* AwaitContext */); + } + function doOutsideOfContext(context, func) { + // contextFlagsToClear will contain only the context flags that are + // currently set that we need to temporarily clear + // We don't just blindly reset to the previous flags to ensure + // that we do not mutate cached flags for the incremental + // parser (ThisNodeHasError, ThisNodeOrAnySubNodesHasError, and + // HasAggregatedChildData). + var contextFlagsToClear = context & contextFlags; + if (contextFlagsToClear) { + // clear the requested context flags + setContextFlag(/*val*/ false, contextFlagsToClear); + var result = func(); + // restore the context flags we just cleared + setContextFlag(/*val*/ true, contextFlagsToClear); + return result; + } + // no need to do anything special as we are not in any of the requested contexts + return func(); + } + function doInsideOfContext(context, func) { + // contextFlagsToSet will contain only the context flags that + // are not currently set that we need to temporarily enable. + // We don't just blindly reset to the previous flags to ensure + // that we do not mutate cached flags for the incremental + // parser (ThisNodeHasError, ThisNodeOrAnySubNodesHasError, and + // HasAggregatedChildData). + var contextFlagsToSet = context & ~contextFlags; + if (contextFlagsToSet) { + // set the requested context flags + setContextFlag(/*val*/ true, contextFlagsToSet); + var result = func(); + // reset the context flags we just set + setContextFlag(/*val*/ false, contextFlagsToSet); + return result; + } + // no need to do anything special as we are already in all of the requested contexts + return func(); + } + function allowInAnd(func) { + return doOutsideOfContext(32768 /* DisallowInContext */, func); + } + function disallowInAnd(func) { + return doInsideOfContext(32768 /* DisallowInContext */, func); + } + function doInYieldContext(func) { + return doInsideOfContext(65536 /* YieldContext */, func); + } + function doInDecoratorContext(func) { + return doInsideOfContext(131072 /* DecoratorContext */, func); + } + function doInAwaitContext(func) { + return doInsideOfContext(262144 /* AwaitContext */, func); + } + function doOutsideOfAwaitContext(func) { + return doOutsideOfContext(262144 /* AwaitContext */, func); + } + function doInYieldAndAwaitContext(func) { + return doInsideOfContext(65536 /* YieldContext */ | 262144 /* AwaitContext */, func); + } + function inContext(flags) { + return (contextFlags & flags) !== 0; + } + function inYieldContext() { + return inContext(65536 /* YieldContext */); + } + function inDisallowInContext() { + return inContext(32768 /* DisallowInContext */); + } + function inDecoratorContext() { + return inContext(131072 /* DecoratorContext */); + } + function inAwaitContext() { + return inContext(262144 /* AwaitContext */); + } + function parseErrorAtCurrentToken(message, arg0) { + var start = scanner.getTokenPos(); + var length = scanner.getTextPos() - start; + parseErrorAtPosition(start, length, message, arg0); + } + function parseErrorAtPosition(start, length, message, arg0) { + // Don't report another error if it would just be at the same position as the last error. + var lastError = ts.lastOrUndefined(parseDiagnostics); + if (!lastError || start !== lastError.start) { + parseDiagnostics.push(ts.createFileDiagnostic(sourceFile, start, length, message, arg0)); + } + // Mark that we've encountered an error. We'll set an appropriate bit on the next + // node we finish so that it can't be reused incrementally. + parseErrorBeforeNextFinishedNode = true; + } + function scanError(message, length) { + var pos = scanner.getTextPos(); + parseErrorAtPosition(pos, length || 0, message); + } + function getNodePos() { + return scanner.getStartPos(); + } + function getNodeEnd() { + return scanner.getStartPos(); + } + // Use this function to access the current token instead of reading the currentToken + // variable. Since function results aren't narrowed in control flow analysis, this ensures + // that the type checker doesn't make wrong assumptions about the type of the current + // token (e.g. a call to nextToken() changes the current token but the checker doesn't + // reason about this side effect). Mainstream VMs inline simple functions like this, so + // there is no performance penalty. + function token() { + return currentToken; + } + function nextToken() { + return currentToken = scanner.scan(); + } + function reScanGreaterToken() { + return currentToken = scanner.reScanGreaterToken(); + } + function reScanSlashToken() { + return currentToken = scanner.reScanSlashToken(); + } + function reScanTemplateToken() { + return currentToken = scanner.reScanTemplateToken(); + } + function scanJsxIdentifier() { + return currentToken = scanner.scanJsxIdentifier(); + } + function scanJsxText() { + return currentToken = scanner.scanJsxToken(); + } + function scanJsxAttributeValue() { + return currentToken = scanner.scanJsxAttributeValue(); + } + function speculationHelper(callback, isLookAhead) { + // Keep track of the state we'll need to rollback to if lookahead fails (or if the + // caller asked us to always reset our state). + var saveToken = currentToken; + var saveParseDiagnosticsLength = parseDiagnostics.length; + var saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode; + // Note: it is not actually necessary to save/restore the context flags here. That's + // because the saving/restoring of these flags happens naturally through the recursive + // descent nature of our parser. However, we still store this here just so we can + // assert that invariant holds. + var saveContextFlags = contextFlags; + // If we're only looking ahead, then tell the scanner to only lookahead as well. + // Otherwise, if we're actually speculatively parsing, then tell the scanner to do the + // same. + var result = isLookAhead + ? scanner.lookAhead(callback) + : scanner.tryScan(callback); + ts.Debug.assert(saveContextFlags === contextFlags); + // If our callback returned something 'falsy' or we're just looking ahead, + // then unconditionally restore us to where we were. + if (!result || isLookAhead) { + currentToken = saveToken; + parseDiagnostics.length = saveParseDiagnosticsLength; + parseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode; + } + return result; + } + /** Invokes the provided callback then unconditionally restores the parser to the state it + * was in immediately prior to invoking the callback. The result of invoking the callback + * is returned from this function. + */ + function lookAhead(callback) { + return speculationHelper(callback, /*isLookAhead*/ true); + } + /** Invokes the provided callback. If the callback returns something falsy, then it restores + * the parser to the state it was in immediately prior to invoking the callback. If the + * callback returns something truthy, then the parser state is not rolled back. The result + * of invoking the callback is returned from this function. + */ + function tryParse(callback) { + return speculationHelper(callback, /*isLookAhead*/ false); + } + // Ignore strict mode flag because we will report an error in type checker instead. + function isIdentifier() { + if (token() === 69 /* Identifier */) { + return true; + } + // If we have a 'yield' keyword, and we're in the [yield] context, then 'yield' is + // considered a keyword and is not an identifier. + if (token() === 114 /* YieldKeyword */ && inYieldContext()) { + return false; + } + // If we have a 'await' keyword, and we're in the [Await] context, then 'await' is + // considered a keyword and is not an identifier. + if (token() === 119 /* AwaitKeyword */ && inAwaitContext()) { + return false; + } + return token() > 105 /* LastReservedWord */; + } + function parseExpected(kind, diagnosticMessage, shouldAdvance) { + if (shouldAdvance === void 0) { shouldAdvance = true; } + if (token() === kind) { + if (shouldAdvance) { + nextToken(); + } + return true; + } + // Report specific message if provided with one. Otherwise, report generic fallback message. + if (diagnosticMessage) { + parseErrorAtCurrentToken(diagnosticMessage); + } + else { + parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(kind)); + } + return false; + } + function parseOptional(t) { + if (token() === t) { + nextToken(); + return true; + } + return false; + } + function parseOptionalToken(t) { + if (token() === t) { + return parseTokenNode(); + } + return undefined; + } + function parseExpectedToken(t, reportAtCurrentPosition, diagnosticMessage, arg0) { + return parseOptionalToken(t) || + createMissingNode(t, reportAtCurrentPosition, diagnosticMessage, arg0); + } + function parseTokenNode() { + var node = createNode(token()); + nextToken(); + return finishNode(node); + } + function canParseSemicolon() { + // If there's a real semicolon, then we can always parse it out. + if (token() === 23 /* SemicolonToken */) { + return true; + } + // We can parse out an optional semicolon in ASI cases in the following cases. + return token() === 16 /* CloseBraceToken */ || token() === 1 /* EndOfFileToken */ || scanner.hasPrecedingLineBreak(); + } + function parseSemicolon() { + if (canParseSemicolon()) { + if (token() === 23 /* SemicolonToken */) { + // consume the semicolon if it was explicitly provided. + nextToken(); + } + return true; + } + else { + return parseExpected(23 /* SemicolonToken */); + } + } + // note: this function creates only node + function createNode(kind, pos) { + nodeCount++; + if (!(pos >= 0)) { + pos = scanner.getStartPos(); + } + return kind >= 139 /* FirstNode */ ? new NodeConstructor(kind, pos, pos) : + kind === 69 /* Identifier */ ? new IdentifierConstructor(kind, pos, pos) : + new TokenConstructor(kind, pos, pos); + } + function createNodeArray(elements, pos) { + var array = (elements || []); + if (!(pos >= 0)) { + pos = getNodePos(); + } + array.pos = pos; + array.end = pos; + return array; + } + function finishNode(node, end) { + node.end = end === undefined ? scanner.getStartPos() : end; + if (contextFlags) { + node.flags |= contextFlags; + } + // Keep track on the node if we encountered an error while parsing it. If we did, then + // we cannot reuse the node incrementally. Once we've marked this node, clear out the + // flag so that we don't mark any subsequent nodes. + if (parseErrorBeforeNextFinishedNode) { + parseErrorBeforeNextFinishedNode = false; + node.flags |= 524288 /* ThisNodeHasError */; + } + return node; + } + function createMissingNode(kind, reportAtCurrentPosition, diagnosticMessage, arg0) { + if (reportAtCurrentPosition) { + parseErrorAtPosition(scanner.getStartPos(), 0, diagnosticMessage, arg0); + } + else { + parseErrorAtCurrentToken(diagnosticMessage, arg0); + } + var result = createNode(kind, scanner.getStartPos()); + result.text = ""; + return finishNode(result); + } + function internIdentifier(text) { + text = ts.escapeIdentifier(text); + return identifiers[text] || (identifiers[text] = text); + } + // An identifier that starts with two underscores has an extra underscore character prepended to it to avoid issues + // with magic property names like '__proto__'. The 'identifiers' object is used to share a single string instance for + // each identifier in order to reduce memory consumption. + function createIdentifier(isIdentifier, diagnosticMessage) { + identifierCount++; + if (isIdentifier) { + var node = createNode(69 /* Identifier */); + // Store original token kind if it is not just an Identifier so we can report appropriate error later in type checker + if (token() !== 69 /* Identifier */) { + node.originalKeywordKind = token(); + } + node.text = internIdentifier(scanner.getTokenValue()); + nextToken(); + return finishNode(node); + } + return createMissingNode(69 /* Identifier */, /*reportAtCurrentPosition*/ false, diagnosticMessage || ts.Diagnostics.Identifier_expected); + } + function parseIdentifier(diagnosticMessage) { + return createIdentifier(isIdentifier(), diagnosticMessage); + } + function parseIdentifierName() { + return createIdentifier(ts.tokenIsIdentifierOrKeyword(token())); + } + function isLiteralPropertyName() { + return ts.tokenIsIdentifierOrKeyword(token()) || + token() === 9 /* StringLiteral */ || + token() === 8 /* NumericLiteral */; + } + function parsePropertyNameWorker(allowComputedPropertyNames) { + if (token() === 9 /* StringLiteral */ || token() === 8 /* NumericLiteral */) { + return parseLiteralNode(/*internName*/ true); + } + if (allowComputedPropertyNames && token() === 19 /* OpenBracketToken */) { + return parseComputedPropertyName(); + } + return parseIdentifierName(); + } + function parsePropertyName() { + return parsePropertyNameWorker(/*allowComputedPropertyNames*/ true); + } + function parseSimplePropertyName() { + return parsePropertyNameWorker(/*allowComputedPropertyNames*/ false); + } + function isSimplePropertyName() { + return token() === 9 /* StringLiteral */ || token() === 8 /* NumericLiteral */ || ts.tokenIsIdentifierOrKeyword(token()); + } + function parseComputedPropertyName() { + // PropertyName [Yield]: + // LiteralPropertyName + // ComputedPropertyName[?Yield] + var node = createNode(140 /* ComputedPropertyName */); + parseExpected(19 /* OpenBracketToken */); + // We parse any expression (including a comma expression). But the grammar + // says that only an assignment expression is allowed, so the grammar checker + // will error if it sees a comma expression. + node.expression = allowInAnd(parseExpression); + parseExpected(20 /* CloseBracketToken */); + return finishNode(node); + } + function parseContextualModifier(t) { + return token() === t && tryParse(nextTokenCanFollowModifier); + } + function nextTokenIsOnSameLineAndCanFollowModifier() { + nextToken(); + if (scanner.hasPrecedingLineBreak()) { + return false; + } + return canFollowModifier(); + } + function nextTokenCanFollowModifier() { + if (token() === 74 /* ConstKeyword */) { + // 'const' is only a modifier if followed by 'enum'. + return nextToken() === 81 /* EnumKeyword */; + } + if (token() === 82 /* ExportKeyword */) { + nextToken(); + if (token() === 77 /* DefaultKeyword */) { + return lookAhead(nextTokenIsClassOrFunctionOrAsync); + } + return token() !== 37 /* AsteriskToken */ && token() !== 116 /* AsKeyword */ && token() !== 15 /* OpenBraceToken */ && canFollowModifier(); + } + if (token() === 77 /* DefaultKeyword */) { + return nextTokenIsClassOrFunctionOrAsync(); + } + if (token() === 113 /* StaticKeyword */) { + nextToken(); + return canFollowModifier(); + } + return nextTokenIsOnSameLineAndCanFollowModifier(); + } + function parseAnyContextualModifier() { + return ts.isModifierKind(token()) && tryParse(nextTokenCanFollowModifier); + } + function canFollowModifier() { + return token() === 19 /* OpenBracketToken */ + || token() === 15 /* OpenBraceToken */ + || token() === 37 /* AsteriskToken */ + || token() === 22 /* DotDotDotToken */ + || isLiteralPropertyName(); + } + function nextTokenIsClassOrFunctionOrAsync() { + nextToken(); + return token() === 73 /* ClassKeyword */ || token() === 87 /* FunctionKeyword */ || + (token() === 118 /* AsyncKeyword */ && lookAhead(nextTokenIsFunctionKeywordOnSameLine)); + } + // True if positioned at the start of a list element + function isListElement(parsingContext, inErrorRecovery) { + var node = currentNode(parsingContext); + if (node) { + return true; + } + switch (parsingContext) { + case 0 /* SourceElements */: + case 1 /* BlockStatements */: + case 3 /* SwitchClauseStatements */: + // If we're in error recovery, then we don't want to treat ';' as an empty statement. + // The problem is that ';' can show up in far too many contexts, and if we see one + // and assume it's a statement, then we may bail out inappropriately from whatever + // we're parsing. For example, if we have a semicolon in the middle of a class, then + // we really don't want to assume the class is over and we're on a statement in the + // outer module. We just want to consume and move on. + return !(token() === 23 /* SemicolonToken */ && inErrorRecovery) && isStartOfStatement(); + case 2 /* SwitchClauses */: + return token() === 71 /* CaseKeyword */ || token() === 77 /* DefaultKeyword */; + case 4 /* TypeMembers */: + return lookAhead(isTypeMemberStart); + case 5 /* ClassMembers */: + // We allow semicolons as class elements (as specified by ES6) as long as we're + // not in error recovery. If we're in error recovery, we don't want an errant + // semicolon to be treated as a class member (since they're almost always used + // for statements. + return lookAhead(isClassMemberStart) || (token() === 23 /* SemicolonToken */ && !inErrorRecovery); + case 6 /* EnumMembers */: + // Include open bracket computed properties. This technically also lets in indexers, + // which would be a candidate for improved error reporting. + return token() === 19 /* OpenBracketToken */ || isLiteralPropertyName(); + case 12 /* ObjectLiteralMembers */: + return token() === 19 /* OpenBracketToken */ || token() === 37 /* AsteriskToken */ || isLiteralPropertyName(); + case 9 /* ObjectBindingElements */: + return token() === 19 /* OpenBracketToken */ || isLiteralPropertyName(); + case 7 /* HeritageClauseElement */: + // If we see { } then only consume it as an expression if it is followed by , or { + // That way we won't consume the body of a class in its heritage clause. + if (token() === 15 /* OpenBraceToken */) { + return lookAhead(isValidHeritageClauseObjectLiteral); + } + if (!inErrorRecovery) { + return isStartOfLeftHandSideExpression() && !isHeritageClauseExtendsOrImplementsKeyword(); + } + else { + // If we're in error recovery we tighten up what we're willing to match. + // That way we don't treat something like "this" as a valid heritage clause + // element during recovery. + return isIdentifier() && !isHeritageClauseExtendsOrImplementsKeyword(); + } + case 8 /* VariableDeclarations */: + return isIdentifierOrPattern(); + case 10 /* ArrayBindingElements */: + return token() === 24 /* CommaToken */ || token() === 22 /* DotDotDotToken */ || isIdentifierOrPattern(); + case 17 /* TypeParameters */: + return isIdentifier(); + case 11 /* ArgumentExpressions */: + case 15 /* ArrayLiteralMembers */: + return token() === 24 /* CommaToken */ || token() === 22 /* DotDotDotToken */ || isStartOfExpression(); + case 16 /* Parameters */: + return isStartOfParameter(); + case 18 /* TypeArguments */: + case 19 /* TupleElementTypes */: + return token() === 24 /* CommaToken */ || isStartOfType(); + case 20 /* HeritageClauses */: + return isHeritageClause(); + case 21 /* ImportOrExportSpecifiers */: + return ts.tokenIsIdentifierOrKeyword(token()); + case 13 /* JsxAttributes */: + return ts.tokenIsIdentifierOrKeyword(token()) || token() === 15 /* OpenBraceToken */; + case 14 /* JsxChildren */: + return true; + case 22 /* JSDocFunctionParameters */: + case 23 /* JSDocTypeArguments */: + case 25 /* JSDocTupleTypes */: + return JSDocParser.isJSDocType(); + case 24 /* JSDocRecordMembers */: + return isSimplePropertyName(); + } + ts.Debug.fail("Non-exhaustive case in 'isListElement'."); + } + function isValidHeritageClauseObjectLiteral() { + ts.Debug.assert(token() === 15 /* OpenBraceToken */); + if (nextToken() === 16 /* CloseBraceToken */) { + // if we see "extends {}" then only treat the {} as what we're extending (and not + // the class body) if we have: + // + // extends {} { + // extends {}, + // extends {} extends + // extends {} implements + var next = nextToken(); + return next === 24 /* CommaToken */ || next === 15 /* OpenBraceToken */ || next === 83 /* ExtendsKeyword */ || next === 106 /* ImplementsKeyword */; + } + return true; + } + function nextTokenIsIdentifier() { + nextToken(); + return isIdentifier(); + } + function nextTokenIsIdentifierOrKeyword() { + nextToken(); + return ts.tokenIsIdentifierOrKeyword(token()); + } + function isHeritageClauseExtendsOrImplementsKeyword() { + if (token() === 106 /* ImplementsKeyword */ || + token() === 83 /* ExtendsKeyword */) { + return lookAhead(nextTokenIsStartOfExpression); + } + return false; + } + function nextTokenIsStartOfExpression() { + nextToken(); + return isStartOfExpression(); + } + // True if positioned at a list terminator + function isListTerminator(kind) { + if (token() === 1 /* EndOfFileToken */) { + // Being at the end of the file ends all lists. + return true; + } + switch (kind) { + case 1 /* BlockStatements */: + case 2 /* SwitchClauses */: + case 4 /* TypeMembers */: + case 5 /* ClassMembers */: + case 6 /* EnumMembers */: + case 12 /* ObjectLiteralMembers */: + case 9 /* ObjectBindingElements */: + case 21 /* ImportOrExportSpecifiers */: + return token() === 16 /* CloseBraceToken */; + case 3 /* SwitchClauseStatements */: + return token() === 16 /* CloseBraceToken */ || token() === 71 /* CaseKeyword */ || token() === 77 /* DefaultKeyword */; + case 7 /* HeritageClauseElement */: + return token() === 15 /* OpenBraceToken */ || token() === 83 /* ExtendsKeyword */ || token() === 106 /* ImplementsKeyword */; + case 8 /* VariableDeclarations */: + return isVariableDeclaratorListTerminator(); + case 17 /* TypeParameters */: + // Tokens other than '>' are here for better error recovery + return token() === 27 /* GreaterThanToken */ || token() === 17 /* OpenParenToken */ || token() === 15 /* OpenBraceToken */ || token() === 83 /* ExtendsKeyword */ || token() === 106 /* ImplementsKeyword */; + case 11 /* ArgumentExpressions */: + // Tokens other than ')' are here for better error recovery + return token() === 18 /* CloseParenToken */ || token() === 23 /* SemicolonToken */; + case 15 /* ArrayLiteralMembers */: + case 19 /* TupleElementTypes */: + case 10 /* ArrayBindingElements */: + return token() === 20 /* CloseBracketToken */; + case 16 /* Parameters */: + // Tokens other than ')' and ']' (the latter for index signatures) are here for better error recovery + return token() === 18 /* CloseParenToken */ || token() === 20 /* CloseBracketToken */ /*|| token === SyntaxKind.OpenBraceToken*/; + case 18 /* TypeArguments */: + // Tokens other than '>' are here for better error recovery + return token() === 27 /* GreaterThanToken */ || token() === 17 /* OpenParenToken */; + case 20 /* HeritageClauses */: + return token() === 15 /* OpenBraceToken */ || token() === 16 /* CloseBraceToken */; + case 13 /* JsxAttributes */: + return token() === 27 /* GreaterThanToken */ || token() === 39 /* SlashToken */; + case 14 /* JsxChildren */: + return token() === 25 /* LessThanToken */ && lookAhead(nextTokenIsSlash); + case 22 /* JSDocFunctionParameters */: + return token() === 18 /* CloseParenToken */ || token() === 54 /* ColonToken */ || token() === 16 /* CloseBraceToken */; + case 23 /* JSDocTypeArguments */: + return token() === 27 /* GreaterThanToken */ || token() === 16 /* CloseBraceToken */; + case 25 /* JSDocTupleTypes */: + return token() === 20 /* CloseBracketToken */ || token() === 16 /* CloseBraceToken */; + case 24 /* JSDocRecordMembers */: + return token() === 16 /* CloseBraceToken */; + } + } + function isVariableDeclaratorListTerminator() { + // If we can consume a semicolon (either explicitly, or with ASI), then consider us done + // with parsing the list of variable declarators. + if (canParseSemicolon()) { + return true; + } + // in the case where we're parsing the variable declarator of a 'for-in' statement, we + // are done if we see an 'in' keyword in front of us. Same with for-of + if (isInOrOfKeyword(token())) { + return true; + } + // ERROR RECOVERY TWEAK: + // For better error recovery, if we see an '=>' then we just stop immediately. We've got an + // arrow function here and it's going to be very unlikely that we'll resynchronize and get + // another variable declaration. + if (token() === 34 /* EqualsGreaterThanToken */) { + return true; + } + // Keep trying to parse out variable declarators. + return false; + } + // True if positioned at element or terminator of the current list or any enclosing list + function isInSomeParsingContext() { + for (var kind = 0; kind < 26 /* Count */; kind++) { + if (parsingContext & (1 << kind)) { + if (isListElement(kind, /*inErrorRecovery*/ true) || isListTerminator(kind)) { + return true; + } + } + } + return false; + } + // Parses a list of elements + function parseList(kind, parseElement) { + var saveParsingContext = parsingContext; + parsingContext |= 1 << kind; + var result = createNodeArray(); + while (!isListTerminator(kind)) { + if (isListElement(kind, /*inErrorRecovery*/ false)) { + var element = parseListElement(kind, parseElement); + result.push(element); + continue; + } + if (abortParsingListOrMoveToNextToken(kind)) { + break; + } + } + result.end = getNodeEnd(); + parsingContext = saveParsingContext; + return result; + } + function parseListElement(parsingContext, parseElement) { + var node = currentNode(parsingContext); + if (node) { + return consumeNode(node); + } + return parseElement(); + } + function currentNode(parsingContext) { + // If there is an outstanding parse error that we've encountered, but not attached to + // some node, then we cannot get a node from the old source tree. This is because we + // want to mark the next node we encounter as being unusable. + // + // Note: This may be too conservative. Perhaps we could reuse the node and set the bit + // on it (or its leftmost child) as having the error. For now though, being conservative + // is nice and likely won't ever affect perf. + if (parseErrorBeforeNextFinishedNode) { + return undefined; + } + if (!syntaxCursor) { + // if we don't have a cursor, we could never return a node from the old tree. + return undefined; + } + var node = syntaxCursor.currentNode(scanner.getStartPos()); + // Can't reuse a missing node. + if (ts.nodeIsMissing(node)) { + return undefined; + } + // Can't reuse a node that intersected the change range. + if (node.intersectsChange) { + return undefined; + } + // Can't reuse a node that contains a parse error. This is necessary so that we + // produce the same set of errors again. + if (ts.containsParseError(node)) { + return undefined; + } + // We can only reuse a node if it was parsed under the same strict mode that we're + // currently in. i.e. if we originally parsed a node in non-strict mode, but then + // the user added 'using strict' at the top of the file, then we can't use that node + // again as the presence of strict mode may cause us to parse the tokens in the file + // differently. + // + // Note: we *can* reuse tokens when the strict mode changes. That's because tokens + // are unaffected by strict mode. It's just the parser will decide what to do with it + // differently depending on what mode it is in. + // + // This also applies to all our other context flags as well. + var nodeContextFlags = node.flags & 1540096 /* ContextFlags */; + if (nodeContextFlags !== contextFlags) { + return undefined; + } + // Ok, we have a node that looks like it could be reused. Now verify that it is valid + // in the current list parsing context that we're currently at. + if (!canReuseNode(node, parsingContext)) { + return undefined; + } + return node; + } + function consumeNode(node) { + // Move the scanner so it is after the node we just consumed. + scanner.setTextPos(node.end); + nextToken(); + return node; + } + function canReuseNode(node, parsingContext) { + switch (parsingContext) { + case 5 /* ClassMembers */: + return isReusableClassMember(node); + case 2 /* SwitchClauses */: + return isReusableSwitchClause(node); + case 0 /* SourceElements */: + case 1 /* BlockStatements */: + case 3 /* SwitchClauseStatements */: + return isReusableStatement(node); + case 6 /* EnumMembers */: + return isReusableEnumMember(node); + case 4 /* TypeMembers */: + return isReusableTypeMember(node); + case 8 /* VariableDeclarations */: + return isReusableVariableDeclaration(node); + case 16 /* Parameters */: + return isReusableParameter(node); + // Any other lists we do not care about reusing nodes in. But feel free to add if + // you can do so safely. Danger areas involve nodes that may involve speculative + // parsing. If speculative parsing is involved with the node, then the range the + // parser reached while looking ahead might be in the edited range (see the example + // in canReuseVariableDeclaratorNode for a good case of this). + case 20 /* HeritageClauses */: + // This would probably be safe to reuse. There is no speculative parsing with + // heritage clauses. + case 17 /* TypeParameters */: + // This would probably be safe to reuse. There is no speculative parsing with + // type parameters. Note that that's because type *parameters* only occur in + // unambiguous *type* contexts. While type *arguments* occur in very ambiguous + // *expression* contexts. + case 19 /* TupleElementTypes */: + // This would probably be safe to reuse. There is no speculative parsing with + // tuple types. + // Technically, type argument list types are probably safe to reuse. While + // speculative parsing is involved with them (since type argument lists are only + // produced from speculative parsing a < as a type argument list), we only have + // the types because speculative parsing succeeded. Thus, the lookahead never + // went past the end of the list and rewound. + case 18 /* TypeArguments */: + // Note: these are almost certainly not safe to ever reuse. Expressions commonly + // need a large amount of lookahead, and we should not reuse them as they may + // have actually intersected the edit. + case 11 /* ArgumentExpressions */: + // This is not safe to reuse for the same reason as the 'AssignmentExpression' + // cases. i.e. a property assignment may end with an expression, and thus might + // have lookahead far beyond it's old node. + case 12 /* ObjectLiteralMembers */: + // This is probably not safe to reuse. There can be speculative parsing with + // type names in a heritage clause. There can be generic names in the type + // name list, and there can be left hand side expressions (which can have type + // arguments.) + case 7 /* HeritageClauseElement */: + // Perhaps safe to reuse, but it's unlikely we'd see more than a dozen attributes + // on any given element. Same for children. + case 13 /* JsxAttributes */: + case 14 /* JsxChildren */: + } + return false; + } + function isReusableClassMember(node) { + if (node) { + switch (node.kind) { + case 148 /* Constructor */: + case 153 /* IndexSignature */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 145 /* PropertyDeclaration */: + case 198 /* SemicolonClassElement */: + return true; + case 147 /* MethodDeclaration */: + // Method declarations are not necessarily reusable. An object-literal + // may have a method calls "constructor(...)" and we must reparse that + // into an actual .ConstructorDeclaration. + var methodDeclaration = node; + var nameIsConstructor = methodDeclaration.name.kind === 69 /* Identifier */ && + methodDeclaration.name.originalKeywordKind === 121 /* ConstructorKeyword */; + return !nameIsConstructor; + } + } + return false; + } + function isReusableSwitchClause(node) { + if (node) { + switch (node.kind) { + case 249 /* CaseClause */: + case 250 /* DefaultClause */: + return true; + } + } + return false; + } + function isReusableStatement(node) { + if (node) { + switch (node.kind) { + case 220 /* FunctionDeclaration */: + case 200 /* VariableStatement */: + case 199 /* Block */: + case 203 /* IfStatement */: + case 202 /* ExpressionStatement */: + case 215 /* ThrowStatement */: + case 211 /* ReturnStatement */: + case 213 /* SwitchStatement */: + case 210 /* BreakStatement */: + case 209 /* ContinueStatement */: + case 207 /* ForInStatement */: + case 208 /* ForOfStatement */: + case 206 /* ForStatement */: + case 205 /* WhileStatement */: + case 212 /* WithStatement */: + case 201 /* EmptyStatement */: + case 216 /* TryStatement */: + case 214 /* LabeledStatement */: + case 204 /* DoStatement */: + case 217 /* DebuggerStatement */: + case 230 /* ImportDeclaration */: + case 229 /* ImportEqualsDeclaration */: + case 236 /* ExportDeclaration */: + case 235 /* ExportAssignment */: + case 225 /* ModuleDeclaration */: + case 221 /* ClassDeclaration */: + case 222 /* InterfaceDeclaration */: + case 224 /* EnumDeclaration */: + case 223 /* TypeAliasDeclaration */: + return true; + } + } + return false; + } + function isReusableEnumMember(node) { + return node.kind === 255 /* EnumMember */; + } + function isReusableTypeMember(node) { + if (node) { + switch (node.kind) { + case 152 /* ConstructSignature */: + case 146 /* MethodSignature */: + case 153 /* IndexSignature */: + case 144 /* PropertySignature */: + case 151 /* CallSignature */: + return true; + } + } + return false; + } + function isReusableVariableDeclaration(node) { + if (node.kind !== 218 /* VariableDeclaration */) { + return false; + } + // Very subtle incremental parsing bug. Consider the following code: + // + // let v = new List < A, B + // + // This is actually legal code. It's a list of variable declarators "v = new List() + // + // then we have a problem. "v = new List= 0) { + // Always preserve a trailing comma by marking it on the NodeArray + result.hasTrailingComma = true; + } + result.end = getNodeEnd(); + parsingContext = saveParsingContext; + return result; + } + function createMissingList() { + return createNodeArray(); + } + function parseBracketedList(kind, parseElement, open, close) { + if (parseExpected(open)) { + var result = parseDelimitedList(kind, parseElement); + parseExpected(close); + return result; + } + return createMissingList(); + } + // The allowReservedWords parameter controls whether reserved words are permitted after the first dot + function parseEntityName(allowReservedWords, diagnosticMessage) { + var entity = parseIdentifier(diagnosticMessage); + while (parseOptional(21 /* DotToken */)) { + var node = createNode(139 /* QualifiedName */, entity.pos); // !!! + node.left = entity; + node.right = parseRightSideOfDot(allowReservedWords); + entity = finishNode(node); + } + return entity; + } + function parseRightSideOfDot(allowIdentifierNames) { + // Technically a keyword is valid here as all identifiers and keywords are identifier names. + // However, often we'll encounter this in error situations when the identifier or keyword + // is actually starting another valid construct. + // + // So, we check for the following specific case: + // + // name. + // identifierOrKeyword identifierNameOrKeyword + // + // Note: the newlines are important here. For example, if that above code + // were rewritten into: + // + // name.identifierOrKeyword + // identifierNameOrKeyword + // + // Then we would consider it valid. That's because ASI would take effect and + // the code would be implicitly: "name.identifierOrKeyword; identifierNameOrKeyword". + // In the first case though, ASI will not take effect because there is not a + // line terminator after the identifier or keyword. + if (scanner.hasPrecedingLineBreak() && ts.tokenIsIdentifierOrKeyword(token())) { + var matchesPattern = lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine); + if (matchesPattern) { + // Report that we need an identifier. However, report it right after the dot, + // and not on the next token. This is because the next token might actually + // be an identifier and the error would be quite confusing. + return createMissingNode(69 /* Identifier */, /*reportAtCurrentPosition*/ true, ts.Diagnostics.Identifier_expected); + } + } + return allowIdentifierNames ? parseIdentifierName() : parseIdentifier(); + } + function parseTemplateExpression() { + var template = createNode(189 /* TemplateExpression */); + template.head = parseTemplateLiteralFragment(); + ts.Debug.assert(template.head.kind === 12 /* TemplateHead */, "Template head has wrong token kind"); + var templateSpans = createNodeArray(); + do { + templateSpans.push(parseTemplateSpan()); + } while (ts.lastOrUndefined(templateSpans).literal.kind === 13 /* TemplateMiddle */); + templateSpans.end = getNodeEnd(); + template.templateSpans = templateSpans; + return finishNode(template); + } + function parseTemplateSpan() { + var span = createNode(197 /* TemplateSpan */); + span.expression = allowInAnd(parseExpression); + var literal; + if (token() === 16 /* CloseBraceToken */) { + reScanTemplateToken(); + literal = parseTemplateLiteralFragment(); + } + else { + literal = parseExpectedToken(14 /* TemplateTail */, /*reportAtCurrentPosition*/ false, ts.Diagnostics._0_expected, ts.tokenToString(16 /* CloseBraceToken */)); + } + span.literal = literal; + return finishNode(span); + } + function parseLiteralNode(internName) { + return parseLiteralLikeNode(token(), internName); + } + function parseTemplateLiteralFragment() { + return parseLiteralLikeNode(token(), /*internName*/ false); + } + function parseLiteralLikeNode(kind, internName) { + var node = createNode(kind); + var text = scanner.getTokenValue(); + node.text = internName ? internIdentifier(text) : text; + if (scanner.hasExtendedUnicodeEscape()) { + node.hasExtendedUnicodeEscape = true; + } + if (scanner.isUnterminated()) { + node.isUnterminated = true; + } + var tokenPos = scanner.getTokenPos(); + nextToken(); + finishNode(node); + // Octal literals are not allowed in strict mode or ES5 + // Note that theoretically the following condition would hold true literals like 009, + // which is not octal.But because of how the scanner separates the tokens, we would + // never get a token like this. Instead, we would get 00 and 9 as two separate tokens. + // We also do not need to check for negatives because any prefix operator would be part of a + // parent unary expression. + if (node.kind === 8 /* NumericLiteral */ + && sourceText.charCodeAt(tokenPos) === 48 /* _0 */ + && ts.isOctalDigit(sourceText.charCodeAt(tokenPos + 1))) { + node.isOctalLiteral = true; + } + return node; + } + // TYPES + function parseTypeReference() { + var typeName = parseEntityName(/*allowReservedWords*/ false, ts.Diagnostics.Type_expected); + var node = createNode(155 /* TypeReference */, typeName.pos); + node.typeName = typeName; + if (!scanner.hasPrecedingLineBreak() && token() === 25 /* LessThanToken */) { + node.typeArguments = parseBracketedList(18 /* TypeArguments */, parseType, 25 /* LessThanToken */, 27 /* GreaterThanToken */); + } + return finishNode(node); + } + function parseThisTypePredicate(lhs) { + nextToken(); + var node = createNode(154 /* TypePredicate */, lhs.pos); + node.parameterName = lhs; + node.type = parseType(); + return finishNode(node); + } + function parseThisTypeNode() { + var node = createNode(165 /* ThisType */); + nextToken(); + return finishNode(node); + } + function parseTypeQuery() { + var node = createNode(158 /* TypeQuery */); + parseExpected(101 /* TypeOfKeyword */); + node.exprName = parseEntityName(/*allowReservedWords*/ true); + return finishNode(node); + } + function parseTypeParameter() { + var node = createNode(141 /* TypeParameter */); + node.name = parseIdentifier(); + if (parseOptional(83 /* ExtendsKeyword */)) { + // It's not uncommon for people to write improper constraints to a generic. If the + // user writes a constraint that is an expression and not an actual type, then parse + // it out as an expression (so we can recover well), but report that a type is needed + // instead. + if (isStartOfType() || !isStartOfExpression()) { + node.constraint = parseType(); + } + else { + // It was not a type, and it looked like an expression. Parse out an expression + // here so we recover well. Note: it is important that we call parseUnaryExpression + // and not parseExpression here. If the user has: + // + // + // + // We do *not* want to consume the > as we're consuming the expression for "". + node.expression = parseUnaryExpressionOrHigher(); + } + } + return finishNode(node); + } + function parseTypeParameters() { + if (token() === 25 /* LessThanToken */) { + return parseBracketedList(17 /* TypeParameters */, parseTypeParameter, 25 /* LessThanToken */, 27 /* GreaterThanToken */); + } + } + function parseParameterType() { + if (parseOptional(54 /* ColonToken */)) { + return parseType(); + } + return undefined; + } + function isStartOfParameter() { + return token() === 22 /* DotDotDotToken */ || isIdentifierOrPattern() || ts.isModifierKind(token()) || token() === 55 /* AtToken */ || token() === 97 /* ThisKeyword */; + } + function parseParameter() { + var node = createNode(142 /* Parameter */); + if (token() === 97 /* ThisKeyword */) { + node.name = createIdentifier(/*isIdentifier*/ true, undefined); + node.type = parseParameterType(); + return finishNode(node); + } + node.decorators = parseDecorators(); + node.modifiers = parseModifiers(); + node.dotDotDotToken = parseOptionalToken(22 /* DotDotDotToken */); + // FormalParameter [Yield,Await]: + // BindingElement[?Yield,?Await] + node.name = parseIdentifierOrPattern(); + if (ts.getFullWidth(node.name) === 0 && !ts.hasModifiers(node) && ts.isModifierKind(token())) { + // in cases like + // 'use strict' + // function foo(static) + // isParameter('static') === true, because of isModifier('static') + // however 'static' is not a legal identifier in a strict mode. + // so result of this function will be ParameterDeclaration (flags = 0, name = missing, type = undefined, initializer = undefined) + // and current token will not change => parsing of the enclosing parameter list will last till the end of time (or OOM) + // to avoid this we'll advance cursor to the next token. + nextToken(); + } + node.questionToken = parseOptionalToken(53 /* QuestionToken */); + node.type = parseParameterType(); + node.initializer = parseBindingElementInitializer(/*inParameter*/ true); + // Do not check for initializers in an ambient context for parameters. This is not + // a grammar error because the grammar allows arbitrary call signatures in + // an ambient context. + // It is actually not necessary for this to be an error at all. The reason is that + // function/constructor implementations are syntactically disallowed in ambient + // contexts. In addition, parameter initializers are semantically disallowed in + // overload signatures. So parameter initializers are transitively disallowed in + // ambient contexts. + return addJSDocComment(finishNode(node)); + } + function parseBindingElementInitializer(inParameter) { + return inParameter ? parseParameterInitializer() : parseNonParameterInitializer(); + } + function parseParameterInitializer() { + return parseInitializer(/*inParameter*/ true); + } + function fillSignature(returnToken, yieldContext, awaitContext, requireCompleteParameterList, signature) { + var returnTokenRequired = returnToken === 34 /* EqualsGreaterThanToken */; + signature.typeParameters = parseTypeParameters(); + signature.parameters = parseParameterList(yieldContext, awaitContext, requireCompleteParameterList); + if (returnTokenRequired) { + parseExpected(returnToken); + signature.type = parseTypeOrTypePredicate(); + } + else if (parseOptional(returnToken)) { + signature.type = parseTypeOrTypePredicate(); + } + } + function parseParameterList(yieldContext, awaitContext, requireCompleteParameterList) { + // FormalParameters [Yield,Await]: (modified) + // [empty] + // FormalParameterList[?Yield,Await] + // + // FormalParameter[Yield,Await]: (modified) + // BindingElement[?Yield,Await] + // + // BindingElement [Yield,Await]: (modified) + // SingleNameBinding[?Yield,?Await] + // BindingPattern[?Yield,?Await]Initializer [In, ?Yield,?Await] opt + // + // SingleNameBinding [Yield,Await]: + // BindingIdentifier[?Yield,?Await]Initializer [In, ?Yield,?Await] opt + if (parseExpected(17 /* OpenParenToken */)) { + var savedYieldContext = inYieldContext(); + var savedAwaitContext = inAwaitContext(); + setYieldContext(yieldContext); + setAwaitContext(awaitContext); + var result = parseDelimitedList(16 /* Parameters */, parseParameter); + setYieldContext(savedYieldContext); + setAwaitContext(savedAwaitContext); + if (!parseExpected(18 /* CloseParenToken */) && requireCompleteParameterList) { + // Caller insisted that we had to end with a ) We didn't. So just return + // undefined here. + return undefined; + } + return result; + } + // We didn't even have an open paren. If the caller requires a complete parameter list, + // we definitely can't provide that. However, if they're ok with an incomplete one, + // then just return an empty set of parameters. + return requireCompleteParameterList ? undefined : createMissingList(); + } + function parseTypeMemberSemicolon() { + // We allow type members to be separated by commas or (possibly ASI) semicolons. + // First check if it was a comma. If so, we're done with the member. + if (parseOptional(24 /* CommaToken */)) { + return; + } + // Didn't have a comma. We must have a (possible ASI) semicolon. + parseSemicolon(); + } + function parseSignatureMember(kind) { + var node = createNode(kind); + if (kind === 152 /* ConstructSignature */) { + parseExpected(92 /* NewKeyword */); + } + fillSignature(54 /* ColonToken */, /*yieldContext*/ false, /*awaitContext*/ false, /*requireCompleteParameterList*/ false, node); + parseTypeMemberSemicolon(); + return addJSDocComment(finishNode(node)); + } + function isIndexSignature() { + if (token() !== 19 /* OpenBracketToken */) { + return false; + } + return lookAhead(isUnambiguouslyIndexSignature); + } + function isUnambiguouslyIndexSignature() { + // The only allowed sequence is: + // + // [id: + // + // However, for error recovery, we also check the following cases: + // + // [... + // [id, + // [id?, + // [id?: + // [id?] + // [public id + // [private id + // [protected id + // [] + // + nextToken(); + if (token() === 22 /* DotDotDotToken */ || token() === 20 /* CloseBracketToken */) { + return true; + } + if (ts.isModifierKind(token())) { + nextToken(); + if (isIdentifier()) { + return true; + } + } + else if (!isIdentifier()) { + return false; + } + else { + // Skip the identifier + nextToken(); + } + // A colon signifies a well formed indexer + // A comma should be a badly formed indexer because comma expressions are not allowed + // in computed properties. + if (token() === 54 /* ColonToken */ || token() === 24 /* CommaToken */) { + return true; + } + // Question mark could be an indexer with an optional property, + // or it could be a conditional expression in a computed property. + if (token() !== 53 /* QuestionToken */) { + return false; + } + // If any of the following tokens are after the question mark, it cannot + // be a conditional expression, so treat it as an indexer. + nextToken(); + return token() === 54 /* ColonToken */ || token() === 24 /* CommaToken */ || token() === 20 /* CloseBracketToken */; + } + function parseIndexSignatureDeclaration(fullStart, decorators, modifiers) { + var node = createNode(153 /* IndexSignature */, fullStart); + node.decorators = decorators; + node.modifiers = modifiers; + node.parameters = parseBracketedList(16 /* Parameters */, parseParameter, 19 /* OpenBracketToken */, 20 /* CloseBracketToken */); + node.type = parseTypeAnnotation(); + parseTypeMemberSemicolon(); + return finishNode(node); + } + function parsePropertyOrMethodSignature(fullStart, modifiers) { + var name = parsePropertyName(); + var questionToken = parseOptionalToken(53 /* QuestionToken */); + if (token() === 17 /* OpenParenToken */ || token() === 25 /* LessThanToken */) { + var method = createNode(146 /* MethodSignature */, fullStart); + method.modifiers = modifiers; method.name = name; method.questionToken = questionToken; // Method signatures don't exist in expression contexts. So they have neither // [Yield] nor [Await] fillSignature(54 /* ColonToken */, /*yieldContext*/ false, /*awaitContext*/ false, /*requireCompleteParameterList*/ false, method); parseTypeMemberSemicolon(); - return finishNode(method); + return addJSDocComment(finishNode(method)); } else { var property = createNode(144 /* PropertySignature */, fullStart); - setModifiers(property, modifiers); + property.modifiers = modifiers; property.name = name; property.questionToken = questionToken; property.type = parseTypeAnnotation(); @@ -10271,7 +14786,7 @@ var ts; property.initializer = parseNonParameterInitializer(); } parseTypeMemberSemicolon(); - return finishNode(property); + return addJSDocComment(finishNode(property)); } } function isTypeMemberStart() { @@ -10465,8 +14980,7 @@ var ts; function parseUnionOrIntersectionType(kind, parseConstituentType, operator) { var type = parseConstituentType(); if (token() === operator) { - var types = [type]; - types.pos = type.pos; + var types = createNodeArray([type], type.pos); while (parseOptional(operator)) { types.push(parseConstituentType()); } @@ -10557,7 +15071,7 @@ var ts; function parseType() { // The rules about 'yield' only apply to actual code/expression contexts. They don't // apply to 'type' contexts. So we disable these parameters here before moving on. - return doOutsideOfContext(41943040 /* TypeExcludesFlags */, parseTypeWorker); + return doOutsideOfContext(327680 /* TypeExcludesFlags */, parseTypeWorker); } function parseTypeWorker() { if (isStartOfFunctionType()) { @@ -10788,7 +15302,7 @@ var ts; var node; if (asyncModifier) { node = createNode(180 /* ArrowFunction */, asyncModifier.pos); - setModifiers(node, asyncModifier); + node.modifiers = asyncModifier; } else { node = createNode(180 /* ArrowFunction */, identifier.pos); @@ -10796,12 +15310,11 @@ var ts; var parameter = createNode(142 /* Parameter */, identifier.pos); parameter.name = identifier; finishNode(parameter); - node.parameters = [parameter]; - node.parameters.pos = parameter.pos; + node.parameters = createNodeArray([parameter], parameter.pos); node.parameters.end = parameter.end; node.equalsGreaterThanToken = parseExpectedToken(34 /* EqualsGreaterThanToken */, /*reportAtCurrentPosition*/ false, ts.Diagnostics._0_expected, "=>"); node.body = parseArrowFunctionExpressionBody(/*isAsync*/ !!asyncModifier); - return finishNode(node); + return addJSDocComment(finishNode(node)); } function tryParseParenthesizedArrowFunctionExpression() { var triState = isParenthesizedArrowFunctionExpression(); @@ -10820,7 +15333,7 @@ var ts; // Didn't appear to actually be a parenthesized arrow function. Just bail out. return undefined; } - var isAsync = !!(arrowFunction.flags & 256 /* Async */); + var isAsync = !!(ts.getModifierFlags(arrowFunction) & 256 /* Async */); // If we have an arrow, then try to parse the body. Even if not, try to parse if we // have an opening brace, just in case we're in an error state. var lastToken = token(); @@ -10828,7 +15341,7 @@ var ts; arrowFunction.body = (lastToken === 34 /* EqualsGreaterThanToken */ || lastToken === 15 /* OpenBraceToken */) ? parseArrowFunctionExpressionBody(isAsync) : parseIdentifier(); - return finishNode(arrowFunction); + return addJSDocComment(finishNode(arrowFunction)); } // True -> We definitely expect a parenthesized arrow function here. // False -> There *cannot* be a parenthesized arrow function here. @@ -10977,8 +15490,8 @@ var ts; } function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity) { var node = createNode(180 /* ArrowFunction */); - setModifiers(node, parseModifiersForArrowFunction()); - var isAsync = !!(node.flags & 256 /* Async */); + node.modifiers = parseModifiersForArrowFunction(); + var isAsync = !!(ts.getModifierFlags(node) & 256 /* Async */); // Arrow functions are never generators. // // If we're speculatively parsing a signature for a parenthesized arrow function, then @@ -11546,8 +16059,7 @@ var ts; ts.Debug.fail("Unknown JSX child kind " + token()); } function parseJsxChildren(openingTagName) { - var result = []; - result.pos = scanner.getStartPos(); + var result = createNodeArray(); var saveParsingContext = parsingContext; parsingContext |= 1 << 14 /* JsxChildren */; while (true) { @@ -11635,8 +16147,8 @@ var ts; scanJsxIdentifier(); var node = createNode(246 /* JsxAttribute */); node.name = parseIdentifierName(); - if (parseOptional(56 /* EqualsToken */)) { - switch (token()) { + if (token() === 56 /* EqualsToken */) { + switch (scanJsxAttributeValue()) { case 9 /* StringLiteral */: node.initializer = parseLiteralNode(); break; @@ -11884,7 +16396,7 @@ var ts; } function tryParseAccessorDeclaration(fullStart, decorators, modifiers) { if (parseContextualModifier(123 /* GetKeyword */)) { - return addJSDocComment(parseAccessorDeclaration(149 /* GetAccessor */, fullStart, decorators, modifiers)); + return parseAccessorDeclaration(149 /* GetAccessor */, fullStart, decorators, modifiers); } else if (parseContextualModifier(131 /* SetKeyword */)) { return parseAccessorDeclaration(150 /* SetAccessor */, fullStart, decorators, modifiers); @@ -11955,11 +16467,11 @@ var ts; setDecoratorContext(/*val*/ false); } var node = createNode(179 /* FunctionExpression */); - setModifiers(node, parseModifiers()); + node.modifiers = parseModifiers(); parseExpected(87 /* FunctionKeyword */); node.asteriskToken = parseOptionalToken(37 /* AsteriskToken */); var isGenerator = !!node.asteriskToken; - var isAsync = !!(node.flags & 256 /* Async */); + var isAsync = !!(ts.getModifierFlags(node) & 256 /* Async */); node.name = isGenerator && isAsync ? doInYieldAndAwaitContext(parseOptionalIdentifier) : isGenerator ? doInYieldContext(parseOptionalIdentifier) : @@ -11989,6 +16501,9 @@ var ts; function parseBlock(ignoreMissingOpenBrace, diagnosticMessage) { var node = createNode(199 /* Block */); if (parseExpected(15 /* OpenBraceToken */, diagnosticMessage) || ignoreMissingOpenBrace) { + if (scanner.hasPrecedingLineBreak()) { + node.multiLine = true; + } node.statements = parseList(1 /* BlockStatements */, parseStatement); parseExpected(16 /* CloseBraceToken */); } @@ -12483,7 +16998,7 @@ var ts; var node = createMissingNode(239 /* MissingDeclaration */, /*reportAtCurrentPosition*/ true, ts.Diagnostics.Declaration_expected); node.pos = fullStart; node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; return finishNode(node); } } @@ -12566,10 +17081,10 @@ var ts; case 102 /* VarKeyword */: break; case 108 /* LetKeyword */: - node.flags |= 1024 /* Let */; + node.flags |= 1 /* Let */; break; case 74 /* ConstKeyword */: - node.flags |= 2048 /* Const */; + node.flags |= 2 /* Const */; break; default: ts.Debug.fail(); @@ -12601,7 +17116,7 @@ var ts; function parseVariableStatement(fullStart, decorators, modifiers) { var node = createNode(200 /* VariableStatement */, fullStart); node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; node.declarationList = parseVariableDeclarationList(/*inForStatementInitializer*/ false); parseSemicolon(); return addJSDocComment(finishNode(node)); @@ -12609,12 +17124,12 @@ var ts; function parseFunctionDeclaration(fullStart, decorators, modifiers) { var node = createNode(220 /* FunctionDeclaration */, fullStart); node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; parseExpected(87 /* FunctionKeyword */); node.asteriskToken = parseOptionalToken(37 /* AsteriskToken */); - node.name = node.flags & 512 /* Default */ ? parseOptionalIdentifier() : parseIdentifier(); + node.name = ts.hasModifier(node, 512 /* Default */) ? parseOptionalIdentifier() : parseIdentifier(); var isGenerator = !!node.asteriskToken; - var isAsync = !!(node.flags & 256 /* Async */); + var isAsync = ts.hasModifier(node, 256 /* Async */); fillSignature(54 /* ColonToken */, /*yieldContext*/ isGenerator, /*awaitContext*/ isAsync, /*requireCompleteParameterList*/ false, node); node.body = parseFunctionBlockOrSemicolon(isGenerator, isAsync, ts.Diagnostics.or_expected); return addJSDocComment(finishNode(node)); @@ -12622,7 +17137,7 @@ var ts; function parseConstructorDeclaration(pos, decorators, modifiers) { var node = createNode(148 /* Constructor */, pos); node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; parseExpected(121 /* ConstructorKeyword */); fillSignature(54 /* ColonToken */, /*yieldContext*/ false, /*awaitContext*/ false, /*requireCompleteParameterList*/ false, node); node.body = parseFunctionBlockOrSemicolon(/*isGenerator*/ false, /*isAsync*/ false, ts.Diagnostics.or_expected); @@ -12631,12 +17146,12 @@ var ts; function parseMethodDeclaration(fullStart, decorators, modifiers, asteriskToken, name, questionToken, diagnosticMessage) { var method = createNode(147 /* MethodDeclaration */, fullStart); method.decorators = decorators; - setModifiers(method, modifiers); + method.modifiers = modifiers; method.asteriskToken = asteriskToken; method.name = name; method.questionToken = questionToken; var isGenerator = !!asteriskToken; - var isAsync = !!(method.flags & 256 /* Async */); + var isAsync = ts.hasModifier(method, 256 /* Async */); fillSignature(54 /* ColonToken */, /*yieldContext*/ isGenerator, /*awaitContext*/ isAsync, /*requireCompleteParameterList*/ false, method); method.body = parseFunctionBlockOrSemicolon(isGenerator, isAsync, diagnosticMessage); return addJSDocComment(finishNode(method)); @@ -12644,7 +17159,7 @@ var ts; function parsePropertyDeclaration(fullStart, decorators, modifiers, name, questionToken) { var property = createNode(145 /* PropertyDeclaration */, fullStart); property.decorators = decorators; - setModifiers(property, modifiers); + property.modifiers = modifiers; property.name = name; property.questionToken = questionToken; property.type = parseTypeAnnotation(); @@ -12657,11 +17172,11 @@ var ts; // AccessibilityModifier_opt static_opt PropertyName TypeAnnotation_opt Initializer_opt[In, ?Yield]; // // The checker may still error in the static case to explicitly disallow the yield expression. - property.initializer = modifiers && modifiers.flags & 32 /* Static */ + property.initializer = ts.hasModifier(property, 32 /* Static */) ? allowInAnd(parseNonParameterInitializer) - : doOutsideOfContext(8388608 /* YieldContext */ | 4194304 /* DisallowInContext */, parseNonParameterInitializer); + : doOutsideOfContext(65536 /* YieldContext */ | 32768 /* DisallowInContext */, parseNonParameterInitializer); parseSemicolon(); - return finishNode(property); + return addJSDocComment(finishNode(property)); } function parsePropertyOrMethodDeclaration(fullStart, decorators, modifiers) { var asteriskToken = parseOptionalToken(37 /* AsteriskToken */); @@ -12682,11 +17197,11 @@ var ts; function parseAccessorDeclaration(kind, fullStart, decorators, modifiers) { var node = createNode(kind, fullStart); node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; node.name = parsePropertyName(); fillSignature(54 /* ColonToken */, /*yieldContext*/ false, /*awaitContext*/ false, /*requireCompleteParameterList*/ false, node); node.body = parseFunctionBlockOrSemicolon(/*isGenerator*/ false, /*isAsync*/ false); - return finishNode(node); + return addJSDocComment(finishNode(node)); } function isClassMemberModifier(idToken) { switch (idToken) { @@ -12765,13 +17280,15 @@ var ts; if (!parseOptional(55 /* AtToken */)) { break; } - if (!decorators) { - decorators = []; - decorators.pos = decoratorStart; - } var decorator = createNode(143 /* Decorator */, decoratorStart); decorator.expression = doInDecoratorContext(parseLeftHandSideExpressionOrHigher); - decorators.push(finishNode(decorator)); + finishNode(decorator); + if (!decorators) { + decorators = createNodeArray([decorator], decoratorStart); + } + else { + decorators.push(decorator); + } } if (decorators) { decorators.end = getNodeEnd(); @@ -12786,7 +17303,6 @@ var ts; * In such situations, 'permitInvalidConstAsModifier' should be set to true. */ function parseModifiers(permitInvalidConstAsModifier) { - var flags = 0; var modifiers; while (true) { var modifierStart = scanner.getStartPos(); @@ -12803,31 +17319,27 @@ var ts; break; } } + var modifier = finishNode(createNode(modifierKind, modifierStart)); if (!modifiers) { - modifiers = []; - modifiers.pos = modifierStart; + modifiers = createNodeArray([modifier], modifierStart); + } + else { + modifiers.push(modifier); } - flags |= ts.modifierToFlag(modifierKind); - modifiers.push(finishNode(createNode(modifierKind, modifierStart))); } if (modifiers) { - modifiers.flags = flags; modifiers.end = scanner.getStartPos(); } return modifiers; } function parseModifiersForArrowFunction() { - var flags = 0; var modifiers; if (token() === 118 /* AsyncKeyword */) { var modifierStart = scanner.getStartPos(); var modifierKind = token(); nextToken(); - modifiers = []; - modifiers.pos = modifierStart; - flags |= ts.modifierToFlag(modifierKind); - modifiers.push(finishNode(createNode(modifierKind, modifierStart))); - modifiers.flags = flags; + var modifier = finishNode(createNode(modifierKind, modifierStart)); + modifiers = createNodeArray([modifier], modifierStart); modifiers.end = scanner.getStartPos(); } return modifiers; @@ -12862,8 +17374,8 @@ var ts; } if (decorators || modifiers) { // treat this as a property declaration with a missing name. - var name_7 = createMissingNode(69 /* Identifier */, /*reportAtCurrentPosition*/ true, ts.Diagnostics.Declaration_expected); - return parsePropertyDeclaration(fullStart, decorators, modifiers, name_7, /*questionToken*/ undefined); + var name_10 = createMissingNode(69 /* Identifier */, /*reportAtCurrentPosition*/ true, ts.Diagnostics.Declaration_expected); + return parsePropertyDeclaration(fullStart, decorators, modifiers, name_10, /*questionToken*/ undefined); } // 'isClassMemberStart' should have hinted not to attempt parsing. ts.Debug.fail("Should not have attempted to parse class member declaration."); @@ -12880,7 +17392,7 @@ var ts; function parseClassDeclarationOrExpression(fullStart, decorators, modifiers, kind) { var node = createNode(kind, fullStart); node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; parseExpected(73 /* ClassKeyword */); node.name = parseNameOfClassDeclarationOrExpression(); node.typeParameters = parseTypeParameters(); @@ -12894,7 +17406,7 @@ var ts; else { node.members = createMissingList(); } - return finishNode(node); + return addJSDocComment(finishNode(node)); } function parseNameOfClassDeclarationOrExpression() { // implements is a future reserved word so @@ -12944,18 +17456,18 @@ var ts; function parseInterfaceDeclaration(fullStart, decorators, modifiers) { var node = createNode(222 /* InterfaceDeclaration */, fullStart); node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; parseExpected(107 /* InterfaceKeyword */); node.name = parseIdentifier(); node.typeParameters = parseTypeParameters(); node.heritageClauses = parseHeritageClauses(/*isClassHeritageClause*/ false); node.members = parseObjectTypeMembers(); - return finishNode(node); + return addJSDocComment(finishNode(node)); } function parseTypeAliasDeclaration(fullStart, decorators, modifiers) { var node = createNode(223 /* TypeAliasDeclaration */, fullStart); node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; parseExpected(134 /* TypeKeyword */); node.name = parseIdentifier(); node.typeParameters = parseTypeParameters(); @@ -12972,12 +17484,12 @@ var ts; var node = createNode(255 /* EnumMember */, scanner.getStartPos()); node.name = parsePropertyName(); node.initializer = allowInAnd(parseNonParameterInitializer); - return finishNode(node); + return addJSDocComment(finishNode(node)); } function parseEnumDeclaration(fullStart, decorators, modifiers) { var node = createNode(224 /* EnumDeclaration */, fullStart); node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; parseExpected(81 /* EnumKeyword */); node.name = parseIdentifier(); if (parseExpected(15 /* OpenBraceToken */)) { @@ -12987,7 +17499,7 @@ var ts; else { node.members = createMissingList(); } - return finishNode(node); + return addJSDocComment(finishNode(node)); } function parseModuleBlock() { var node = createNode(226 /* ModuleBlock */, scanner.getStartPos()); @@ -13004,24 +17516,24 @@ var ts; var node = createNode(225 /* ModuleDeclaration */, fullStart); // If we are parsing a dotted namespace name, we want to // propagate the 'Namespace' flag across the names if set. - var namespaceFlag = flags & 4096 /* Namespace */; + var namespaceFlag = flags & 16 /* Namespace */; node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; node.flags |= flags; node.name = parseIdentifier(); node.body = parseOptional(21 /* DotToken */) - ? parseModuleOrNamespaceDeclaration(getNodePos(), /*decorators*/ undefined, /*modifiers*/ undefined, 1 /* Export */ | namespaceFlag) + ? parseModuleOrNamespaceDeclaration(getNodePos(), /*decorators*/ undefined, /*modifiers*/ undefined, 4 /* NestedNamespace */ | namespaceFlag) : parseModuleBlock(); - return finishNode(node); + return addJSDocComment(finishNode(node)); } function parseAmbientExternalModuleDeclaration(fullStart, decorators, modifiers) { var node = createNode(225 /* ModuleDeclaration */, fullStart); node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; if (token() === 137 /* GlobalKeyword */) { // parse 'global' as name of global scope augmentation node.name = parseIdentifier(); - node.flags |= 131072 /* GlobalAugmentation */; + node.flags |= 512 /* GlobalAugmentation */; } else { node.name = parseLiteralNode(/*internName*/ true); @@ -13035,13 +17547,13 @@ var ts; return finishNode(node); } function parseModuleDeclaration(fullStart, decorators, modifiers) { - var flags = modifiers ? modifiers.flags : 0; + var flags = 0; if (token() === 137 /* GlobalKeyword */) { // global augmentation return parseAmbientExternalModuleDeclaration(fullStart, decorators, modifiers); } else if (parseOptional(126 /* NamespaceKeyword */)) { - flags |= 4096 /* Namespace */; + flags |= 16 /* Namespace */; } else { parseExpected(125 /* ModuleKeyword */); @@ -13083,18 +17595,18 @@ var ts; // import x = M.x; var importEqualsDeclaration = createNode(229 /* ImportEqualsDeclaration */, fullStart); importEqualsDeclaration.decorators = decorators; - setModifiers(importEqualsDeclaration, modifiers); + importEqualsDeclaration.modifiers = modifiers; importEqualsDeclaration.name = identifier; parseExpected(56 /* EqualsToken */); importEqualsDeclaration.moduleReference = parseModuleReference(); parseSemicolon(); - return finishNode(importEqualsDeclaration); + return addJSDocComment(finishNode(importEqualsDeclaration)); } } // Import statement var importDeclaration = createNode(230 /* ImportDeclaration */, fullStart); importDeclaration.decorators = decorators; - setModifiers(importDeclaration, modifiers); + importDeclaration.modifiers = modifiers; // ImportDeclaration: // import ImportClause from ModuleSpecifier ; // import ModuleSpecifier; @@ -13214,7 +17726,7 @@ var ts; function parseExportDeclaration(fullStart, decorators, modifiers) { var node = createNode(236 /* ExportDeclaration */, fullStart); node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; if (parseOptional(37 /* AsteriskToken */)) { parseExpected(136 /* FromKeyword */); node.moduleSpecifier = parseModuleSpecifier(); @@ -13235,7 +17747,7 @@ var ts; function parseExportAssignment(fullStart, decorators, modifiers) { var node = createNode(235 /* ExportAssignment */, fullStart); node.decorators = decorators; - setModifiers(node, modifiers); + node.modifiers = modifiers; if (parseOptional(56 /* EqualsToken */)) { node.isExportEquals = true; } @@ -13314,7 +17826,7 @@ var ts; } function setExternalModuleIndicator(sourceFile) { sourceFile.externalModuleIndicator = ts.forEach(sourceFile.statements, function (node) { - return node.flags & 1 /* Export */ + return ts.hasModifier(node, 1 /* Export */) || node.kind === 229 /* ImportEqualsDeclaration */ && node.moduleReference.kind === 240 /* ExternalModuleReference */ || node.kind === 230 /* ImportDeclaration */ || node.kind === 235 /* ExportAssignment */ @@ -13380,6 +17892,7 @@ var ts; JSDocParser.isJSDocType = isJSDocType; function parseJSDocTypeExpressionForTests(content, start, length) { initializeState("file.js", content, 2 /* Latest */, /*_syntaxCursor:*/ undefined, 1 /* JS */); + sourceFile = createSourceFile("file.js", 2 /* Latest */, 1 /* JS */); scanner.setText(content, start, length); currentToken = scanner.scan(); var jsDocTypeExpression = parseJSDocTypeExpression(); @@ -13566,19 +18079,7 @@ var ts; } function parseJSDocRecordType() { var result = createNode(265 /* JSDocRecordType */); - nextToken(); - result.members = parseDelimitedList(24 /* JSDocRecordMembers */, parseJSDocRecordMember); - checkForTrailingComma(result.members); - parseExpected(16 /* CloseBraceToken */); - return finishNode(result); - } - function parseJSDocRecordMember() { - var result = createNode(266 /* JSDocRecordMember */); - result.name = parseSimplePropertyName(); - if (token() === 54 /* ColonToken */) { - nextToken(); - result.type = parseJSDocType(); - } + result.literal = parseTypeLiteral(); return finishNode(result); } function parseJSDocNonNullableType() { @@ -13610,2929 +18111,4388 @@ var ts; } function parseJSDocTypeList(firstType) { ts.Debug.assert(!!firstType); - var types = []; - types.pos = firstType.pos; - types.push(firstType); + var types = createNodeArray([firstType], firstType.pos); while (parseOptional(47 /* BarToken */)) { types.push(parseJSDocType()); } - types.end = scanner.getStartPos(); - return types; - } - function parseJSDocAllType() { - var result = createNode(258 /* JSDocAllType */); - nextToken(); - return finishNode(result); - } - function parseJSDocLiteralType() { - var result = createNode(282 /* JSDocLiteralType */); - result.literal = parseLiteralTypeNode(); - return finishNode(result); - } - function parseJSDocUnknownOrNullableType() { - var pos = scanner.getStartPos(); - // skip the ? - nextToken(); - // Need to lookahead to decide if this is a nullable or unknown type. - // Here are cases where we'll pick the unknown type: - // - // Foo(?, - // { a: ? } - // Foo(?) - // Foo - // Foo(?= - // (?| - if (token() === 24 /* CommaToken */ || - token() === 16 /* CloseBraceToken */ || - token() === 18 /* CloseParenToken */ || - token() === 27 /* GreaterThanToken */ || - token() === 56 /* EqualsToken */ || - token() === 47 /* BarToken */) { - var result = createNode(259 /* JSDocUnknownType */, pos); + types.end = scanner.getStartPos(); + return types; + } + function parseJSDocAllType() { + var result = createNode(258 /* JSDocAllType */); + nextToken(); + return finishNode(result); + } + function parseJSDocLiteralType() { + var result = createNode(282 /* JSDocLiteralType */); + result.literal = parseLiteralTypeNode(); + return finishNode(result); + } + function parseJSDocUnknownOrNullableType() { + var pos = scanner.getStartPos(); + // skip the ? + nextToken(); + // Need to lookahead to decide if this is a nullable or unknown type. + // Here are cases where we'll pick the unknown type: + // + // Foo(?, + // { a: ? } + // Foo(?) + // Foo + // Foo(?= + // (?| + if (token() === 24 /* CommaToken */ || + token() === 16 /* CloseBraceToken */ || + token() === 18 /* CloseParenToken */ || + token() === 27 /* GreaterThanToken */ || + token() === 56 /* EqualsToken */ || + token() === 47 /* BarToken */) { + var result = createNode(259 /* JSDocUnknownType */, pos); + return finishNode(result); + } + else { + var result = createNode(263 /* JSDocNullableType */, pos); + result.type = parseJSDocType(); + return finishNode(result); + } + } + function parseIsolatedJSDocComment(content, start, length) { + initializeState("file.js", content, 2 /* Latest */, /*_syntaxCursor:*/ undefined, 1 /* JS */); + sourceFile = { languageVariant: 0 /* Standard */, text: content }; + var jsDoc = parseJSDocCommentWorker(start, length); + var diagnostics = parseDiagnostics; + clearState(); + return jsDoc ? { jsDoc: jsDoc, diagnostics: diagnostics } : undefined; + } + JSDocParser.parseIsolatedJSDocComment = parseIsolatedJSDocComment; + function parseJSDocComment(parent, start, length) { + var saveToken = currentToken; + var saveParseDiagnosticsLength = parseDiagnostics.length; + var saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode; + var comment = parseJSDocCommentWorker(start, length); + if (comment) { + comment.parent = parent; + } + currentToken = saveToken; + parseDiagnostics.length = saveParseDiagnosticsLength; + parseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode; + return comment; + } + JSDocParser.parseJSDocComment = parseJSDocComment; + var JSDocState; + (function (JSDocState) { + JSDocState[JSDocState["BeginningOfLine"] = 0] = "BeginningOfLine"; + JSDocState[JSDocState["SawAsterisk"] = 1] = "SawAsterisk"; + JSDocState[JSDocState["SavingComments"] = 2] = "SavingComments"; + })(JSDocState || (JSDocState = {})); + function parseJSDocCommentWorker(start, length) { + var content = sourceText; + start = start || 0; + var end = length === undefined ? content.length : start + length; + length = end - start; + ts.Debug.assert(start >= 0); + ts.Debug.assert(start <= end); + ts.Debug.assert(end <= content.length); + var tags; + var comments = []; + var result; + // Check for /** (JSDoc opening part) + if (!isJsDocStart(content, start)) { + return result; + } + // + 3 for leading /**, - 5 in total for /** */ + scanner.scanRange(start + 3, length - 5, function () { + // Initially we can parse out a tag. We also have seen a starting asterisk. + // This is so that /** * @type */ doesn't parse. + var advanceToken = true; + var state = 1 /* SawAsterisk */; + var margin = undefined; + // + 4 for leading '/** ' + var indent = start - Math.max(content.lastIndexOf("\n", start), 0) + 4; + function pushComment(text) { + if (!margin) { + margin = indent; + } + comments.push(text); + indent += text.length; + } + nextJSDocToken(); + while (token() === 5 /* WhitespaceTrivia */) { + nextJSDocToken(); + } + if (token() === 4 /* NewLineTrivia */) { + state = 0 /* BeginningOfLine */; + nextJSDocToken(); + } + while (token() !== 1 /* EndOfFileToken */) { + switch (token()) { + case 55 /* AtToken */: + if (state === 0 /* BeginningOfLine */ || state === 1 /* SawAsterisk */) { + removeTrailingNewlines(comments); + parseTag(indent); + // NOTE: According to usejsdoc.org, a tag goes to end of line, except the last tag. + // Real-world comments may break this rule, so "BeginningOfLine" will not be a real line beginning + // for malformed examples like `/** @param {string} x @returns {number} the length */` + state = 0 /* BeginningOfLine */; + advanceToken = false; + margin = undefined; + indent++; + } + else { + pushComment(scanner.getTokenText()); + } + break; + case 4 /* NewLineTrivia */: + comments.push(scanner.getTokenText()); + state = 0 /* BeginningOfLine */; + indent = 0; + break; + case 37 /* AsteriskToken */: + var asterisk = scanner.getTokenText(); + if (state === 1 /* SawAsterisk */) { + // If we've already seen an asterisk, then we can no longer parse a tag on this line + state = 2 /* SavingComments */; + pushComment(asterisk); + } + else { + // Ignore the first asterisk on a line + state = 1 /* SawAsterisk */; + indent += asterisk.length; + } + break; + case 69 /* Identifier */: + // Anything else is doc comment text. We just save it. Because it + // wasn't a tag, we can no longer parse a tag on this line until we hit the next + // line break. + pushComment(scanner.getTokenText()); + state = 2 /* SavingComments */; + break; + case 5 /* WhitespaceTrivia */: + // only collect whitespace if we're already saving comments or have just crossed the comment indent margin + var whitespace = scanner.getTokenText(); + if (state === 2 /* SavingComments */ || margin !== undefined && indent + whitespace.length > margin) { + comments.push(whitespace.slice(margin - indent - 1)); + } + indent += whitespace.length; + break; + case 1 /* EndOfFileToken */: + break; + default: + pushComment(scanner.getTokenText()); + break; + } + if (advanceToken) { + nextJSDocToken(); + } + else { + advanceToken = true; + } + } + removeLeadingNewlines(comments); + removeTrailingNewlines(comments); + result = createJSDocComment(); + }); + return result; + function removeLeadingNewlines(comments) { + while (comments.length && (comments[0] === "\n" || comments[0] === "\r")) { + comments.shift(); + } + } + function removeTrailingNewlines(comments) { + while (comments.length && (comments[comments.length - 1] === "\n" || comments[comments.length - 1] === "\r")) { + comments.pop(); + } + } + function isJsDocStart(content, start) { + return content.charCodeAt(start) === 47 /* slash */ && + content.charCodeAt(start + 1) === 42 /* asterisk */ && + content.charCodeAt(start + 2) === 42 /* asterisk */ && + content.charCodeAt(start + 3) !== 42 /* asterisk */; + } + function createJSDocComment() { + var result = createNode(273 /* JSDocComment */, start); + result.tags = tags; + result.comment = comments.length ? comments.join("") : undefined; + return finishNode(result, end); + } + function skipWhitespace() { + while (token() === 5 /* WhitespaceTrivia */ || token() === 4 /* NewLineTrivia */) { + nextJSDocToken(); + } + } + function parseTag(indent) { + ts.Debug.assert(token() === 55 /* AtToken */); + var atToken = createNode(55 /* AtToken */, scanner.getTokenPos()); + atToken.end = scanner.getTextPos(); + nextJSDocToken(); + var tagName = parseJSDocIdentifierName(); + skipWhitespace(); + if (!tagName) { + return; + } + var tag; + if (tagName) { + switch (tagName.text) { + case "param": + tag = parseParamTag(atToken, tagName); + break; + case "return": + case "returns": + tag = parseReturnTag(atToken, tagName); + break; + case "template": + tag = parseTemplateTag(atToken, tagName); + break; + case "type": + tag = parseTypeTag(atToken, tagName); + break; + case "typedef": + tag = parseTypedefTag(atToken, tagName); + break; + default: + tag = parseUnknownTag(atToken, tagName); + break; + } + } + else { + tag = parseUnknownTag(atToken, tagName); + } + if (!tag) { + // a badly malformed tag should not be added to the list of tags + return; + } + addTag(tag, parseTagComments(indent + tag.end - tag.pos)); + } + function parseTagComments(indent) { + var comments = []; + var state = 1 /* SawAsterisk */; + var margin; + function pushComment(text) { + if (!margin) { + margin = indent; + } + comments.push(text); + indent += text.length; + } + while (token() !== 55 /* AtToken */ && token() !== 1 /* EndOfFileToken */) { + switch (token()) { + case 4 /* NewLineTrivia */: + if (state >= 1 /* SawAsterisk */) { + state = 0 /* BeginningOfLine */; + comments.push(scanner.getTokenText()); + } + indent = 0; + break; + case 55 /* AtToken */: + // Done + break; + case 5 /* WhitespaceTrivia */: + if (state === 2 /* SavingComments */) { + pushComment(scanner.getTokenText()); + } + else { + var whitespace = scanner.getTokenText(); + // if the whitespace crosses the margin, take only the whitespace that passes the margin + if (margin !== undefined && indent + whitespace.length > margin) { + comments.push(whitespace.slice(margin - indent - 1)); + } + indent += whitespace.length; + } + break; + case 37 /* AsteriskToken */: + if (state === 0 /* BeginningOfLine */) { + // leading asterisks start recording on the *next* (non-whitespace) token + state = 1 /* SawAsterisk */; + indent += scanner.getTokenText().length; + break; + } + // FALLTHROUGH otherwise to record the * as a comment + default: + state = 2 /* SavingComments */; // leading identifiers start recording as well + pushComment(scanner.getTokenText()); + break; + } + if (token() === 55 /* AtToken */) { + // Done + break; + } + nextJSDocToken(); + } + removeLeadingNewlines(comments); + removeTrailingNewlines(comments); + return comments; + } + function parseUnknownTag(atToken, tagName) { + var result = createNode(274 /* JSDocTag */, atToken.pos); + result.atToken = atToken; + result.tagName = tagName; + return finishNode(result); + } + function addTag(tag, comments) { + tag.comment = comments.join(""); + if (!tags) { + tags = createNodeArray([tag], tag.pos); + } + else { + tags.push(tag); + } + tags.end = tag.end; + } + function tryParseTypeExpression() { + return tryParse(function () { + skipWhitespace(); + if (token() !== 15 /* OpenBraceToken */) { + return undefined; + } + return parseJSDocTypeExpression(); + }); + } + function parseParamTag(atToken, tagName) { + var typeExpression = tryParseTypeExpression(); + skipWhitespace(); + var name; + var isBracketed; + // Looking for something like '[foo]' or 'foo' + if (parseOptionalToken(19 /* OpenBracketToken */)) { + name = parseJSDocIdentifierName(); + skipWhitespace(); + isBracketed = true; + // May have an optional default, e.g. '[foo = 42]' + if (parseOptionalToken(56 /* EqualsToken */)) { + parseExpression(); + } + parseExpected(20 /* CloseBracketToken */); + } + else if (ts.tokenIsIdentifierOrKeyword(token())) { + name = parseJSDocIdentifierName(); + } + if (!name) { + parseErrorAtPosition(scanner.getStartPos(), 0, ts.Diagnostics.Identifier_expected); + return undefined; + } + var preName, postName; + if (typeExpression) { + postName = name; + } + else { + preName = name; + } + if (!typeExpression) { + typeExpression = tryParseTypeExpression(); + } + var result = createNode(275 /* JSDocParameterTag */, atToken.pos); + result.atToken = atToken; + result.tagName = tagName; + result.preParameterName = preName; + result.typeExpression = typeExpression; + result.postParameterName = postName; + result.parameterName = postName || preName; + result.isBracketed = isBracketed; + return finishNode(result); + } + function parseReturnTag(atToken, tagName) { + if (ts.forEach(tags, function (t) { return t.kind === 276 /* JSDocReturnTag */; })) { + parseErrorAtPosition(tagName.pos, scanner.getTokenPos() - tagName.pos, ts.Diagnostics._0_tag_already_specified, tagName.text); + } + var result = createNode(276 /* JSDocReturnTag */, atToken.pos); + result.atToken = atToken; + result.tagName = tagName; + result.typeExpression = tryParseTypeExpression(); return finishNode(result); } - else { - var result = createNode(263 /* JSDocNullableType */, pos); - result.type = parseJSDocType(); + function parseTypeTag(atToken, tagName) { + if (ts.forEach(tags, function (t) { return t.kind === 277 /* JSDocTypeTag */; })) { + parseErrorAtPosition(tagName.pos, scanner.getTokenPos() - tagName.pos, ts.Diagnostics._0_tag_already_specified, tagName.text); + } + var result = createNode(277 /* JSDocTypeTag */, atToken.pos); + result.atToken = atToken; + result.tagName = tagName; + result.typeExpression = tryParseTypeExpression(); return finishNode(result); } - } - function parseIsolatedJSDocComment(content, start, length) { - initializeState("file.js", content, 2 /* Latest */, /*_syntaxCursor:*/ undefined, 1 /* JS */); - sourceFile = { languageVariant: 0 /* Standard */, text: content }; - var jsDocComment = parseJSDocCommentWorker(start, length); - var diagnostics = parseDiagnostics; - clearState(); - return jsDocComment ? { jsDocComment: jsDocComment, diagnostics: diagnostics } : undefined; - } - JSDocParser.parseIsolatedJSDocComment = parseIsolatedJSDocComment; - function parseJSDocComment(parent, start, length) { - var saveToken = currentToken; - var saveParseDiagnosticsLength = parseDiagnostics.length; - var saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode; - var comment = parseJSDocCommentWorker(start, length); - if (comment) { - comment.parent = parent; + function parsePropertyTag(atToken, tagName) { + var typeExpression = tryParseTypeExpression(); + skipWhitespace(); + var name = parseJSDocIdentifierName(); + skipWhitespace(); + if (!name) { + parseErrorAtPosition(scanner.getStartPos(), /*length*/ 0, ts.Diagnostics.Identifier_expected); + return undefined; + } + var result = createNode(280 /* JSDocPropertyTag */, atToken.pos); + result.atToken = atToken; + result.tagName = tagName; + result.name = name; + result.typeExpression = typeExpression; + return finishNode(result); } - currentToken = saveToken; - parseDiagnostics.length = saveParseDiagnosticsLength; - parseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode; - return comment; - } - JSDocParser.parseJSDocComment = parseJSDocComment; - function parseJSDocCommentWorker(start, length) { - var content = sourceText; - start = start || 0; - var end = length === undefined ? content.length : start + length; - length = end - start; - ts.Debug.assert(start >= 0); - ts.Debug.assert(start <= end); - ts.Debug.assert(end <= content.length); - var tags; - var result; - // Check for /** (JSDoc opening part) - if (content.charCodeAt(start) === 47 /* slash */ && - content.charCodeAt(start + 1) === 42 /* asterisk */ && - content.charCodeAt(start + 2) === 42 /* asterisk */ && - content.charCodeAt(start + 3) !== 42 /* asterisk */) { - // + 3 for leading /**, - 5 in total for /** */ - scanner.scanRange(start + 3, length - 5, function () { - // Initially we can parse out a tag. We also have seen a starting asterisk. - // This is so that /** * @type */ doesn't parse. + function parseTypedefTag(atToken, tagName) { + var typeExpression = tryParseTypeExpression(); + skipWhitespace(); + var typedefTag = createNode(279 /* JSDocTypedefTag */, atToken.pos); + typedefTag.atToken = atToken; + typedefTag.tagName = tagName; + typedefTag.name = parseJSDocIdentifierName(); + typedefTag.typeExpression = typeExpression; + skipWhitespace(); + if (typeExpression) { + if (typeExpression.type.kind === 267 /* JSDocTypeReference */) { + var jsDocTypeReference = typeExpression.type; + if (jsDocTypeReference.name.kind === 69 /* Identifier */) { + var name_11 = jsDocTypeReference.name; + if (name_11.text === "Object") { + typedefTag.jsDocTypeLiteral = scanChildTags(); + } + } + } + if (!typedefTag.jsDocTypeLiteral) { + typedefTag.jsDocTypeLiteral = typeExpression.type; + } + } + else { + typedefTag.jsDocTypeLiteral = scanChildTags(); + } + return finishNode(typedefTag); + function scanChildTags() { + var jsDocTypeLiteral = createNode(281 /* JSDocTypeLiteral */, scanner.getStartPos()); + var resumePos = scanner.getStartPos(); var canParseTag = true; - var seenAsterisk = true; - nextJSDocToken(); - while (token() !== 1 /* EndOfFileToken */) { + var seenAsterisk = false; + var parentTagTerminated = false; + while (token() !== 1 /* EndOfFileToken */ && !parentTagTerminated) { + nextJSDocToken(); switch (token()) { case 55 /* AtToken */: if (canParseTag) { - parseTag(); + parentTagTerminated = !tryParseChildTag(jsDocTypeLiteral); + if (!parentTagTerminated) { + resumePos = scanner.getStartPos(); + } } - // This will take us to the end of the line, so it's OK to parse a tag on the next pass through the loop seenAsterisk = false; break; case 4 /* NewLineTrivia */: - // After a line break, we can parse a tag, and we haven't seen an asterisk on the next line yet + resumePos = scanner.getStartPos() - 1; canParseTag = true; seenAsterisk = false; break; case 37 /* AsteriskToken */: if (seenAsterisk) { - // If we've already seen an asterisk, then we can no longer parse a tag on this line canParseTag = false; } - // Ignore the first asterisk on a line seenAsterisk = true; break; case 69 /* Identifier */: - // Anything else is doc comment text. We can't do anything with it. Because it - // wasn't a tag, we can no longer parse a tag on this line until we hit the next - // line break. canParseTag = false; - break; case 1 /* EndOfFileToken */: break; } - nextJSDocToken(); } - result = createJSDocComment(); - }); - } - return result; - function createJSDocComment() { - if (!tags) { - return undefined; - } - var result = createNode(273 /* JSDocComment */, start); - result.tags = tags; - return finishNode(result, end); - } - function skipWhitespace() { - while (token() === 5 /* WhitespaceTrivia */ || token() === 4 /* NewLineTrivia */) { - nextJSDocToken(); + scanner.setTextPos(resumePos); + return finishNode(jsDocTypeLiteral); } } - function parseTag() { + function tryParseChildTag(parentTag) { ts.Debug.assert(token() === 55 /* AtToken */); - var atToken = createNode(55 /* AtToken */, scanner.getTokenPos()); + var atToken = createNode(55 /* AtToken */, scanner.getStartPos()); atToken.end = scanner.getTextPos(); nextJSDocToken(); var tagName = parseJSDocIdentifierName(); + skipWhitespace(); if (!tagName) { - return; + return false; + } + switch (tagName.text) { + case "type": + if (parentTag.jsDocTypeTag) { + // already has a @type tag, terminate the parent tag now. + return false; + } + parentTag.jsDocTypeTag = parseTypeTag(atToken, tagName); + return true; + case "prop": + case "property": + if (!parentTag.jsDocPropertyTags) { + parentTag.jsDocPropertyTags = []; + } + var propertyTag = parsePropertyTag(atToken, tagName); + parentTag.jsDocPropertyTags.push(propertyTag); + return true; } - var tag = handleTag(atToken, tagName) || handleUnknownTag(atToken, tagName); - addTag(tag); + return false; } - function handleTag(atToken, tagName) { - if (tagName) { - switch (tagName.text) { - case "param": - return handleParamTag(atToken, tagName); - case "return": - case "returns": - return handleReturnTag(atToken, tagName); - case "template": - return handleTemplateTag(atToken, tagName); - case "type": - return handleTypeTag(atToken, tagName); - case "typedef": - return handleTypedefTag(atToken, tagName); + function parseTemplateTag(atToken, tagName) { + if (ts.forEach(tags, function (t) { return t.kind === 278 /* JSDocTemplateTag */; })) { + parseErrorAtPosition(tagName.pos, scanner.getTokenPos() - tagName.pos, ts.Diagnostics._0_tag_already_specified, tagName.text); + } + // Type parameter list looks like '@template T,U,V' + var typeParameters = createNodeArray(); + while (true) { + var name_12 = parseJSDocIdentifierName(); + skipWhitespace(); + if (!name_12) { + parseErrorAtPosition(scanner.getStartPos(), 0, ts.Diagnostics.Identifier_expected); + return undefined; + } + var typeParameter = createNode(141 /* TypeParameter */, name_12.pos); + typeParameter.name = name_12; + finishNode(typeParameter); + typeParameters.push(typeParameter); + if (token() === 24 /* CommaToken */) { + nextJSDocToken(); + skipWhitespace(); + } + else { + break; } } - return undefined; - } - function handleUnknownTag(atToken, tagName) { - var result = createNode(274 /* JSDocTag */, atToken.pos); + var result = createNode(278 /* JSDocTemplateTag */, atToken.pos); result.atToken = atToken; result.tagName = tagName; - return finishNode(result); + result.typeParameters = typeParameters; + finishNode(result); + typeParameters.end = result.end; + return result; + } + function nextJSDocToken() { + return currentToken = scanner.scanJSDocToken(); + } + function parseJSDocIdentifierName() { + return createJSDocIdentifier(ts.tokenIsIdentifierOrKeyword(token())); + } + function createJSDocIdentifier(isIdentifier) { + if (!isIdentifier) { + parseErrorAtCurrentToken(ts.Diagnostics.Identifier_expected); + return undefined; + } + var pos = scanner.getTokenPos(); + var end = scanner.getTextPos(); + var result = createNode(69 /* Identifier */, pos); + result.text = content.substring(pos, end); + finishNode(result, end); + nextJSDocToken(); + return result; + } + } + JSDocParser.parseJSDocCommentWorker = parseJSDocCommentWorker; + })(JSDocParser = Parser.JSDocParser || (Parser.JSDocParser = {})); + })(Parser || (Parser = {})); + var IncrementalParser; + (function (IncrementalParser) { + function updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks) { + aggressiveChecks = aggressiveChecks || ts.Debug.shouldAssert(2 /* Aggressive */); + checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks); + if (ts.textChangeRangeIsUnchanged(textChangeRange)) { + // if the text didn't change, then we can just return our current source file as-is. + return sourceFile; + } + if (sourceFile.statements.length === 0) { + // If we don't have any statements in the current source file, then there's no real + // way to incrementally parse. So just do a full parse instead. + return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setParentNodes*/ true, sourceFile.scriptKind); + } + // Make sure we're not trying to incrementally update a source file more than once. Once + // we do an update the original source file is considered unusable from that point onwards. + // + // This is because we do incremental parsing in-place. i.e. we take nodes from the old + // tree and give them new positions and parents. From that point on, trusting the old + // tree at all is not possible as far too much of it may violate invariants. + var incrementalSourceFile = sourceFile; + ts.Debug.assert(!incrementalSourceFile.hasBeenIncrementallyParsed); + incrementalSourceFile.hasBeenIncrementallyParsed = true; + var oldText = sourceFile.text; + var syntaxCursor = createSyntaxCursor(sourceFile); + // Make the actual change larger so that we know to reparse anything whose lookahead + // might have intersected the change. + var changeRange = extendToAffectedRange(sourceFile, textChangeRange); + checkChangeRange(sourceFile, newText, changeRange, aggressiveChecks); + // Ensure that extending the affected range only moved the start of the change range + // earlier in the file. + ts.Debug.assert(changeRange.span.start <= textChangeRange.span.start); + ts.Debug.assert(ts.textSpanEnd(changeRange.span) === ts.textSpanEnd(textChangeRange.span)); + ts.Debug.assert(ts.textSpanEnd(ts.textChangeRangeNewSpan(changeRange)) === ts.textSpanEnd(ts.textChangeRangeNewSpan(textChangeRange))); + // The is the amount the nodes after the edit range need to be adjusted. It can be + // positive (if the edit added characters), negative (if the edit deleted characters) + // or zero (if this was a pure overwrite with nothing added/removed). + var delta = ts.textChangeRangeNewSpan(changeRange).length - changeRange.span.length; + // If we added or removed characters during the edit, then we need to go and adjust all + // the nodes after the edit. Those nodes may move forward (if we inserted chars) or they + // may move backward (if we deleted chars). + // + // Doing this helps us out in two ways. First, it means that any nodes/tokens we want + // to reuse are already at the appropriate position in the new text. That way when we + // reuse them, we don't have to figure out if they need to be adjusted. Second, it makes + // it very easy to determine if we can reuse a node. If the node's position is at where + // we are in the text, then we can reuse it. Otherwise we can't. If the node's position + // is ahead of us, then we'll need to rescan tokens. If the node's position is behind + // us, then we'll need to skip it or crumble it as appropriate + // + // We will also adjust the positions of nodes that intersect the change range as well. + // By doing this, we ensure that all the positions in the old tree are consistent, not + // just the positions of nodes entirely before/after the change range. By being + // consistent, we can then easily map from positions to nodes in the old tree easily. + // + // Also, mark any syntax elements that intersect the changed span. We know, up front, + // that we cannot reuse these elements. + updateTokenPositionsAndMarkElements(incrementalSourceFile, changeRange.span.start, ts.textSpanEnd(changeRange.span), ts.textSpanEnd(ts.textChangeRangeNewSpan(changeRange)), delta, oldText, newText, aggressiveChecks); + // Now that we've set up our internal incremental state just proceed and parse the + // source file in the normal fashion. When possible the parser will retrieve and + // reuse nodes from the old tree. + // + // Note: passing in 'true' for setNodeParents is very important. When incrementally + // parsing, we will be reusing nodes from the old tree, and placing it into new + // parents. If we don't set the parents now, we'll end up with an observably + // inconsistent tree. Setting the parents on the new tree should be very fast. We + // will immediately bail out of walking any subtrees when we can see that their parents + // are already correct. + var result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /*setParentNodes*/ true, sourceFile.scriptKind); + return result; + } + IncrementalParser.updateSourceFile = updateSourceFile; + function moveElementEntirelyPastChangeRange(element, isArray, delta, oldText, newText, aggressiveChecks) { + if (isArray) { + visitArray(element); + } + else { + visitNode(element); + } + return; + function visitNode(node) { + var text = ""; + if (aggressiveChecks && shouldCheckNode(node)) { + text = oldText.substring(node.pos, node.end); + } + // Ditch any existing LS children we may have created. This way we can avoid + // moving them forward. + if (node._children) { + node._children = undefined; + } + node.pos += delta; + node.end += delta; + if (aggressiveChecks && shouldCheckNode(node)) { + ts.Debug.assert(text === newText.substring(node.pos, node.end)); + } + forEachChild(node, visitNode, visitArray); + if (node.jsDocComments) { + for (var _i = 0, _a = node.jsDocComments; _i < _a.length; _i++) { + var jsDocComment = _a[_i]; + forEachChild(jsDocComment, visitNode, visitArray); + } + } + checkNodePositions(node, aggressiveChecks); + } + function visitArray(array) { + array._children = undefined; + array.pos += delta; + array.end += delta; + for (var _i = 0, array_8 = array; _i < array_8.length; _i++) { + var node = array_8[_i]; + visitNode(node); + } + } + } + function shouldCheckNode(node) { + switch (node.kind) { + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: + case 69 /* Identifier */: + return true; + } + return false; + } + function adjustIntersectingElement(element, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta) { + ts.Debug.assert(element.end >= changeStart, "Adjusting an element that was entirely before the change range"); + ts.Debug.assert(element.pos <= changeRangeOldEnd, "Adjusting an element that was entirely after the change range"); + ts.Debug.assert(element.pos <= element.end); + // We have an element that intersects the change range in some way. It may have its + // start, or its end (or both) in the changed range. We want to adjust any part + // that intersects such that the final tree is in a consistent state. i.e. all + // children have spans within the span of their parent, and all siblings are ordered + // properly. + // We may need to update both the 'pos' and the 'end' of the element. + // If the 'pos' is before the start of the change, then we don't need to touch it. + // If it isn't, then the 'pos' must be inside the change. How we update it will + // depend if delta is positive or negative. If delta is positive then we have + // something like: + // + // -------------------AAA----------------- + // -------------------BBBCCCCCCC----------------- + // + // In this case, we consider any node that started in the change range to still be + // starting at the same position. + // + // however, if the delta is negative, then we instead have something like this: + // + // -------------------XXXYYYYYYY----------------- + // -------------------ZZZ----------------- + // + // In this case, any element that started in the 'X' range will keep its position. + // However any element that started after that will have their pos adjusted to be + // at the end of the new range. i.e. any node that started in the 'Y' range will + // be adjusted to have their start at the end of the 'Z' range. + // + // The element will keep its position if possible. Or Move backward to the new-end + // if it's in the 'Y' range. + element.pos = Math.min(element.pos, changeRangeNewEnd); + // If the 'end' is after the change range, then we always adjust it by the delta + // amount. However, if the end is in the change range, then how we adjust it + // will depend on if delta is positive or negative. If delta is positive then we + // have something like: + // + // -------------------AAA----------------- + // -------------------BBBCCCCCCC----------------- + // + // In this case, we consider any node that ended inside the change range to keep its + // end position. + // + // however, if the delta is negative, then we instead have something like this: + // + // -------------------XXXYYYYYYY----------------- + // -------------------ZZZ----------------- + // + // In this case, any element that ended in the 'X' range will keep its position. + // However any element that ended after that will have their pos adjusted to be + // at the end of the new range. i.e. any node that ended in the 'Y' range will + // be adjusted to have their end at the end of the 'Z' range. + if (element.end >= changeRangeOldEnd) { + // Element ends after the change range. Always adjust the end pos. + element.end += delta; + } + else { + // Element ends in the change range. The element will keep its position if + // possible. Or Move backward to the new-end if it's in the 'Y' range. + element.end = Math.min(element.end, changeRangeNewEnd); + } + ts.Debug.assert(element.pos <= element.end); + if (element.parent) { + ts.Debug.assert(element.pos >= element.parent.pos); + ts.Debug.assert(element.end <= element.parent.end); + } + } + function checkNodePositions(node, aggressiveChecks) { + if (aggressiveChecks) { + var pos_2 = node.pos; + forEachChild(node, function (child) { + ts.Debug.assert(child.pos >= pos_2); + pos_2 = child.end; + }); + ts.Debug.assert(pos_2 <= node.end); + } + } + function updateTokenPositionsAndMarkElements(sourceFile, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta, oldText, newText, aggressiveChecks) { + visitNode(sourceFile); + return; + function visitNode(child) { + ts.Debug.assert(child.pos <= child.end); + if (child.pos > changeRangeOldEnd) { + // Node is entirely past the change range. We need to move both its pos and + // end, forward or backward appropriately. + moveElementEntirelyPastChangeRange(child, /*isArray*/ false, delta, oldText, newText, aggressiveChecks); + return; + } + // Check if the element intersects the change range. If it does, then it is not + // reusable. Also, we'll need to recurse to see what constituent portions we may + // be able to use. + var fullEnd = child.end; + if (fullEnd >= changeStart) { + child.intersectsChange = true; + child._children = undefined; + // Adjust the pos or end (or both) of the intersecting element accordingly. + adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta); + forEachChild(child, visitNode, visitArray); + checkNodePositions(child, aggressiveChecks); + return; + } + // Otherwise, the node is entirely before the change range. No need to do anything with it. + ts.Debug.assert(fullEnd < changeStart); + } + function visitArray(array) { + ts.Debug.assert(array.pos <= array.end); + if (array.pos > changeRangeOldEnd) { + // Array is entirely after the change range. We need to move it, and move any of + // its children. + moveElementEntirelyPastChangeRange(array, /*isArray*/ true, delta, oldText, newText, aggressiveChecks); + return; + } + // Check if the element intersects the change range. If it does, then it is not + // reusable. Also, we'll need to recurse to see what constituent portions we may + // be able to use. + var fullEnd = array.end; + if (fullEnd >= changeStart) { + array.intersectsChange = true; + array._children = undefined; + // Adjust the pos or end (or both) of the intersecting array accordingly. + adjustIntersectingElement(array, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta); + for (var _i = 0, array_9 = array; _i < array_9.length; _i++) { + var node = array_9[_i]; + visitNode(node); + } + return; + } + // Otherwise, the array is entirely before the change range. No need to do anything with it. + ts.Debug.assert(fullEnd < changeStart); + } + } + function extendToAffectedRange(sourceFile, changeRange) { + // Consider the following code: + // void foo() { /; } + // + // If the text changes with an insertion of / just before the semicolon then we end up with: + // void foo() { //; } + // + // If we were to just use the changeRange a is, then we would not rescan the { token + // (as it does not intersect the actual original change range). Because an edit may + // change the token touching it, we actually need to look back *at least* one token so + // that the prior token sees that change. + var maxLookahead = 1; + var start = changeRange.span.start; + // the first iteration aligns us with the change start. subsequent iteration move us to + // the left by maxLookahead tokens. We only need to do this as long as we're not at the + // start of the tree. + for (var i = 0; start > 0 && i <= maxLookahead; i++) { + var nearestNode = findNearestNodeStartingBeforeOrAtPosition(sourceFile, start); + ts.Debug.assert(nearestNode.pos <= start); + var position = nearestNode.pos; + start = Math.max(0, position - 1); + } + var finalSpan = ts.createTextSpanFromBounds(start, ts.textSpanEnd(changeRange.span)); + var finalLength = changeRange.newLength + (changeRange.span.start - start); + return ts.createTextChangeRange(finalSpan, finalLength); + } + function findNearestNodeStartingBeforeOrAtPosition(sourceFile, position) { + var bestResult = sourceFile; + var lastNodeEntirelyBeforePosition; + forEachChild(sourceFile, visit); + if (lastNodeEntirelyBeforePosition) { + var lastChildOfLastEntireNodeBeforePosition = getLastChild(lastNodeEntirelyBeforePosition); + if (lastChildOfLastEntireNodeBeforePosition.pos > bestResult.pos) { + bestResult = lastChildOfLastEntireNodeBeforePosition; } - function addTag(tag) { - if (tag) { - if (!tags) { - tags = []; - tags.pos = tag.pos; - } - tags.push(tag); - tags.end = tag.end; + } + return bestResult; + function getLastChild(node) { + while (true) { + var lastChild = getLastChildWorker(node); + if (lastChild) { + node = lastChild; } - } - function tryParseTypeExpression() { - if (token() !== 15 /* OpenBraceToken */) { - return undefined; + else { + return node; } - var typeExpression = parseJSDocTypeExpression(); - return typeExpression; } - function handleParamTag(atToken, tagName) { - var typeExpression = tryParseTypeExpression(); - skipWhitespace(); - var name; - var isBracketed; - // Looking for something like '[foo]' or 'foo' - if (parseOptionalToken(19 /* OpenBracketToken */)) { - name = parseJSDocIdentifierName(); - isBracketed = true; - // May have an optional default, e.g. '[foo = 42]' - if (parseOptionalToken(56 /* EqualsToken */)) { - parseExpression(); - } - parseExpected(20 /* CloseBracketToken */); - } - else if (ts.tokenIsIdentifierOrKeyword(token())) { - name = parseJSDocIdentifierName(); + } + function getLastChildWorker(node) { + var last = undefined; + forEachChild(node, function (child) { + if (ts.nodeIsPresent(child)) { + last = child; } - if (!name) { - parseErrorAtPosition(scanner.getStartPos(), 0, ts.Diagnostics.Identifier_expected); - return undefined; + }); + return last; + } + function visit(child) { + if (ts.nodeIsMissing(child)) { + // Missing nodes are effectively invisible to us. We never even consider them + // When trying to find the nearest node before us. + return; + } + // If the child intersects this position, then this node is currently the nearest + // node that starts before the position. + if (child.pos <= position) { + if (child.pos >= bestResult.pos) { + // This node starts before the position, and is closer to the position than + // the previous best node we found. It is now the new best node. + bestResult = child; } - var preName, postName; - if (typeExpression) { - postName = name; + // Now, the node may overlap the position, or it may end entirely before the + // position. If it overlaps with the position, then either it, or one of its + // children must be the nearest node before the position. So we can just + // recurse into this child to see if we can find something better. + if (position < child.end) { + // The nearest node is either this child, or one of the children inside + // of it. We've already marked this child as the best so far. Recurse + // in case one of the children is better. + forEachChild(child, visit); + // Once we look at the children of this node, then there's no need to + // continue any further. + return true; } else { - preName = name; - } - if (!typeExpression) { - typeExpression = tryParseTypeExpression(); + ts.Debug.assert(child.end <= position); + // The child ends entirely before this position. Say you have the following + // (where $ is the position) + // + // ? $ : <...> <...> + // + // We would want to find the nearest preceding node in "complex expr 2". + // To support that, we keep track of this node, and once we're done searching + // for a best node, we recurse down this node to see if we can find a good + // result in it. + // + // This approach allows us to quickly skip over nodes that are entirely + // before the position, while still allowing us to find any nodes in the + // last one that might be what we want. + lastNodeEntirelyBeforePosition = child; } - var result = createNode(275 /* JSDocParameterTag */, atToken.pos); - result.atToken = atToken; - result.tagName = tagName; - result.preParameterName = preName; - result.typeExpression = typeExpression; - result.postParameterName = postName; - result.isBracketed = isBracketed; - return finishNode(result); } - function handleReturnTag(atToken, tagName) { - if (ts.forEach(tags, function (t) { return t.kind === 276 /* JSDocReturnTag */; })) { - parseErrorAtPosition(tagName.pos, scanner.getTokenPos() - tagName.pos, ts.Diagnostics._0_tag_already_specified, tagName.text); - } - var result = createNode(276 /* JSDocReturnTag */, atToken.pos); - result.atToken = atToken; - result.tagName = tagName; - result.typeExpression = tryParseTypeExpression(); - return finishNode(result); + else { + ts.Debug.assert(child.pos > position); + // We're now at a node that is entirely past the position we're searching for. + // This node (and all following nodes) could never contribute to the result, + // so just skip them by returning 'true' here. + return true; } - function handleTypeTag(atToken, tagName) { - if (ts.forEach(tags, function (t) { return t.kind === 277 /* JSDocTypeTag */; })) { - parseErrorAtPosition(tagName.pos, scanner.getTokenPos() - tagName.pos, ts.Diagnostics._0_tag_already_specified, tagName.text); + } + } + function checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks) { + var oldText = sourceFile.text; + if (textChangeRange) { + ts.Debug.assert((oldText.length - textChangeRange.span.length + textChangeRange.newLength) === newText.length); + if (aggressiveChecks || ts.Debug.shouldAssert(3 /* VeryAggressive */)) { + var oldTextPrefix = oldText.substr(0, textChangeRange.span.start); + var newTextPrefix = newText.substr(0, textChangeRange.span.start); + ts.Debug.assert(oldTextPrefix === newTextPrefix); + var oldTextSuffix = oldText.substring(ts.textSpanEnd(textChangeRange.span), oldText.length); + var newTextSuffix = newText.substring(ts.textSpanEnd(ts.textChangeRangeNewSpan(textChangeRange)), newText.length); + ts.Debug.assert(oldTextSuffix === newTextSuffix); + } + } + } + function createSyntaxCursor(sourceFile) { + var currentArray = sourceFile.statements; + var currentArrayIndex = 0; + ts.Debug.assert(currentArrayIndex < currentArray.length); + var current = currentArray[currentArrayIndex]; + var lastQueriedPosition = -1 /* Value */; + return { + currentNode: function (position) { + // Only compute the current node if the position is different than the last time + // we were asked. The parser commonly asks for the node at the same position + // twice. Once to know if can read an appropriate list element at a certain point, + // and then to actually read and consume the node. + if (position !== lastQueriedPosition) { + // Much of the time the parser will need the very next node in the array that + // we just returned a node from.So just simply check for that case and move + // forward in the array instead of searching for the node again. + if (current && current.end === position && currentArrayIndex < (currentArray.length - 1)) { + currentArrayIndex++; + current = currentArray[currentArrayIndex]; + } + // If we don't have a node, or the node we have isn't in the right position, + // then try to find a viable node at the position requested. + if (!current || current.pos !== position) { + findHighestListElementThatStartsAtPosition(position); + } } - var result = createNode(277 /* JSDocTypeTag */, atToken.pos); - result.atToken = atToken; - result.tagName = tagName; - result.typeExpression = tryParseTypeExpression(); - return finishNode(result); + // Cache this query so that we don't do any extra work if the parser calls back + // into us. Note: this is very common as the parser will make pairs of calls like + // 'isListElement -> parseListElement'. If we were unable to find a node when + // called with 'isListElement', we don't want to redo the work when parseListElement + // is called immediately after. + lastQueriedPosition = position; + // Either we don'd have a node, or we have a node at the position being asked for. + ts.Debug.assert(!current || current.pos === position); + return current; } - function handlePropertyTag(atToken, tagName) { - var typeExpression = tryParseTypeExpression(); - skipWhitespace(); - var name = parseJSDocIdentifierName(); - if (!name) { - parseErrorAtPosition(scanner.getStartPos(), /*length*/ 0, ts.Diagnostics.Identifier_expected); - return undefined; + }; + // Finds the highest element in the tree we can find that starts at the provided position. + // The element must be a direct child of some node list in the tree. This way after we + // return it, we can easily return its next sibling in the list. + function findHighestListElementThatStartsAtPosition(position) { + // Clear out any cached state about the last node we found. + currentArray = undefined; + currentArrayIndex = -1 /* Value */; + current = undefined; + // Recurse into the source file to find the highest node at this position. + forEachChild(sourceFile, visitNode, visitArray); + return; + function visitNode(node) { + if (position >= node.pos && position < node.end) { + // Position was within this node. Keep searching deeper to find the node. + forEachChild(node, visitNode, visitArray); + // don't proceed any further in the search. + return true; } - var result = createNode(280 /* JSDocPropertyTag */, atToken.pos); - result.atToken = atToken; - result.tagName = tagName; - result.name = name; - result.typeExpression = typeExpression; - return finishNode(result); + // position wasn't in this node, have to keep searching. + return false; } - function handleTypedefTag(atToken, tagName) { - var typeExpression = tryParseTypeExpression(); - skipWhitespace(); - var typedefTag = createNode(279 /* JSDocTypedefTag */, atToken.pos); - typedefTag.atToken = atToken; - typedefTag.tagName = tagName; - typedefTag.name = parseJSDocIdentifierName(); - typedefTag.typeExpression = typeExpression; - if (typeExpression) { - if (typeExpression.type.kind === 267 /* JSDocTypeReference */) { - var jsDocTypeReference = typeExpression.type; - if (jsDocTypeReference.name.kind === 69 /* Identifier */) { - var name_8 = jsDocTypeReference.name; - if (name_8.text === "Object") { - typedefTag.jsDocTypeLiteral = scanChildTags(); + function visitArray(array) { + if (position >= array.pos && position < array.end) { + // position was in this array. Search through this array to see if we find a + // viable element. + for (var i = 0, n = array.length; i < n; i++) { + var child = array[i]; + if (child) { + if (child.pos === position) { + // Found the right node. We're done. + currentArray = array; + currentArrayIndex = i; + current = child; + return true; + } + else { + if (child.pos < position && position < child.end) { + // Position in somewhere within this child. Search in it and + // stop searching in this array. + forEachChild(child, visitNode, visitArray); + return true; + } } } } - if (!typedefTag.jsDocTypeLiteral) { - typedefTag.jsDocTypeLiteral = typeExpression.type; - } } - else { - typedefTag.jsDocTypeLiteral = scanChildTags(); + // position wasn't in this array, have to keep searching. + return false; + } + } + } + var InvalidPosition; + (function (InvalidPosition) { + InvalidPosition[InvalidPosition["Value"] = -1] = "Value"; + })(InvalidPosition || (InvalidPosition = {})); + })(IncrementalParser || (IncrementalParser = {})); +})(ts || (ts = {})); +/// +/// +/* @internal */ +var ts; +(function (ts) { + (function (ModuleInstanceState) { + ModuleInstanceState[ModuleInstanceState["NonInstantiated"] = 0] = "NonInstantiated"; + ModuleInstanceState[ModuleInstanceState["Instantiated"] = 1] = "Instantiated"; + ModuleInstanceState[ModuleInstanceState["ConstEnumOnly"] = 2] = "ConstEnumOnly"; + })(ts.ModuleInstanceState || (ts.ModuleInstanceState = {})); + var ModuleInstanceState = ts.ModuleInstanceState; + function getModuleInstanceState(node) { + // A module is uninstantiated if it contains only + // 1. interface declarations, type alias declarations + if (node.kind === 222 /* InterfaceDeclaration */ || node.kind === 223 /* TypeAliasDeclaration */) { + return 0 /* NonInstantiated */; + } + else if (ts.isConstEnumDeclaration(node)) { + return 2 /* ConstEnumOnly */; + } + else if ((node.kind === 230 /* ImportDeclaration */ || node.kind === 229 /* ImportEqualsDeclaration */) && !(ts.hasModifier(node, 1 /* Export */))) { + return 0 /* NonInstantiated */; + } + else if (node.kind === 226 /* ModuleBlock */) { + var state_1 = 0 /* NonInstantiated */; + ts.forEachChild(node, function (n) { + switch (getModuleInstanceState(n)) { + case 0 /* NonInstantiated */: + // child is non-instantiated - continue searching + return false; + case 2 /* ConstEnumOnly */: + // child is const enum only - record state and continue searching + state_1 = 2 /* ConstEnumOnly */; + return false; + case 1 /* Instantiated */: + // child is instantiated - record state and stop + state_1 = 1 /* Instantiated */; + return true; + } + }); + return state_1; + } + else if (node.kind === 225 /* ModuleDeclaration */) { + var body = node.body; + return body ? getModuleInstanceState(body) : 1 /* Instantiated */; + } + else { + return 1 /* Instantiated */; + } + } + ts.getModuleInstanceState = getModuleInstanceState; + var ContainerFlags; + (function (ContainerFlags) { + // The current node is not a container, and no container manipulation should happen before + // recursing into it. + ContainerFlags[ContainerFlags["None"] = 0] = "None"; + // The current node is a container. It should be set as the current container (and block- + // container) before recursing into it. The current node does not have locals. Examples: + // + // Classes, ObjectLiterals, TypeLiterals, Interfaces... + ContainerFlags[ContainerFlags["IsContainer"] = 1] = "IsContainer"; + // The current node is a block-scoped-container. It should be set as the current block- + // container before recursing into it. Examples: + // + // Blocks (when not parented by functions), Catch clauses, For/For-in/For-of statements... + ContainerFlags[ContainerFlags["IsBlockScopedContainer"] = 2] = "IsBlockScopedContainer"; + // The current node is the container of a control flow path. The current control flow should + // be saved and restored, and a new control flow initialized within the container. + ContainerFlags[ContainerFlags["IsControlFlowContainer"] = 4] = "IsControlFlowContainer"; + ContainerFlags[ContainerFlags["IsFunctionLike"] = 8] = "IsFunctionLike"; + ContainerFlags[ContainerFlags["IsFunctionExpression"] = 16] = "IsFunctionExpression"; + ContainerFlags[ContainerFlags["HasLocals"] = 32] = "HasLocals"; + ContainerFlags[ContainerFlags["IsInterface"] = 64] = "IsInterface"; + })(ContainerFlags || (ContainerFlags = {})); + var binder = createBinder(); + function bindSourceFile(file, options) { + ts.performance.mark("beforeBind"); + binder(file, options); + ts.performance.mark("afterBind"); + ts.performance.measure("Bind", "beforeBind", "afterBind"); + } + ts.bindSourceFile = bindSourceFile; + function createBinder() { + var file; + var options; + var languageVersion; + var parent; + var container; + var blockScopeContainer; + var lastContainer; + var seenThisKeyword; + // state used by control flow analysis + var currentFlow; + var currentBreakTarget; + var currentContinueTarget; + var currentReturnTarget; + var currentTrueTarget; + var currentFalseTarget; + var preSwitchCaseFlow; + var activeLabels; + var hasExplicitReturn; + // state used for emit helpers + var emitFlags; + // If this file is an external module, then it is automatically in strict-mode according to + // ES6. If it is not an external module, then we'll determine if it is in strict mode or + // not depending on if we see "use strict" in certain places (or if we hit a class/namespace). + var inStrictMode; + var symbolCount = 0; + var Symbol; + var classifiableNames; + var unreachableFlow = { flags: 1 /* Unreachable */ }; + var reportedUnreachableFlow = { flags: 1 /* Unreachable */ }; + // state used to aggregate transform flags during bind. + var subtreeTransformFlags = 0 /* None */; + var skipTransformFlagAggregation; + function bindSourceFile(f, opts) { + file = f; + options = opts; + languageVersion = ts.getEmitScriptTarget(options); + inStrictMode = !!file.externalModuleIndicator; + classifiableNames = ts.createMap(); + symbolCount = 0; + skipTransformFlagAggregation = ts.isDeclarationFile(file); + Symbol = ts.objectAllocator.getSymbolConstructor(); + if (!file.locals) { + bind(file); + file.symbolCount = symbolCount; + file.classifiableNames = classifiableNames; + } + file = undefined; + options = undefined; + languageVersion = undefined; + parent = undefined; + container = undefined; + blockScopeContainer = undefined; + lastContainer = undefined; + seenThisKeyword = false; + currentFlow = undefined; + currentBreakTarget = undefined; + currentContinueTarget = undefined; + currentReturnTarget = undefined; + currentTrueTarget = undefined; + currentFalseTarget = undefined; + activeLabels = undefined; + hasExplicitReturn = false; + emitFlags = 0 /* None */; + subtreeTransformFlags = 0 /* None */; + } + return bindSourceFile; + function createSymbol(flags, name) { + symbolCount++; + return new Symbol(flags, name); + } + function addDeclarationToSymbol(symbol, node, symbolFlags) { + symbol.flags |= symbolFlags; + node.symbol = symbol; + if (!symbol.declarations) { + symbol.declarations = []; + } + symbol.declarations.push(node); + if (symbolFlags & 1952 /* HasExports */ && !symbol.exports) { + symbol.exports = ts.createMap(); + } + if (symbolFlags & 6240 /* HasMembers */ && !symbol.members) { + symbol.members = ts.createMap(); + } + if (symbolFlags & 107455 /* Value */) { + var valueDeclaration = symbol.valueDeclaration; + if (!valueDeclaration || + (valueDeclaration.kind !== node.kind && valueDeclaration.kind === 225 /* ModuleDeclaration */)) { + // other kinds of value declarations take precedence over modules + symbol.valueDeclaration = node; + } + } + } + // Should not be called on a declaration with a computed property name, + // unless it is a well known Symbol. + function getDeclarationName(node) { + if (node.name) { + if (ts.isAmbientModule(node)) { + return ts.isGlobalScopeAugmentation(node) ? "__global" : "\"" + node.name.text + "\""; + } + if (node.name.kind === 140 /* ComputedPropertyName */) { + var nameExpression = node.name.expression; + // treat computed property names where expression is string/numeric literal as just string/numeric literal + if (ts.isStringOrNumericLiteral(nameExpression.kind)) { + return nameExpression.text; } - return finishNode(typedefTag); - function scanChildTags() { - var jsDocTypeLiteral = createNode(281 /* JSDocTypeLiteral */, scanner.getStartPos()); - var resumePos = scanner.getStartPos(); - var canParseTag = true; - var seenAsterisk = false; - var parentTagTerminated = false; - while (token() !== 1 /* EndOfFileToken */ && !parentTagTerminated) { - nextJSDocToken(); - switch (token()) { - case 55 /* AtToken */: - if (canParseTag) { - parentTagTerminated = !tryParseChildTag(jsDocTypeLiteral); - if (!parentTagTerminated) { - resumePos = scanner.getStartPos(); - } - } - seenAsterisk = false; - break; - case 4 /* NewLineTrivia */: - resumePos = scanner.getStartPos() - 1; - canParseTag = true; - seenAsterisk = false; - break; - case 37 /* AsteriskToken */: - if (seenAsterisk) { - canParseTag = false; - } - seenAsterisk = true; - break; - case 69 /* Identifier */: - canParseTag = false; - case 1 /* EndOfFileToken */: - break; + ts.Debug.assert(ts.isWellKnownSymbolSyntactically(nameExpression)); + return ts.getPropertyNameForKnownSymbolName(nameExpression.name.text); + } + return node.name.text; + } + switch (node.kind) { + case 148 /* Constructor */: + return "__constructor"; + case 156 /* FunctionType */: + case 151 /* CallSignature */: + return "__call"; + case 157 /* ConstructorType */: + case 152 /* ConstructSignature */: + return "__new"; + case 153 /* IndexSignature */: + return "__index"; + case 236 /* ExportDeclaration */: + return "__export"; + case 235 /* ExportAssignment */: + return node.isExportEquals ? "export=" : "default"; + case 187 /* BinaryExpression */: + switch (ts.getSpecialPropertyAssignmentKind(node)) { + case 2 /* ModuleExports */: + // module.exports = ... + return "export="; + case 1 /* ExportsProperty */: + case 4 /* ThisProperty */: + // exports.x = ... or this.y = ... + return node.left.name.text; + case 3 /* PrototypeProperty */: + // className.prototype.methodName = ... + return node.left.expression.name.text; + } + ts.Debug.fail("Unknown binary declaration kind"); + break; + case 220 /* FunctionDeclaration */: + case 221 /* ClassDeclaration */: + return ts.hasModifier(node, 512 /* Default */) ? "default" : undefined; + case 269 /* JSDocFunctionType */: + return ts.isJSDocConstructSignature(node) ? "__new" : "__call"; + case 142 /* Parameter */: + // Parameters with names are handled at the top of this function. Parameters + // without names can only come from JSDocFunctionTypes. + ts.Debug.assert(node.parent.kind === 269 /* JSDocFunctionType */); + var functionType = node.parent; + var index = ts.indexOf(functionType.parameters, node); + return "arg" + index; + case 279 /* JSDocTypedefTag */: + var parentNode = node.parent && node.parent.parent; + var nameFromParentNode = void 0; + if (parentNode && parentNode.kind === 200 /* VariableStatement */) { + if (parentNode.declarationList.declarations.length > 0) { + var nameIdentifier = parentNode.declarationList.declarations[0].name; + if (nameIdentifier.kind === 69 /* Identifier */) { + nameFromParentNode = nameIdentifier.text; } } - scanner.setTextPos(resumePos); - return finishNode(jsDocTypeLiteral); } + return nameFromParentNode; + } + } + function getDisplayName(node) { + return node.name ? ts.declarationNameToString(node.name) : getDeclarationName(node); + } + /** + * Declares a Symbol for the node and adds it to symbols. Reports errors for conflicting identifier names. + * @param symbolTable - The symbol table which node will be added to. + * @param parent - node's parent declaration. + * @param node - The declaration to be added to the symbol table + * @param includes - The SymbolFlags that node has in addition to its declaration type (eg: export, ambient, etc.) + * @param excludes - The flags which node cannot be declared alongside in a symbol table. Used to report forbidden declarations. + */ + function declareSymbol(symbolTable, parent, node, includes, excludes) { + ts.Debug.assert(!ts.hasDynamicName(node)); + var isDefaultExport = ts.hasModifier(node, 512 /* Default */); + // The exported symbol for an export default function/class node is always named "default" + var name = isDefaultExport && parent ? "default" : getDeclarationName(node); + var symbol; + if (name === undefined) { + symbol = createSymbol(0 /* None */, "__missing"); + } + else { + // Check and see if the symbol table already has a symbol with this name. If not, + // create a new symbol with this name and add it to the table. Note that we don't + // give the new symbol any flags *yet*. This ensures that it will not conflict + // with the 'excludes' flags we pass in. + // + // If we do get an existing symbol, see if it conflicts with the new symbol we're + // creating. For example, a 'var' symbol and a 'class' symbol will conflict within + // the same symbol table. If we have a conflict, report the issue on each + // declaration we have for this symbol, and then create a new symbol for this + // declaration. + // + // Note that when properties declared in Javascript constructors + // (marked by isReplaceableByMethod) conflict with another symbol, the property loses. + // Always. This allows the common Javascript pattern of overwriting a prototype method + // with an bound instance method of the same type: `this.method = this.method.bind(this)` + // + // If we created a new symbol, either because we didn't have a symbol with this name + // in the symbol table, or we conflicted with an existing symbol, then just add this + // node as the sole declaration of the new symbol. + // + // Otherwise, we'll be merging into a compatible existing symbol (for example when + // you have multiple 'vars' with the same name in the same container). In this case + // just add this node into the declarations list of the symbol. + symbol = symbolTable[name] || (symbolTable[name] = createSymbol(0 /* None */, name)); + if (name && (includes & 788448 /* Classifiable */)) { + classifiableNames[name] = name; } - function tryParseChildTag(parentTag) { - ts.Debug.assert(token() === 55 /* AtToken */); - var atToken = createNode(55 /* AtToken */, scanner.getStartPos()); - atToken.end = scanner.getTextPos(); - nextJSDocToken(); - var tagName = parseJSDocIdentifierName(); - if (!tagName) { - return false; + if (symbol.flags & excludes) { + if (symbol.isReplaceableByMethod) { + // Javascript constructor-declared symbols can be discarded in favor of + // prototype symbols like methods. + symbol = symbolTable[name] = createSymbol(0 /* None */, name); } - switch (tagName.text) { - case "type": - if (parentTag.jsDocTypeTag) { - // already has a @type tag, terminate the parent tag now. - return false; - } - parentTag.jsDocTypeTag = handleTypeTag(atToken, tagName); - return true; - case "prop": - case "property": - if (!parentTag.jsDocPropertyTags) { - parentTag.jsDocPropertyTags = []; + else { + if (node.name) { + node.name.parent = node; + } + // Report errors every position with duplicate declaration + // Report errors on previous encountered declarations + var message_1 = symbol.flags & 2 /* BlockScopedVariable */ + ? ts.Diagnostics.Cannot_redeclare_block_scoped_variable_0 + : ts.Diagnostics.Duplicate_identifier_0; + ts.forEach(symbol.declarations, function (declaration) { + if (ts.hasModifier(declaration, 512 /* Default */)) { + message_1 = ts.Diagnostics.A_module_cannot_have_multiple_default_exports; } - var propertyTag = handlePropertyTag(atToken, tagName); - parentTag.jsDocPropertyTags.push(propertyTag); - return true; + }); + ts.forEach(symbol.declarations, function (declaration) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(declaration.name || declaration, message_1, getDisplayName(declaration))); + }); + file.bindDiagnostics.push(ts.createDiagnosticForNode(node.name || node, message_1, getDisplayName(node))); + symbol = createSymbol(0 /* None */, name); } - return false; } - function handleTemplateTag(atToken, tagName) { - if (ts.forEach(tags, function (t) { return t.kind === 278 /* JSDocTemplateTag */; })) { - parseErrorAtPosition(tagName.pos, scanner.getTokenPos() - tagName.pos, ts.Diagnostics._0_tag_already_specified, tagName.text); - } - // Type parameter list looks like '@template T,U,V' - var typeParameters = []; - typeParameters.pos = scanner.getStartPos(); - while (true) { - var name_9 = parseJSDocIdentifierName(); - if (!name_9) { - parseErrorAtPosition(scanner.getStartPos(), 0, ts.Diagnostics.Identifier_expected); - return undefined; - } - var typeParameter = createNode(141 /* TypeParameter */, name_9.pos); - typeParameter.name = name_9; - finishNode(typeParameter); - typeParameters.push(typeParameter); - if (token() === 24 /* CommaToken */) { - nextJSDocToken(); - } - else { - break; - } - } - var result = createNode(278 /* JSDocTemplateTag */, atToken.pos); - result.atToken = atToken; - result.tagName = tagName; - result.typeParameters = typeParameters; - finishNode(result); - typeParameters.end = result.end; - return result; + } + addDeclarationToSymbol(symbol, node, includes); + symbol.parent = parent; + return symbol; + } + function declareModuleMember(node, symbolFlags, symbolExcludes) { + var hasExportModifier = ts.getCombinedModifierFlags(node) & 1 /* Export */; + if (symbolFlags & 8388608 /* Alias */) { + if (node.kind === 238 /* ExportSpecifier */ || (node.kind === 229 /* ImportEqualsDeclaration */ && hasExportModifier)) { + return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); } - function nextJSDocToken() { - return currentToken = scanner.scanJSDocToken(); + else { + return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); } - function parseJSDocIdentifierName() { - return createJSDocIdentifier(ts.tokenIsIdentifierOrKeyword(token())); + } + else { + // Exported module members are given 2 symbols: A local symbol that is classified with an ExportValue, + // ExportType, or ExportContainer flag, and an associated export symbol with all the correct flags set + // on it. There are 2 main reasons: + // + // 1. We treat locals and exports of the same name as mutually exclusive within a container. + // That means the binder will issue a Duplicate Identifier error if you mix locals and exports + // with the same name in the same container. + // TODO: Make this a more specific error and decouple it from the exclusion logic. + // 2. When we checkIdentifier in the checker, we set its resolved symbol to the local symbol, + // but return the export symbol (by calling getExportSymbolOfValueSymbolIfExported). That way + // when the emitter comes back to it, it knows not to qualify the name if it was found in a containing scope. + // NOTE: Nested ambient modules always should go to to 'locals' table to prevent their automatic merge + // during global merging in the checker. Why? The only case when ambient module is permitted inside another module is module augmentation + // and this case is specially handled. Module augmentations should only be merged with original module definition + // and should never be merged directly with other augmentation, and the latter case would be possible if automatic merge is allowed. + if (!ts.isAmbientModule(node) && (hasExportModifier || container.flags & 32 /* ExportContext */)) { + var exportKind = (symbolFlags & 107455 /* Value */ ? 1048576 /* ExportValue */ : 0) | + (symbolFlags & 793064 /* Type */ ? 2097152 /* ExportType */ : 0) | + (symbolFlags & 1920 /* Namespace */ ? 4194304 /* ExportNamespace */ : 0); + var local = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes); + local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); + node.localSymbol = local; + return local; } - function createJSDocIdentifier(isIdentifier) { - if (!isIdentifier) { - parseErrorAtCurrentToken(ts.Diagnostics.Identifier_expected); - return undefined; - } - var pos = scanner.getTokenPos(); - var end = scanner.getTextPos(); - var result = createNode(69 /* Identifier */, pos); - result.text = content.substring(pos, end); - finishNode(result, end); - nextJSDocToken(); - return result; + else { + return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); } } - JSDocParser.parseJSDocCommentWorker = parseJSDocCommentWorker; - })(JSDocParser = Parser.JSDocParser || (Parser.JSDocParser = {})); - })(Parser || (Parser = {})); - var IncrementalParser; - (function (IncrementalParser) { - function updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks) { - aggressiveChecks = aggressiveChecks || ts.Debug.shouldAssert(2 /* Aggressive */); - checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks); - if (ts.textChangeRangeIsUnchanged(textChangeRange)) { - // if the text didn't change, then we can just return our current source file as-is. - return sourceFile; - } - if (sourceFile.statements.length === 0) { - // If we don't have any statements in the current source file, then there's no real - // way to incrementally parse. So just do a full parse instead. - return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setParentNodes*/ true, sourceFile.scriptKind); - } - // Make sure we're not trying to incrementally update a source file more than once. Once - // we do an update the original source file is considered unusable from that point onwards. - // - // This is because we do incremental parsing in-place. i.e. we take nodes from the old - // tree and give them new positions and parents. From that point on, trusting the old - // tree at all is not possible as far too much of it may violate invariants. - var incrementalSourceFile = sourceFile; - ts.Debug.assert(!incrementalSourceFile.hasBeenIncrementallyParsed); - incrementalSourceFile.hasBeenIncrementallyParsed = true; - var oldText = sourceFile.text; - var syntaxCursor = createSyntaxCursor(sourceFile); - // Make the actual change larger so that we know to reparse anything whose lookahead - // might have intersected the change. - var changeRange = extendToAffectedRange(sourceFile, textChangeRange); - checkChangeRange(sourceFile, newText, changeRange, aggressiveChecks); - // Ensure that extending the affected range only moved the start of the change range - // earlier in the file. - ts.Debug.assert(changeRange.span.start <= textChangeRange.span.start); - ts.Debug.assert(ts.textSpanEnd(changeRange.span) === ts.textSpanEnd(textChangeRange.span)); - ts.Debug.assert(ts.textSpanEnd(ts.textChangeRangeNewSpan(changeRange)) === ts.textSpanEnd(ts.textChangeRangeNewSpan(textChangeRange))); - // The is the amount the nodes after the edit range need to be adjusted. It can be - // positive (if the edit added characters), negative (if the edit deleted characters) - // or zero (if this was a pure overwrite with nothing added/removed). - var delta = ts.textChangeRangeNewSpan(changeRange).length - changeRange.span.length; - // If we added or removed characters during the edit, then we need to go and adjust all - // the nodes after the edit. Those nodes may move forward (if we inserted chars) or they - // may move backward (if we deleted chars). - // - // Doing this helps us out in two ways. First, it means that any nodes/tokens we want - // to reuse are already at the appropriate position in the new text. That way when we - // reuse them, we don't have to figure out if they need to be adjusted. Second, it makes - // it very easy to determine if we can reuse a node. If the node's position is at where - // we are in the text, then we can reuse it. Otherwise we can't. If the node's position - // is ahead of us, then we'll need to rescan tokens. If the node's position is behind - // us, then we'll need to skip it or crumble it as appropriate - // - // We will also adjust the positions of nodes that intersect the change range as well. - // By doing this, we ensure that all the positions in the old tree are consistent, not - // just the positions of nodes entirely before/after the change range. By being - // consistent, we can then easily map from positions to nodes in the old tree easily. + } + // All container nodes are kept on a linked list in declaration order. This list is used by + // the getLocalNameOfContainer function in the type checker to validate that the local name + // used for a container is unique. + function bindContainer(node, containerFlags) { + // Before we recurse into a node's children, we first save the existing parent, container + // and block-container. Then after we pop out of processing the children, we restore + // these saved values. + var saveContainer = container; + var savedBlockScopeContainer = blockScopeContainer; + // Depending on what kind of node this is, we may have to adjust the current container + // and block-container. If the current node is a container, then it is automatically + // considered the current block-container as well. Also, for containers that we know + // may contain locals, we proactively initialize the .locals field. We do this because + // it's highly likely that the .locals will be needed to place some child in (for example, + // a parameter, or variable declaration). // - // Also, mark any syntax elements that intersect the changed span. We know, up front, - // that we cannot reuse these elements. - updateTokenPositionsAndMarkElements(incrementalSourceFile, changeRange.span.start, ts.textSpanEnd(changeRange.span), ts.textSpanEnd(ts.textChangeRangeNewSpan(changeRange)), delta, oldText, newText, aggressiveChecks); - // Now that we've set up our internal incremental state just proceed and parse the - // source file in the normal fashion. When possible the parser will retrieve and - // reuse nodes from the old tree. + // However, we do not proactively create the .locals for block-containers because it's + // totally normal and common for block-containers to never actually have a block-scoped + // variable in them. We don't want to end up allocating an object for every 'block' we + // run into when most of them won't be necessary. // - // Note: passing in 'true' for setNodeParents is very important. When incrementally - // parsing, we will be reusing nodes from the old tree, and placing it into new - // parents. If we don't set the parents now, we'll end up with an observably - // inconsistent tree. Setting the parents on the new tree should be very fast. We - // will immediately bail out of walking any subtrees when we can see that their parents - // are already correct. - var result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /*setParentNodes*/ true, sourceFile.scriptKind); - return result; - } - IncrementalParser.updateSourceFile = updateSourceFile; - function moveElementEntirelyPastChangeRange(element, isArray, delta, oldText, newText, aggressiveChecks) { - if (isArray) { - visitArray(element); + // Finally, if this is a block-container, then we clear out any existing .locals object + // it may contain within it. This happens in incremental scenarios. Because we can be + // reusing a node from a previous compilation, that node may have had 'locals' created + // for it. We must clear this so we don't accidentally move any stale data forward from + // a previous compilation. + if (containerFlags & 1 /* IsContainer */) { + container = blockScopeContainer = node; + if (containerFlags & 32 /* HasLocals */) { + container.locals = ts.createMap(); + } + addToContainerChain(container); } - else { - visitNode(element); + else if (containerFlags & 2 /* IsBlockScopedContainer */) { + blockScopeContainer = node; + blockScopeContainer.locals = undefined; } - return; - function visitNode(node) { - var text = ""; - if (aggressiveChecks && shouldCheckNode(node)) { - text = oldText.substring(node.pos, node.end); + if (containerFlags & 4 /* IsControlFlowContainer */) { + var saveCurrentFlow = currentFlow; + var saveBreakTarget = currentBreakTarget; + var saveContinueTarget = currentContinueTarget; + var saveReturnTarget = currentReturnTarget; + var saveActiveLabels = activeLabels; + var saveHasExplicitReturn = hasExplicitReturn; + var isIIFE = containerFlags & 16 /* IsFunctionExpression */ && !!ts.getImmediatelyInvokedFunctionExpression(node); + // An IIFE is considered part of the containing control flow. Return statements behave + // similarly to break statements that exit to a label just past the statement body. + if (isIIFE) { + currentReturnTarget = createBranchLabel(); } - // Ditch any existing LS children we may have created. This way we can avoid - // moving them forward. - if (node._children) { - node._children = undefined; + else { + currentFlow = { flags: 2 /* Start */ }; + if (containerFlags & 16 /* IsFunctionExpression */) { + currentFlow.container = node; + } + currentReturnTarget = undefined; } - node.pos += delta; - node.end += delta; - if (aggressiveChecks && shouldCheckNode(node)) { - ts.Debug.assert(text === newText.substring(node.pos, node.end)); + currentBreakTarget = undefined; + currentContinueTarget = undefined; + activeLabels = undefined; + hasExplicitReturn = false; + bindChildren(node); + // Reset all reachability check related flags on node (for incremental scenarios) + // Reset all emit helper flags on node (for incremental scenarios) + node.flags &= ~32128 /* ReachabilityAndEmitFlags */; + if (!(currentFlow.flags & 1 /* Unreachable */) && containerFlags & 8 /* IsFunctionLike */ && ts.nodeIsPresent(node.body)) { + node.flags |= 128 /* HasImplicitReturn */; + if (hasExplicitReturn) + node.flags |= 256 /* HasExplicitReturn */; } - forEachChild(node, visitNode, visitArray); - if (node.jsDocComments) { - for (var _i = 0, _a = node.jsDocComments; _i < _a.length; _i++) { - var jsDocComment = _a[_i]; - forEachChild(jsDocComment, visitNode, visitArray); - } + if (node.kind === 256 /* SourceFile */) { + node.flags |= emitFlags; } - checkNodePositions(node, aggressiveChecks); - } - function visitArray(array) { - array._children = undefined; - array.pos += delta; - array.end += delta; - for (var _i = 0, array_9 = array; _i < array_9.length; _i++) { - var node = array_9[_i]; - visitNode(node); + if (isIIFE) { + addAntecedent(currentReturnTarget, currentFlow); + currentFlow = finishFlowLabel(currentReturnTarget); } + else { + currentFlow = saveCurrentFlow; + } + currentBreakTarget = saveBreakTarget; + currentContinueTarget = saveContinueTarget; + currentReturnTarget = saveReturnTarget; + activeLabels = saveActiveLabels; + hasExplicitReturn = saveHasExplicitReturn; } - } - function shouldCheckNode(node) { - switch (node.kind) { - case 9 /* StringLiteral */: - case 8 /* NumericLiteral */: - case 69 /* Identifier */: - return true; + else if (containerFlags & 64 /* IsInterface */) { + seenThisKeyword = false; + bindChildren(node); + node.flags = seenThisKeyword ? node.flags | 64 /* ContainsThis */ : node.flags & ~64 /* ContainsThis */; } - return false; + else { + bindChildren(node); + } + container = saveContainer; + blockScopeContainer = savedBlockScopeContainer; } - function adjustIntersectingElement(element, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta) { - ts.Debug.assert(element.end >= changeStart, "Adjusting an element that was entirely before the change range"); - ts.Debug.assert(element.pos <= changeRangeOldEnd, "Adjusting an element that was entirely after the change range"); - ts.Debug.assert(element.pos <= element.end); - // We have an element that intersects the change range in some way. It may have its - // start, or its end (or both) in the changed range. We want to adjust any part - // that intersects such that the final tree is in a consistent state. i.e. all - // children have spans within the span of their parent, and all siblings are ordered - // properly. - // We may need to update both the 'pos' and the 'end' of the element. - // If the 'pos' is before the start of the change, then we don't need to touch it. - // If it isn't, then the 'pos' must be inside the change. How we update it will - // depend if delta is positive or negative. If delta is positive then we have - // something like: - // - // -------------------AAA----------------- - // -------------------BBBCCCCCCC----------------- - // - // In this case, we consider any node that started in the change range to still be - // starting at the same position. - // - // however, if the delta is negative, then we instead have something like this: - // - // -------------------XXXYYYYYYY----------------- - // -------------------ZZZ----------------- - // - // In this case, any element that started in the 'X' range will keep its position. - // However any element that started after that will have their pos adjusted to be - // at the end of the new range. i.e. any node that started in the 'Y' range will - // be adjusted to have their start at the end of the 'Z' range. - // - // The element will keep its position if possible. Or Move backward to the new-end - // if it's in the 'Y' range. - element.pos = Math.min(element.pos, changeRangeNewEnd); - // If the 'end' is after the change range, then we always adjust it by the delta - // amount. However, if the end is in the change range, then how we adjust it - // will depend on if delta is positive or negative. If delta is positive then we - // have something like: - // - // -------------------AAA----------------- - // -------------------BBBCCCCCCC----------------- - // - // In this case, we consider any node that ended inside the change range to keep its - // end position. - // - // however, if the delta is negative, then we instead have something like this: - // - // -------------------XXXYYYYYYY----------------- - // -------------------ZZZ----------------- - // - // In this case, any element that ended in the 'X' range will keep its position. - // However any element that ended after that will have their pos adjusted to be - // at the end of the new range. i.e. any node that ended in the 'Y' range will - // be adjusted to have their end at the end of the 'Z' range. - if (element.end >= changeRangeOldEnd) { - // Element ends after the change range. Always adjust the end pos. - element.end += delta; + function bindChildren(node) { + if (skipTransformFlagAggregation) { + bindChildrenWorker(node); + } + else if (node.transformFlags & 536870912 /* HasComputedFlags */) { + skipTransformFlagAggregation = true; + bindChildrenWorker(node); + skipTransformFlagAggregation = false; } else { - // Element ends in the change range. The element will keep its position if - // possible. Or Move backward to the new-end if it's in the 'Y' range. - element.end = Math.min(element.end, changeRangeNewEnd); + var savedSubtreeTransformFlags = subtreeTransformFlags; + subtreeTransformFlags = 0; + bindChildrenWorker(node); + subtreeTransformFlags = savedSubtreeTransformFlags | computeTransformFlagsForNode(node, subtreeTransformFlags); } - ts.Debug.assert(element.pos <= element.end); - if (element.parent) { - ts.Debug.assert(element.pos >= element.parent.pos); - ts.Debug.assert(element.end <= element.parent.end); + } + function bindChildrenWorker(node) { + // Binding of JsDocComment should be done before the current block scope container changes. + // because the scope of JsDocComment should not be affected by whether the current node is a + // container or not. + if (ts.isInJavaScriptFile(node) && node.jsDocComments) { + ts.forEach(node.jsDocComments, bind); + } + if (checkUnreachable(node)) { + ts.forEachChild(node, bind); + return; + } + switch (node.kind) { + case 205 /* WhileStatement */: + bindWhileStatement(node); + break; + case 204 /* DoStatement */: + bindDoStatement(node); + break; + case 206 /* ForStatement */: + bindForStatement(node); + break; + case 207 /* ForInStatement */: + case 208 /* ForOfStatement */: + bindForInOrForOfStatement(node); + break; + case 203 /* IfStatement */: + bindIfStatement(node); + break; + case 211 /* ReturnStatement */: + case 215 /* ThrowStatement */: + bindReturnOrThrow(node); + break; + case 210 /* BreakStatement */: + case 209 /* ContinueStatement */: + bindBreakOrContinueStatement(node); + break; + case 216 /* TryStatement */: + bindTryStatement(node); + break; + case 213 /* SwitchStatement */: + bindSwitchStatement(node); + break; + case 227 /* CaseBlock */: + bindCaseBlock(node); + break; + case 249 /* CaseClause */: + bindCaseClause(node); + break; + case 214 /* LabeledStatement */: + bindLabeledStatement(node); + break; + case 185 /* PrefixUnaryExpression */: + bindPrefixUnaryExpressionFlow(node); + break; + case 186 /* PostfixUnaryExpression */: + bindPostfixUnaryExpressionFlow(node); + break; + case 187 /* BinaryExpression */: + bindBinaryExpressionFlow(node); + break; + case 181 /* DeleteExpression */: + bindDeleteExpressionFlow(node); + break; + case 188 /* ConditionalExpression */: + bindConditionalExpressionFlow(node); + break; + case 218 /* VariableDeclaration */: + bindVariableDeclarationFlow(node); + break; + case 174 /* CallExpression */: + bindCallExpressionFlow(node); + break; + default: + ts.forEachChild(node, bind); + break; } } - function checkNodePositions(node, aggressiveChecks) { - if (aggressiveChecks) { - var pos_2 = node.pos; - forEachChild(node, function (child) { - ts.Debug.assert(child.pos >= pos_2); - pos_2 = child.end; - }); - ts.Debug.assert(pos_2 <= node.end); + function isNarrowingExpression(expr) { + switch (expr.kind) { + case 69 /* Identifier */: + case 97 /* ThisKeyword */: + case 172 /* PropertyAccessExpression */: + return isNarrowableReference(expr); + case 174 /* CallExpression */: + return hasNarrowableArgument(expr); + case 178 /* ParenthesizedExpression */: + return isNarrowingExpression(expr.expression); + case 187 /* BinaryExpression */: + return isNarrowingBinaryExpression(expr); + case 185 /* PrefixUnaryExpression */: + return expr.operator === 49 /* ExclamationToken */ && isNarrowingExpression(expr.operand); } + return false; } - function updateTokenPositionsAndMarkElements(sourceFile, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta, oldText, newText, aggressiveChecks) { - visitNode(sourceFile); - return; - function visitNode(child) { - ts.Debug.assert(child.pos <= child.end); - if (child.pos > changeRangeOldEnd) { - // Node is entirely past the change range. We need to move both its pos and - // end, forward or backward appropriately. - moveElementEntirelyPastChangeRange(child, /*isArray*/ false, delta, oldText, newText, aggressiveChecks); - return; - } - // Check if the element intersects the change range. If it does, then it is not - // reusable. Also, we'll need to recurse to see what constituent portions we may - // be able to use. - var fullEnd = child.end; - if (fullEnd >= changeStart) { - child.intersectsChange = true; - child._children = undefined; - // Adjust the pos or end (or both) of the intersecting element accordingly. - adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta); - forEachChild(child, visitNode, visitArray); - checkNodePositions(child, aggressiveChecks); - return; + function isNarrowableReference(expr) { + return expr.kind === 69 /* Identifier */ || + expr.kind === 97 /* ThisKeyword */ || + expr.kind === 172 /* PropertyAccessExpression */ && isNarrowableReference(expr.expression); + } + function hasNarrowableArgument(expr) { + if (expr.arguments) { + for (var _i = 0, _a = expr.arguments; _i < _a.length; _i++) { + var argument = _a[_i]; + if (isNarrowableReference(argument)) { + return true; + } } - // Otherwise, the node is entirely before the change range. No need to do anything with it. - ts.Debug.assert(fullEnd < changeStart); } - function visitArray(array) { - ts.Debug.assert(array.pos <= array.end); - if (array.pos > changeRangeOldEnd) { - // Array is entirely after the change range. We need to move it, and move any of - // its children. - moveElementEntirelyPastChangeRange(array, /*isArray*/ true, delta, oldText, newText, aggressiveChecks); - return; - } - // Check if the element intersects the change range. If it does, then it is not - // reusable. Also, we'll need to recurse to see what constituent portions we may - // be able to use. - var fullEnd = array.end; - if (fullEnd >= changeStart) { - array.intersectsChange = true; - array._children = undefined; - // Adjust the pos or end (or both) of the intersecting array accordingly. - adjustIntersectingElement(array, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta); - for (var _i = 0, array_10 = array; _i < array_10.length; _i++) { - var node = array_10[_i]; - visitNode(node); + if (expr.expression.kind === 172 /* PropertyAccessExpression */ && + isNarrowableReference(expr.expression.expression)) { + return true; + } + return false; + } + function isNarrowingTypeofOperands(expr1, expr2) { + return expr1.kind === 182 /* TypeOfExpression */ && isNarrowableOperand(expr1.expression) && expr2.kind === 9 /* StringLiteral */; + } + function isNarrowingBinaryExpression(expr) { + switch (expr.operatorToken.kind) { + case 56 /* EqualsToken */: + return isNarrowableReference(expr.left); + case 30 /* EqualsEqualsToken */: + case 31 /* ExclamationEqualsToken */: + case 32 /* EqualsEqualsEqualsToken */: + case 33 /* ExclamationEqualsEqualsToken */: + return isNarrowableOperand(expr.left) || isNarrowableOperand(expr.right) || + isNarrowingTypeofOperands(expr.right, expr.left) || isNarrowingTypeofOperands(expr.left, expr.right); + case 91 /* InstanceOfKeyword */: + return isNarrowableOperand(expr.left); + case 24 /* CommaToken */: + return isNarrowingExpression(expr.right); + } + return false; + } + function isNarrowableOperand(expr) { + switch (expr.kind) { + case 178 /* ParenthesizedExpression */: + return isNarrowableOperand(expr.expression); + case 187 /* BinaryExpression */: + switch (expr.operatorToken.kind) { + case 56 /* EqualsToken */: + return isNarrowableOperand(expr.left); + case 24 /* CommaToken */: + return isNarrowableOperand(expr.right); } - return; - } - // Otherwise, the array is entirely before the change range. No need to do anything with it. - ts.Debug.assert(fullEnd < changeStart); } + return isNarrowableReference(expr); } - function extendToAffectedRange(sourceFile, changeRange) { - // Consider the following code: - // void foo() { /; } - // - // If the text changes with an insertion of / just before the semicolon then we end up with: - // void foo() { //; } - // - // If we were to just use the changeRange a is, then we would not rescan the { token - // (as it does not intersect the actual original change range). Because an edit may - // change the token touching it, we actually need to look back *at least* one token so - // that the prior token sees that change. - var maxLookahead = 1; - var start = changeRange.span.start; - // the first iteration aligns us with the change start. subsequent iteration move us to - // the left by maxLookahead tokens. We only need to do this as long as we're not at the - // start of the tree. - for (var i = 0; start > 0 && i <= maxLookahead; i++) { - var nearestNode = findNearestNodeStartingBeforeOrAtPosition(sourceFile, start); - ts.Debug.assert(nearestNode.pos <= start); - var position = nearestNode.pos; - start = Math.max(0, position - 1); + function createBranchLabel() { + return { + flags: 4 /* BranchLabel */, + antecedents: undefined + }; + } + function createLoopLabel() { + return { + flags: 8 /* LoopLabel */, + antecedents: undefined + }; + } + function setFlowNodeReferenced(flow) { + // On first reference we set the Referenced flag, thereafter we set the Shared flag + flow.flags |= flow.flags & 256 /* Referenced */ ? 512 /* Shared */ : 256 /* Referenced */; + } + function addAntecedent(label, antecedent) { + if (!(antecedent.flags & 1 /* Unreachable */) && !ts.contains(label.antecedents, antecedent)) { + (label.antecedents || (label.antecedents = [])).push(antecedent); + setFlowNodeReferenced(antecedent); } - var finalSpan = ts.createTextSpanFromBounds(start, ts.textSpanEnd(changeRange.span)); - var finalLength = changeRange.newLength + (changeRange.span.start - start); - return ts.createTextChangeRange(finalSpan, finalLength); } - function findNearestNodeStartingBeforeOrAtPosition(sourceFile, position) { - var bestResult = sourceFile; - var lastNodeEntirelyBeforePosition; - forEachChild(sourceFile, visit); - if (lastNodeEntirelyBeforePosition) { - var lastChildOfLastEntireNodeBeforePosition = getLastChild(lastNodeEntirelyBeforePosition); - if (lastChildOfLastEntireNodeBeforePosition.pos > bestResult.pos) { - bestResult = lastChildOfLastEntireNodeBeforePosition; - } + function createFlowCondition(flags, antecedent, expression) { + if (antecedent.flags & 1 /* Unreachable */) { + return antecedent; } - return bestResult; - function getLastChild(node) { - while (true) { - var lastChild = getLastChildWorker(node); - if (lastChild) { - node = lastChild; - } - else { - return node; - } - } + if (!expression) { + return flags & 32 /* TrueCondition */ ? antecedent : unreachableFlow; } - function getLastChildWorker(node) { - var last = undefined; - forEachChild(node, function (child) { - if (ts.nodeIsPresent(child)) { - last = child; - } - }); - return last; + if (expression.kind === 99 /* TrueKeyword */ && flags & 64 /* FalseCondition */ || + expression.kind === 84 /* FalseKeyword */ && flags & 32 /* TrueCondition */) { + return unreachableFlow; } - function visit(child) { - if (ts.nodeIsMissing(child)) { - // Missing nodes are effectively invisible to us. We never even consider them - // When trying to find the nearest node before us. - return; - } - // If the child intersects this position, then this node is currently the nearest - // node that starts before the position. - if (child.pos <= position) { - if (child.pos >= bestResult.pos) { - // This node starts before the position, and is closer to the position than - // the previous best node we found. It is now the new best node. - bestResult = child; - } - // Now, the node may overlap the position, or it may end entirely before the - // position. If it overlaps with the position, then either it, or one of its - // children must be the nearest node before the position. So we can just - // recurse into this child to see if we can find something better. - if (position < child.end) { - // The nearest node is either this child, or one of the children inside - // of it. We've already marked this child as the best so far. Recurse - // in case one of the children is better. - forEachChild(child, visit); - // Once we look at the children of this node, then there's no need to - // continue any further. - return true; - } - else { - ts.Debug.assert(child.end <= position); - // The child ends entirely before this position. Say you have the following - // (where $ is the position) - // - // ? $ : <...> <...> - // - // We would want to find the nearest preceding node in "complex expr 2". - // To support that, we keep track of this node, and once we're done searching - // for a best node, we recurse down this node to see if we can find a good - // result in it. - // - // This approach allows us to quickly skip over nodes that are entirely - // before the position, while still allowing us to find any nodes in the - // last one that might be what we want. - lastNodeEntirelyBeforePosition = child; - } - } - else { - ts.Debug.assert(child.pos > position); - // We're now at a node that is entirely past the position we're searching for. - // This node (and all following nodes) could never contribute to the result, - // so just skip them by returning 'true' here. - return true; - } + if (!isNarrowingExpression(expression)) { + return antecedent; } + setFlowNodeReferenced(antecedent); + return { + flags: flags, + expression: expression, + antecedent: antecedent + }; } - function checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks) { - var oldText = sourceFile.text; - if (textChangeRange) { - ts.Debug.assert((oldText.length - textChangeRange.span.length + textChangeRange.newLength) === newText.length); - if (aggressiveChecks || ts.Debug.shouldAssert(3 /* VeryAggressive */)) { - var oldTextPrefix = oldText.substr(0, textChangeRange.span.start); - var newTextPrefix = newText.substr(0, textChangeRange.span.start); - ts.Debug.assert(oldTextPrefix === newTextPrefix); - var oldTextSuffix = oldText.substring(ts.textSpanEnd(textChangeRange.span), oldText.length); - var newTextSuffix = newText.substring(ts.textSpanEnd(ts.textChangeRangeNewSpan(textChangeRange)), newText.length); - ts.Debug.assert(oldTextSuffix === newTextSuffix); - } + function createFlowSwitchClause(antecedent, switchStatement, clauseStart, clauseEnd) { + if (!isNarrowingExpression(switchStatement.expression)) { + return antecedent; } + setFlowNodeReferenced(antecedent); + return { + flags: 128 /* SwitchClause */, + switchStatement: switchStatement, + clauseStart: clauseStart, + clauseEnd: clauseEnd, + antecedent: antecedent + }; } - function createSyntaxCursor(sourceFile) { - var currentArray = sourceFile.statements; - var currentArrayIndex = 0; - ts.Debug.assert(currentArrayIndex < currentArray.length); - var current = currentArray[currentArrayIndex]; - var lastQueriedPosition = -1 /* Value */; + function createFlowAssignment(antecedent, node) { + setFlowNodeReferenced(antecedent); return { - currentNode: function (position) { - // Only compute the current node if the position is different than the last time - // we were asked. The parser commonly asks for the node at the same position - // twice. Once to know if can read an appropriate list element at a certain point, - // and then to actually read and consume the node. - if (position !== lastQueriedPosition) { - // Much of the time the parser will need the very next node in the array that - // we just returned a node from.So just simply check for that case and move - // forward in the array instead of searching for the node again. - if (current && current.end === position && currentArrayIndex < (currentArray.length - 1)) { - currentArrayIndex++; - current = currentArray[currentArrayIndex]; - } - // If we don't have a node, or the node we have isn't in the right position, - // then try to find a viable node at the position requested. - if (!current || current.pos !== position) { - findHighestListElementThatStartsAtPosition(position); - } - } - // Cache this query so that we don't do any extra work if the parser calls back - // into us. Note: this is very common as the parser will make pairs of calls like - // 'isListElement -> parseListElement'. If we were unable to find a node when - // called with 'isListElement', we don't want to redo the work when parseListElement - // is called immediately after. - lastQueriedPosition = position; - // Either we don'd have a node, or we have a node at the position being asked for. - ts.Debug.assert(!current || current.pos === position); - return current; - } + flags: 16 /* Assignment */, + antecedent: antecedent, + node: node }; - // Finds the highest element in the tree we can find that starts at the provided position. - // The element must be a direct child of some node list in the tree. This way after we - // return it, we can easily return its next sibling in the list. - function findHighestListElementThatStartsAtPosition(position) { - // Clear out any cached state about the last node we found. - currentArray = undefined; - currentArrayIndex = -1 /* Value */; - current = undefined; - // Recurse into the source file to find the highest node at this position. - forEachChild(sourceFile, visitNode, visitArray); - return; - function visitNode(node) { - if (position >= node.pos && position < node.end) { - // Position was within this node. Keep searching deeper to find the node. - forEachChild(node, visitNode, visitArray); - // don't proceed any further in the search. - return true; - } - // position wasn't in this node, have to keep searching. - return false; + } + function finishFlowLabel(flow) { + var antecedents = flow.antecedents; + if (!antecedents) { + return unreachableFlow; + } + if (antecedents.length === 1) { + return antecedents[0]; + } + return flow; + } + function isStatementCondition(node) { + var parent = node.parent; + switch (parent.kind) { + case 203 /* IfStatement */: + case 205 /* WhileStatement */: + case 204 /* DoStatement */: + return parent.expression === node; + case 206 /* ForStatement */: + case 188 /* ConditionalExpression */: + return parent.condition === node; + } + return false; + } + function isLogicalExpression(node) { + while (true) { + if (node.kind === 178 /* ParenthesizedExpression */) { + node = node.expression; } - function visitArray(array) { - if (position >= array.pos && position < array.end) { - // position was in this array. Search through this array to see if we find a - // viable element. - for (var i = 0, n = array.length; i < n; i++) { - var child = array[i]; - if (child) { - if (child.pos === position) { - // Found the right node. We're done. - currentArray = array; - currentArrayIndex = i; - current = child; - return true; - } - else { - if (child.pos < position && position < child.end) { - // Position in somewhere within this child. Search in it and - // stop searching in this array. - forEachChild(child, visitNode, visitArray); - return true; - } - } - } - } - } - // position wasn't in this array, have to keep searching. - return false; + else if (node.kind === 185 /* PrefixUnaryExpression */ && node.operator === 49 /* ExclamationToken */) { + node = node.operand; + } + else { + return node.kind === 187 /* BinaryExpression */ && (node.operatorToken.kind === 51 /* AmpersandAmpersandToken */ || + node.operatorToken.kind === 52 /* BarBarToken */); } } } - var InvalidPosition; - (function (InvalidPosition) { - InvalidPosition[InvalidPosition["Value"] = -1] = "Value"; - })(InvalidPosition || (InvalidPosition = {})); - })(IncrementalParser || (IncrementalParser = {})); -})(ts || (ts = {})); -/// -/// -/* @internal */ -var ts; -(function (ts) { - (function (ModuleInstanceState) { - ModuleInstanceState[ModuleInstanceState["NonInstantiated"] = 0] = "NonInstantiated"; - ModuleInstanceState[ModuleInstanceState["Instantiated"] = 1] = "Instantiated"; - ModuleInstanceState[ModuleInstanceState["ConstEnumOnly"] = 2] = "ConstEnumOnly"; - })(ts.ModuleInstanceState || (ts.ModuleInstanceState = {})); - var ModuleInstanceState = ts.ModuleInstanceState; - function getModuleInstanceState(node) { - // A module is uninstantiated if it contains only - // 1. interface declarations, type alias declarations - if (node.kind === 222 /* InterfaceDeclaration */ || node.kind === 223 /* TypeAliasDeclaration */) { - return 0 /* NonInstantiated */; + function isTopLevelLogicalExpression(node) { + while (node.parent.kind === 178 /* ParenthesizedExpression */ || + node.parent.kind === 185 /* PrefixUnaryExpression */ && + node.parent.operator === 49 /* ExclamationToken */) { + node = node.parent; + } + return !isStatementCondition(node) && !isLogicalExpression(node.parent); } - else if (ts.isConstEnumDeclaration(node)) { - return 2 /* ConstEnumOnly */; + function bindCondition(node, trueTarget, falseTarget) { + var saveTrueTarget = currentTrueTarget; + var saveFalseTarget = currentFalseTarget; + currentTrueTarget = trueTarget; + currentFalseTarget = falseTarget; + bind(node); + currentTrueTarget = saveTrueTarget; + currentFalseTarget = saveFalseTarget; + if (!node || !isLogicalExpression(node)) { + addAntecedent(trueTarget, createFlowCondition(32 /* TrueCondition */, currentFlow, node)); + addAntecedent(falseTarget, createFlowCondition(64 /* FalseCondition */, currentFlow, node)); + } } - else if ((node.kind === 230 /* ImportDeclaration */ || node.kind === 229 /* ImportEqualsDeclaration */) && !(node.flags & 1 /* Export */)) { - return 0 /* NonInstantiated */; + function bindIterativeStatement(node, breakTarget, continueTarget) { + var saveBreakTarget = currentBreakTarget; + var saveContinueTarget = currentContinueTarget; + currentBreakTarget = breakTarget; + currentContinueTarget = continueTarget; + bind(node); + currentBreakTarget = saveBreakTarget; + currentContinueTarget = saveContinueTarget; } - else if (node.kind === 226 /* ModuleBlock */) { - var state_1 = 0 /* NonInstantiated */; - ts.forEachChild(node, function (n) { - switch (getModuleInstanceState(n)) { - case 0 /* NonInstantiated */: - // child is non-instantiated - continue searching - return false; - case 2 /* ConstEnumOnly */: - // child is const enum only - record state and continue searching - state_1 = 2 /* ConstEnumOnly */; - return false; - case 1 /* Instantiated */: - // child is instantiated - record state and stop - state_1 = 1 /* Instantiated */; - return true; - } - }); - return state_1; + function bindWhileStatement(node) { + var preWhileLabel = createLoopLabel(); + var preBodyLabel = createBranchLabel(); + var postWhileLabel = createBranchLabel(); + addAntecedent(preWhileLabel, currentFlow); + currentFlow = preWhileLabel; + bindCondition(node.expression, preBodyLabel, postWhileLabel); + currentFlow = finishFlowLabel(preBodyLabel); + bindIterativeStatement(node.statement, postWhileLabel, preWhileLabel); + addAntecedent(preWhileLabel, currentFlow); + currentFlow = finishFlowLabel(postWhileLabel); + } + function bindDoStatement(node) { + var preDoLabel = createLoopLabel(); + var preConditionLabel = createBranchLabel(); + var postDoLabel = createBranchLabel(); + addAntecedent(preDoLabel, currentFlow); + currentFlow = preDoLabel; + bindIterativeStatement(node.statement, postDoLabel, preConditionLabel); + addAntecedent(preConditionLabel, currentFlow); + currentFlow = finishFlowLabel(preConditionLabel); + bindCondition(node.expression, preDoLabel, postDoLabel); + currentFlow = finishFlowLabel(postDoLabel); + } + function bindForStatement(node) { + var preLoopLabel = createLoopLabel(); + var preBodyLabel = createBranchLabel(); + var postLoopLabel = createBranchLabel(); + bind(node.initializer); + addAntecedent(preLoopLabel, currentFlow); + currentFlow = preLoopLabel; + bindCondition(node.condition, preBodyLabel, postLoopLabel); + currentFlow = finishFlowLabel(preBodyLabel); + bindIterativeStatement(node.statement, postLoopLabel, preLoopLabel); + bind(node.incrementor); + addAntecedent(preLoopLabel, currentFlow); + currentFlow = finishFlowLabel(postLoopLabel); } - else if (node.kind === 225 /* ModuleDeclaration */) { - var body = node.body; - return body ? getModuleInstanceState(body) : 1 /* Instantiated */; + function bindForInOrForOfStatement(node) { + var preLoopLabel = createLoopLabel(); + var postLoopLabel = createBranchLabel(); + addAntecedent(preLoopLabel, currentFlow); + currentFlow = preLoopLabel; + bind(node.expression); + addAntecedent(postLoopLabel, currentFlow); + bind(node.initializer); + if (node.initializer.kind !== 219 /* VariableDeclarationList */) { + bindAssignmentTargetFlow(node.initializer); + } + bindIterativeStatement(node.statement, postLoopLabel, preLoopLabel); + addAntecedent(preLoopLabel, currentFlow); + currentFlow = finishFlowLabel(postLoopLabel); } - else { - return 1 /* Instantiated */; + function bindIfStatement(node) { + var thenLabel = createBranchLabel(); + var elseLabel = createBranchLabel(); + var postIfLabel = createBranchLabel(); + bindCondition(node.expression, thenLabel, elseLabel); + currentFlow = finishFlowLabel(thenLabel); + bind(node.thenStatement); + addAntecedent(postIfLabel, currentFlow); + currentFlow = finishFlowLabel(elseLabel); + bind(node.elseStatement); + addAntecedent(postIfLabel, currentFlow); + currentFlow = finishFlowLabel(postIfLabel); } - } - ts.getModuleInstanceState = getModuleInstanceState; - var ContainerFlags; - (function (ContainerFlags) { - // The current node is not a container, and no container manipulation should happen before - // recursing into it. - ContainerFlags[ContainerFlags["None"] = 0] = "None"; - // The current node is a container. It should be set as the current container (and block- - // container) before recursing into it. The current node does not have locals. Examples: - // - // Classes, ObjectLiterals, TypeLiterals, Interfaces... - ContainerFlags[ContainerFlags["IsContainer"] = 1] = "IsContainer"; - // The current node is a block-scoped-container. It should be set as the current block- - // container before recursing into it. Examples: - // - // Blocks (when not parented by functions), Catch clauses, For/For-in/For-of statements... - ContainerFlags[ContainerFlags["IsBlockScopedContainer"] = 2] = "IsBlockScopedContainer"; - // The current node is the container of a control flow path. The current control flow should - // be saved and restored, and a new control flow initialized within the container. - ContainerFlags[ContainerFlags["IsControlFlowContainer"] = 4] = "IsControlFlowContainer"; - ContainerFlags[ContainerFlags["IsFunctionLike"] = 8] = "IsFunctionLike"; - ContainerFlags[ContainerFlags["IsFunctionExpression"] = 16] = "IsFunctionExpression"; - ContainerFlags[ContainerFlags["HasLocals"] = 32] = "HasLocals"; - ContainerFlags[ContainerFlags["IsInterface"] = 64] = "IsInterface"; - })(ContainerFlags || (ContainerFlags = {})); - var binder = createBinder(); - function bindSourceFile(file, options) { - ts.performance.mark("beforeBind"); - binder(file, options); - ts.performance.mark("afterBind"); - ts.performance.measure("Bind", "beforeBind", "afterBind"); - } - ts.bindSourceFile = bindSourceFile; - function createBinder() { - var file; - var options; - var languageVersion; - var parent; - var container; - var blockScopeContainer; - var lastContainer; - var seenThisKeyword; - // state used by control flow analysis - var currentFlow; - var currentBreakTarget; - var currentContinueTarget; - var currentReturnTarget; - var currentTrueTarget; - var currentFalseTarget; - var preSwitchCaseFlow; - var activeLabels; - var hasExplicitReturn; - // state used for emit helpers - var emitFlags; - // If this file is an external module, then it is automatically in strict-mode according to - // ES6. If it is not an external module, then we'll determine if it is in strict mode or - // not depending on if we see "use strict" in certain places (or if we hit a class/namespace). - var inStrictMode; - var symbolCount = 0; - var Symbol; - var classifiableNames; - var unreachableFlow = { flags: 1 /* Unreachable */ }; - var reportedUnreachableFlow = { flags: 1 /* Unreachable */ }; - function bindSourceFile(f, opts) { - file = f; - options = opts; - languageVersion = ts.getEmitScriptTarget(options); - inStrictMode = !!file.externalModuleIndicator; - classifiableNames = ts.createMap(); - symbolCount = 0; - Symbol = ts.objectAllocator.getSymbolConstructor(); - if (!file.locals) { - bind(file); - file.symbolCount = symbolCount; - file.classifiableNames = classifiableNames; + function bindReturnOrThrow(node) { + bind(node.expression); + if (node.kind === 211 /* ReturnStatement */) { + hasExplicitReturn = true; + if (currentReturnTarget) { + addAntecedent(currentReturnTarget, currentFlow); + } } - file = undefined; - options = undefined; - languageVersion = undefined; - parent = undefined; - container = undefined; - blockScopeContainer = undefined; - lastContainer = undefined; - seenThisKeyword = false; - currentFlow = undefined; - currentBreakTarget = undefined; - currentContinueTarget = undefined; - currentReturnTarget = undefined; - currentTrueTarget = undefined; - currentFalseTarget = undefined; - activeLabels = undefined; - hasExplicitReturn = false; - emitFlags = 0 /* None */; + currentFlow = unreachableFlow; } - return bindSourceFile; - function createSymbol(flags, name) { - symbolCount++; - return new Symbol(flags, name); + function findActiveLabel(name) { + if (activeLabels) { + for (var _i = 0, activeLabels_1 = activeLabels; _i < activeLabels_1.length; _i++) { + var label = activeLabels_1[_i]; + if (label.name === name) { + return label; + } + } + } + return undefined; } - function addDeclarationToSymbol(symbol, node, symbolFlags) { - symbol.flags |= symbolFlags; - node.symbol = symbol; - if (!symbol.declarations) { - symbol.declarations = []; + function bindbreakOrContinueFlow(node, breakTarget, continueTarget) { + var flowLabel = node.kind === 210 /* BreakStatement */ ? breakTarget : continueTarget; + if (flowLabel) { + addAntecedent(flowLabel, currentFlow); + currentFlow = unreachableFlow; } - symbol.declarations.push(node); - if (symbolFlags & 1952 /* HasExports */ && !symbol.exports) { - symbol.exports = ts.createMap(); + } + function bindBreakOrContinueStatement(node) { + bind(node.label); + if (node.label) { + var activeLabel = findActiveLabel(node.label.text); + if (activeLabel) { + activeLabel.referenced = true; + bindbreakOrContinueFlow(node, activeLabel.breakTarget, activeLabel.continueTarget); + } } - if (symbolFlags & 6240 /* HasMembers */ && !symbol.members) { - symbol.members = ts.createMap(); + else { + bindbreakOrContinueFlow(node, currentBreakTarget, currentContinueTarget); } - if (symbolFlags & 107455 /* Value */) { - var valueDeclaration = symbol.valueDeclaration; - if (!valueDeclaration || - (valueDeclaration.kind !== node.kind && valueDeclaration.kind === 225 /* ModuleDeclaration */)) { - // other kinds of value declarations take precedence over modules - symbol.valueDeclaration = node; - } + } + function bindTryStatement(node) { + var postFinallyLabel = createBranchLabel(); + var preTryFlow = currentFlow; + // TODO: Every statement in try block is potentially an exit point! + bind(node.tryBlock); + addAntecedent(postFinallyLabel, currentFlow); + if (node.catchClause) { + currentFlow = preTryFlow; + bind(node.catchClause); + addAntecedent(postFinallyLabel, currentFlow); + } + if (node.finallyBlock) { + currentFlow = preTryFlow; + bind(node.finallyBlock); } + currentFlow = finishFlowLabel(postFinallyLabel); } - // Should not be called on a declaration with a computed property name, - // unless it is a well known Symbol. - function getDeclarationName(node) { - if (node.name) { - if (ts.isAmbientModule(node)) { - return ts.isGlobalScopeAugmentation(node) ? "__global" : "\"" + node.name.text + "\""; + function bindSwitchStatement(node) { + var postSwitchLabel = createBranchLabel(); + bind(node.expression); + var saveBreakTarget = currentBreakTarget; + var savePreSwitchCaseFlow = preSwitchCaseFlow; + currentBreakTarget = postSwitchLabel; + preSwitchCaseFlow = currentFlow; + bind(node.caseBlock); + addAntecedent(postSwitchLabel, currentFlow); + var hasDefault = ts.forEach(node.caseBlock.clauses, function (c) { return c.kind === 250 /* DefaultClause */; }); + // We mark a switch statement as possibly exhaustive if it has no default clause and if all + // case clauses have unreachable end points (e.g. they all return). + node.possiblyExhaustive = !hasDefault && !postSwitchLabel.antecedents; + if (!hasDefault) { + addAntecedent(postSwitchLabel, createFlowSwitchClause(preSwitchCaseFlow, node, 0, 0)); + } + currentBreakTarget = saveBreakTarget; + preSwitchCaseFlow = savePreSwitchCaseFlow; + currentFlow = finishFlowLabel(postSwitchLabel); + } + function bindCaseBlock(node) { + var clauses = node.clauses; + var fallthroughFlow = unreachableFlow; + for (var i = 0; i < clauses.length; i++) { + var clauseStart = i; + while (!clauses[i].statements.length && i + 1 < clauses.length) { + bind(clauses[i]); + i++; } - if (node.name.kind === 140 /* ComputedPropertyName */) { - var nameExpression = node.name.expression; - // treat computed property names where expression is string/numeric literal as just string/numeric literal - if (ts.isStringOrNumericLiteral(nameExpression.kind)) { - return nameExpression.text; - } - ts.Debug.assert(ts.isWellKnownSymbolSyntactically(nameExpression)); - return ts.getPropertyNameForKnownSymbolName(nameExpression.name.text); + var preCaseLabel = createBranchLabel(); + addAntecedent(preCaseLabel, createFlowSwitchClause(preSwitchCaseFlow, node.parent, clauseStart, i + 1)); + addAntecedent(preCaseLabel, fallthroughFlow); + currentFlow = finishFlowLabel(preCaseLabel); + var clause = clauses[i]; + bind(clause); + fallthroughFlow = currentFlow; + if (!(currentFlow.flags & 1 /* Unreachable */) && i !== clauses.length - 1 && options.noFallthroughCasesInSwitch) { + errorOnFirstToken(clause, ts.Diagnostics.Fallthrough_case_in_switch); } - return node.name.text; - } - switch (node.kind) { - case 148 /* Constructor */: - return "__constructor"; - case 156 /* FunctionType */: - case 151 /* CallSignature */: - return "__call"; - case 157 /* ConstructorType */: - case 152 /* ConstructSignature */: - return "__new"; - case 153 /* IndexSignature */: - return "__index"; - case 236 /* ExportDeclaration */: - return "__export"; - case 235 /* ExportAssignment */: - return node.isExportEquals ? "export=" : "default"; - case 187 /* BinaryExpression */: - switch (ts.getSpecialPropertyAssignmentKind(node)) { - case 2 /* ModuleExports */: - // module.exports = ... - return "export="; - case 1 /* ExportsProperty */: - case 4 /* ThisProperty */: - // exports.x = ... or this.y = ... - return node.left.name.text; - case 3 /* PrototypeProperty */: - // className.prototype.methodName = ... - return node.left.expression.name.text; - } - ts.Debug.fail("Unknown binary declaration kind"); - break; - case 220 /* FunctionDeclaration */: - case 221 /* ClassDeclaration */: - return node.flags & 512 /* Default */ ? "default" : undefined; - case 269 /* JSDocFunctionType */: - return ts.isJSDocConstructSignature(node) ? "__new" : "__call"; - case 142 /* Parameter */: - // Parameters with names are handled at the top of this function. Parameters - // without names can only come from JSDocFunctionTypes. - ts.Debug.assert(node.parent.kind === 269 /* JSDocFunctionType */); - var functionType = node.parent; - var index = ts.indexOf(functionType.parameters, node); - return "p" + index; - case 279 /* JSDocTypedefTag */: - var parentNode = node.parent && node.parent.parent; - var nameFromParentNode = void 0; - if (parentNode && parentNode.kind === 200 /* VariableStatement */) { - if (parentNode.declarationList.declarations.length > 0) { - var nameIdentifier = parentNode.declarationList.declarations[0].name; - if (nameIdentifier.kind === 69 /* Identifier */) { - nameFromParentNode = nameIdentifier.text; - } - } - } - return nameFromParentNode; } } - function getDisplayName(node) { - return node.name ? ts.declarationNameToString(node.name) : getDeclarationName(node); + function bindCaseClause(node) { + var saveCurrentFlow = currentFlow; + currentFlow = preSwitchCaseFlow; + bind(node.expression); + currentFlow = saveCurrentFlow; + ts.forEach(node.statements, bind); } - /** - * Declares a Symbol for the node and adds it to symbols. Reports errors for conflicting identifier names. - * @param symbolTable - The symbol table which node will be added to. - * @param parent - node's parent declaration. - * @param node - The declaration to be added to the symbol table - * @param includes - The SymbolFlags that node has in addition to its declaration type (eg: export, ambient, etc.) - * @param excludes - The flags which node cannot be declared alongside in a symbol table. Used to report forbidden declarations. - */ - function declareSymbol(symbolTable, parent, node, includes, excludes) { - ts.Debug.assert(!ts.hasDynamicName(node)); - var isDefaultExport = node.flags & 512 /* Default */; - // The exported symbol for an export default function/class node is always named "default" - var name = isDefaultExport && parent ? "default" : getDeclarationName(node); - var symbol; - if (name === undefined) { - symbol = createSymbol(0 /* None */, "__missing"); + function pushActiveLabel(name, breakTarget, continueTarget) { + var activeLabel = { + name: name, + breakTarget: breakTarget, + continueTarget: continueTarget, + referenced: false + }; + (activeLabels || (activeLabels = [])).push(activeLabel); + return activeLabel; + } + function popActiveLabel() { + activeLabels.pop(); + } + function bindLabeledStatement(node) { + var preStatementLabel = createLoopLabel(); + var postStatementLabel = createBranchLabel(); + bind(node.label); + addAntecedent(preStatementLabel, currentFlow); + var activeLabel = pushActiveLabel(node.label.text, postStatementLabel, preStatementLabel); + bind(node.statement); + popActiveLabel(); + if (!activeLabel.referenced && !options.allowUnusedLabels) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(node.label, ts.Diagnostics.Unused_label)); + } + addAntecedent(postStatementLabel, currentFlow); + currentFlow = finishFlowLabel(postStatementLabel); + } + function bindDestructuringTargetFlow(node) { + if (node.kind === 187 /* BinaryExpression */ && node.operatorToken.kind === 56 /* EqualsToken */) { + bindAssignmentTargetFlow(node.left); } else { - // Check and see if the symbol table already has a symbol with this name. If not, - // create a new symbol with this name and add it to the table. Note that we don't - // give the new symbol any flags *yet*. This ensures that it will not conflict - // with the 'excludes' flags we pass in. - // - // If we do get an existing symbol, see if it conflicts with the new symbol we're - // creating. For example, a 'var' symbol and a 'class' symbol will conflict within - // the same symbol table. If we have a conflict, report the issue on each - // declaration we have for this symbol, and then create a new symbol for this - // declaration. - // - // Note that when properties declared in Javascript constructors - // (marked by isReplaceableByMethod) conflict with another symbol, the property loses. - // Always. This allows the common Javascript pattern of overwriting a prototype method - // with an bound instance method of the same type: `this.method = this.method.bind(this)` - // - // If we created a new symbol, either because we didn't have a symbol with this name - // in the symbol table, or we conflicted with an existing symbol, then just add this - // node as the sole declaration of the new symbol. - // - // Otherwise, we'll be merging into a compatible existing symbol (for example when - // you have multiple 'vars' with the same name in the same container). In this case - // just add this node into the declarations list of the symbol. - symbol = symbolTable[name] || (symbolTable[name] = createSymbol(0 /* None */, name)); - if (name && (includes & 788448 /* Classifiable */)) { - classifiableNames[name] = name; - } - if (symbol.flags & excludes) { - if (symbol.isReplaceableByMethod) { - // Javascript constructor-declared symbols can be discarded in favor of - // prototype symbols like methods. - symbol = symbolTable[name] = createSymbol(0 /* None */, name); + bindAssignmentTargetFlow(node); + } + } + function bindAssignmentTargetFlow(node) { + if (isNarrowableReference(node)) { + currentFlow = createFlowAssignment(currentFlow, node); + } + else if (node.kind === 170 /* ArrayLiteralExpression */) { + for (var _i = 0, _a = node.elements; _i < _a.length; _i++) { + var e = _a[_i]; + if (e.kind === 191 /* SpreadElementExpression */) { + bindAssignmentTargetFlow(e.expression); } else { - if (node.name) { - node.name.parent = node; - } - // Report errors every position with duplicate declaration - // Report errors on previous encountered declarations - var message_1 = symbol.flags & 2 /* BlockScopedVariable */ - ? ts.Diagnostics.Cannot_redeclare_block_scoped_variable_0 - : ts.Diagnostics.Duplicate_identifier_0; - ts.forEach(symbol.declarations, function (declaration) { - if (declaration.flags & 512 /* Default */) { - message_1 = ts.Diagnostics.A_module_cannot_have_multiple_default_exports; - } - }); - ts.forEach(symbol.declarations, function (declaration) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(declaration.name || declaration, message_1, getDisplayName(declaration))); - }); - file.bindDiagnostics.push(ts.createDiagnosticForNode(node.name || node, message_1, getDisplayName(node))); - symbol = createSymbol(0 /* None */, name); + bindDestructuringTargetFlow(e); } } } - addDeclarationToSymbol(symbol, node, includes); - symbol.parent = parent; - return symbol; - } - function declareModuleMember(node, symbolFlags, symbolExcludes) { - var hasExportModifier = ts.getCombinedNodeFlags(node) & 1 /* Export */; - if (symbolFlags & 8388608 /* Alias */) { - if (node.kind === 238 /* ExportSpecifier */ || (node.kind === 229 /* ImportEqualsDeclaration */ && hasExportModifier)) { - return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); - } - else { - return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); + else if (node.kind === 171 /* ObjectLiteralExpression */) { + for (var _b = 0, _c = node.properties; _b < _c.length; _b++) { + var p = _c[_b]; + if (p.kind === 253 /* PropertyAssignment */) { + bindDestructuringTargetFlow(p.initializer); + } + else if (p.kind === 254 /* ShorthandPropertyAssignment */) { + bindAssignmentTargetFlow(p.name); + } } } + } + function bindLogicalExpression(node, trueTarget, falseTarget) { + var preRightLabel = createBranchLabel(); + if (node.operatorToken.kind === 51 /* AmpersandAmpersandToken */) { + bindCondition(node.left, preRightLabel, falseTarget); + } else { - // Exported module members are given 2 symbols: A local symbol that is classified with an ExportValue, - // ExportType, or ExportContainer flag, and an associated export symbol with all the correct flags set - // on it. There are 2 main reasons: - // - // 1. We treat locals and exports of the same name as mutually exclusive within a container. - // That means the binder will issue a Duplicate Identifier error if you mix locals and exports - // with the same name in the same container. - // TODO: Make this a more specific error and decouple it from the exclusion logic. - // 2. When we checkIdentifier in the checker, we set its resolved symbol to the local symbol, - // but return the export symbol (by calling getExportSymbolOfValueSymbolIfExported). That way - // when the emitter comes back to it, it knows not to qualify the name if it was found in a containing scope. - // NOTE: Nested ambient modules always should go to to 'locals' table to prevent their automatic merge - // during global merging in the checker. Why? The only case when ambient module is permitted inside another module is module augmentation - // and this case is specially handled. Module augmentations should only be merged with original module definition - // and should never be merged directly with other augmentation, and the latter case would be possible if automatic merge is allowed. - if (!ts.isAmbientModule(node) && (hasExportModifier || container.flags & 8192 /* ExportContext */)) { - var exportKind = (symbolFlags & 107455 /* Value */ ? 1048576 /* ExportValue */ : 0) | - (symbolFlags & 793064 /* Type */ ? 2097152 /* ExportType */ : 0) | - (symbolFlags & 1920 /* Namespace */ ? 4194304 /* ExportNamespace */ : 0); - var local = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes); - local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); - node.localSymbol = local; - return local; - } - else { - return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); - } + bindCondition(node.left, trueTarget, preRightLabel); } + currentFlow = finishFlowLabel(preRightLabel); + bind(node.operatorToken); + bindCondition(node.right, trueTarget, falseTarget); } - // All container nodes are kept on a linked list in declaration order. This list is used by - // the getLocalNameOfContainer function in the type checker to validate that the local name - // used for a container is unique. - function bindContainer(node, containerFlags) { - // Before we recurse into a node's children, we first save the existing parent, container - // and block-container. Then after we pop out of processing the children, we restore - // these saved values. - var saveContainer = container; - var savedBlockScopeContainer = blockScopeContainer; - // Depending on what kind of node this is, we may have to adjust the current container - // and block-container. If the current node is a container, then it is automatically - // considered the current block-container as well. Also, for containers that we know - // may contain locals, we proactively initialize the .locals field. We do this because - // it's highly likely that the .locals will be needed to place some child in (for example, - // a parameter, or variable declaration). - // - // However, we do not proactively create the .locals for block-containers because it's - // totally normal and common for block-containers to never actually have a block-scoped - // variable in them. We don't want to end up allocating an object for every 'block' we - // run into when most of them won't be necessary. - // - // Finally, if this is a block-container, then we clear out any existing .locals object - // it may contain within it. This happens in incremental scenarios. Because we can be - // reusing a node from a previous compilation, that node may have had 'locals' created - // for it. We must clear this so we don't accidentally move any stale data forward from - // a previous compilation. - if (containerFlags & 1 /* IsContainer */) { - container = blockScopeContainer = node; - if (containerFlags & 32 /* HasLocals */) { - container.locals = ts.createMap(); + function bindPrefixUnaryExpressionFlow(node) { + if (node.operator === 49 /* ExclamationToken */) { + var saveTrueTarget = currentTrueTarget; + currentTrueTarget = currentFalseTarget; + currentFalseTarget = saveTrueTarget; + ts.forEachChild(node, bind); + currentFalseTarget = currentTrueTarget; + currentTrueTarget = saveTrueTarget; + } + else { + ts.forEachChild(node, bind); + if (node.operator === 57 /* PlusEqualsToken */ || node.operator === 42 /* MinusMinusToken */) { + bindAssignmentTargetFlow(node.operand); } - addToContainerChain(container); } - else if (containerFlags & 2 /* IsBlockScopedContainer */) { - blockScopeContainer = node; - blockScopeContainer.locals = undefined; + } + function bindPostfixUnaryExpressionFlow(node) { + ts.forEachChild(node, bind); + if (node.operator === 41 /* PlusPlusToken */ || node.operator === 42 /* MinusMinusToken */) { + bindAssignmentTargetFlow(node.operand); } - if (containerFlags & 4 /* IsControlFlowContainer */) { - var saveCurrentFlow = currentFlow; - var saveBreakTarget = currentBreakTarget; - var saveContinueTarget = currentContinueTarget; - var saveReturnTarget = currentReturnTarget; - var saveActiveLabels = activeLabels; - var saveHasExplicitReturn = hasExplicitReturn; - var isIIFE = containerFlags & 16 /* IsFunctionExpression */ && !!ts.getImmediatelyInvokedFunctionExpression(node); - // An IIFE is considered part of the containing control flow. Return statements behave - // similarly to break statements that exit to a label just past the statement body. - if (isIIFE) { - currentReturnTarget = createBranchLabel(); + } + function bindBinaryExpressionFlow(node) { + var operator = node.operatorToken.kind; + if (operator === 51 /* AmpersandAmpersandToken */ || operator === 52 /* BarBarToken */) { + if (isTopLevelLogicalExpression(node)) { + var postExpressionLabel = createBranchLabel(); + bindLogicalExpression(node, postExpressionLabel, postExpressionLabel); + currentFlow = finishFlowLabel(postExpressionLabel); } else { - currentFlow = { flags: 2 /* Start */ }; - if (containerFlags & 16 /* IsFunctionExpression */) { - currentFlow.container = node; - } - currentReturnTarget = undefined; - } - currentBreakTarget = undefined; - currentContinueTarget = undefined; - activeLabels = undefined; - hasExplicitReturn = false; - bindChildren(node); - // Reset all reachability check related flags on node (for incremental scenarios) - // Reset all emit helper flags on node (for incremental scenarios) - node.flags &= ~4030464 /* ReachabilityAndEmitFlags */; - if (!(currentFlow.flags & 1 /* Unreachable */) && containerFlags & 8 /* IsFunctionLike */ && ts.nodeIsPresent(node.body)) { - node.flags |= 32768 /* HasImplicitReturn */; - if (hasExplicitReturn) - node.flags |= 65536 /* HasExplicitReturn */; - } - if (node.kind === 256 /* SourceFile */) { - node.flags |= emitFlags; - } - if (isIIFE) { - addAntecedent(currentReturnTarget, currentFlow); - currentFlow = finishFlowLabel(currentReturnTarget); + bindLogicalExpression(node, currentTrueTarget, currentFalseTarget); } - else { - currentFlow = saveCurrentFlow; + } + else { + ts.forEachChild(node, bind); + if (operator === 56 /* EqualsToken */ && !ts.isAssignmentTarget(node)) { + bindAssignmentTargetFlow(node.left); } - currentBreakTarget = saveBreakTarget; - currentContinueTarget = saveContinueTarget; - currentReturnTarget = saveReturnTarget; - activeLabels = saveActiveLabels; - hasExplicitReturn = saveHasExplicitReturn; } - else if (containerFlags & 64 /* IsInterface */) { - seenThisKeyword = false; - bindChildren(node); - node.flags = seenThisKeyword ? node.flags | 16384 /* ContainsThis */ : node.flags & ~16384 /* ContainsThis */; + } + function bindDeleteExpressionFlow(node) { + ts.forEachChild(node, bind); + if (node.expression.kind === 172 /* PropertyAccessExpression */) { + bindAssignmentTargetFlow(node.expression); + } + } + function bindConditionalExpressionFlow(node) { + var trueLabel = createBranchLabel(); + var falseLabel = createBranchLabel(); + var postExpressionLabel = createBranchLabel(); + bindCondition(node.condition, trueLabel, falseLabel); + currentFlow = finishFlowLabel(trueLabel); + bind(node.whenTrue); + addAntecedent(postExpressionLabel, currentFlow); + currentFlow = finishFlowLabel(falseLabel); + bind(node.whenFalse); + addAntecedent(postExpressionLabel, currentFlow); + currentFlow = finishFlowLabel(postExpressionLabel); + } + function bindInitializedVariableFlow(node) { + var name = !ts.isOmittedExpression(node) ? node.name : undefined; + if (ts.isBindingPattern(name)) { + for (var _i = 0, _a = name.elements; _i < _a.length; _i++) { + var child = _a[_i]; + bindInitializedVariableFlow(child); + } } else { - bindChildren(node); + currentFlow = createFlowAssignment(currentFlow, node); } - container = saveContainer; - blockScopeContainer = savedBlockScopeContainer; } - function bindChildren(node) { - // Binding of JsDocComment should be done before the current block scope container changes. - // because the scope of JsDocComment should not be affected by whether the current node is a - // container or not. - if (ts.isInJavaScriptFile(node) && node.jsDocComments) { - for (var _i = 0, _a = node.jsDocComments; _i < _a.length; _i++) { - var jsDocComment = _a[_i]; - bind(jsDocComment); - } + function bindVariableDeclarationFlow(node) { + ts.forEachChild(node, bind); + if (node.initializer || node.parent.parent.kind === 207 /* ForInStatement */ || node.parent.parent.kind === 208 /* ForOfStatement */) { + bindInitializedVariableFlow(node); } - if (checkUnreachable(node)) { + } + function bindCallExpressionFlow(node) { + // If the target of the call expression is a function expression or arrow function we have + // an immediately invoked function expression (IIFE). Initialize the flowNode property to + // the current control flow (which includes evaluation of the IIFE arguments). + var expr = node.expression; + while (expr.kind === 178 /* ParenthesizedExpression */) { + expr = expr.expression; + } + if (expr.kind === 179 /* FunctionExpression */ || expr.kind === 180 /* ArrowFunction */) { + ts.forEach(node.typeArguments, bind); + ts.forEach(node.arguments, bind); + bind(node.expression); + } + else { ts.forEachChild(node, bind); - return; } + } + function getContainerFlags(node) { switch (node.kind) { - case 205 /* WhileStatement */: - bindWhileStatement(node); - break; - case 204 /* DoStatement */: - bindDoStatement(node); - break; + case 192 /* ClassExpression */: + case 221 /* ClassDeclaration */: + case 224 /* EnumDeclaration */: + case 171 /* ObjectLiteralExpression */: + case 159 /* TypeLiteral */: + case 281 /* JSDocTypeLiteral */: + case 265 /* JSDocRecordType */: + return 1 /* IsContainer */; + case 222 /* InterfaceDeclaration */: + return 1 /* IsContainer */ | 64 /* IsInterface */; + case 269 /* JSDocFunctionType */: + case 225 /* ModuleDeclaration */: + case 223 /* TypeAliasDeclaration */: + return 1 /* IsContainer */ | 32 /* HasLocals */; + case 256 /* SourceFile */: + return 1 /* IsContainer */ | 4 /* IsControlFlowContainer */ | 32 /* HasLocals */; + case 148 /* Constructor */: + case 220 /* FunctionDeclaration */: + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 151 /* CallSignature */: + case 152 /* ConstructSignature */: + case 153 /* IndexSignature */: + case 156 /* FunctionType */: + case 157 /* ConstructorType */: + return 1 /* IsContainer */ | 4 /* IsControlFlowContainer */ | 32 /* HasLocals */ | 8 /* IsFunctionLike */; + case 179 /* FunctionExpression */: + case 180 /* ArrowFunction */: + return 1 /* IsContainer */ | 4 /* IsControlFlowContainer */ | 32 /* HasLocals */ | 8 /* IsFunctionLike */ | 16 /* IsFunctionExpression */; + case 226 /* ModuleBlock */: + return 4 /* IsControlFlowContainer */; + case 145 /* PropertyDeclaration */: + return node.initializer ? 4 /* IsControlFlowContainer */ : 0; + case 252 /* CatchClause */: case 206 /* ForStatement */: - bindForStatement(node); - break; case 207 /* ForInStatement */: case 208 /* ForOfStatement */: - bindForInOrForOfStatement(node); - break; - case 203 /* IfStatement */: - bindIfStatement(node); - break; - case 211 /* ReturnStatement */: - case 215 /* ThrowStatement */: - bindReturnOrThrow(node); - break; - case 210 /* BreakStatement */: - case 209 /* ContinueStatement */: - bindBreakOrContinueStatement(node); - break; - case 216 /* TryStatement */: - bindTryStatement(node); - break; - case 213 /* SwitchStatement */: - bindSwitchStatement(node); - break; case 227 /* CaseBlock */: - bindCaseBlock(node); - break; - case 249 /* CaseClause */: - bindCaseClause(node); - break; - case 214 /* LabeledStatement */: - bindLabeledStatement(node); - break; - case 185 /* PrefixUnaryExpression */: - bindPrefixUnaryExpressionFlow(node); - break; - case 187 /* BinaryExpression */: - bindBinaryExpressionFlow(node); - break; - case 181 /* DeleteExpression */: - bindDeleteExpressionFlow(node); - break; - case 188 /* ConditionalExpression */: - bindConditionalExpressionFlow(node); - break; - case 218 /* VariableDeclaration */: - bindVariableDeclarationFlow(node); - break; - case 174 /* CallExpression */: - bindCallExpressionFlow(node); - break; - default: - ts.forEachChild(node, bind); - break; + return 2 /* IsBlockScopedContainer */; + case 199 /* Block */: + // do not treat blocks directly inside a function as a block-scoped-container. + // Locals that reside in this block should go to the function locals. Otherwise 'x' + // would not appear to be a redeclaration of a block scoped local in the following + // example: + // + // function foo() { + // var x; + // let x; + // } + // + // If we placed 'var x' into the function locals and 'let x' into the locals of + // the block, then there would be no collision. + // + // By not creating a new block-scoped-container here, we ensure that both 'var x' + // and 'let x' go into the Function-container's locals, and we do get a collision + // conflict. + return ts.isFunctionLike(node.parent) ? 0 /* None */ : 2 /* IsBlockScopedContainer */; } + return 0 /* None */; } - function isNarrowingExpression(expr) { - switch (expr.kind) { - case 69 /* Identifier */: - case 97 /* ThisKeyword */: - case 172 /* PropertyAccessExpression */: - return isNarrowableReference(expr); - case 174 /* CallExpression */: - return hasNarrowableArgument(expr); - case 178 /* ParenthesizedExpression */: - return isNarrowingExpression(expr.expression); - case 187 /* BinaryExpression */: - return isNarrowingBinaryExpression(expr); - case 185 /* PrefixUnaryExpression */: - return expr.operator === 49 /* ExclamationToken */ && isNarrowingExpression(expr.operand); + function addToContainerChain(next) { + if (lastContainer) { + lastContainer.nextContainer = next; } - return false; + lastContainer = next; } - function isNarrowableReference(expr) { - return expr.kind === 69 /* Identifier */ || - expr.kind === 97 /* ThisKeyword */ || - expr.kind === 172 /* PropertyAccessExpression */ && isNarrowableReference(expr.expression); + function declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes) { + // Just call this directly so that the return type of this function stays "void". + return declareSymbolAndAddToSymbolTableWorker(node, symbolFlags, symbolExcludes); } - function hasNarrowableArgument(expr) { - if (expr.arguments) { - for (var _i = 0, _a = expr.arguments; _i < _a.length; _i++) { - var argument = _a[_i]; - if (isNarrowableReference(argument)) { + function declareSymbolAndAddToSymbolTableWorker(node, symbolFlags, symbolExcludes) { + switch (container.kind) { + // Modules, source files, and classes need specialized handling for how their + // members are declared (for example, a member of a class will go into a specific + // symbol table depending on if it is static or not). We defer to specialized + // handlers to take care of declaring these child members. + case 225 /* ModuleDeclaration */: + return declareModuleMember(node, symbolFlags, symbolExcludes); + case 256 /* SourceFile */: + return declareSourceFileMember(node, symbolFlags, symbolExcludes); + case 192 /* ClassExpression */: + case 221 /* ClassDeclaration */: + return declareClassMember(node, symbolFlags, symbolExcludes); + case 224 /* EnumDeclaration */: + return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); + case 159 /* TypeLiteral */: + case 171 /* ObjectLiteralExpression */: + case 222 /* InterfaceDeclaration */: + case 265 /* JSDocRecordType */: + case 281 /* JSDocTypeLiteral */: + // Interface/Object-types always have their children added to the 'members' of + // their container. They are only accessible through an instance of their + // container, and are never in scope otherwise (even inside the body of the + // object / type / interface declaring them). An exception is type parameters, + // which are in scope without qualification (similar to 'locals'). + return declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); + case 156 /* FunctionType */: + case 157 /* ConstructorType */: + case 151 /* CallSignature */: + case 152 /* ConstructSignature */: + case 153 /* IndexSignature */: + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + case 148 /* Constructor */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + case 180 /* ArrowFunction */: + case 269 /* JSDocFunctionType */: + case 223 /* TypeAliasDeclaration */: + // All the children of these container types are never visible through another + // symbol (i.e. through another symbol's 'exports' or 'members'). Instead, + // they're only accessed 'lexically' (i.e. from code that exists underneath + // their container in the tree. To accomplish this, we simply add their declared + // symbol to the 'locals' of the container. These symbols can then be found as + // the type checker walks up the containers, checking them for matching names. + return declareSymbol(container.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes); + } + } + function declareClassMember(node, symbolFlags, symbolExcludes) { + return ts.hasModifier(node, 32 /* Static */) + ? declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes) + : declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); + } + function declareSourceFileMember(node, symbolFlags, symbolExcludes) { + return ts.isExternalModule(file) + ? declareModuleMember(node, symbolFlags, symbolExcludes) + : declareSymbol(file.locals, undefined, node, symbolFlags, symbolExcludes); + } + function hasExportDeclarations(node) { + var body = node.kind === 256 /* SourceFile */ ? node : node.body; + if (body && (body.kind === 256 /* SourceFile */ || body.kind === 226 /* ModuleBlock */)) { + for (var _i = 0, _a = body.statements; _i < _a.length; _i++) { + var stat = _a[_i]; + if (stat.kind === 236 /* ExportDeclaration */ || stat.kind === 235 /* ExportAssignment */) { return true; } } } - if (expr.expression.kind === 172 /* PropertyAccessExpression */ && - isNarrowableReference(expr.expression.expression)) { - return true; - } return false; } - function isNarrowingTypeofOperands(expr1, expr2) { - return expr1.kind === 182 /* TypeOfExpression */ && isNarrowableOperand(expr1.expression) && expr2.kind === 9 /* StringLiteral */; + function setExportContextFlag(node) { + // A declaration source file or ambient module declaration that contains no export declarations (but possibly regular + // declarations with export modifiers) is an export context in which declarations are implicitly exported. + if (ts.isInAmbientContext(node) && !hasExportDeclarations(node)) { + node.flags |= 32 /* ExportContext */; + } + else { + node.flags &= ~32 /* ExportContext */; + } } - function isNarrowingBinaryExpression(expr) { - switch (expr.operatorToken.kind) { - case 56 /* EqualsToken */: - return isNarrowableReference(expr.left); - case 30 /* EqualsEqualsToken */: - case 31 /* ExclamationEqualsToken */: - case 32 /* EqualsEqualsEqualsToken */: - case 33 /* ExclamationEqualsEqualsToken */: - return isNarrowableOperand(expr.left) || isNarrowableOperand(expr.right) || - isNarrowingTypeofOperands(expr.right, expr.left) || isNarrowingTypeofOperands(expr.left, expr.right); - case 91 /* InstanceOfKeyword */: - return isNarrowableOperand(expr.left); - case 24 /* CommaToken */: - return isNarrowingExpression(expr.right); + function bindModuleDeclaration(node) { + setExportContextFlag(node); + if (ts.isAmbientModule(node)) { + if (ts.hasModifier(node, 1 /* Export */)) { + errorOnFirstToken(node, ts.Diagnostics.export_modifier_cannot_be_applied_to_ambient_modules_and_module_augmentations_since_they_are_always_visible); + } + if (ts.isExternalModuleAugmentation(node)) { + declareSymbolAndAddToSymbolTable(node, 1024 /* NamespaceModule */, 0 /* NamespaceModuleExcludes */); + } + else { + var pattern = void 0; + if (node.name.kind === 9 /* StringLiteral */) { + var text = node.name.text; + if (ts.hasZeroOrOneAsteriskCharacter(text)) { + pattern = ts.tryParsePattern(text); + } + else { + errorOnFirstToken(node.name, ts.Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, text); + } + } + var symbol = declareSymbolAndAddToSymbolTable(node, 512 /* ValueModule */, 106639 /* ValueModuleExcludes */); + if (pattern) { + (file.patternAmbientModules || (file.patternAmbientModules = [])).push({ pattern: pattern, symbol: symbol }); + } + } + } + else { + var state = getModuleInstanceState(node); + if (state === 0 /* NonInstantiated */) { + declareSymbolAndAddToSymbolTable(node, 1024 /* NamespaceModule */, 0 /* NamespaceModuleExcludes */); + } + else { + declareSymbolAndAddToSymbolTable(node, 512 /* ValueModule */, 106639 /* ValueModuleExcludes */); + if (node.symbol.flags & (16 /* Function */ | 32 /* Class */ | 256 /* RegularEnum */)) { + // if module was already merged with some function, class or non-const enum + // treat is a non-const-enum-only + node.symbol.constEnumOnlyModule = false; + } + else { + var currentModuleIsConstEnumOnly = state === 2 /* ConstEnumOnly */; + if (node.symbol.constEnumOnlyModule === undefined) { + // non-merged case - use the current state + node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly; + } + else { + // merged case: module is const enum only if all its pieces are non-instantiated or const enum + node.symbol.constEnumOnlyModule = node.symbol.constEnumOnlyModule && currentModuleIsConstEnumOnly; + } + } + } } - return false; } - function isNarrowableOperand(expr) { - switch (expr.kind) { - case 178 /* ParenthesizedExpression */: - return isNarrowableOperand(expr.expression); - case 187 /* BinaryExpression */: - switch (expr.operatorToken.kind) { - case 56 /* EqualsToken */: - return isNarrowableOperand(expr.left); - case 24 /* CommaToken */: - return isNarrowableOperand(expr.right); + function bindFunctionOrConstructorType(node) { + // For a given function symbol "<...>(...) => T" we want to generate a symbol identical + // to the one we would get for: { <...>(...): T } + // + // We do that by making an anonymous type literal symbol, and then setting the function + // symbol as its sole member. To the rest of the system, this symbol will be indistinguishable + // from an actual type literal symbol you would have gotten had you used the long form. + var symbol = createSymbol(131072 /* Signature */, getDeclarationName(node)); + addDeclarationToSymbol(symbol, node, 131072 /* Signature */); + var typeLiteralSymbol = createSymbol(2048 /* TypeLiteral */, "__type"); + addDeclarationToSymbol(typeLiteralSymbol, node, 2048 /* TypeLiteral */); + typeLiteralSymbol.members = ts.createMap(); + typeLiteralSymbol.members[symbol.name] = symbol; + } + function bindObjectLiteralExpression(node) { + var ElementKind; + (function (ElementKind) { + ElementKind[ElementKind["Property"] = 1] = "Property"; + ElementKind[ElementKind["Accessor"] = 2] = "Accessor"; + })(ElementKind || (ElementKind = {})); + if (inStrictMode) { + var seen = ts.createMap(); + for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { + var prop = _a[_i]; + if (prop.name.kind !== 69 /* Identifier */) { + continue; + } + var identifier = prop.name; + // ECMA-262 11.1.5 Object Initializer + // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true + // a.This production is contained in strict code and IsDataDescriptor(previous) is true and + // IsDataDescriptor(propId.descriptor) is true. + // b.IsDataDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true. + // c.IsAccessorDescriptor(previous) is true and IsDataDescriptor(propId.descriptor) is true. + // d.IsAccessorDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true + // and either both previous and propId.descriptor have[[Get]] fields or both previous and propId.descriptor have[[Set]] fields + var currentKind = prop.kind === 253 /* PropertyAssignment */ || prop.kind === 254 /* ShorthandPropertyAssignment */ || prop.kind === 147 /* MethodDeclaration */ + ? 1 /* Property */ + : 2 /* Accessor */; + var existingKind = seen[identifier.text]; + if (!existingKind) { + seen[identifier.text] = currentKind; + continue; + } + if (currentKind === 1 /* Property */ && existingKind === 1 /* Property */) { + var span_1 = ts.getErrorSpanForNode(file, identifier); + file.bindDiagnostics.push(ts.createFileDiagnostic(file, span_1.start, span_1.length, ts.Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode)); } + } } - return isNarrowableReference(expr); + return bindAnonymousDeclaration(node, 4096 /* ObjectLiteral */, "__object"); } - function createBranchLabel() { - return { - flags: 4 /* BranchLabel */, - antecedents: undefined - }; + function bindAnonymousDeclaration(node, symbolFlags, name) { + var symbol = createSymbol(symbolFlags, name); + addDeclarationToSymbol(symbol, node, symbolFlags); } - function createLoopLabel() { - return { - flags: 8 /* LoopLabel */, - antecedents: undefined - }; + function bindBlockScopedDeclaration(node, symbolFlags, symbolExcludes) { + switch (blockScopeContainer.kind) { + case 225 /* ModuleDeclaration */: + declareModuleMember(node, symbolFlags, symbolExcludes); + break; + case 256 /* SourceFile */: + if (ts.isExternalModule(container)) { + declareModuleMember(node, symbolFlags, symbolExcludes); + break; + } + // fall through. + default: + if (!blockScopeContainer.locals) { + blockScopeContainer.locals = ts.createMap(); + addToContainerChain(blockScopeContainer); + } + declareSymbol(blockScopeContainer.locals, undefined, node, symbolFlags, symbolExcludes); + } } - function setFlowNodeReferenced(flow) { - // On first reference we set the Referenced flag, thereafter we set the Shared flag - flow.flags |= flow.flags & 256 /* Referenced */ ? 512 /* Shared */ : 256 /* Referenced */; + function bindBlockScopedVariableDeclaration(node) { + bindBlockScopedDeclaration(node, 2 /* BlockScopedVariable */, 107455 /* BlockScopedVariableExcludes */); } - function addAntecedent(label, antecedent) { - if (!(antecedent.flags & 1 /* Unreachable */) && !ts.contains(label.antecedents, antecedent)) { - (label.antecedents || (label.antecedents = [])).push(antecedent); - setFlowNodeReferenced(antecedent); + // The binder visits every node in the syntax tree so it is a convenient place to perform a single localized + // check for reserved words used as identifiers in strict mode code. + function checkStrictModeIdentifier(node) { + if (inStrictMode && + node.originalKeywordKind >= 106 /* FirstFutureReservedWord */ && + node.originalKeywordKind <= 114 /* LastFutureReservedWord */ && + !ts.isIdentifierName(node) && + !ts.isInAmbientContext(node)) { + // Report error only if there are no parse errors in file + if (!file.parseDiagnostics.length) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(node, getStrictModeIdentifierMessage(node), ts.declarationNameToString(node))); + } } } - function createFlowCondition(flags, antecedent, expression) { - if (antecedent.flags & 1 /* Unreachable */) { - return antecedent; + function getStrictModeIdentifierMessage(node) { + // Provide specialized messages to help the user understand why we think they're in + // strict mode. + if (ts.getContainingClass(node)) { + return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode; } - if (!expression) { - return flags & 32 /* TrueCondition */ ? antecedent : unreachableFlow; + if (file.externalModuleIndicator) { + return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Modules_are_automatically_in_strict_mode; } - if (expression.kind === 99 /* TrueKeyword */ && flags & 64 /* FalseCondition */ || - expression.kind === 84 /* FalseKeyword */ && flags & 32 /* TrueCondition */) { - return unreachableFlow; + return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode; + } + function checkStrictModeBinaryExpression(node) { + if (inStrictMode && ts.isLeftHandSideExpression(node.left) && ts.isAssignmentOperator(node.operatorToken.kind)) { + // ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an + // Assignment operator(11.13) or of a PostfixExpression(11.3) + checkStrictModeEvalOrArguments(node, node.left); } - if (!isNarrowingExpression(expression)) { - return antecedent; + } + function checkStrictModeCatchClause(node) { + // It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the + // Catch production is eval or arguments + if (inStrictMode && node.variableDeclaration) { + checkStrictModeEvalOrArguments(node, node.variableDeclaration.name); } - setFlowNodeReferenced(antecedent); - return { - flags: flags, - expression: expression, - antecedent: antecedent - }; } - function createFlowSwitchClause(antecedent, switchStatement, clauseStart, clauseEnd) { - if (!isNarrowingExpression(switchStatement.expression)) { - return antecedent; + function checkStrictModeDeleteExpression(node) { + // Grammar checking + if (inStrictMode && node.expression.kind === 69 /* Identifier */) { + // When a delete operator occurs within strict mode code, a SyntaxError is thrown if its + // UnaryExpression is a direct reference to a variable, function argument, or function name + var span_2 = ts.getErrorSpanForNode(file, node.expression); + file.bindDiagnostics.push(ts.createFileDiagnostic(file, span_2.start, span_2.length, ts.Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode)); } - setFlowNodeReferenced(antecedent); - return { - flags: 128 /* SwitchClause */, - switchStatement: switchStatement, - clauseStart: clauseStart, - clauseEnd: clauseEnd, - antecedent: antecedent - }; } - function createFlowAssignment(antecedent, node) { - setFlowNodeReferenced(antecedent); - return { - flags: 16 /* Assignment */, - antecedent: antecedent, - node: node - }; + function isEvalOrArgumentsIdentifier(node) { + return node.kind === 69 /* Identifier */ && + (node.text === "eval" || node.text === "arguments"); } - function finishFlowLabel(flow) { - var antecedents = flow.antecedents; - if (!antecedents) { - return unreachableFlow; + function checkStrictModeEvalOrArguments(contextNode, name) { + if (name && name.kind === 69 /* Identifier */) { + var identifier = name; + if (isEvalOrArgumentsIdentifier(identifier)) { + // We check first if the name is inside class declaration or class expression; if so give explicit message + // otherwise report generic error message. + var span_3 = ts.getErrorSpanForNode(file, name); + file.bindDiagnostics.push(ts.createFileDiagnostic(file, span_3.start, span_3.length, getStrictModeEvalOrArgumentsMessage(contextNode), identifier.text)); + } } - if (antecedents.length === 1) { - return antecedents[0]; + } + function getStrictModeEvalOrArgumentsMessage(node) { + // Provide specialized messages to help the user understand why we think they're in + // strict mode. + if (ts.getContainingClass(node)) { + return ts.Diagnostics.Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode; } - return flow; + if (file.externalModuleIndicator) { + return ts.Diagnostics.Invalid_use_of_0_Modules_are_automatically_in_strict_mode; + } + return ts.Diagnostics.Invalid_use_of_0_in_strict_mode; } - function isStatementCondition(node) { - var parent = node.parent; - switch (parent.kind) { - case 203 /* IfStatement */: - case 205 /* WhileStatement */: - case 204 /* DoStatement */: - return parent.expression === node; - case 206 /* ForStatement */: - case 188 /* ConditionalExpression */: - return parent.condition === node; + function checkStrictModeFunctionName(node) { + if (inStrictMode) { + // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a strict mode FunctionDeclaration or FunctionExpression (13.1)) + checkStrictModeEvalOrArguments(node, node.name); } - return false; } - function isLogicalExpression(node) { - while (true) { - if (node.kind === 178 /* ParenthesizedExpression */) { - node = node.expression; - } - else if (node.kind === 185 /* PrefixUnaryExpression */ && node.operator === 49 /* ExclamationToken */) { - node = node.operand; - } - else { - return node.kind === 187 /* BinaryExpression */ && (node.operatorToken.kind === 51 /* AmpersandAmpersandToken */ || - node.operatorToken.kind === 52 /* BarBarToken */); + function getStrictModeBlockScopeFunctionDeclarationMessage(node) { + // Provide specialized messages to help the user understand why we think they're in + // strict mode. + if (ts.getContainingClass(node)) { + return ts.Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Class_definitions_are_automatically_in_strict_mode; + } + if (file.externalModuleIndicator) { + return ts.Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Modules_are_automatically_in_strict_mode; + } + return ts.Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5; + } + function checkStrictModeFunctionDeclaration(node) { + if (languageVersion < 2 /* ES6 */) { + // Report error if function is not top level function declaration + if (blockScopeContainer.kind !== 256 /* SourceFile */ && + blockScopeContainer.kind !== 225 /* ModuleDeclaration */ && + !ts.isFunctionLike(blockScopeContainer)) { + // We check first if the name is inside class declaration or class expression; if so give explicit message + // otherwise report generic error message. + var errorSpan = ts.getErrorSpanForNode(file, node); + file.bindDiagnostics.push(ts.createFileDiagnostic(file, errorSpan.start, errorSpan.length, getStrictModeBlockScopeFunctionDeclarationMessage(node))); } } } - function isTopLevelLogicalExpression(node) { - while (node.parent.kind === 178 /* ParenthesizedExpression */ || - node.parent.kind === 185 /* PrefixUnaryExpression */ && - node.parent.operator === 49 /* ExclamationToken */) { - node = node.parent; + function checkStrictModeNumericLiteral(node) { + if (inStrictMode && node.isOctalLiteral) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Octal_literals_are_not_allowed_in_strict_mode)); } - return !isStatementCondition(node) && !isLogicalExpression(node.parent); } - function bindCondition(node, trueTarget, falseTarget) { - var saveTrueTarget = currentTrueTarget; - var saveFalseTarget = currentFalseTarget; - currentTrueTarget = trueTarget; - currentFalseTarget = falseTarget; - bind(node); - currentTrueTarget = saveTrueTarget; - currentFalseTarget = saveFalseTarget; - if (!node || !isLogicalExpression(node)) { - addAntecedent(trueTarget, createFlowCondition(32 /* TrueCondition */, currentFlow, node)); - addAntecedent(falseTarget, createFlowCondition(64 /* FalseCondition */, currentFlow, node)); + function checkStrictModePostfixUnaryExpression(node) { + // Grammar checking + // The identifier eval or arguments may not appear as the LeftHandSideExpression of an + // Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression + // operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator. + if (inStrictMode) { + checkStrictModeEvalOrArguments(node, node.operand); } } - function bindIterativeStatement(node, breakTarget, continueTarget) { - var saveBreakTarget = currentBreakTarget; - var saveContinueTarget = currentContinueTarget; - currentBreakTarget = breakTarget; - currentContinueTarget = continueTarget; - bind(node); - currentBreakTarget = saveBreakTarget; - currentContinueTarget = saveContinueTarget; + function checkStrictModePrefixUnaryExpression(node) { + // Grammar checking + if (inStrictMode) { + if (node.operator === 41 /* PlusPlusToken */ || node.operator === 42 /* MinusMinusToken */) { + checkStrictModeEvalOrArguments(node, node.operand); + } + } } - function bindWhileStatement(node) { - var preWhileLabel = createLoopLabel(); - var preBodyLabel = createBranchLabel(); - var postWhileLabel = createBranchLabel(); - addAntecedent(preWhileLabel, currentFlow); - currentFlow = preWhileLabel; - bindCondition(node.expression, preBodyLabel, postWhileLabel); - currentFlow = finishFlowLabel(preBodyLabel); - bindIterativeStatement(node.statement, postWhileLabel, preWhileLabel); - addAntecedent(preWhileLabel, currentFlow); - currentFlow = finishFlowLabel(postWhileLabel); + function checkStrictModeWithStatement(node) { + // Grammar checking for withStatement + if (inStrictMode) { + errorOnFirstToken(node, ts.Diagnostics.with_statements_are_not_allowed_in_strict_mode); + } } - function bindDoStatement(node) { - var preDoLabel = createLoopLabel(); - var preConditionLabel = createBranchLabel(); - var postDoLabel = createBranchLabel(); - addAntecedent(preDoLabel, currentFlow); - currentFlow = preDoLabel; - bindIterativeStatement(node.statement, postDoLabel, preConditionLabel); - addAntecedent(preConditionLabel, currentFlow); - currentFlow = finishFlowLabel(preConditionLabel); - bindCondition(node.expression, preDoLabel, postDoLabel); - currentFlow = finishFlowLabel(postDoLabel); + function errorOnFirstToken(node, message, arg0, arg1, arg2) { + var span = ts.getSpanOfTokenAtPosition(file, node.pos); + file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, message, arg0, arg1, arg2)); } - function bindForStatement(node) { - var preLoopLabel = createLoopLabel(); - var preBodyLabel = createBranchLabel(); - var postLoopLabel = createBranchLabel(); - bind(node.initializer); - addAntecedent(preLoopLabel, currentFlow); - currentFlow = preLoopLabel; - bindCondition(node.condition, preBodyLabel, postLoopLabel); - currentFlow = finishFlowLabel(preBodyLabel); - bindIterativeStatement(node.statement, postLoopLabel, preLoopLabel); - bind(node.incrementor); - addAntecedent(preLoopLabel, currentFlow); - currentFlow = finishFlowLabel(postLoopLabel); + function getDestructuringParameterName(node) { + return "__" + ts.indexOf(node.parent.parameters, node); } - function bindForInOrForOfStatement(node) { - var preLoopLabel = createLoopLabel(); - var postLoopLabel = createBranchLabel(); - addAntecedent(preLoopLabel, currentFlow); - currentFlow = preLoopLabel; - bind(node.expression); - addAntecedent(postLoopLabel, currentFlow); - bind(node.initializer); - if (node.initializer.kind !== 219 /* VariableDeclarationList */) { - bindAssignmentTargetFlow(node.initializer); + function bind(node) { + if (!node) { + return; } - bindIterativeStatement(node.statement, postLoopLabel, preLoopLabel); - addAntecedent(preLoopLabel, currentFlow); - currentFlow = finishFlowLabel(postLoopLabel); - } - function bindIfStatement(node) { - var thenLabel = createBranchLabel(); - var elseLabel = createBranchLabel(); - var postIfLabel = createBranchLabel(); - bindCondition(node.expression, thenLabel, elseLabel); - currentFlow = finishFlowLabel(thenLabel); - bind(node.thenStatement); - addAntecedent(postIfLabel, currentFlow); - currentFlow = finishFlowLabel(elseLabel); - bind(node.elseStatement); - addAntecedent(postIfLabel, currentFlow); - currentFlow = finishFlowLabel(postIfLabel); - } - function bindReturnOrThrow(node) { - bind(node.expression); - if (node.kind === 211 /* ReturnStatement */) { - hasExplicitReturn = true; - if (currentReturnTarget) { - addAntecedent(currentReturnTarget, currentFlow); + node.parent = parent; + var saveInStrictMode = inStrictMode; + // First we bind declaration nodes to a symbol if possible. We'll both create a symbol + // and then potentially add the symbol to an appropriate symbol table. Possible + // destination symbol tables are: + // + // 1) The 'exports' table of the current container's symbol. + // 2) The 'members' table of the current container's symbol. + // 3) The 'locals' table of the current container. + // + // However, not all symbols will end up in any of these tables. 'Anonymous' symbols + // (like TypeLiterals for example) will not be put in any table. + bindWorker(node); + // Then we recurse into the children of the node to bind them as well. For certain + // symbols we do specialized work when we recurse. For example, we'll keep track of + // the current 'container' node when it changes. This helps us know which symbol table + // a local should go into for example. Since terminal nodes are known not to have + // children, as an optimization we don't process those. + if (node.kind > 138 /* LastToken */) { + var saveParent = parent; + parent = node; + var containerFlags = getContainerFlags(node); + if (containerFlags === 0 /* None */) { + bindChildren(node); } + else { + bindContainer(node, containerFlags); + } + parent = saveParent; } - currentFlow = unreachableFlow; + else if (!skipTransformFlagAggregation && (node.transformFlags & 536870912 /* HasComputedFlags */) === 0) { + subtreeTransformFlags |= computeTransformFlagsForNode(node, 0); + } + inStrictMode = saveInStrictMode; } - function findActiveLabel(name) { - if (activeLabels) { - for (var _i = 0, activeLabels_1 = activeLabels; _i < activeLabels_1.length; _i++) { - var label = activeLabels_1[_i]; - if (label.name === name) { - return label; + function updateStrictModeStatementList(statements) { + if (!inStrictMode) { + for (var _i = 0, statements_1 = statements; _i < statements_1.length; _i++) { + var statement = statements_1[_i]; + if (!ts.isPrologueDirective(statement)) { + return; + } + if (isUseStrictPrologueDirective(statement)) { + inStrictMode = true; + return; } } } - return undefined; } - function bindbreakOrContinueFlow(node, breakTarget, continueTarget) { - var flowLabel = node.kind === 210 /* BreakStatement */ ? breakTarget : continueTarget; - if (flowLabel) { - addAntecedent(flowLabel, currentFlow); - currentFlow = unreachableFlow; + /// Should be called only on prologue directives (isPrologueDirective(node) should be true) + function isUseStrictPrologueDirective(node) { + var nodeText = ts.getTextOfNodeFromSourceText(file.text, node.expression); + // Note: the node text must be exactly "use strict" or 'use strict'. It is not ok for the + // string to contain unicode escapes (as per ES5). + return nodeText === '"use strict"' || nodeText === "'use strict'"; + } + function bindWorker(node) { + switch (node.kind) { + /* Strict mode checks */ + case 69 /* Identifier */: + case 97 /* ThisKeyword */: + if (currentFlow && (ts.isExpression(node) || parent.kind === 254 /* ShorthandPropertyAssignment */)) { + node.flowNode = currentFlow; + } + return checkStrictModeIdentifier(node); + case 172 /* PropertyAccessExpression */: + if (currentFlow && isNarrowableReference(node)) { + node.flowNode = currentFlow; + } + break; + case 187 /* BinaryExpression */: + if (ts.isInJavaScriptFile(node)) { + var specialKind = ts.getSpecialPropertyAssignmentKind(node); + switch (specialKind) { + case 1 /* ExportsProperty */: + bindExportsPropertyAssignment(node); + break; + case 2 /* ModuleExports */: + bindModuleExportsAssignment(node); + break; + case 3 /* PrototypeProperty */: + bindPrototypePropertyAssignment(node); + break; + case 4 /* ThisProperty */: + bindThisPropertyAssignment(node); + break; + case 0 /* None */: + // Nothing to do + break; + default: + ts.Debug.fail("Unknown special property assignment kind"); + } + } + return checkStrictModeBinaryExpression(node); + case 252 /* CatchClause */: + return checkStrictModeCatchClause(node); + case 181 /* DeleteExpression */: + return checkStrictModeDeleteExpression(node); + case 8 /* NumericLiteral */: + return checkStrictModeNumericLiteral(node); + case 186 /* PostfixUnaryExpression */: + return checkStrictModePostfixUnaryExpression(node); + case 185 /* PrefixUnaryExpression */: + return checkStrictModePrefixUnaryExpression(node); + case 212 /* WithStatement */: + return checkStrictModeWithStatement(node); + case 165 /* ThisType */: + seenThisKeyword = true; + return; + case 154 /* TypePredicate */: + return checkTypePredicate(node); + case 141 /* TypeParameter */: + return declareSymbolAndAddToSymbolTable(node, 262144 /* TypeParameter */, 530920 /* TypeParameterExcludes */); + case 142 /* Parameter */: + return bindParameter(node); + case 218 /* VariableDeclaration */: + case 169 /* BindingElement */: + return bindVariableDeclarationOrBindingElement(node); + case 145 /* PropertyDeclaration */: + case 144 /* PropertySignature */: + case 266 /* JSDocRecordMember */: + return bindPropertyOrMethodOrAccessor(node, 4 /* Property */ | (node.questionToken ? 536870912 /* Optional */ : 0 /* None */), 0 /* PropertyExcludes */); + case 280 /* JSDocPropertyTag */: + return bindJSDocProperty(node); + case 253 /* PropertyAssignment */: + case 254 /* ShorthandPropertyAssignment */: + return bindPropertyOrMethodOrAccessor(node, 4 /* Property */, 0 /* PropertyExcludes */); + case 255 /* EnumMember */: + return bindPropertyOrMethodOrAccessor(node, 8 /* EnumMember */, 900095 /* EnumMemberExcludes */); + case 247 /* JsxSpreadAttribute */: + emitFlags |= 16384 /* HasJsxSpreadAttributes */; + return; + case 151 /* CallSignature */: + case 152 /* ConstructSignature */: + case 153 /* IndexSignature */: + return declareSymbolAndAddToSymbolTable(node, 131072 /* Signature */, 0 /* None */); + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + // If this is an ObjectLiteralExpression method, then it sits in the same space + // as other properties in the object literal. So we use SymbolFlags.PropertyExcludes + // so that it will conflict with any other object literal members with the same + // name. + return bindPropertyOrMethodOrAccessor(node, 8192 /* Method */ | (node.questionToken ? 536870912 /* Optional */ : 0 /* None */), ts.isObjectLiteralMethod(node) ? 0 /* PropertyExcludes */ : 99263 /* MethodExcludes */); + case 220 /* FunctionDeclaration */: + return bindFunctionDeclaration(node); + case 148 /* Constructor */: + return declareSymbolAndAddToSymbolTable(node, 16384 /* Constructor */, /*symbolExcludes:*/ 0 /* None */); + case 149 /* GetAccessor */: + return bindPropertyOrMethodOrAccessor(node, 32768 /* GetAccessor */, 41919 /* GetAccessorExcludes */); + case 150 /* SetAccessor */: + return bindPropertyOrMethodOrAccessor(node, 65536 /* SetAccessor */, 74687 /* SetAccessorExcludes */); + case 156 /* FunctionType */: + case 157 /* ConstructorType */: + case 269 /* JSDocFunctionType */: + return bindFunctionOrConstructorType(node); + case 159 /* TypeLiteral */: + case 281 /* JSDocTypeLiteral */: + case 265 /* JSDocRecordType */: + return bindAnonymousDeclaration(node, 2048 /* TypeLiteral */, "__type"); + case 171 /* ObjectLiteralExpression */: + return bindObjectLiteralExpression(node); + case 179 /* FunctionExpression */: + case 180 /* ArrowFunction */: + return bindFunctionExpression(node); + case 174 /* CallExpression */: + if (ts.isInJavaScriptFile(node)) { + bindCallExpression(node); + } + break; + // Members of classes, interfaces, and modules + case 192 /* ClassExpression */: + case 221 /* ClassDeclaration */: + // All classes are automatically in strict mode in ES6. + inStrictMode = true; + return bindClassLikeDeclaration(node); + case 222 /* InterfaceDeclaration */: + return bindBlockScopedDeclaration(node, 64 /* Interface */, 792968 /* InterfaceExcludes */); + case 279 /* JSDocTypedefTag */: + case 223 /* TypeAliasDeclaration */: + return bindBlockScopedDeclaration(node, 524288 /* TypeAlias */, 793064 /* TypeAliasExcludes */); + case 224 /* EnumDeclaration */: + return bindEnumDeclaration(node); + case 225 /* ModuleDeclaration */: + return bindModuleDeclaration(node); + // Imports and exports + case 229 /* ImportEqualsDeclaration */: + case 232 /* NamespaceImport */: + case 234 /* ImportSpecifier */: + case 238 /* ExportSpecifier */: + return declareSymbolAndAddToSymbolTable(node, 8388608 /* Alias */, 8388608 /* AliasExcludes */); + case 228 /* NamespaceExportDeclaration */: + return bindNamespaceExportDeclaration(node); + case 231 /* ImportClause */: + return bindImportClause(node); + case 236 /* ExportDeclaration */: + return bindExportDeclaration(node); + case 235 /* ExportAssignment */: + return bindExportAssignment(node); + case 256 /* SourceFile */: + updateStrictModeStatementList(node.statements); + return bindSourceFileIfExternalModule(); + case 199 /* Block */: + if (!ts.isFunctionLike(node.parent)) { + return; + } + // Fall through + case 226 /* ModuleBlock */: + return updateStrictModeStatementList(node.statements); } } - function bindBreakOrContinueStatement(node) { - bind(node.label); - if (node.label) { - var activeLabel = findActiveLabel(node.label.text); - if (activeLabel) { - activeLabel.referenced = true; - bindbreakOrContinueFlow(node, activeLabel.breakTarget, activeLabel.continueTarget); - } + function checkTypePredicate(node) { + var parameterName = node.parameterName, type = node.type; + if (parameterName && parameterName.kind === 69 /* Identifier */) { + checkStrictModeIdentifier(parameterName); + } + if (parameterName && parameterName.kind === 165 /* ThisType */) { + seenThisKeyword = true; + } + bind(type); + } + function bindSourceFileIfExternalModule() { + setExportContextFlag(file); + if (ts.isExternalModule(file)) { + bindSourceFileAsExternalModule(); + } + } + function bindSourceFileAsExternalModule() { + bindAnonymousDeclaration(file, 512 /* ValueModule */, "\"" + ts.removeFileExtension(file.fileName) + "\""); + } + function bindExportAssignment(node) { + if (!container.symbol || !container.symbol.exports) { + // Export assignment in some sort of block construct + bindAnonymousDeclaration(node, 8388608 /* Alias */, getDeclarationName(node)); + } + else { + var flags = node.kind === 235 /* ExportAssignment */ && ts.exportAssignmentIsAlias(node) + ? 8388608 /* Alias */ + : 4 /* Property */; + declareSymbol(container.symbol.exports, container.symbol, node, flags, 0 /* PropertyExcludes */ | 8388608 /* AliasExcludes */); + } + } + function bindNamespaceExportDeclaration(node) { + if (node.modifiers && node.modifiers.length) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Modifiers_cannot_appear_here)); + } + if (node.parent.kind !== 256 /* SourceFile */) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Global_module_exports_may_only_appear_at_top_level)); + return; } else { - bindbreakOrContinueFlow(node, currentBreakTarget, currentContinueTarget); + var parent_6 = node.parent; + if (!ts.isExternalModule(parent_6)) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Global_module_exports_may_only_appear_in_module_files)); + return; + } + if (!parent_6.isDeclarationFile) { + file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Global_module_exports_may_only_appear_in_declaration_files)); + return; + } } + file.symbol.globalExports = file.symbol.globalExports || ts.createMap(); + declareSymbol(file.symbol.globalExports, file.symbol, node, 8388608 /* Alias */, 8388608 /* AliasExcludes */); } - function bindTryStatement(node) { - var postFinallyLabel = createBranchLabel(); - var preTryFlow = currentFlow; - // TODO: Every statement in try block is potentially an exit point! - bind(node.tryBlock); - addAntecedent(postFinallyLabel, currentFlow); - if (node.catchClause) { - currentFlow = preTryFlow; - bind(node.catchClause); - addAntecedent(postFinallyLabel, currentFlow); + function bindExportDeclaration(node) { + if (!container.symbol || !container.symbol.exports) { + // Export * in some sort of block construct + bindAnonymousDeclaration(node, 1073741824 /* ExportStar */, getDeclarationName(node)); } - if (node.finallyBlock) { - currentFlow = preTryFlow; - bind(node.finallyBlock); + else if (!node.exportClause) { + // All export * declarations are collected in an __export symbol + declareSymbol(container.symbol.exports, container.symbol, node, 1073741824 /* ExportStar */, 0 /* None */); } - currentFlow = finishFlowLabel(postFinallyLabel); } - function bindSwitchStatement(node) { - var postSwitchLabel = createBranchLabel(); - bind(node.expression); - var saveBreakTarget = currentBreakTarget; - var savePreSwitchCaseFlow = preSwitchCaseFlow; - currentBreakTarget = postSwitchLabel; - preSwitchCaseFlow = currentFlow; - bind(node.caseBlock); - addAntecedent(postSwitchLabel, currentFlow); - var hasDefault = ts.forEach(node.caseBlock.clauses, function (c) { return c.kind === 250 /* DefaultClause */; }); - // We mark a switch statement as possibly exhaustive if it has no default clause and if all - // case clauses have unreachable end points (e.g. they all return). - node.possiblyExhaustive = !hasDefault && !postSwitchLabel.antecedents; - if (!hasDefault) { - addAntecedent(postSwitchLabel, createFlowSwitchClause(preSwitchCaseFlow, node, 0, 0)); + function bindImportClause(node) { + if (node.name) { + declareSymbolAndAddToSymbolTable(node, 8388608 /* Alias */, 8388608 /* AliasExcludes */); } - currentBreakTarget = saveBreakTarget; - preSwitchCaseFlow = savePreSwitchCaseFlow; - currentFlow = finishFlowLabel(postSwitchLabel); } - function bindCaseBlock(node) { - var clauses = node.clauses; - var fallthroughFlow = unreachableFlow; - for (var i = 0; i < clauses.length; i++) { - var clauseStart = i; - while (!clauses[i].statements.length && i + 1 < clauses.length) { - bind(clauses[i]); - i++; - } - var preCaseLabel = createBranchLabel(); - addAntecedent(preCaseLabel, createFlowSwitchClause(preSwitchCaseFlow, node.parent, clauseStart, i + 1)); - addAntecedent(preCaseLabel, fallthroughFlow); - currentFlow = finishFlowLabel(preCaseLabel); - var clause = clauses[i]; - bind(clause); - fallthroughFlow = currentFlow; - if (!(currentFlow.flags & 1 /* Unreachable */) && i !== clauses.length - 1 && options.noFallthroughCasesInSwitch) { - errorOnFirstToken(clause, ts.Diagnostics.Fallthrough_case_in_switch); - } + function setCommonJsModuleIndicator(node) { + if (!file.commonJsModuleIndicator) { + file.commonJsModuleIndicator = node; + bindSourceFileAsExternalModule(); } } - function bindCaseClause(node) { - var saveCurrentFlow = currentFlow; - currentFlow = preSwitchCaseFlow; - bind(node.expression); - currentFlow = saveCurrentFlow; - ts.forEach(node.statements, bind); - } - function pushActiveLabel(name, breakTarget, continueTarget) { - var activeLabel = { - name: name, - breakTarget: breakTarget, - continueTarget: continueTarget, - referenced: false - }; - (activeLabels || (activeLabels = [])).push(activeLabel); - return activeLabel; + function bindExportsPropertyAssignment(node) { + // When we create a property via 'exports.foo = bar', the 'exports.foo' property access + // expression is the declaration + setCommonJsModuleIndicator(node); + declareSymbol(file.symbol.exports, file.symbol, node.left, 4 /* Property */ | 7340032 /* Export */, 0 /* None */); } - function popActiveLabel() { - activeLabels.pop(); + function bindModuleExportsAssignment(node) { + // 'module.exports = expr' assignment + setCommonJsModuleIndicator(node); + declareSymbol(file.symbol.exports, file.symbol, node, 4 /* Property */ | 7340032 /* Export */ | 512 /* ValueModule */, 0 /* None */); } - function bindLabeledStatement(node) { - var preStatementLabel = createLoopLabel(); - var postStatementLabel = createBranchLabel(); - bind(node.label); - addAntecedent(preStatementLabel, currentFlow); - var activeLabel = pushActiveLabel(node.label.text, postStatementLabel, preStatementLabel); - bind(node.statement); - popActiveLabel(); - if (!activeLabel.referenced && !options.allowUnusedLabels) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(node.label, ts.Diagnostics.Unused_label)); + function bindThisPropertyAssignment(node) { + ts.Debug.assert(ts.isInJavaScriptFile(node)); + // Declare a 'member' if the container is an ES5 class or ES6 constructor + if (container.kind === 220 /* FunctionDeclaration */ || container.kind === 179 /* FunctionExpression */) { + container.symbol.members = container.symbol.members || ts.createMap(); + // It's acceptable for multiple 'this' assignments of the same identifier to occur + declareSymbol(container.symbol.members, container.symbol, node, 4 /* Property */, 0 /* PropertyExcludes */ & ~4 /* Property */); + } + else if (container.kind === 148 /* Constructor */) { + // this.foo assignment in a JavaScript class + // Bind this property to the containing class + var saveContainer = container; + container = container.parent; + var symbol = bindPropertyOrMethodOrAccessor(node, 4 /* Property */, 0 /* None */); + if (symbol) { + // constructor-declared symbols can be overwritten by subsequent method declarations + symbol.isReplaceableByMethod = true; + } + container = saveContainer; } - addAntecedent(postStatementLabel, currentFlow); - currentFlow = finishFlowLabel(postStatementLabel); } - function bindDestructuringTargetFlow(node) { - if (node.kind === 187 /* BinaryExpression */ && node.operatorToken.kind === 56 /* EqualsToken */) { - bindAssignmentTargetFlow(node.left); + function bindPrototypePropertyAssignment(node) { + // We saw a node of the form 'x.prototype.y = z'. Declare a 'member' y on x if x was a function. + // Look up the function in the local scope, since prototype assignments should + // follow the function declaration + var leftSideOfAssignment = node.left; + var classPrototype = leftSideOfAssignment.expression; + var constructorFunction = classPrototype.expression; + // Fix up parent pointers since we're going to use these nodes before we bind into them + leftSideOfAssignment.parent = node; + constructorFunction.parent = classPrototype; + classPrototype.parent = leftSideOfAssignment; + var funcSymbol = container.locals[constructorFunction.text]; + if (!funcSymbol || !(funcSymbol.flags & 16 /* Function */ || ts.isDeclarationOfFunctionExpression(funcSymbol))) { + return; } - else { - bindAssignmentTargetFlow(node); + // Set up the members collection if it doesn't exist already + if (!funcSymbol.members) { + funcSymbol.members = ts.createMap(); } + // Declare the method/property + declareSymbol(funcSymbol.members, funcSymbol, leftSideOfAssignment, 4 /* Property */, 0 /* PropertyExcludes */); } - function bindAssignmentTargetFlow(node) { - if (isNarrowableReference(node)) { - currentFlow = createFlowAssignment(currentFlow, node); + function bindCallExpression(node) { + // We're only inspecting call expressions to detect CommonJS modules, so we can skip + // this check if we've already seen the module indicator + if (!file.commonJsModuleIndicator && ts.isRequireCall(node, /*checkArgumentIsStringLiteral*/ false)) { + setCommonJsModuleIndicator(node); } - else if (node.kind === 170 /* ArrayLiteralExpression */) { - for (var _i = 0, _a = node.elements; _i < _a.length; _i++) { - var e = _a[_i]; - if (e.kind === 191 /* SpreadElementExpression */) { - bindAssignmentTargetFlow(e.expression); - } - else { - bindDestructuringTargetFlow(e); - } + } + function bindClassLikeDeclaration(node) { + if (!ts.isDeclarationFile(file) && !ts.isInAmbientContext(node)) { + if (ts.getClassExtendsHeritageClauseElement(node) !== undefined) { + emitFlags |= 1024 /* HasClassExtends */; } - } - else if (node.kind === 171 /* ObjectLiteralExpression */) { - for (var _b = 0, _c = node.properties; _b < _c.length; _b++) { - var p = _c[_b]; - if (p.kind === 253 /* PropertyAssignment */) { - bindDestructuringTargetFlow(p.initializer); - } - else if (p.kind === 254 /* ShorthandPropertyAssignment */) { - bindAssignmentTargetFlow(p.name); - } + if (ts.nodeIsDecorated(node)) { + emitFlags |= 2048 /* HasDecorators */; } } - } - function bindLogicalExpression(node, trueTarget, falseTarget) { - var preRightLabel = createBranchLabel(); - if (node.operatorToken.kind === 51 /* AmpersandAmpersandToken */) { - bindCondition(node.left, preRightLabel, falseTarget); + if (node.kind === 221 /* ClassDeclaration */) { + bindBlockScopedDeclaration(node, 32 /* Class */, 899519 /* ClassExcludes */); } else { - bindCondition(node.left, trueTarget, preRightLabel); - } - currentFlow = finishFlowLabel(preRightLabel); - bind(node.operatorToken); - bindCondition(node.right, trueTarget, falseTarget); - } - function bindPrefixUnaryExpressionFlow(node) { - if (node.operator === 49 /* ExclamationToken */) { - var saveTrueTarget = currentTrueTarget; - currentTrueTarget = currentFalseTarget; - currentFalseTarget = saveTrueTarget; - ts.forEachChild(node, bind); - currentFalseTarget = currentTrueTarget; - currentTrueTarget = saveTrueTarget; + var bindingName = node.name ? node.name.text : "__class"; + bindAnonymousDeclaration(node, 32 /* Class */, bindingName); + // Add name of class expression into the map for semantic classifier + if (node.name) { + classifiableNames[node.name.text] = node.name.text; + } } - else { - ts.forEachChild(node, bind); + var symbol = node.symbol; + // TypeScript 1.0 spec (April 2014): 8.4 + // Every class automatically contains a static property member named 'prototype', the + // type of which is an instantiation of the class type with type Any supplied as a type + // argument for each type parameter. It is an error to explicitly declare a static + // property member with the name 'prototype'. + // + // Note: we check for this here because this class may be merging into a module. The + // module might have an exported variable called 'prototype'. We can't allow that as + // that would clash with the built-in 'prototype' for the class. + var prototypeSymbol = createSymbol(4 /* Property */ | 134217728 /* Prototype */, "prototype"); + if (symbol.exports[prototypeSymbol.name]) { + if (node.name) { + node.name.parent = node; + } + file.bindDiagnostics.push(ts.createDiagnosticForNode(symbol.exports[prototypeSymbol.name].declarations[0], ts.Diagnostics.Duplicate_identifier_0, prototypeSymbol.name)); } + symbol.exports[prototypeSymbol.name] = prototypeSymbol; + prototypeSymbol.parent = symbol; } - function bindBinaryExpressionFlow(node) { - var operator = node.operatorToken.kind; - if (operator === 51 /* AmpersandAmpersandToken */ || operator === 52 /* BarBarToken */) { - if (isTopLevelLogicalExpression(node)) { - var postExpressionLabel = createBranchLabel(); - bindLogicalExpression(node, postExpressionLabel, postExpressionLabel); - currentFlow = finishFlowLabel(postExpressionLabel); + function bindEnumDeclaration(node) { + return ts.isConst(node) + ? bindBlockScopedDeclaration(node, 128 /* ConstEnum */, 899967 /* ConstEnumExcludes */) + : bindBlockScopedDeclaration(node, 256 /* RegularEnum */, 899327 /* RegularEnumExcludes */); + } + function bindVariableDeclarationOrBindingElement(node) { + if (inStrictMode) { + checkStrictModeEvalOrArguments(node, node.name); + } + if (!ts.isBindingPattern(node.name)) { + if (ts.isBlockOrCatchScoped(node)) { + bindBlockScopedVariableDeclaration(node); } - else { - bindLogicalExpression(node, currentTrueTarget, currentFalseTarget); + else if (ts.isParameterDeclaration(node)) { + // It is safe to walk up parent chain to find whether the node is a destructing parameter declaration + // because its parent chain has already been set up, since parents are set before descending into children. + // + // If node is a binding element in parameter declaration, we need to use ParameterExcludes. + // Using ParameterExcludes flag allows the compiler to report an error on duplicate identifiers in Parameter Declaration + // For example: + // function foo([a,a]) {} // Duplicate Identifier error + // function bar(a,a) {} // Duplicate Identifier error, parameter declaration in this case is handled in bindParameter + // // which correctly set excluded symbols + declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 107455 /* ParameterExcludes */); } - } - else { - ts.forEachChild(node, bind); - if (operator === 56 /* EqualsToken */ && !ts.isAssignmentTarget(node)) { - bindAssignmentTargetFlow(node.left); + else { + declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 107454 /* FunctionScopedVariableExcludes */); } } } - function bindDeleteExpressionFlow(node) { - ts.forEachChild(node, bind); - if (node.expression.kind === 172 /* PropertyAccessExpression */) { - bindAssignmentTargetFlow(node.expression); + function bindParameter(node) { + if (!ts.isDeclarationFile(file) && + !ts.isInAmbientContext(node) && + ts.nodeIsDecorated(node)) { + emitFlags |= (2048 /* HasDecorators */ | 4096 /* HasParamDecorators */); } - } - function bindConditionalExpressionFlow(node) { - var trueLabel = createBranchLabel(); - var falseLabel = createBranchLabel(); - var postExpressionLabel = createBranchLabel(); - bindCondition(node.condition, trueLabel, falseLabel); - currentFlow = finishFlowLabel(trueLabel); - bind(node.whenTrue); - addAntecedent(postExpressionLabel, currentFlow); - currentFlow = finishFlowLabel(falseLabel); - bind(node.whenFalse); - addAntecedent(postExpressionLabel, currentFlow); - currentFlow = finishFlowLabel(postExpressionLabel); - } - function bindInitializedVariableFlow(node) { - var name = node.name; - if (ts.isBindingPattern(name)) { - for (var _i = 0, _a = name.elements; _i < _a.length; _i++) { - var child = _a[_i]; - bindInitializedVariableFlow(child); - } + if (inStrictMode) { + // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a + // strict mode FunctionLikeDeclaration or FunctionExpression(13.1) + checkStrictModeEvalOrArguments(node, node.name); + } + if (ts.isBindingPattern(node.name)) { + bindAnonymousDeclaration(node, 1 /* FunctionScopedVariable */, getDestructuringParameterName(node)); } else { - currentFlow = createFlowAssignment(currentFlow, node); + declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 107455 /* ParameterExcludes */); } - } - function bindVariableDeclarationFlow(node) { - ts.forEachChild(node, bind); - if (node.initializer || node.parent.parent.kind === 207 /* ForInStatement */ || node.parent.parent.kind === 208 /* ForOfStatement */) { - bindInitializedVariableFlow(node); + // If this is a property-parameter, then also declare the property symbol into the + // containing class. + if (ts.isParameterPropertyDeclaration(node)) { + var classDeclaration = node.parent.parent; + declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, 4 /* Property */ | (node.questionToken ? 536870912 /* Optional */ : 0 /* None */), 0 /* PropertyExcludes */); } } - function bindCallExpressionFlow(node) { - // If the target of the call expression is a function expression or arrow function we have - // an immediately invoked function expression (IIFE). Initialize the flowNode property to - // the current control flow (which includes evaluation of the IIFE arguments). - var expr = node.expression; - while (expr.kind === 178 /* ParenthesizedExpression */) { - expr = expr.expression; + function bindFunctionDeclaration(node) { + if (!ts.isDeclarationFile(file) && !ts.isInAmbientContext(node)) { + if (ts.isAsyncFunctionLike(node)) { + emitFlags |= 8192 /* HasAsyncFunctions */; + } } - if (expr.kind === 179 /* FunctionExpression */ || expr.kind === 180 /* ArrowFunction */) { - ts.forEach(node.typeArguments, bind); - ts.forEach(node.arguments, bind); - bind(node.expression); + checkStrictModeFunctionName(node); + if (inStrictMode) { + checkStrictModeFunctionDeclaration(node); + bindBlockScopedDeclaration(node, 16 /* Function */, 106927 /* FunctionExcludes */); } else { - ts.forEachChild(node, bind); + declareSymbolAndAddToSymbolTable(node, 16 /* Function */, 106927 /* FunctionExcludes */); } } - function getContainerFlags(node) { - switch (node.kind) { - case 192 /* ClassExpression */: - case 221 /* ClassDeclaration */: - case 224 /* EnumDeclaration */: - case 171 /* ObjectLiteralExpression */: - case 159 /* TypeLiteral */: - case 281 /* JSDocTypeLiteral */: - case 265 /* JSDocRecordType */: - return 1 /* IsContainer */; - case 222 /* InterfaceDeclaration */: - return 1 /* IsContainer */ | 64 /* IsInterface */; - case 269 /* JSDocFunctionType */: - case 225 /* ModuleDeclaration */: - case 223 /* TypeAliasDeclaration */: - return 1 /* IsContainer */ | 32 /* HasLocals */; - case 256 /* SourceFile */: - return 1 /* IsContainer */ | 4 /* IsControlFlowContainer */ | 32 /* HasLocals */; - case 148 /* Constructor */: - case 220 /* FunctionDeclaration */: - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 151 /* CallSignature */: - case 152 /* ConstructSignature */: - case 153 /* IndexSignature */: - case 156 /* FunctionType */: - case 157 /* ConstructorType */: - return 1 /* IsContainer */ | 4 /* IsControlFlowContainer */ | 32 /* HasLocals */ | 8 /* IsFunctionLike */; - case 179 /* FunctionExpression */: - case 180 /* ArrowFunction */: - return 1 /* IsContainer */ | 4 /* IsControlFlowContainer */ | 32 /* HasLocals */ | 8 /* IsFunctionLike */ | 16 /* IsFunctionExpression */; - case 226 /* ModuleBlock */: - return 4 /* IsControlFlowContainer */; - case 145 /* PropertyDeclaration */: - return node.initializer ? 4 /* IsControlFlowContainer */ : 0; - case 252 /* CatchClause */: - case 206 /* ForStatement */: - case 207 /* ForInStatement */: - case 208 /* ForOfStatement */: - case 227 /* CaseBlock */: - return 2 /* IsBlockScopedContainer */; - case 199 /* Block */: - // do not treat blocks directly inside a function as a block-scoped-container. - // Locals that reside in this block should go to the function locals. Otherwise 'x' - // would not appear to be a redeclaration of a block scoped local in the following - // example: - // - // function foo() { - // var x; - // let x; - // } - // - // If we placed 'var x' into the function locals and 'let x' into the locals of - // the block, then there would be no collision. - // - // By not creating a new block-scoped-container here, we ensure that both 'var x' - // and 'let x' go into the Function-container's locals, and we do get a collision - // conflict. - return ts.isFunctionLike(node.parent) ? 0 /* None */ : 2 /* IsBlockScopedContainer */; + function bindFunctionExpression(node) { + if (!ts.isDeclarationFile(file) && !ts.isInAmbientContext(node)) { + if (ts.isAsyncFunctionLike(node)) { + emitFlags |= 8192 /* HasAsyncFunctions */; + } } - return 0 /* None */; + if (currentFlow) { + node.flowNode = currentFlow; + } + checkStrictModeFunctionName(node); + var bindingName = node.name ? node.name.text : "__function"; + return bindAnonymousDeclaration(node, 16 /* Function */, bindingName); } - function addToContainerChain(next) { - if (lastContainer) { - lastContainer.nextContainer = next; + function bindPropertyOrMethodOrAccessor(node, symbolFlags, symbolExcludes) { + if (!ts.isDeclarationFile(file) && !ts.isInAmbientContext(node)) { + if (ts.isAsyncFunctionLike(node)) { + emitFlags |= 8192 /* HasAsyncFunctions */; + } + if (ts.nodeIsDecorated(node)) { + emitFlags |= 2048 /* HasDecorators */; + } } - lastContainer = next; + return ts.hasDynamicName(node) + ? bindAnonymousDeclaration(node, symbolFlags, "__computed") + : declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); + } + function bindJSDocProperty(node) { + return declareSymbolAndAddToSymbolTable(node, 4 /* Property */, 0 /* PropertyExcludes */); + } + // reachability checks + function shouldReportErrorOnModuleDeclaration(node) { + var instanceState = getModuleInstanceState(node); + return instanceState === 1 /* Instantiated */ || (instanceState === 2 /* ConstEnumOnly */ && options.preserveConstEnums); + } + function checkUnreachable(node) { + if (!(currentFlow.flags & 1 /* Unreachable */)) { + return false; + } + if (currentFlow === unreachableFlow) { + var reportError = + // report error on all statements except empty ones + (ts.isStatementButNotDeclaration(node) && node.kind !== 201 /* EmptyStatement */) || + // report error on class declarations + node.kind === 221 /* ClassDeclaration */ || + // report error on instantiated modules or const-enums only modules if preserveConstEnums is set + (node.kind === 225 /* ModuleDeclaration */ && shouldReportErrorOnModuleDeclaration(node)) || + // report error on regular enums and const enums if preserveConstEnums is set + (node.kind === 224 /* EnumDeclaration */ && (!ts.isConstEnumDeclaration(node) || options.preserveConstEnums)); + if (reportError) { + currentFlow = reportedUnreachableFlow; + // unreachable code is reported if + // - user has explicitly asked about it AND + // - statement is in not ambient context (statements in ambient context is already an error + // so we should not report extras) AND + // - node is not variable statement OR + // - node is block scoped variable statement OR + // - node is not block scoped variable statement and at least one variable declaration has initializer + // Rationale: we don't want to report errors on non-initialized var's since they are hoisted + // On the other side we do want to report errors on non-initialized 'lets' because of TDZ + var reportUnreachableCode = !options.allowUnreachableCode && + !ts.isInAmbientContext(node) && + (node.kind !== 200 /* VariableStatement */ || + ts.getCombinedNodeFlags(node.declarationList) & 3 /* BlockScoped */ || + ts.forEach(node.declarationList.declarations, function (d) { return d.initializer; })); + if (reportUnreachableCode) { + errorOnFirstToken(node, ts.Diagnostics.Unreachable_code_detected); + } + } + } + return true; + } + } + /** + * Computes the transform flags for a node, given the transform flags of its subtree + * + * @param node The node to analyze + * @param subtreeFlags Transform flags computed for this node's subtree + */ + function computeTransformFlagsForNode(node, subtreeFlags) { + var kind = node.kind; + switch (kind) { + case 174 /* CallExpression */: + return computeCallExpression(node, subtreeFlags); + case 225 /* ModuleDeclaration */: + return computeModuleDeclaration(node, subtreeFlags); + case 178 /* ParenthesizedExpression */: + return computeParenthesizedExpression(node, subtreeFlags); + case 187 /* BinaryExpression */: + return computeBinaryExpression(node, subtreeFlags); + case 202 /* ExpressionStatement */: + return computeExpressionStatement(node, subtreeFlags); + case 142 /* Parameter */: + return computeParameter(node, subtreeFlags); + case 180 /* ArrowFunction */: + return computeArrowFunction(node, subtreeFlags); + case 179 /* FunctionExpression */: + return computeFunctionExpression(node, subtreeFlags); + case 220 /* FunctionDeclaration */: + return computeFunctionDeclaration(node, subtreeFlags); + case 218 /* VariableDeclaration */: + return computeVariableDeclaration(node, subtreeFlags); + case 219 /* VariableDeclarationList */: + return computeVariableDeclarationList(node, subtreeFlags); + case 200 /* VariableStatement */: + return computeVariableStatement(node, subtreeFlags); + case 214 /* LabeledStatement */: + return computeLabeledStatement(node, subtreeFlags); + case 221 /* ClassDeclaration */: + return computeClassDeclaration(node, subtreeFlags); + case 192 /* ClassExpression */: + return computeClassExpression(node, subtreeFlags); + case 251 /* HeritageClause */: + return computeHeritageClause(node, subtreeFlags); + case 194 /* ExpressionWithTypeArguments */: + return computeExpressionWithTypeArguments(node, subtreeFlags); + case 148 /* Constructor */: + return computeConstructor(node, subtreeFlags); + case 145 /* PropertyDeclaration */: + return computePropertyDeclaration(node, subtreeFlags); + case 147 /* MethodDeclaration */: + return computeMethod(node, subtreeFlags); + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + return computeAccessor(node, subtreeFlags); + case 229 /* ImportEqualsDeclaration */: + return computeImportEquals(node, subtreeFlags); + case 172 /* PropertyAccessExpression */: + return computePropertyAccess(node, subtreeFlags); + default: + return computeOther(node, kind, subtreeFlags); } - function declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes) { - // Just call this directly so that the return type of this function stays "void". - return declareSymbolAndAddToSymbolTableWorker(node, symbolFlags, symbolExcludes); + } + ts.computeTransformFlagsForNode = computeTransformFlagsForNode; + function computeCallExpression(node, subtreeFlags) { + var transformFlags = subtreeFlags; + var expression = node.expression; + var expressionKind = expression.kind; + if (subtreeFlags & 262144 /* ContainsSpreadElementExpression */ + || isSuperOrSuperProperty(expression, expressionKind)) { + // If the this node contains a SpreadElementExpression, or is a super call, then it is an ES6 + // node. + transformFlags |= 192 /* AssertES6 */; } - function declareSymbolAndAddToSymbolTableWorker(node, symbolFlags, symbolExcludes) { - switch (container.kind) { - // Modules, source files, and classes need specialized handling for how their - // members are declared (for example, a member of a class will go into a specific - // symbol table depending on if it is static or not). We defer to specialized - // handlers to take care of declaring these child members. - case 225 /* ModuleDeclaration */: - return declareModuleMember(node, symbolFlags, symbolExcludes); - case 256 /* SourceFile */: - return declareSourceFileMember(node, symbolFlags, symbolExcludes); - case 192 /* ClassExpression */: - case 221 /* ClassDeclaration */: - return declareClassMember(node, symbolFlags, symbolExcludes); - case 224 /* EnumDeclaration */: - return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); - case 159 /* TypeLiteral */: - case 171 /* ObjectLiteralExpression */: - case 222 /* InterfaceDeclaration */: - case 265 /* JSDocRecordType */: - case 281 /* JSDocTypeLiteral */: - // Interface/Object-types always have their children added to the 'members' of - // their container. They are only accessible through an instance of their - // container, and are never in scope otherwise (even inside the body of the - // object / type / interface declaring them). An exception is type parameters, - // which are in scope without qualification (similar to 'locals'). - return declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); - case 156 /* FunctionType */: - case 157 /* ConstructorType */: - case 151 /* CallSignature */: - case 152 /* ConstructSignature */: - case 153 /* IndexSignature */: - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - case 148 /* Constructor */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - case 180 /* ArrowFunction */: - case 269 /* JSDocFunctionType */: - case 223 /* TypeAliasDeclaration */: - // All the children of these container types are never visible through another - // symbol (i.e. through another symbol's 'exports' or 'members'). Instead, - // they're only accessed 'lexically' (i.e. from code that exists underneath - // their container in the tree. To accomplish this, we simply add their declared - // symbol to the 'locals' of the container. These symbols can then be found as - // the type checker walks up the containers, checking them for matching names. - return declareSymbol(container.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes); - } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~537133909 /* ArrayLiteralOrCallOrNewExcludes */; + } + function isSuperOrSuperProperty(node, kind) { + switch (kind) { + case 95 /* SuperKeyword */: + return true; + case 172 /* PropertyAccessExpression */: + case 173 /* ElementAccessExpression */: + var expression = node.expression; + var expressionKind = expression.kind; + return expressionKind === 95 /* SuperKeyword */; } - function declareClassMember(node, symbolFlags, symbolExcludes) { - return node.flags & 32 /* Static */ - ? declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes) - : declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); + return false; + } + function computeBinaryExpression(node, subtreeFlags) { + var transformFlags = subtreeFlags; + var operatorTokenKind = node.operatorToken.kind; + var leftKind = node.left.kind; + if (operatorTokenKind === 56 /* EqualsToken */ + && (leftKind === 171 /* ObjectLiteralExpression */ + || leftKind === 170 /* ArrayLiteralExpression */)) { + // Destructuring assignments are ES6 syntax. + transformFlags |= 192 /* AssertES6 */ | 256 /* DestructuringAssignment */; + } + else if (operatorTokenKind === 38 /* AsteriskAsteriskToken */ + || operatorTokenKind === 60 /* AsteriskAsteriskEqualsToken */) { + // Exponentiation is ES7 syntax. + transformFlags |= 48 /* AssertES7 */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~536871765 /* NodeExcludes */; + } + function computeParameter(node, subtreeFlags) { + var transformFlags = subtreeFlags; + var modifierFlags = ts.getModifierFlags(node); + var name = node.name; + var initializer = node.initializer; + var dotDotDotToken = node.dotDotDotToken; + // If the parameter has a question token, then it is TypeScript syntax. + if (node.questionToken) { + transformFlags |= 3 /* AssertTypeScript */; + } + // If the parameter's name is 'this', then it is TypeScript syntax. + if (subtreeFlags & 2048 /* ContainsDecorators */ + || (name && ts.isIdentifier(name) && name.originalKeywordKind === 97 /* ThisKeyword */)) { + transformFlags |= 3 /* AssertTypeScript */; + } + // If a parameter has an accessibility modifier, then it is TypeScript syntax. + if (modifierFlags & 92 /* ParameterPropertyModifier */) { + transformFlags |= 3 /* AssertTypeScript */ | 131072 /* ContainsParameterPropertyAssignments */; + } + // If a parameter has an initializer, a binding pattern or a dotDotDot token, then + // it is ES6 syntax and its container must emit default value assignments or parameter destructuring downlevel. + if (subtreeFlags & 2097152 /* ContainsBindingPattern */ || initializer || dotDotDotToken) { + transformFlags |= 192 /* AssertES6 */ | 65536 /* ContainsDefaultValueAssignments */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~538968917 /* ParameterExcludes */; + } + function computeParenthesizedExpression(node, subtreeFlags) { + var transformFlags = subtreeFlags; + var expression = node.expression; + var expressionKind = expression.kind; + var expressionTransformFlags = expression.transformFlags; + // If the node is synthesized, it means the emitter put the parentheses there, + // not the user. If we didn't want them, the emitter would not have put them + // there. + if (expressionKind === 195 /* AsExpression */ + || expressionKind === 177 /* TypeAssertionExpression */) { + transformFlags |= 3 /* AssertTypeScript */; + } + // If the expression of a ParenthesizedExpression is a destructuring assignment, + // then the ParenthesizedExpression is a destructuring assignment. + if (expressionTransformFlags & 256 /* DestructuringAssignment */) { + transformFlags |= 256 /* DestructuringAssignment */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~536871765 /* NodeExcludes */; + } + function computeClassDeclaration(node, subtreeFlags) { + var transformFlags; + var modifierFlags = ts.getModifierFlags(node); + if (modifierFlags & 2 /* Ambient */) { + // An ambient declaration is TypeScript syntax. + transformFlags = 3 /* AssertTypeScript */; } - function declareSourceFileMember(node, symbolFlags, symbolExcludes) { - return ts.isExternalModule(file) - ? declareModuleMember(node, symbolFlags, symbolExcludes) - : declareSymbol(file.locals, undefined, node, symbolFlags, symbolExcludes); + else { + // A ClassDeclaration is ES6 syntax. + transformFlags = subtreeFlags | 192 /* AssertES6 */; + // A class with a parameter property assignment, property initializer, or decorator is + // TypeScript syntax. + // An exported declaration may be TypeScript syntax. + if ((subtreeFlags & 137216 /* TypeScriptClassSyntaxMask */) + || (modifierFlags & 1 /* Export */)) { + transformFlags |= 3 /* AssertTypeScript */; + } + if (subtreeFlags & 32768 /* ContainsLexicalThisInComputedPropertyName */) { + // A computed property name containing `this` might need to be rewritten, + // so propagate the ContainsLexicalThis flag upward. + transformFlags |= 8192 /* ContainsLexicalThis */; + } + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~537590613 /* ClassExcludes */; + } + function computeClassExpression(node, subtreeFlags) { + // A ClassExpression is ES6 syntax. + var transformFlags = subtreeFlags | 192 /* AssertES6 */; + // A class with a parameter property assignment, property initializer, or decorator is + // TypeScript syntax. + if (subtreeFlags & 137216 /* TypeScriptClassSyntaxMask */) { + transformFlags |= 3 /* AssertTypeScript */; + } + if (subtreeFlags & 32768 /* ContainsLexicalThisInComputedPropertyName */) { + // A computed property name containing `this` might need to be rewritten, + // so propagate the ContainsLexicalThis flag upward. + transformFlags |= 8192 /* ContainsLexicalThis */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~537590613 /* ClassExcludes */; + } + function computeHeritageClause(node, subtreeFlags) { + var transformFlags = subtreeFlags; + switch (node.token) { + case 83 /* ExtendsKeyword */: + // An `extends` HeritageClause is ES6 syntax. + transformFlags |= 192 /* AssertES6 */; + break; + case 106 /* ImplementsKeyword */: + // An `implements` HeritageClause is TypeScript syntax. + transformFlags |= 3 /* AssertTypeScript */; + break; + default: + ts.Debug.fail("Unexpected token for heritage clause"); + break; } - function hasExportDeclarations(node) { - var body = node.kind === 256 /* SourceFile */ ? node : node.body; - if (body && (body.kind === 256 /* SourceFile */ || body.kind === 226 /* ModuleBlock */)) { - for (var _i = 0, _a = body.statements; _i < _a.length; _i++) { - var stat = _a[_i]; - if (stat.kind === 236 /* ExportDeclaration */ || stat.kind === 235 /* ExportAssignment */) { - return true; - } - } - } - return false; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~536871765 /* NodeExcludes */; + } + function computeExpressionWithTypeArguments(node, subtreeFlags) { + // An ExpressionWithTypeArguments is ES6 syntax, as it is used in the + // extends clause of a class. + var transformFlags = subtreeFlags | 192 /* AssertES6 */; + // If an ExpressionWithTypeArguments contains type arguments, then it + // is TypeScript syntax. + if (node.typeArguments) { + transformFlags |= 3 /* AssertTypeScript */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~536871765 /* NodeExcludes */; + } + function computeConstructor(node, subtreeFlags) { + var transformFlags = subtreeFlags; + var body = node.body; + if (body === undefined) { + // An overload constructor is TypeScript syntax. + transformFlags |= 3 /* AssertTypeScript */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~550593365 /* ConstructorExcludes */; + } + function computeMethod(node, subtreeFlags) { + // A MethodDeclaration is ES6 syntax. + var transformFlags = subtreeFlags | 192 /* AssertES6 */; + var modifierFlags = ts.getModifierFlags(node); + var body = node.body; + var typeParameters = node.typeParameters; + var asteriskToken = node.asteriskToken; + // A MethodDeclaration is TypeScript syntax if it is either async, abstract, overloaded, + // generic, or has a decorator. + if (!body + || typeParameters + || (modifierFlags & (256 /* Async */ | 128 /* Abstract */)) + || (subtreeFlags & 2048 /* ContainsDecorators */)) { + transformFlags |= 3 /* AssertTypeScript */; + } + // Currently, we only support generators that were originally async function bodies. + if (asteriskToken && ts.getEmitFlags(node) & 2097152 /* AsyncFunctionBody */) { + transformFlags |= 1536 /* AssertGenerator */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~550593365 /* MethodOrAccessorExcludes */; + } + function computeAccessor(node, subtreeFlags) { + var transformFlags = subtreeFlags; + var modifierFlags = ts.getModifierFlags(node); + var body = node.body; + // A MethodDeclaration is TypeScript syntax if it is either async, abstract, overloaded, + // generic, or has a decorator. + if (!body + || (modifierFlags & (256 /* Async */ | 128 /* Abstract */)) + || (subtreeFlags & 2048 /* ContainsDecorators */)) { + transformFlags |= 3 /* AssertTypeScript */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~550593365 /* MethodOrAccessorExcludes */; + } + function computePropertyDeclaration(node, subtreeFlags) { + // A PropertyDeclaration is TypeScript syntax. + var transformFlags = subtreeFlags | 3 /* AssertTypeScript */; + // If the PropertyDeclaration has an initializer, we need to inform its ancestor + // so that it handle the transformation. + if (node.initializer) { + transformFlags |= 4096 /* ContainsPropertyInitializer */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~536871765 /* NodeExcludes */; + } + function computeFunctionDeclaration(node, subtreeFlags) { + var transformFlags; + var modifierFlags = ts.getModifierFlags(node); + var body = node.body; + var asteriskToken = node.asteriskToken; + if (!body || (modifierFlags & 2 /* Ambient */)) { + // An ambient declaration is TypeScript syntax. + // A FunctionDeclaration without a body is an overload and is TypeScript syntax. + transformFlags = 3 /* AssertTypeScript */; } - function setExportContextFlag(node) { - // A declaration source file or ambient module declaration that contains no export declarations (but possibly regular - // declarations with export modifiers) is an export context in which declarations are implicitly exported. - if (ts.isInAmbientContext(node) && !hasExportDeclarations(node)) { - node.flags |= 8192 /* ExportContext */; - } - else { - node.flags &= ~8192 /* ExportContext */; - } + else { + transformFlags = subtreeFlags | 8388608 /* ContainsHoistedDeclarationOrCompletion */; + // If a FunctionDeclaration is exported, then it is either ES6 or TypeScript syntax. + if (modifierFlags & 1 /* Export */) { + transformFlags |= 3 /* AssertTypeScript */ | 192 /* AssertES6 */; + } + // If a FunctionDeclaration is async, then it is TypeScript syntax. + if (modifierFlags & 256 /* Async */) { + transformFlags |= 3 /* AssertTypeScript */; + } + // If a FunctionDeclaration's subtree has marked the container as needing to capture the + // lexical this, or the function contains parameters with initializers, then this node is + // ES6 syntax. + if (subtreeFlags & 81920 /* ES6FunctionSyntaxMask */) { + transformFlags |= 192 /* AssertES6 */; + } + // If a FunctionDeclaration is generator function and is the body of a + // transformed async function, then this node can be transformed to a + // down-level generator. + // Currently we do not support transforming any other generator fucntions + // down level. + if (asteriskToken && ts.getEmitFlags(node) & 2097152 /* AsyncFunctionBody */) { + transformFlags |= 1536 /* AssertGenerator */; + } + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~550726485 /* FunctionExcludes */; + } + function computeFunctionExpression(node, subtreeFlags) { + var transformFlags = subtreeFlags; + var modifierFlags = ts.getModifierFlags(node); + var asteriskToken = node.asteriskToken; + // An async function expression is TypeScript syntax. + if (modifierFlags & 256 /* Async */) { + transformFlags |= 3 /* AssertTypeScript */; + } + // If a FunctionExpression's subtree has marked the container as needing to capture the + // lexical this, or the function contains parameters with initializers, then this node is + // ES6 syntax. + if (subtreeFlags & 81920 /* ES6FunctionSyntaxMask */) { + transformFlags |= 192 /* AssertES6 */; + } + // If a FunctionExpression is generator function and is the body of a + // transformed async function, then this node can be transformed to a + // down-level generator. + // Currently we do not support transforming any other generator fucntions + // down level. + if (asteriskToken && ts.getEmitFlags(node) & 2097152 /* AsyncFunctionBody */) { + transformFlags |= 1536 /* AssertGenerator */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~550726485 /* FunctionExcludes */; + } + function computeArrowFunction(node, subtreeFlags) { + // An ArrowFunction is ES6 syntax, and excludes markers that should not escape the scope of an ArrowFunction. + var transformFlags = subtreeFlags | 192 /* AssertES6 */; + var modifierFlags = ts.getModifierFlags(node); + // An async arrow function is TypeScript syntax. + if (modifierFlags & 256 /* Async */) { + transformFlags |= 3 /* AssertTypeScript */; + } + // If an ArrowFunction contains a lexical this, its container must capture the lexical this. + if (subtreeFlags & 8192 /* ContainsLexicalThis */) { + transformFlags |= 16384 /* ContainsCapturedLexicalThis */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~550710101 /* ArrowFunctionExcludes */; + } + function computePropertyAccess(node, subtreeFlags) { + var transformFlags = subtreeFlags; + var expression = node.expression; + var expressionKind = expression.kind; + // If a PropertyAccessExpression starts with a super keyword, then it is + // ES6 syntax, and requires a lexical `this` binding. + if (expressionKind === 95 /* SuperKeyword */) { + transformFlags |= 8192 /* ContainsLexicalThis */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~536871765 /* NodeExcludes */; + } + function computeVariableDeclaration(node, subtreeFlags) { + var transformFlags = subtreeFlags; + var nameKind = node.name.kind; + // A VariableDeclaration with a binding pattern is ES6 syntax. + if (nameKind === 167 /* ObjectBindingPattern */ || nameKind === 168 /* ArrayBindingPattern */) { + transformFlags |= 192 /* AssertES6 */ | 2097152 /* ContainsBindingPattern */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~536871765 /* NodeExcludes */; + } + function computeVariableStatement(node, subtreeFlags) { + var transformFlags; + var modifierFlags = ts.getModifierFlags(node); + var declarationListTransformFlags = node.declarationList.transformFlags; + // An ambient declaration is TypeScript syntax. + if (modifierFlags & 2 /* Ambient */) { + transformFlags = 3 /* AssertTypeScript */; } - function bindModuleDeclaration(node) { - setExportContextFlag(node); - if (ts.isAmbientModule(node)) { - if (node.flags & 1 /* Export */) { - errorOnFirstToken(node, ts.Diagnostics.export_modifier_cannot_be_applied_to_ambient_modules_and_module_augmentations_since_they_are_always_visible); + else { + transformFlags = subtreeFlags; + // If a VariableStatement is exported, then it is either ES6 or TypeScript syntax. + if (modifierFlags & 1 /* Export */) { + transformFlags |= 192 /* AssertES6 */ | 3 /* AssertTypeScript */; + } + if (declarationListTransformFlags & 2097152 /* ContainsBindingPattern */) { + transformFlags |= 192 /* AssertES6 */; + } + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~536871765 /* NodeExcludes */; + } + function computeLabeledStatement(node, subtreeFlags) { + var transformFlags = subtreeFlags; + // A labeled statement containing a block scoped binding *may* need to be transformed from ES6. + if (subtreeFlags & 1048576 /* ContainsBlockScopedBinding */ + && ts.isIterationStatement(node, /*lookInLabeledStatements*/ true)) { + transformFlags |= 192 /* AssertES6 */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~536871765 /* NodeExcludes */; + } + function computeImportEquals(node, subtreeFlags) { + var transformFlags = subtreeFlags; + // An ImportEqualsDeclaration with a namespace reference is TypeScript. + if (!ts.isExternalModuleImportEqualsDeclaration(node)) { + transformFlags |= 3 /* AssertTypeScript */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~536871765 /* NodeExcludes */; + } + function computeExpressionStatement(node, subtreeFlags) { + var transformFlags = subtreeFlags; + // If the expression of an expression statement is a destructuring assignment, + // then we treat the statement as ES6 so that we can indicate that we do not + // need to hold on to the right-hand side. + if (node.expression.transformFlags & 256 /* DestructuringAssignment */) { + transformFlags |= 192 /* AssertES6 */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~536871765 /* NodeExcludes */; + } + function computeModuleDeclaration(node, subtreeFlags) { + var transformFlags = 3 /* AssertTypeScript */; + var modifierFlags = ts.getModifierFlags(node); + if ((modifierFlags & 2 /* Ambient */) === 0) { + transformFlags |= subtreeFlags; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~546335573 /* ModuleExcludes */; + } + function computeVariableDeclarationList(node, subtreeFlags) { + var transformFlags = subtreeFlags | 8388608 /* ContainsHoistedDeclarationOrCompletion */; + if (subtreeFlags & 2097152 /* ContainsBindingPattern */) { + transformFlags |= 192 /* AssertES6 */; + } + // If a VariableDeclarationList is `let` or `const`, then it is ES6 syntax. + if (node.flags & 3 /* BlockScoped */) { + transformFlags |= 192 /* AssertES6 */ | 1048576 /* ContainsBlockScopedBinding */; + } + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~538968917 /* VariableDeclarationListExcludes */; + } + function computeOther(node, kind, subtreeFlags) { + // Mark transformations needed for each node + var transformFlags = subtreeFlags; + var excludeFlags = 536871765 /* NodeExcludes */; + switch (kind) { + case 112 /* PublicKeyword */: + case 110 /* PrivateKeyword */: + case 111 /* ProtectedKeyword */: + case 115 /* AbstractKeyword */: + case 122 /* DeclareKeyword */: + case 118 /* AsyncKeyword */: + case 74 /* ConstKeyword */: + case 184 /* AwaitExpression */: + case 224 /* EnumDeclaration */: + case 255 /* EnumMember */: + case 177 /* TypeAssertionExpression */: + case 195 /* AsExpression */: + case 196 /* NonNullExpression */: + case 128 /* ReadonlyKeyword */: + // These nodes are TypeScript syntax. + transformFlags |= 3 /* AssertTypeScript */; + break; + case 241 /* JsxElement */: + case 242 /* JsxSelfClosingElement */: + case 243 /* JsxOpeningElement */: + case 244 /* JsxText */: + case 245 /* JsxClosingElement */: + case 246 /* JsxAttribute */: + case 247 /* JsxSpreadAttribute */: + case 248 /* JsxExpression */: + // These nodes are Jsx syntax. + transformFlags |= 12 /* AssertJsx */; + break; + case 82 /* ExportKeyword */: + // This node is both ES6 and TypeScript syntax. + transformFlags |= 192 /* AssertES6 */ | 3 /* AssertTypeScript */; + break; + case 77 /* DefaultKeyword */: + case 11 /* NoSubstitutionTemplateLiteral */: + case 12 /* TemplateHead */: + case 13 /* TemplateMiddle */: + case 14 /* TemplateTail */: + case 189 /* TemplateExpression */: + case 176 /* TaggedTemplateExpression */: + case 254 /* ShorthandPropertyAssignment */: + case 208 /* ForOfStatement */: + // These nodes are ES6 syntax. + transformFlags |= 192 /* AssertES6 */; + break; + case 190 /* YieldExpression */: + // This node is ES6 syntax. + transformFlags |= 192 /* AssertES6 */ | 4194304 /* ContainsYield */; + break; + case 117 /* AnyKeyword */: + case 130 /* NumberKeyword */: + case 127 /* NeverKeyword */: + case 132 /* StringKeyword */: + case 120 /* BooleanKeyword */: + case 133 /* SymbolKeyword */: + case 103 /* VoidKeyword */: + case 141 /* TypeParameter */: + case 144 /* PropertySignature */: + case 146 /* MethodSignature */: + case 151 /* CallSignature */: + case 152 /* ConstructSignature */: + case 153 /* IndexSignature */: + case 154 /* TypePredicate */: + case 155 /* TypeReference */: + case 156 /* FunctionType */: + case 157 /* ConstructorType */: + case 158 /* TypeQuery */: + case 159 /* TypeLiteral */: + case 160 /* ArrayType */: + case 161 /* TupleType */: + case 162 /* UnionType */: + case 163 /* IntersectionType */: + case 164 /* ParenthesizedType */: + case 222 /* InterfaceDeclaration */: + case 223 /* TypeAliasDeclaration */: + case 165 /* ThisType */: + case 166 /* LiteralType */: + // Types and signatures are TypeScript syntax, and exclude all other facts. + transformFlags = 3 /* AssertTypeScript */; + excludeFlags = -3 /* TypeExcludes */; + break; + case 140 /* ComputedPropertyName */: + // Even though computed property names are ES6, we don't treat them as such. + // This is so that they can flow through PropertyName transforms unaffected. + // Instead, we mark the container as ES6, so that it can properly handle the transform. + transformFlags |= 524288 /* ContainsComputedPropertyName */; + if (subtreeFlags & 8192 /* ContainsLexicalThis */) { + // A computed method name like `[this.getName()](x: string) { ... }` needs to + // distinguish itself from the normal case of a method body containing `this`: + // `this` inside a method doesn't need to be rewritten (the method provides `this`), + // whereas `this` inside a computed name *might* need to be rewritten if the class/object + // is inside an arrow function: + // `_this = this; () => class K { [_this.getName()]() { ... } }` + // To make this distinction, use ContainsLexicalThisInComputedPropertyName + // instead of ContainsLexicalThis for computed property names + transformFlags |= 32768 /* ContainsLexicalThisInComputedPropertyName */; } - if (ts.isExternalModuleAugmentation(node)) { - declareSymbolAndAddToSymbolTable(node, 1024 /* NamespaceModule */, 0 /* NamespaceModuleExcludes */); + break; + case 191 /* SpreadElementExpression */: + // This node is ES6 syntax, but is handled by a containing node. + transformFlags |= 262144 /* ContainsSpreadElementExpression */; + break; + case 95 /* SuperKeyword */: + // This node is ES6 syntax. + transformFlags |= 192 /* AssertES6 */; + break; + case 97 /* ThisKeyword */: + // Mark this node and its ancestors as containing a lexical `this` keyword. + transformFlags |= 8192 /* ContainsLexicalThis */; + break; + case 167 /* ObjectBindingPattern */: + case 168 /* ArrayBindingPattern */: + // These nodes are ES6 syntax. + transformFlags |= 192 /* AssertES6 */ | 2097152 /* ContainsBindingPattern */; + break; + case 143 /* Decorator */: + // This node is TypeScript syntax, and marks its container as also being TypeScript syntax. + transformFlags |= 3 /* AssertTypeScript */ | 2048 /* ContainsDecorators */; + break; + case 171 /* ObjectLiteralExpression */: + excludeFlags = 537430869 /* ObjectLiteralExcludes */; + if (subtreeFlags & 524288 /* ContainsComputedPropertyName */) { + // If an ObjectLiteralExpression contains a ComputedPropertyName, then it + // is an ES6 node. + transformFlags |= 192 /* AssertES6 */; } - else { - var pattern = void 0; - if (node.name.kind === 9 /* StringLiteral */) { - var text = node.name.text; - if (ts.hasZeroOrOneAsteriskCharacter(text)) { - pattern = ts.tryParsePattern(text); - } - else { - errorOnFirstToken(node.name, ts.Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, text); - } - } - var symbol = declareSymbolAndAddToSymbolTable(node, 512 /* ValueModule */, 106639 /* ValueModuleExcludes */); - if (pattern) { - (file.patternAmbientModules || (file.patternAmbientModules = [])).push({ pattern: pattern, symbol: symbol }); - } + if (subtreeFlags & 32768 /* ContainsLexicalThisInComputedPropertyName */) { + // A computed property name containing `this` might need to be rewritten, + // so propagate the ContainsLexicalThis flag upward. + transformFlags |= 8192 /* ContainsLexicalThis */; } - } - else { - var state = getModuleInstanceState(node); - if (state === 0 /* NonInstantiated */) { - declareSymbolAndAddToSymbolTable(node, 1024 /* NamespaceModule */, 0 /* NamespaceModuleExcludes */); + break; + case 170 /* ArrayLiteralExpression */: + case 175 /* NewExpression */: + excludeFlags = 537133909 /* ArrayLiteralOrCallOrNewExcludes */; + if (subtreeFlags & 262144 /* ContainsSpreadElementExpression */) { + // If the this node contains a SpreadElementExpression, then it is an ES6 + // node. + transformFlags |= 192 /* AssertES6 */; } - else { - declareSymbolAndAddToSymbolTable(node, 512 /* ValueModule */, 106639 /* ValueModuleExcludes */); - if (node.symbol.flags & (16 /* Function */ | 32 /* Class */ | 256 /* RegularEnum */)) { - // if module was already merged with some function, class or non-const enum - // treat is a non-const-enum-only - node.symbol.constEnumOnlyModule = false; - } - else { - var currentModuleIsConstEnumOnly = state === 2 /* ConstEnumOnly */; - if (node.symbol.constEnumOnlyModule === undefined) { - // non-merged case - use the current state - node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly; - } - else { - // merged case: module is const enum only if all its pieces are non-instantiated or const enum - node.symbol.constEnumOnlyModule = node.symbol.constEnumOnlyModule && currentModuleIsConstEnumOnly; - } - } + break; + case 204 /* DoStatement */: + case 205 /* WhileStatement */: + case 206 /* ForStatement */: + case 207 /* ForInStatement */: + // A loop containing a block scoped binding *may* need to be transformed from ES6. + if (subtreeFlags & 1048576 /* ContainsBlockScopedBinding */) { + transformFlags |= 192 /* AssertES6 */; } - } - } - function bindFunctionOrConstructorType(node) { - // For a given function symbol "<...>(...) => T" we want to generate a symbol identical - // to the one we would get for: { <...>(...): T } - // - // We do that by making an anonymous type literal symbol, and then setting the function - // symbol as its sole member. To the rest of the system, this symbol will be indistinguishable - // from an actual type literal symbol you would have gotten had you used the long form. - var symbol = createSymbol(131072 /* Signature */, getDeclarationName(node)); - addDeclarationToSymbol(symbol, node, 131072 /* Signature */); - var typeLiteralSymbol = createSymbol(2048 /* TypeLiteral */, "__type"); - addDeclarationToSymbol(typeLiteralSymbol, node, 2048 /* TypeLiteral */); - typeLiteralSymbol.members = ts.createMap(); - typeLiteralSymbol.members[symbol.name] = symbol; - } - function bindObjectLiteralExpression(node) { - var ElementKind; - (function (ElementKind) { - ElementKind[ElementKind["Property"] = 1] = "Property"; - ElementKind[ElementKind["Accessor"] = 2] = "Accessor"; - })(ElementKind || (ElementKind = {})); - if (inStrictMode) { - var seen = ts.createMap(); - for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { - var prop = _a[_i]; - if (prop.name.kind !== 69 /* Identifier */) { - continue; - } - var identifier = prop.name; - // ECMA-262 11.1.5 Object Initializer - // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true - // a.This production is contained in strict code and IsDataDescriptor(previous) is true and - // IsDataDescriptor(propId.descriptor) is true. - // b.IsDataDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true. - // c.IsAccessorDescriptor(previous) is true and IsDataDescriptor(propId.descriptor) is true. - // d.IsAccessorDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true - // and either both previous and propId.descriptor have[[Get]] fields or both previous and propId.descriptor have[[Set]] fields - var currentKind = prop.kind === 253 /* PropertyAssignment */ || prop.kind === 254 /* ShorthandPropertyAssignment */ || prop.kind === 147 /* MethodDeclaration */ - ? 1 /* Property */ - : 2 /* Accessor */; - var existingKind = seen[identifier.text]; - if (!existingKind) { - seen[identifier.text] = currentKind; - continue; - } - if (currentKind === 1 /* Property */ && existingKind === 1 /* Property */) { - var span = ts.getErrorSpanForNode(file, identifier); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, ts.Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode)); - } + break; + case 256 /* SourceFile */: + if (subtreeFlags & 16384 /* ContainsCapturedLexicalThis */) { + transformFlags |= 192 /* AssertES6 */; } - } - return bindAnonymousDeclaration(node, 4096 /* ObjectLiteral */, "__object"); - } - function bindAnonymousDeclaration(node, symbolFlags, name) { - var symbol = createSymbol(symbolFlags, name); - addDeclarationToSymbol(symbol, node, symbolFlags); + break; + case 211 /* ReturnStatement */: + case 209 /* ContinueStatement */: + case 210 /* BreakStatement */: + transformFlags |= 8388608 /* ContainsHoistedDeclarationOrCompletion */; + break; } - function bindBlockScopedDeclaration(node, symbolFlags, symbolExcludes) { - switch (blockScopeContainer.kind) { - case 225 /* ModuleDeclaration */: - declareModuleMember(node, symbolFlags, symbolExcludes); - break; - case 256 /* SourceFile */: - if (ts.isExternalModule(container)) { - declareModuleMember(node, symbolFlags, symbolExcludes); - break; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~excludeFlags; + } +})(ts || (ts = {})); +/// +/// +var ts; +(function (ts) { + function trace(host, message) { + host.trace(ts.formatMessage.apply(undefined, arguments)); + } + ts.trace = trace; + /* @internal */ + function isTraceEnabled(compilerOptions, host) { + return compilerOptions.traceResolution && host.trace !== undefined; + } + ts.isTraceEnabled = isTraceEnabled; + /* @internal */ + function createResolvedModule(resolvedFileName, isExternalLibraryImport, failedLookupLocations) { + return { resolvedModule: resolvedFileName ? { resolvedFileName: resolvedFileName, isExternalLibraryImport: isExternalLibraryImport } : undefined, failedLookupLocations: failedLookupLocations }; + } + ts.createResolvedModule = createResolvedModule; + function moduleHasNonRelativeName(moduleName) { + return !(ts.isRootedDiskPath(moduleName) || ts.isExternalModuleNameRelative(moduleName)); + } + function tryReadTypesSection(packageJsonPath, baseDirectory, state) { + var jsonContent = readJson(packageJsonPath, state.host); + function tryReadFromField(fieldName) { + if (ts.hasProperty(jsonContent, fieldName)) { + var typesFile = jsonContent[fieldName]; + if (typeof typesFile === "string") { + var typesFilePath_1 = ts.normalizePath(ts.combinePaths(baseDirectory, typesFile)); + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.package_json_has_0_field_1_that_references_2, fieldName, typesFile, typesFilePath_1); } - // fall through. - default: - if (!blockScopeContainer.locals) { - blockScopeContainer.locals = ts.createMap(); - addToContainerChain(blockScopeContainer); + return typesFilePath_1; + } + else { + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, fieldName, typeof typesFile); } - declareSymbol(blockScopeContainer.locals, undefined, node, symbolFlags, symbolExcludes); - } - } - function bindBlockScopedVariableDeclaration(node) { - bindBlockScopedDeclaration(node, 2 /* BlockScopedVariable */, 107455 /* BlockScopedVariableExcludes */); - } - // The binder visits every node in the syntax tree so it is a convenient place to perform a single localized - // check for reserved words used as identifiers in strict mode code. - function checkStrictModeIdentifier(node) { - if (inStrictMode && - node.originalKeywordKind >= 106 /* FirstFutureReservedWord */ && - node.originalKeywordKind <= 114 /* LastFutureReservedWord */ && - !ts.isIdentifierName(node) && - !ts.isInAmbientContext(node)) { - // Report error only if there are no parse errors in file - if (!file.parseDiagnostics.length) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(node, getStrictModeIdentifierMessage(node), ts.declarationNameToString(node))); } } } - function getStrictModeIdentifierMessage(node) { - // Provide specialized messages to help the user understand why we think they're in - // strict mode. - if (ts.getContainingClass(node)) { - return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode; - } - if (file.externalModuleIndicator) { - return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Modules_are_automatically_in_strict_mode; - } - return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode; + var typesFilePath = tryReadFromField("typings") || tryReadFromField("types"); + if (typesFilePath) { + return typesFilePath; } - function checkStrictModeBinaryExpression(node) { - if (inStrictMode && ts.isLeftHandSideExpression(node.left) && ts.isAssignmentOperator(node.operatorToken.kind)) { - // ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an - // Assignment operator(11.13) or of a PostfixExpression(11.3) - checkStrictModeEvalOrArguments(node, node.left); + // Use the main module for inferring types if no types package specified and the allowJs is set + if (state.compilerOptions.allowJs && jsonContent.main && typeof jsonContent.main === "string") { + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.No_types_specified_in_package_json_but_allowJs_is_set_so_returning_main_value_of_0, jsonContent.main); } + var mainFilePath = ts.normalizePath(ts.combinePaths(baseDirectory, jsonContent.main)); + return mainFilePath; } - function checkStrictModeCatchClause(node) { - // It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the - // Catch production is eval or arguments - if (inStrictMode && node.variableDeclaration) { - checkStrictModeEvalOrArguments(node, node.variableDeclaration.name); - } + return undefined; + } + function readJson(path, host) { + try { + var jsonText = host.readFile(path); + return jsonText ? JSON.parse(jsonText) : {}; } - function checkStrictModeDeleteExpression(node) { - // Grammar checking - if (inStrictMode && node.expression.kind === 69 /* Identifier */) { - // When a delete operator occurs within strict mode code, a SyntaxError is thrown if its - // UnaryExpression is a direct reference to a variable, function argument, or function name - var span = ts.getErrorSpanForNode(file, node.expression); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, ts.Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode)); - } + catch (e) { + // gracefully handle if readFile fails or returns not JSON + return {}; } - function isEvalOrArgumentsIdentifier(node) { - return node.kind === 69 /* Identifier */ && - (node.text === "eval" || node.text === "arguments"); + } + var typeReferenceExtensions = [".d.ts"]; + function getEffectiveTypeRoots(options, host) { + if (options.typeRoots) { + return options.typeRoots; } - function checkStrictModeEvalOrArguments(contextNode, name) { - if (name && name.kind === 69 /* Identifier */) { - var identifier = name; - if (isEvalOrArgumentsIdentifier(identifier)) { - // We check first if the name is inside class declaration or class expression; if so give explicit message - // otherwise report generic error message. - var span = ts.getErrorSpanForNode(file, name); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, getStrictModeEvalOrArgumentsMessage(contextNode), identifier.text)); - } - } + var currentDirectory; + if (options.configFilePath) { + currentDirectory = ts.getDirectoryPath(options.configFilePath); } - function getStrictModeEvalOrArgumentsMessage(node) { - // Provide specialized messages to help the user understand why we think they're in - // strict mode. - if (ts.getContainingClass(node)) { - return ts.Diagnostics.Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode; - } - if (file.externalModuleIndicator) { - return ts.Diagnostics.Invalid_use_of_0_Modules_are_automatically_in_strict_mode; - } - return ts.Diagnostics.Invalid_use_of_0_in_strict_mode; + else if (host.getCurrentDirectory) { + currentDirectory = host.getCurrentDirectory(); } - function checkStrictModeFunctionName(node) { - if (inStrictMode) { - // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a strict mode FunctionDeclaration or FunctionExpression (13.1)) - checkStrictModeEvalOrArguments(node, node.name); - } + return currentDirectory && getDefaultTypeRoots(currentDirectory, host); + } + ts.getEffectiveTypeRoots = getEffectiveTypeRoots; + /** + * Returns the path to every node_modules/@types directory from some ancestor directory. + * Returns undefined if there are none. + */ + function getDefaultTypeRoots(currentDirectory, host) { + if (!host.directoryExists) { + return [ts.combinePaths(currentDirectory, nodeModulesAtTypes)]; } - function getStrictModeBlockScopeFunctionDeclarationMessage(node) { - // Provide specialized messages to help the user understand why we think they're in - // strict mode. - if (ts.getContainingClass(node)) { - return ts.Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Class_definitions_are_automatically_in_strict_mode; + var typeRoots; + while (true) { + var atTypes = ts.combinePaths(currentDirectory, nodeModulesAtTypes); + if (host.directoryExists(atTypes)) { + (typeRoots || (typeRoots = [])).push(atTypes); } - if (file.externalModuleIndicator) { - return ts.Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Modules_are_automatically_in_strict_mode; + var parent_7 = ts.getDirectoryPath(currentDirectory); + if (parent_7 === currentDirectory) { + break; } - return ts.Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5; + currentDirectory = parent_7; } - function checkStrictModeFunctionDeclaration(node) { - if (languageVersion < 2 /* ES6 */) { - // Report error if function is not top level function declaration - if (blockScopeContainer.kind !== 256 /* SourceFile */ && - blockScopeContainer.kind !== 225 /* ModuleDeclaration */ && - !ts.isFunctionLike(blockScopeContainer)) { - // We check first if the name is inside class declaration or class expression; if so give explicit message - // otherwise report generic error message. - var errorSpan = ts.getErrorSpanForNode(file, node); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, errorSpan.start, errorSpan.length, getStrictModeBlockScopeFunctionDeclarationMessage(node))); + return typeRoots; + } + var nodeModulesAtTypes = ts.combinePaths("node_modules", "@types"); + /** + * @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. + * This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups + * is assumed to be the same as root directory of the project. + */ + function resolveTypeReferenceDirective(typeReferenceDirectiveName, containingFile, options, host) { + var traceEnabled = isTraceEnabled(options, host); + var moduleResolutionState = { + compilerOptions: options, + host: host, + skipTsx: true, + traceEnabled: traceEnabled + }; + var typeRoots = getEffectiveTypeRoots(options, host); + if (traceEnabled) { + if (containingFile === undefined) { + if (typeRoots === undefined) { + trace(host, ts.Diagnostics.Resolving_type_reference_directive_0_containing_file_not_set_root_directory_not_set, typeReferenceDirectiveName); + } + else { + trace(host, ts.Diagnostics.Resolving_type_reference_directive_0_containing_file_not_set_root_directory_1, typeReferenceDirectiveName, typeRoots); } } - } - function checkStrictModeNumericLiteral(node) { - if (inStrictMode && node.isOctalLiteral) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Octal_literals_are_not_allowed_in_strict_mode)); - } - } - function checkStrictModePostfixUnaryExpression(node) { - // Grammar checking - // The identifier eval or arguments may not appear as the LeftHandSideExpression of an - // Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression - // operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator. - if (inStrictMode) { - checkStrictModeEvalOrArguments(node, node.operand); - } - } - function checkStrictModePrefixUnaryExpression(node) { - // Grammar checking - if (inStrictMode) { - if (node.operator === 41 /* PlusPlusToken */ || node.operator === 42 /* MinusMinusToken */) { - checkStrictModeEvalOrArguments(node, node.operand); + else { + if (typeRoots === undefined) { + trace(host, ts.Diagnostics.Resolving_type_reference_directive_0_containing_file_1_root_directory_not_set, typeReferenceDirectiveName, containingFile); + } + else { + trace(host, ts.Diagnostics.Resolving_type_reference_directive_0_containing_file_1_root_directory_2, typeReferenceDirectiveName, containingFile, typeRoots); } } } - function checkStrictModeWithStatement(node) { - // Grammar checking for withStatement - if (inStrictMode) { - errorOnFirstToken(node, ts.Diagnostics.with_statements_are_not_allowed_in_strict_mode); + var failedLookupLocations = []; + // Check primary library paths + if (typeRoots && typeRoots.length) { + if (traceEnabled) { + trace(host, ts.Diagnostics.Resolving_with_primary_search_path_0, typeRoots.join(", ")); + } + var primarySearchPaths = typeRoots; + for (var _i = 0, primarySearchPaths_1 = primarySearchPaths; _i < primarySearchPaths_1.length; _i++) { + var typeRoot = primarySearchPaths_1[_i]; + var candidate = ts.combinePaths(typeRoot, typeReferenceDirectiveName); + var candidateDirectory = ts.getDirectoryPath(candidate); + var resolvedFile_1 = loadNodeModuleFromDirectory(typeReferenceExtensions, candidate, failedLookupLocations, !directoryProbablyExists(candidateDirectory, host), moduleResolutionState); + if (resolvedFile_1) { + if (traceEnabled) { + trace(host, ts.Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, resolvedFile_1, true); + } + return { + resolvedTypeReferenceDirective: { primary: true, resolvedFileName: resolvedFile_1 }, + failedLookupLocations: failedLookupLocations + }; + } } } - function errorOnFirstToken(node, message, arg0, arg1, arg2) { - var span = ts.getSpanOfTokenAtPosition(file, node.pos); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, message, arg0, arg1, arg2)); + else { + if (traceEnabled) { + trace(host, ts.Diagnostics.Root_directory_cannot_be_determined_skipping_primary_search_paths); + } } - function getDestructuringParameterName(node) { - return "__" + ts.indexOf(node.parent.parameters, node); + var resolvedFile; + var initialLocationForSecondaryLookup; + if (containingFile) { + initialLocationForSecondaryLookup = ts.getDirectoryPath(containingFile); } - function bind(node) { - if (!node) { - return; + if (initialLocationForSecondaryLookup !== undefined) { + // check secondary locations + if (traceEnabled) { + trace(host, ts.Diagnostics.Looking_up_in_node_modules_folder_initial_location_0, initialLocationForSecondaryLookup); } - node.parent = parent; - var saveInStrictMode = inStrictMode; - // First we bind declaration nodes to a symbol if possible. We'll both create a symbol - // and then potentially add the symbol to an appropriate symbol table. Possible - // destination symbol tables are: - // - // 1) The 'exports' table of the current container's symbol. - // 2) The 'members' table of the current container's symbol. - // 3) The 'locals' table of the current container. - // - // However, not all symbols will end up in any of these tables. 'Anonymous' symbols - // (like TypeLiterals for example) will not be put in any table. - bindWorker(node); - // Then we recurse into the children of the node to bind them as well. For certain - // symbols we do specialized work when we recurse. For example, we'll keep track of - // the current 'container' node when it changes. This helps us know which symbol table - // a local should go into for example. Since terminal nodes are known not to have - // children, as an optimization we don't process those. - if (node.kind > 138 /* LastToken */) { - var saveParent = parent; - parent = node; - var containerFlags = getContainerFlags(node); - if (containerFlags === 0 /* None */) { - bindChildren(node); + resolvedFile = loadModuleFromNodeModules(typeReferenceDirectiveName, initialLocationForSecondaryLookup, failedLookupLocations, moduleResolutionState, /*checkOneLevel*/ false); + if (traceEnabled) { + if (resolvedFile) { + trace(host, ts.Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, resolvedFile, false); } else { - bindContainer(node, containerFlags); + trace(host, ts.Diagnostics.Type_reference_directive_0_was_not_resolved, typeReferenceDirectiveName); } - parent = saveParent; } - inStrictMode = saveInStrictMode; } - function updateStrictModeStatementList(statements) { - if (!inStrictMode) { - for (var _i = 0, statements_1 = statements; _i < statements_1.length; _i++) { - var statement = statements_1[_i]; - if (!ts.isPrologueDirective(statement)) { - return; - } - if (isUseStrictPrologueDirective(statement)) { - inStrictMode = true; - return; - } - } + else { + if (traceEnabled) { + trace(host, ts.Diagnostics.Containing_file_is_not_specified_and_root_directory_cannot_be_determined_skipping_lookup_in_node_modules_folder); } } - /// Should be called only on prologue directives (isPrologueDirective(node) should be true) - function isUseStrictPrologueDirective(node) { - var nodeText = ts.getTextOfNodeFromSourceText(file.text, node.expression); - // Note: the node text must be exactly "use strict" or 'use strict'. It is not ok for the - // string to contain unicode escapes (as per ES5). - return nodeText === '"use strict"' || nodeText === "'use strict'"; + return { + resolvedTypeReferenceDirective: resolvedFile + ? { primary: false, resolvedFileName: resolvedFile } + : undefined, + failedLookupLocations: failedLookupLocations + }; + } + ts.resolveTypeReferenceDirective = resolveTypeReferenceDirective; + /** + * Given a set of options, returns the set of type directive names + * that should be included for this program automatically. + * This list could either come from the config file, + * or from enumerating the types root + initial secondary types lookup location. + * More type directives might appear in the program later as a result of loading actual source files; + * this list is only the set of defaults that are implicitly included. + */ + function getAutomaticTypeDirectiveNames(options, host) { + // Use explicit type list from tsconfig.json + if (options.types) { + return options.types; } - function bindWorker(node) { - switch (node.kind) { - /* Strict mode checks */ - case 69 /* Identifier */: - case 97 /* ThisKeyword */: - if (currentFlow && (ts.isExpression(node) || parent.kind === 254 /* ShorthandPropertyAssignment */)) { - node.flowNode = currentFlow; - } - return checkStrictModeIdentifier(node); - case 172 /* PropertyAccessExpression */: - if (currentFlow && isNarrowableReference(node)) { - node.flowNode = currentFlow; - } - break; - case 187 /* BinaryExpression */: - if (ts.isInJavaScriptFile(node)) { - var specialKind = ts.getSpecialPropertyAssignmentKind(node); - switch (specialKind) { - case 1 /* ExportsProperty */: - bindExportsPropertyAssignment(node); - break; - case 2 /* ModuleExports */: - bindModuleExportsAssignment(node); - break; - case 3 /* PrototypeProperty */: - bindPrototypePropertyAssignment(node); - break; - case 4 /* ThisProperty */: - bindThisPropertyAssignment(node); - break; - case 0 /* None */: - // Nothing to do - break; - default: - ts.Debug.fail("Unknown special property assignment kind"); + // Walk the primary type lookup locations + var result = []; + if (host.directoryExists && host.getDirectories) { + var typeRoots = getEffectiveTypeRoots(options, host); + if (typeRoots) { + for (var _i = 0, typeRoots_1 = typeRoots; _i < typeRoots_1.length; _i++) { + var root = typeRoots_1[_i]; + if (host.directoryExists(root)) { + for (var _a = 0, _b = host.getDirectories(root); _a < _b.length; _a++) { + var typeDirectivePath = _b[_a]; + var normalized = ts.normalizePath(typeDirectivePath); + var packageJsonPath = pathToPackageJson(ts.combinePaths(root, normalized)); + // tslint:disable-next-line:no-null-keyword + var isNotNeededPackage = host.fileExists(packageJsonPath) && readJson(packageJsonPath, host).typings === null; + if (!isNotNeededPackage) { + // Return just the type directive names + result.push(ts.getBaseFileName(normalized)); + } } } - return checkStrictModeBinaryExpression(node); - case 252 /* CatchClause */: - return checkStrictModeCatchClause(node); - case 181 /* DeleteExpression */: - return checkStrictModeDeleteExpression(node); - case 8 /* NumericLiteral */: - return checkStrictModeNumericLiteral(node); - case 186 /* PostfixUnaryExpression */: - return checkStrictModePostfixUnaryExpression(node); - case 185 /* PrefixUnaryExpression */: - return checkStrictModePrefixUnaryExpression(node); - case 212 /* WithStatement */: - return checkStrictModeWithStatement(node); - case 165 /* ThisType */: - seenThisKeyword = true; - return; - case 154 /* TypePredicate */: - return checkTypePredicate(node); - case 141 /* TypeParameter */: - return declareSymbolAndAddToSymbolTable(node, 262144 /* TypeParameter */, 530920 /* TypeParameterExcludes */); - case 142 /* Parameter */: - return bindParameter(node); - case 218 /* VariableDeclaration */: - case 169 /* BindingElement */: - return bindVariableDeclarationOrBindingElement(node); - case 145 /* PropertyDeclaration */: - case 144 /* PropertySignature */: - case 266 /* JSDocRecordMember */: - return bindPropertyOrMethodOrAccessor(node, 4 /* Property */ | (node.questionToken ? 536870912 /* Optional */ : 0 /* None */), 0 /* PropertyExcludes */); - case 280 /* JSDocPropertyTag */: - return bindJSDocProperty(node); - case 253 /* PropertyAssignment */: - case 254 /* ShorthandPropertyAssignment */: - return bindPropertyOrMethodOrAccessor(node, 4 /* Property */, 0 /* PropertyExcludes */); - case 255 /* EnumMember */: - return bindPropertyOrMethodOrAccessor(node, 8 /* EnumMember */, 900095 /* EnumMemberExcludes */); - case 247 /* JsxSpreadAttribute */: - emitFlags |= 1073741824 /* HasJsxSpreadAttribute */; - return; - case 151 /* CallSignature */: - case 152 /* ConstructSignature */: - case 153 /* IndexSignature */: - return declareSymbolAndAddToSymbolTable(node, 131072 /* Signature */, 0 /* None */); - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - // If this is an ObjectLiteralExpression method, then it sits in the same space - // as other properties in the object literal. So we use SymbolFlags.PropertyExcludes - // so that it will conflict with any other object literal members with the same - // name. - return bindPropertyOrMethodOrAccessor(node, 8192 /* Method */ | (node.questionToken ? 536870912 /* Optional */ : 0 /* None */), ts.isObjectLiteralMethod(node) ? 0 /* PropertyExcludes */ : 99263 /* MethodExcludes */); - case 220 /* FunctionDeclaration */: - return bindFunctionDeclaration(node); - case 148 /* Constructor */: - return declareSymbolAndAddToSymbolTable(node, 16384 /* Constructor */, /*symbolExcludes:*/ 0 /* None */); - case 149 /* GetAccessor */: - return bindPropertyOrMethodOrAccessor(node, 32768 /* GetAccessor */, 41919 /* GetAccessorExcludes */); - case 150 /* SetAccessor */: - return bindPropertyOrMethodOrAccessor(node, 65536 /* SetAccessor */, 74687 /* SetAccessorExcludes */); - case 156 /* FunctionType */: - case 157 /* ConstructorType */: - case 269 /* JSDocFunctionType */: - return bindFunctionOrConstructorType(node); - case 159 /* TypeLiteral */: - case 281 /* JSDocTypeLiteral */: - case 265 /* JSDocRecordType */: - return bindAnonymousDeclaration(node, 2048 /* TypeLiteral */, "__type"); - case 171 /* ObjectLiteralExpression */: - return bindObjectLiteralExpression(node); - case 179 /* FunctionExpression */: - case 180 /* ArrowFunction */: - return bindFunctionExpression(node); - case 174 /* CallExpression */: - if (ts.isInJavaScriptFile(node)) { - bindCallExpression(node); - } - break; - // Members of classes, interfaces, and modules - case 192 /* ClassExpression */: - case 221 /* ClassDeclaration */: - // All classes are automatically in strict mode in ES6. - inStrictMode = true; - return bindClassLikeDeclaration(node); - case 222 /* InterfaceDeclaration */: - return bindBlockScopedDeclaration(node, 64 /* Interface */, 792968 /* InterfaceExcludes */); - case 279 /* JSDocTypedefTag */: - case 223 /* TypeAliasDeclaration */: - return bindBlockScopedDeclaration(node, 524288 /* TypeAlias */, 793064 /* TypeAliasExcludes */); - case 224 /* EnumDeclaration */: - return bindEnumDeclaration(node); - case 225 /* ModuleDeclaration */: - return bindModuleDeclaration(node); - // Imports and exports - case 229 /* ImportEqualsDeclaration */: - case 232 /* NamespaceImport */: - case 234 /* ImportSpecifier */: - case 238 /* ExportSpecifier */: - return declareSymbolAndAddToSymbolTable(node, 8388608 /* Alias */, 8388608 /* AliasExcludes */); - case 228 /* NamespaceExportDeclaration */: - return bindNamespaceExportDeclaration(node); - case 231 /* ImportClause */: - return bindImportClause(node); - case 236 /* ExportDeclaration */: - return bindExportDeclaration(node); - case 235 /* ExportAssignment */: - return bindExportAssignment(node); - case 256 /* SourceFile */: - updateStrictModeStatementList(node.statements); - return bindSourceFileIfExternalModule(); - case 199 /* Block */: - if (!ts.isFunctionLike(node.parent)) { - return; - } - // Fall through - case 226 /* ModuleBlock */: - return updateStrictModeStatementList(node.statements); + } } } - function checkTypePredicate(node) { - var parameterName = node.parameterName, type = node.type; - if (parameterName && parameterName.kind === 69 /* Identifier */) { - checkStrictModeIdentifier(parameterName); - } - if (parameterName && parameterName.kind === 165 /* ThisType */) { - seenThisKeyword = true; - } - bind(type); + return result; + } + ts.getAutomaticTypeDirectiveNames = getAutomaticTypeDirectiveNames; + function resolveModuleName(moduleName, containingFile, compilerOptions, host) { + var traceEnabled = isTraceEnabled(compilerOptions, host); + if (traceEnabled) { + trace(host, ts.Diagnostics.Resolving_module_0_from_1, moduleName, containingFile); } - function bindSourceFileIfExternalModule() { - setExportContextFlag(file); - if (ts.isExternalModule(file)) { - bindSourceFileAsExternalModule(); + var moduleResolution = compilerOptions.moduleResolution; + if (moduleResolution === undefined) { + moduleResolution = ts.getEmitModuleKind(compilerOptions) === ts.ModuleKind.CommonJS ? ts.ModuleResolutionKind.NodeJs : ts.ModuleResolutionKind.Classic; + if (traceEnabled) { + trace(host, ts.Diagnostics.Module_resolution_kind_is_not_specified_using_0, ts.ModuleResolutionKind[moduleResolution]); } } - function bindSourceFileAsExternalModule() { - bindAnonymousDeclaration(file, 512 /* ValueModule */, "\"" + ts.removeFileExtension(file.fileName) + "\""); - } - function bindExportAssignment(node) { - if (!container.symbol || !container.symbol.exports) { - // Export assignment in some sort of block construct - bindAnonymousDeclaration(node, 8388608 /* Alias */, getDeclarationName(node)); - } - else { - var flags = node.kind === 235 /* ExportAssignment */ && ts.exportAssignmentIsAlias(node) - ? 8388608 /* Alias */ - : 4 /* Property */; - declareSymbol(container.symbol.exports, container.symbol, node, flags, 0 /* PropertyExcludes */ | 8388608 /* AliasExcludes */); + else { + if (traceEnabled) { + trace(host, ts.Diagnostics.Explicitly_specified_module_resolution_kind_Colon_0, ts.ModuleResolutionKind[moduleResolution]); } } - function bindNamespaceExportDeclaration(node) { - if (node.modifiers && node.modifiers.length) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Modifiers_cannot_appear_here)); - } - if (node.parent.kind !== 256 /* SourceFile */) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Global_module_exports_may_only_appear_at_top_level)); - return; - } - else { - var parent_6 = node.parent; - if (!ts.isExternalModule(parent_6)) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Global_module_exports_may_only_appear_in_module_files)); - return; - } - if (!parent_6.isDeclarationFile) { - file.bindDiagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Global_module_exports_may_only_appear_in_declaration_files)); - return; - } - } - file.symbol.globalExports = file.symbol.globalExports || ts.createMap(); - declareSymbol(file.symbol.globalExports, file.symbol, node, 8388608 /* Alias */, 8388608 /* AliasExcludes */); + var result; + switch (moduleResolution) { + case ts.ModuleResolutionKind.NodeJs: + result = nodeModuleNameResolver(moduleName, containingFile, compilerOptions, host); + break; + case ts.ModuleResolutionKind.Classic: + result = classicNameResolver(moduleName, containingFile, compilerOptions, host); + break; } - function bindExportDeclaration(node) { - if (!container.symbol || !container.symbol.exports) { - // Export * in some sort of block construct - bindAnonymousDeclaration(node, 1073741824 /* ExportStar */, getDeclarationName(node)); + if (traceEnabled) { + if (result.resolvedModule) { + trace(host, ts.Diagnostics.Module_name_0_was_successfully_resolved_to_1, moduleName, result.resolvedModule.resolvedFileName); } - else if (!node.exportClause) { - // All export * declarations are collected in an __export symbol - declareSymbol(container.symbol.exports, container.symbol, node, 1073741824 /* ExportStar */, 0 /* None */); + else { + trace(host, ts.Diagnostics.Module_name_0_was_not_resolved, moduleName); } } - function bindImportClause(node) { - if (node.name) { - declareSymbolAndAddToSymbolTable(node, 8388608 /* Alias */, 8388608 /* AliasExcludes */); - } + return result; + } + ts.resolveModuleName = resolveModuleName; + /** + * Any module resolution kind can be augmented with optional settings: 'baseUrl', 'paths' and 'rootDirs' - they are used to + * mitigate differences between design time structure of the project and its runtime counterpart so the same import name + * can be resolved successfully by TypeScript compiler and runtime module loader. + * If these settings are set then loading procedure will try to use them to resolve module name and it can of failure it will + * fallback to standard resolution routine. + * + * - baseUrl - this setting controls how non-relative module names are resolved. If this setting is specified then non-relative + * names will be resolved relative to baseUrl: i.e. if baseUrl is '/a/b' then candidate location to resolve module name 'c/d' will + * be '/a/b/c/d' + * - paths - this setting can only be used when baseUrl is specified. allows to tune how non-relative module names + * will be resolved based on the content of the module name. + * Structure of 'paths' compiler options + * 'paths': { + * pattern-1: [...substitutions], + * pattern-2: [...substitutions], + * ... + * pattern-n: [...substitutions] + * } + * Pattern here is a string that can contain zero or one '*' character. During module resolution module name will be matched against + * all patterns in the list. Matching for patterns that don't contain '*' means that module name must be equal to pattern respecting the case. + * If pattern contains '*' then to match pattern "*" module name must start with the and end with . + * denotes part of the module name between and . + * If module name can be matches with multiple patterns then pattern with the longest prefix will be picked. + * After selecting pattern we'll use list of substitutions to get candidate locations of the module and the try to load module + * from the candidate location. + * Substitution is a string that can contain zero or one '*'. To get candidate location from substitution we'll pick every + * substitution in the list and replace '*' with string. If candidate location is not rooted it + * will be converted to absolute using baseUrl. + * For example: + * baseUrl: /a/b/c + * "paths": { + * // match all module names + * "*": [ + * "*", // use matched name as is, + * // will be looked as /a/b/c/ + * + * "folder1/*" // substitution will convert matched name to 'folder1/', + * // since it is not rooted then final candidate location will be /a/b/c/folder1/ + * ], + * // match module names that start with 'components/' + * "components/*": [ "/root/components/*" ] // substitution will convert /components/folder1/ to '/root/components/folder1/', + * // it is rooted so it will be final candidate location + * } + * + * 'rootDirs' allows the project to be spreaded across multiple locations and resolve modules with relative names as if + * they were in the same location. For example lets say there are two files + * '/local/src/content/file1.ts' + * '/shared/components/contracts/src/content/protocols/file2.ts' + * After bundling content of '/shared/components/contracts/src' will be merged with '/local/src' so + * if file1 has the following import 'import {x} from "./protocols/file2"' it will be resolved successfully in runtime. + * 'rootDirs' provides the way to tell compiler that in order to get the whole project it should behave as if content of all + * root dirs were merged together. + * I.e. for the example above 'rootDirs' will have two entries: [ '/local/src', '/shared/components/contracts/src' ]. + * Compiler will first convert './protocols/file2' into absolute path relative to the location of containing file: + * '/local/src/content/protocols/file2' and try to load it - failure. + * Then it will search 'rootDirs' looking for a longest matching prefix of this absolute path and if such prefix is found - absolute path will + * be converted to a path relative to found rootDir entry './content/protocols/file2' (*). As a last step compiler will check all remaining + * entries in 'rootDirs', use them to build absolute path out of (*) and try to resolve module from this location. + */ + function tryLoadModuleUsingOptionalResolutionSettings(moduleName, containingDirectory, loader, failedLookupLocations, supportedExtensions, state) { + if (moduleHasNonRelativeName(moduleName)) { + return tryLoadModuleUsingBaseUrl(moduleName, loader, failedLookupLocations, supportedExtensions, state); } - function setCommonJsModuleIndicator(node) { - if (!file.commonJsModuleIndicator) { - file.commonJsModuleIndicator = node; - bindSourceFileAsExternalModule(); - } + else { + return tryLoadModuleUsingRootDirs(moduleName, containingDirectory, loader, failedLookupLocations, supportedExtensions, state); } - function bindExportsPropertyAssignment(node) { - // When we create a property via 'exports.foo = bar', the 'exports.foo' property access - // expression is the declaration - setCommonJsModuleIndicator(node); - declareSymbol(file.symbol.exports, file.symbol, node.left, 4 /* Property */ | 7340032 /* Export */, 0 /* None */); + } + function tryLoadModuleUsingRootDirs(moduleName, containingDirectory, loader, failedLookupLocations, supportedExtensions, state) { + if (!state.compilerOptions.rootDirs) { + return undefined; } - function bindModuleExportsAssignment(node) { - // 'module.exports = expr' assignment - setCommonJsModuleIndicator(node); - declareSymbol(file.symbol.exports, file.symbol, node, 4 /* Property */ | 7340032 /* Export */ | 512 /* ValueModule */, 0 /* None */); + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.rootDirs_option_is_set_using_it_to_resolve_relative_module_name_0, moduleName); } - function bindThisPropertyAssignment(node) { - ts.Debug.assert(ts.isInJavaScriptFile(node)); - // Declare a 'member' if the container is an ES5 class or ES6 constructor - if (container.kind === 220 /* FunctionDeclaration */ || container.kind === 179 /* FunctionExpression */) { - container.symbol.members = container.symbol.members || ts.createMap(); - // It's acceptable for multiple 'this' assignments of the same identifier to occur - declareSymbol(container.symbol.members, container.symbol, node, 4 /* Property */, 0 /* PropertyExcludes */ & ~4 /* Property */); - } - else if (container.kind === 148 /* Constructor */) { - // this.foo assignment in a JavaScript class - // Bind this property to the containing class - var saveContainer = container; - container = container.parent; - var symbol = bindPropertyOrMethodOrAccessor(node, 4 /* Property */, 0 /* None */); - if (symbol) { - // constructor-declared symbols can be overwritten by subsequent method declarations - symbol.isReplaceableByMethod = true; - } - container = saveContainer; + var candidate = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName)); + var matchedRootDir; + var matchedNormalizedPrefix; + for (var _i = 0, _a = state.compilerOptions.rootDirs; _i < _a.length; _i++) { + var rootDir = _a[_i]; + // rootDirs are expected to be absolute + // in case of tsconfig.json this will happen automatically - compiler will expand relative names + // using location of tsconfig.json as base location + var normalizedRoot = ts.normalizePath(rootDir); + if (!ts.endsWith(normalizedRoot, ts.directorySeparator)) { + normalizedRoot += ts.directorySeparator; } - } - function bindPrototypePropertyAssignment(node) { - // We saw a node of the form 'x.prototype.y = z'. Declare a 'member' y on x if x was a function. - // Look up the function in the local scope, since prototype assignments should - // follow the function declaration - var leftSideOfAssignment = node.left; - var classPrototype = leftSideOfAssignment.expression; - var constructorFunction = classPrototype.expression; - // Fix up parent pointers since we're going to use these nodes before we bind into them - leftSideOfAssignment.parent = node; - constructorFunction.parent = classPrototype; - classPrototype.parent = leftSideOfAssignment; - var funcSymbol = container.locals[constructorFunction.text]; - if (!funcSymbol || !(funcSymbol.flags & 16 /* Function */ || ts.isDeclarationOfFunctionExpression(funcSymbol))) { - return; + var isLongestMatchingPrefix = ts.startsWith(candidate, normalizedRoot) && + (matchedNormalizedPrefix === undefined || matchedNormalizedPrefix.length < normalizedRoot.length); + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Checking_if_0_is_the_longest_matching_prefix_for_1_2, normalizedRoot, candidate, isLongestMatchingPrefix); } - // Set up the members collection if it doesn't exist already - if (!funcSymbol.members) { - funcSymbol.members = ts.createMap(); + if (isLongestMatchingPrefix) { + matchedNormalizedPrefix = normalizedRoot; + matchedRootDir = rootDir; } - // Declare the method/property - declareSymbol(funcSymbol.members, funcSymbol, leftSideOfAssignment, 4 /* Property */, 0 /* PropertyExcludes */); } - function bindCallExpression(node) { - // We're only inspecting call expressions to detect CommonJS modules, so we can skip - // this check if we've already seen the module indicator - if (!file.commonJsModuleIndicator && ts.isRequireCall(node, /*checkArgumentIsStringLiteral*/ false)) { - setCommonJsModuleIndicator(node); + if (matchedNormalizedPrefix) { + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Longest_matching_prefix_for_0_is_1, candidate, matchedNormalizedPrefix); } - } - function bindClassLikeDeclaration(node) { - if (!ts.isDeclarationFile(file) && !ts.isInAmbientContext(node)) { - if (ts.getClassExtendsHeritageClauseElement(node) !== undefined) { - emitFlags |= 262144 /* HasClassExtends */; - } - if (ts.nodeIsDecorated(node)) { - emitFlags |= 524288 /* HasDecorators */; - } + var suffix = candidate.substr(matchedNormalizedPrefix.length); + // first - try to load from a initial location + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Loading_0_from_the_root_dir_1_candidate_location_2, suffix, matchedNormalizedPrefix, candidate); } - if (node.kind === 221 /* ClassDeclaration */) { - bindBlockScopedDeclaration(node, 32 /* Class */, 899519 /* ClassExcludes */); + var resolvedFileName = loader(candidate, supportedExtensions, failedLookupLocations, !directoryProbablyExists(containingDirectory, state.host), state); + if (resolvedFileName) { + return resolvedFileName; } - else { - var bindingName = node.name ? node.name.text : "__class"; - bindAnonymousDeclaration(node, 32 /* Class */, bindingName); - // Add name of class expression into the map for semantic classifier - if (node.name) { - classifiableNames[node.name.text] = node.name.text; - } + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Trying_other_entries_in_rootDirs); } - var symbol = node.symbol; - // TypeScript 1.0 spec (April 2014): 8.4 - // Every class automatically contains a static property member named 'prototype', the - // type of which is an instantiation of the class type with type Any supplied as a type - // argument for each type parameter. It is an error to explicitly declare a static - // property member with the name 'prototype'. - // - // Note: we check for this here because this class may be merging into a module. The - // module might have an exported variable called 'prototype'. We can't allow that as - // that would clash with the built-in 'prototype' for the class. - var prototypeSymbol = createSymbol(4 /* Property */ | 134217728 /* Prototype */, "prototype"); - if (symbol.exports[prototypeSymbol.name]) { - if (node.name) { - node.name.parent = node; + // then try to resolve using remaining entries in rootDirs + for (var _b = 0, _c = state.compilerOptions.rootDirs; _b < _c.length; _b++) { + var rootDir = _c[_b]; + if (rootDir === matchedRootDir) { + // skip the initially matched entry + continue; + } + var candidate_1 = ts.combinePaths(ts.normalizePath(rootDir), suffix); + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Loading_0_from_the_root_dir_1_candidate_location_2, suffix, rootDir, candidate_1); + } + var baseDirectory = ts.getDirectoryPath(candidate_1); + var resolvedFileName_1 = loader(candidate_1, supportedExtensions, failedLookupLocations, !directoryProbablyExists(baseDirectory, state.host), state); + if (resolvedFileName_1) { + return resolvedFileName_1; } - file.bindDiagnostics.push(ts.createDiagnosticForNode(symbol.exports[prototypeSymbol.name].declarations[0], ts.Diagnostics.Duplicate_identifier_0, prototypeSymbol.name)); } - symbol.exports[prototypeSymbol.name] = prototypeSymbol; - prototypeSymbol.parent = symbol; + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Module_resolution_using_rootDirs_has_failed); + } } - function bindEnumDeclaration(node) { - return ts.isConst(node) - ? bindBlockScopedDeclaration(node, 128 /* ConstEnum */, 899967 /* ConstEnumExcludes */) - : bindBlockScopedDeclaration(node, 256 /* RegularEnum */, 899327 /* RegularEnumExcludes */); + return undefined; + } + function tryLoadModuleUsingBaseUrl(moduleName, loader, failedLookupLocations, supportedExtensions, state) { + if (!state.compilerOptions.baseUrl) { + return undefined; } - function bindVariableDeclarationOrBindingElement(node) { - if (inStrictMode) { - checkStrictModeEvalOrArguments(node, node.name); + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.baseUrl_option_is_set_to_0_using_this_value_to_resolve_non_relative_module_name_1, state.compilerOptions.baseUrl, moduleName); + } + // string is for exact match + var matchedPattern = undefined; + if (state.compilerOptions.paths) { + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.paths_option_is_specified_looking_for_a_pattern_to_match_module_name_0, moduleName); } - if (!ts.isBindingPattern(node.name)) { - if (ts.isBlockOrCatchScoped(node)) { - bindBlockScopedVariableDeclaration(node); - } - else if (ts.isParameterDeclaration(node)) { - // It is safe to walk up parent chain to find whether the node is a destructing parameter declaration - // because its parent chain has already been set up, since parents are set before descending into children. - // - // If node is a binding element in parameter declaration, we need to use ParameterExcludes. - // Using ParameterExcludes flag allows the compiler to report an error on duplicate identifiers in Parameter Declaration - // For example: - // function foo([a,a]) {} // Duplicate Identifier error - // function bar(a,a) {} // Duplicate Identifier error, parameter declaration in this case is handled in bindParameter - // // which correctly set excluded symbols - declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 107455 /* ParameterExcludes */); + matchedPattern = ts.matchPatternOrExact(ts.getOwnKeys(state.compilerOptions.paths), moduleName); + } + if (matchedPattern) { + var matchedStar = typeof matchedPattern === "string" ? undefined : ts.matchedText(matchedPattern, moduleName); + var matchedPatternText = typeof matchedPattern === "string" ? matchedPattern : ts.patternText(matchedPattern); + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Module_name_0_matched_pattern_1, moduleName, matchedPatternText); + } + for (var _i = 0, _a = state.compilerOptions.paths[matchedPatternText]; _i < _a.length; _i++) { + var subst = _a[_i]; + var path = matchedStar ? subst.replace("*", matchedStar) : subst; + var candidate = ts.normalizePath(ts.combinePaths(state.compilerOptions.baseUrl, path)); + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Trying_substitution_0_candidate_module_location_Colon_1, subst, path); } - else { - declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 107454 /* FunctionScopedVariableExcludes */); + var resolvedFileName = loader(candidate, supportedExtensions, failedLookupLocations, !directoryProbablyExists(ts.getDirectoryPath(candidate), state.host), state); + if (resolvedFileName) { + return resolvedFileName; } } + return undefined; } - function bindParameter(node) { - if (!ts.isDeclarationFile(file) && - !ts.isInAmbientContext(node) && - ts.nodeIsDecorated(node)) { - emitFlags |= (524288 /* HasDecorators */ | 1048576 /* HasParamDecorators */); - } - if (inStrictMode) { - // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a - // strict mode FunctionLikeDeclaration or FunctionExpression(13.1) - checkStrictModeEvalOrArguments(node, node.name); + else { + var candidate = ts.normalizePath(ts.combinePaths(state.compilerOptions.baseUrl, moduleName)); + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Resolving_module_name_0_relative_to_base_url_1_2, moduleName, state.compilerOptions.baseUrl, candidate); } - if (ts.isBindingPattern(node.name)) { - bindAnonymousDeclaration(node, 1 /* FunctionScopedVariable */, getDestructuringParameterName(node)); + return loader(candidate, supportedExtensions, failedLookupLocations, !directoryProbablyExists(ts.getDirectoryPath(candidate), state.host), state); + } + } + function nodeModuleNameResolver(moduleName, containingFile, compilerOptions, host) { + var containingDirectory = ts.getDirectoryPath(containingFile); + var supportedExtensions = ts.getSupportedExtensions(compilerOptions); + var traceEnabled = isTraceEnabled(compilerOptions, host); + var failedLookupLocations = []; + var state = { compilerOptions: compilerOptions, host: host, traceEnabled: traceEnabled, skipTsx: false }; + var resolvedFileName = tryLoadModuleUsingOptionalResolutionSettings(moduleName, containingDirectory, nodeLoadModuleByRelativeName, failedLookupLocations, supportedExtensions, state); + var isExternalLibraryImport = false; + if (!resolvedFileName) { + if (moduleHasNonRelativeName(moduleName)) { + if (traceEnabled) { + trace(host, ts.Diagnostics.Loading_module_0_from_node_modules_folder, moduleName); + } + resolvedFileName = loadModuleFromNodeModules(moduleName, containingDirectory, failedLookupLocations, state, /*checkOneLevel*/ false); + isExternalLibraryImport = resolvedFileName !== undefined; } else { - declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 107455 /* ParameterExcludes */); - } - // If this is a property-parameter, then also declare the property symbol into the - // containing class. - if (ts.isParameterPropertyDeclaration(node)) { - var classDeclaration = node.parent.parent; - declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, 4 /* Property */ | (node.questionToken ? 536870912 /* Optional */ : 0 /* None */), 0 /* PropertyExcludes */); + var candidate = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName)); + resolvedFileName = nodeLoadModuleByRelativeName(candidate, supportedExtensions, failedLookupLocations, /*onlyRecordFailures*/ false, state); } } - function bindFunctionDeclaration(node) { - if (!ts.isDeclarationFile(file) && !ts.isInAmbientContext(node)) { - if (ts.isAsyncFunctionLike(node)) { - emitFlags |= 2097152 /* HasAsyncFunctions */; - } + if (resolvedFileName && host.realpath) { + var originalFileName = resolvedFileName; + resolvedFileName = ts.normalizePath(host.realpath(resolvedFileName)); + if (traceEnabled) { + trace(host, ts.Diagnostics.Resolving_real_path_for_0_result_1, originalFileName, resolvedFileName); } - checkStrictModeFunctionName(node); - if (inStrictMode) { - checkStrictModeFunctionDeclaration(node); - bindBlockScopedDeclaration(node, 16 /* Function */, 106927 /* FunctionExcludes */); + } + return createResolvedModule(resolvedFileName, isExternalLibraryImport, failedLookupLocations); + } + ts.nodeModuleNameResolver = nodeModuleNameResolver; + function nodeLoadModuleByRelativeName(candidate, supportedExtensions, failedLookupLocations, onlyRecordFailures, state) { + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Loading_module_as_file_Slash_folder_candidate_module_location_0, candidate); + } + var resolvedFileName = !ts.pathEndsWithDirectorySeparator(candidate) && loadModuleFromFile(candidate, supportedExtensions, failedLookupLocations, onlyRecordFailures, state); + return resolvedFileName || loadNodeModuleFromDirectory(supportedExtensions, candidate, failedLookupLocations, onlyRecordFailures, state); + } + /* @internal */ + function directoryProbablyExists(directoryName, host) { + // if host does not support 'directoryExists' assume that directory will exist + return !host.directoryExists || host.directoryExists(directoryName); + } + ts.directoryProbablyExists = directoryProbablyExists; + /** + * @param {boolean} onlyRecordFailures - if true then function won't try to actually load files but instead record all attempts as failures. This flag is necessary + * in cases when we know upfront that all load attempts will fail (because containing folder does not exists) however we still need to record all failed lookup locations. + */ + function loadModuleFromFile(candidate, extensions, failedLookupLocation, onlyRecordFailures, state) { + // First, try adding an extension. An import of "foo" could be matched by a file "foo.ts", or "foo.js" by "foo.js.ts" + var resolvedByAddingExtension = tryAddingExtensions(candidate, extensions, failedLookupLocation, onlyRecordFailures, state); + if (resolvedByAddingExtension) { + return resolvedByAddingExtension; + } + // If that didn't work, try stripping a ".js" or ".jsx" extension and replacing it with a TypeScript one; + // e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts" + if (ts.hasJavaScriptFileExtension(candidate)) { + var extensionless = ts.removeFileExtension(candidate); + if (state.traceEnabled) { + var extension = candidate.substring(extensionless.length); + trace(state.host, ts.Diagnostics.File_name_0_has_a_1_extension_stripping_it, candidate, extension); } - else { - declareSymbolAndAddToSymbolTable(node, 16 /* Function */, 106927 /* FunctionExcludes */); + return tryAddingExtensions(extensionless, extensions, failedLookupLocation, onlyRecordFailures, state); + } + } + /** Try to return an existing file that adds one of the `extensions` to `candidate`. */ + function tryAddingExtensions(candidate, extensions, failedLookupLocation, onlyRecordFailures, state) { + if (!onlyRecordFailures) { + // check if containing folder exists - if it doesn't then just record failures for all supported extensions without disk probing + var directory = ts.getDirectoryPath(candidate); + if (directory) { + onlyRecordFailures = !directoryProbablyExists(directory, state.host); } } - function bindFunctionExpression(node) { - if (!ts.isDeclarationFile(file) && !ts.isInAmbientContext(node)) { - if (ts.isAsyncFunctionLike(node)) { - emitFlags |= 2097152 /* HasAsyncFunctions */; - } + return ts.forEach(extensions, function (ext) { + return !(state.skipTsx && ts.isJsxOrTsxExtension(ext)) && tryFile(candidate + ext, failedLookupLocation, onlyRecordFailures, state); + }); + } + /** Return the file if it exists. */ + function tryFile(fileName, failedLookupLocation, onlyRecordFailures, state) { + if (!onlyRecordFailures && state.host.fileExists(fileName)) { + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.File_0_exist_use_it_as_a_name_resolution_result, fileName); } - if (currentFlow) { - node.flowNode = currentFlow; + return fileName; + } + else { + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.File_0_does_not_exist, fileName); } - checkStrictModeFunctionName(node); - var bindingName = node.name ? node.name.text : "__function"; - return bindAnonymousDeclaration(node, 16 /* Function */, bindingName); + failedLookupLocation.push(fileName); + return undefined; } - function bindPropertyOrMethodOrAccessor(node, symbolFlags, symbolExcludes) { - if (!ts.isDeclarationFile(file) && !ts.isInAmbientContext(node)) { - if (ts.isAsyncFunctionLike(node)) { - emitFlags |= 2097152 /* HasAsyncFunctions */; + } + function loadNodeModuleFromDirectory(extensions, candidate, failedLookupLocation, onlyRecordFailures, state) { + var packageJsonPath = pathToPackageJson(candidate); + var directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, state.host); + if (directoryExists && state.host.fileExists(packageJsonPath)) { + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.Found_package_json_at_0, packageJsonPath); + } + var typesFile = tryReadTypesSection(packageJsonPath, candidate, state); + if (typesFile) { + var onlyRecordFailures_1 = !directoryProbablyExists(ts.getDirectoryPath(typesFile), state.host); + // A package.json "typings" may specify an exact filename, or may choose to omit an extension. + var result = tryFile(typesFile, failedLookupLocation, onlyRecordFailures_1, state) || + tryAddingExtensions(typesFile, extensions, failedLookupLocation, onlyRecordFailures_1, state); + if (result) { + return result; } - if (ts.nodeIsDecorated(node)) { - emitFlags |= 524288 /* HasDecorators */; + } + else { + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.package_json_does_not_have_types_field); } } - return ts.hasDynamicName(node) - ? bindAnonymousDeclaration(node, symbolFlags, "__computed") - : declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); } - function bindJSDocProperty(node) { - return declareSymbolAndAddToSymbolTable(node, 4 /* Property */, 0 /* PropertyExcludes */); + else { + if (state.traceEnabled) { + trace(state.host, ts.Diagnostics.File_0_does_not_exist, packageJsonPath); + } + // record package json as one of failed lookup locations - in the future if this file will appear it will invalidate resolution results + failedLookupLocation.push(packageJsonPath); } - // reachability checks - function shouldReportErrorOnModuleDeclaration(node) { - var instanceState = getModuleInstanceState(node); - return instanceState === 1 /* Instantiated */ || (instanceState === 2 /* ConstEnumOnly */ && options.preserveConstEnums); + return loadModuleFromFile(ts.combinePaths(candidate, "index"), extensions, failedLookupLocation, !directoryExists, state); + } + function pathToPackageJson(directory) { + return ts.combinePaths(directory, "package.json"); + } + function loadModuleFromNodeModulesFolder(moduleName, directory, failedLookupLocations, state) { + var nodeModulesFolder = ts.combinePaths(directory, "node_modules"); + var nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, state.host); + var candidate = ts.normalizePath(ts.combinePaths(nodeModulesFolder, moduleName)); + var supportedExtensions = ts.getSupportedExtensions(state.compilerOptions); + var result = loadModuleFromFile(candidate, supportedExtensions, failedLookupLocations, !nodeModulesFolderExists, state); + if (result) { + return result; } - function checkUnreachable(node) { - if (!(currentFlow.flags & 1 /* Unreachable */)) { - return false; - } - if (currentFlow === unreachableFlow) { - var reportError = - // report error on all statements except empty ones - (ts.isStatement(node) && node.kind !== 201 /* EmptyStatement */) || - // report error on class declarations - node.kind === 221 /* ClassDeclaration */ || - // report error on instantiated modules or const-enums only modules if preserveConstEnums is set - (node.kind === 225 /* ModuleDeclaration */ && shouldReportErrorOnModuleDeclaration(node)) || - // report error on regular enums and const enums if preserveConstEnums is set - (node.kind === 224 /* EnumDeclaration */ && (!ts.isConstEnumDeclaration(node) || options.preserveConstEnums)); - if (reportError) { - currentFlow = reportedUnreachableFlow; - // unreachable code is reported if - // - user has explicitly asked about it AND - // - statement is in not ambient context (statements in ambient context is already an error - // so we should not report extras) AND - // - node is not variable statement OR - // - node is block scoped variable statement OR - // - node is not block scoped variable statement and at least one variable declaration has initializer - // Rationale: we don't want to report errors on non-initialized var's since they are hoisted - // On the other side we do want to report errors on non-initialized 'lets' because of TDZ - var reportUnreachableCode = !options.allowUnreachableCode && - !ts.isInAmbientContext(node) && - (node.kind !== 200 /* VariableStatement */ || - ts.getCombinedNodeFlags(node.declarationList) & 3072 /* BlockScoped */ || - ts.forEach(node.declarationList.declarations, function (d) { return d.initializer; })); - if (reportUnreachableCode) { - errorOnFirstToken(node, ts.Diagnostics.Unreachable_code_detected); + result = loadNodeModuleFromDirectory(supportedExtensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state); + if (result) { + return result; + } + } + /* @internal */ + function loadModuleFromNodeModules(moduleName, directory, failedLookupLocations, state, checkOneLevel) { + directory = ts.normalizeSlashes(directory); + while (true) { + var baseName = ts.getBaseFileName(directory); + if (baseName !== "node_modules") { + // Try to load source from the package + var packageResult = loadModuleFromNodeModulesFolder(moduleName, directory, failedLookupLocations, state); + if (packageResult && ts.hasTypeScriptFileExtension(packageResult)) { + // Always prefer a TypeScript (.ts, .tsx, .d.ts) file shipped with the package + return packageResult; + } + else { + // Else prefer a types package over non-TypeScript results (e.g. JavaScript files) + var typesResult = loadModuleFromNodeModulesFolder(ts.combinePaths("@types", moduleName), directory, failedLookupLocations, state); + if (typesResult || packageResult) { + return typesResult || packageResult; } } } - return true; + var parentPath = ts.getDirectoryPath(directory); + if (parentPath === directory || checkOneLevel) { + break; + } + directory = parentPath; + } + return undefined; + } + ts.loadModuleFromNodeModules = loadModuleFromNodeModules; + function classicNameResolver(moduleName, containingFile, compilerOptions, host) { + var traceEnabled = isTraceEnabled(compilerOptions, host); + var state = { compilerOptions: compilerOptions, host: host, traceEnabled: traceEnabled, skipTsx: !compilerOptions.jsx }; + var failedLookupLocations = []; + var supportedExtensions = ts.getSupportedExtensions(compilerOptions); + var containingDirectory = ts.getDirectoryPath(containingFile); + var resolvedFileName = tryLoadModuleUsingOptionalResolutionSettings(moduleName, containingDirectory, loadModuleFromFile, failedLookupLocations, supportedExtensions, state); + if (resolvedFileName) { + return createResolvedModule(resolvedFileName, /*isExternalLibraryImport*/ false, failedLookupLocations); + } + var referencedSourceFile; + if (moduleHasNonRelativeName(moduleName)) { + while (true) { + var searchName = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName)); + referencedSourceFile = loadModuleFromFile(searchName, supportedExtensions, failedLookupLocations, /*onlyRecordFailures*/ false, state); + if (referencedSourceFile) { + break; + } + var parentPath = ts.getDirectoryPath(containingDirectory); + if (parentPath === containingDirectory) { + break; + } + containingDirectory = parentPath; + } } + else { + var candidate = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName)); + referencedSourceFile = loadModuleFromFile(candidate, supportedExtensions, failedLookupLocations, /*onlyRecordFailures*/ false, state); + } + return referencedSourceFile + ? { resolvedModule: { resolvedFileName: referencedSourceFile }, failedLookupLocations: failedLookupLocations } + : { resolvedModule: undefined, failedLookupLocations: failedLookupLocations }; } + ts.classicNameResolver = classicNameResolver; })(ts || (ts = {})); +/// /// /* @internal */ var ts; (function (ts) { + var ambientModuleSymbolRegex = /^".+"$/; var nextSymbolId = 1; var nextNodeId = 1; var nextMergeId = 1; @@ -16622,6 +22582,7 @@ var ts; getAliasedSymbol: resolveAlias, getEmitResolver: getEmitResolver, getExportsOfModule: getExportsOfModuleAsArray, + getAmbientModules: getAmbientModules, getJsxElementAttributesType: getJsxElementAttributesType, getJsxIntrinsicTagNames: getJsxIntrinsicTagNames, isOptionalParameter: isOptionalParameter @@ -16647,6 +22608,7 @@ var ts; var esSymbolType = createIntrinsicType(512 /* ESSymbol */, "symbol"); var voidType = createIntrinsicType(1024 /* Void */, "void"); var neverType = createIntrinsicType(8192 /* Never */, "never"); + var silentNeverType = createIntrinsicType(8192 /* Never */, "never"); var emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); var emptyGenericType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); emptyGenericType.instantiations = ts.createMap(); @@ -16658,6 +22620,7 @@ var ts; var anySignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); var unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, unknownType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); var resolvingSignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); + var silentNeverSignature = createSignature(undefined, undefined, undefined, emptyArray, silentNeverType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); var enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true); var globals = ts.createMap(); /** @@ -16668,6 +22631,7 @@ var ts; var patternAmbientModules; var getGlobalESSymbolConstructorSymbol; var getGlobalPromiseConstructorSymbol; + var tryGetGlobalPromiseConstructorSymbol; var globalObjectType; var globalFunctionType; var globalArrayType; @@ -16824,6 +22788,7 @@ var ts; var assignableRelation = ts.createMap(); var comparableRelation = ts.createMap(); var identityRelation = ts.createMap(); + var enumRelation = ts.createMap(); // This is for caching the result of getSymbolDisplayBuilder. Do not access directly. var _displayBuilder; var TypeSystemPropertyName; @@ -17117,7 +23082,7 @@ var ts; } var initializerOfNonStaticProperty = current.parent && current.parent.kind === 145 /* PropertyDeclaration */ && - (current.parent.flags & 32 /* Static */) === 0 && + (ts.getModifierFlags(current.parent) & 32 /* Static */) === 0 && current.parent.initializer === current; if (initializerOfNonStaticProperty) { return true; @@ -17226,7 +23191,7 @@ var ts; // local variables of the constructor. This effectively means that entities from outer scopes // by the same name as a constructor parameter or local variable are inaccessible // in initializer expressions for instance member variables. - if (ts.isClassLike(location.parent) && !(location.flags & 32 /* Static */)) { + if (ts.isClassLike(location.parent) && !(ts.getModifierFlags(location) & 32 /* Static */)) { var ctor = findConstructorDeclaration(location.parent); if (ctor && ctor.locals) { if (getSymbol(ctor.locals, name, meaning & 107455 /* Value */)) { @@ -17240,7 +23205,7 @@ var ts; case 192 /* ClassExpression */: case 222 /* InterfaceDeclaration */: if (result = getSymbol(getSymbolOfNode(location).members, name, meaning & 793064 /* Type */)) { - if (lastLocation && lastLocation.flags & 32 /* Static */) { + if (lastLocation && ts.getModifierFlags(lastLocation) & 32 /* Static */) { // TypeScript 1.0 spec (April 2014): 3.4.1 // The scope of a type parameter extends over the entire declaration with which the type // parameter list is associated, with the exception of static member declarations in classes. @@ -17336,7 +23301,8 @@ var ts; if (nameNotFoundMessage) { if (!errorLocation || !checkAndReportErrorForMissingPrefix(errorLocation, name, nameArg) && - !checkAndReportErrorForExtendingInterface(errorLocation)) { + !checkAndReportErrorForExtendingInterface(errorLocation) && + !checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning)) { error(errorLocation, nameNotFoundMessage, typeof nameArg === "string" ? nameArg : ts.declarationNameToString(nameArg)); } } @@ -17368,8 +23334,8 @@ var ts; checkResolvedBlockScopedVariable(exportOrLocalSymbol, errorLocation); } } - // If we're in an external module, we can't reference symbols created from UMD export declarations - if (result && isInExternalModule) { + // If we're in an external module, we can't reference value symbols created from UMD export declarations + if (result && isInExternalModule && (meaning & 107455 /* Value */) === 107455 /* Value */) { var decls = result.declarations; if (decls && decls.length === 1 && decls[0].kind === 228 /* NamespaceExportDeclaration */) { error(errorLocation, ts.Diagnostics.Identifier_0_must_be_imported_from_a_module, name); @@ -17398,7 +23364,7 @@ var ts; } // No static member is present. // Check if we're in an instance method and look for a relevant instance member. - if (location === container && !(location.flags & 32 /* Static */)) { + if (location === container && !(ts.getModifierFlags(location) & 32 /* Static */)) { var instanceType = getDeclaredTypeOfSymbol(classSymbol).thisType; if (getPropertyOfType(instanceType, name)) { error(errorLocation, ts.Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0, typeof nameArg === "string" ? nameArg : ts.declarationNameToString(nameArg)); @@ -17434,6 +23400,16 @@ var ts; return undefined; } } + function checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning) { + if (meaning & (107455 /* Value */ & ~1024 /* NamespaceModule */)) { + var symbol = resolveSymbol(resolveName(errorLocation, name, 793064 /* Type */ & ~107455 /* Value */, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined)); + if (symbol && !(symbol.flags & 1024 /* NamespaceModule */)) { + error(errorLocation, ts.Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, name); + return true; + } + } + return false; + } function checkResolvedBlockScopedVariable(result, errorLocation) { ts.Debug.assert((result.flags & 2 /* BlockScopedVariable */) !== 0); // Block-scoped variables cannot be used before their definition @@ -17481,7 +23457,7 @@ var ts; function getTargetOfImportClause(node) { var moduleSymbol = resolveExternalModuleName(node, node.parent.moduleSpecifier); if (moduleSymbol) { - var exportDefaultSymbol = ts.isShorthandAmbientModule(moduleSymbol.valueDeclaration) ? + var exportDefaultSymbol = ts.isShorthandAmbientModuleSymbol(moduleSymbol) ? moduleSymbol : moduleSymbol.exports["export="] ? getPropertyOfType(getTypeOfSymbol(moduleSymbol.exports["export="]), "default") : @@ -17552,31 +23528,31 @@ var ts; var moduleSymbol = resolveExternalModuleName(node, node.moduleSpecifier); var targetSymbol = resolveESModuleSymbol(moduleSymbol, node.moduleSpecifier); if (targetSymbol) { - var name_10 = specifier.propertyName || specifier.name; - if (name_10.text) { - if (ts.isShorthandAmbientModule(moduleSymbol.valueDeclaration)) { + var name_13 = specifier.propertyName || specifier.name; + if (name_13.text) { + if (ts.isShorthandAmbientModuleSymbol(moduleSymbol)) { return moduleSymbol; } var symbolFromVariable = void 0; // First check if module was specified with "export=". If so, get the member from the resolved type if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports["export="]) { - symbolFromVariable = getPropertyOfType(getTypeOfSymbol(targetSymbol), name_10.text); + symbolFromVariable = getPropertyOfType(getTypeOfSymbol(targetSymbol), name_13.text); } else { - symbolFromVariable = getPropertyOfVariable(targetSymbol, name_10.text); + symbolFromVariable = getPropertyOfVariable(targetSymbol, name_13.text); } // if symbolFromVariable is export - get its final target symbolFromVariable = resolveSymbol(symbolFromVariable); - var symbolFromModule = getExportOfModule(targetSymbol, name_10.text); + var symbolFromModule = getExportOfModule(targetSymbol, name_13.text); // If the export member we're looking for is default, and there is no real default but allowSyntheticDefaultImports is on, return the entire module as the default - if (!symbolFromModule && allowSyntheticDefaultImports && name_10.text === "default") { + if (!symbolFromModule && allowSyntheticDefaultImports && name_13.text === "default") { symbolFromModule = resolveExternalModuleSymbol(moduleSymbol) || resolveSymbol(moduleSymbol); } var symbol = symbolFromModule && symbolFromVariable ? combineValueAndTypeSymbols(symbolFromVariable, symbolFromModule) : symbolFromModule || symbolFromVariable; if (!symbol) { - error(name_10, ts.Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(moduleSymbol), ts.declarationNameToString(name_10)); + error(name_13, ts.Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(moduleSymbol), ts.declarationNameToString(name_13)); } return symbol; } @@ -17697,14 +23673,14 @@ var ts; return symbol.parent ? getFullyQualifiedName(symbol.parent) + "." + symbolToString(symbol) : symbolToString(symbol); } // Resolves a qualified name and any involved aliases - function resolveEntityName(name, meaning, ignoreErrors, dontResolveAlias) { + function resolveEntityName(name, meaning, ignoreErrors, dontResolveAlias, location) { if (ts.nodeIsMissing(name)) { return undefined; } var symbol; if (name.kind === 69 /* Identifier */) { var message = meaning === 1920 /* Namespace */ ? ts.Diagnostics.Cannot_find_namespace_0 : ts.Diagnostics.Cannot_find_name_0; - symbol = resolveName(name, name.text, meaning, ignoreErrors ? undefined : message, name); + symbol = resolveName(location || name, name.text, meaning, ignoreErrors ? undefined : message, name); if (!symbol) { return undefined; } @@ -17712,7 +23688,7 @@ var ts; else if (name.kind === 139 /* QualifiedName */ || name.kind === 172 /* PropertyAccessExpression */) { var left = name.kind === 139 /* QualifiedName */ ? name.left : name.expression; var right = name.kind === 139 /* QualifiedName */ ? name.right : name.name; - var namespace = resolveEntityName(left, 1920 /* Namespace */, ignoreErrors); + var namespace = resolveEntityName(left, 1920 /* Namespace */, ignoreErrors, /*dontResolveAlias*/ false, location); if (!namespace || ts.nodeIsMissing(right)) { return undefined; } @@ -17722,7 +23698,7 @@ var ts; symbol = getSymbol(getExportsOfSymbol(namespace), right.text, meaning); if (!symbol) { if (!ignoreErrors) { - error(right, ts.Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(namespace), ts.declarationNameToString(right)); + error(right, ts.Diagnostics.Namespace_0_has_no_exported_member_1, getFullyQualifiedName(namespace), ts.declarationNameToString(right)); } return undefined; } @@ -17741,9 +23717,12 @@ var ts; return; } var moduleReferenceLiteral = moduleReferenceExpression; + return resolveExternalModule(location, moduleReferenceLiteral.text, moduleNotFoundError, moduleReferenceLiteral); + } + function resolveExternalModule(location, moduleReference, moduleNotFoundError, errorNode) { // Module names are escaped in our symbol table. However, string literal values aren't. // Escape the name in the "require(...)" clause to ensure we find the right symbol. - var moduleName = ts.escapeIdentifier(moduleReferenceLiteral.text); + var moduleName = ts.escapeIdentifier(moduleReference); if (moduleName === undefined) { return; } @@ -17755,7 +23734,7 @@ var ts; return getMergedSymbol(symbol); } } - var resolvedModule = ts.getResolvedModule(ts.getSourceFileOfNode(location), moduleReferenceLiteral.text); + var resolvedModule = ts.getResolvedModule(ts.getSourceFileOfNode(location), moduleReference); var sourceFile = resolvedModule && host.getSourceFile(resolvedModule.resolvedFileName); if (sourceFile) { if (sourceFile.symbol) { @@ -17764,7 +23743,7 @@ var ts; } if (moduleNotFoundError) { // report errors only if it was requested - error(moduleReferenceLiteral, ts.Diagnostics.File_0_is_not_a_module, sourceFile.fileName); + error(errorNode, ts.Diagnostics.File_0_is_not_a_module, sourceFile.fileName); } return undefined; } @@ -17779,10 +23758,10 @@ var ts; var tsExtension = ts.tryExtractTypeScriptExtension(moduleName); if (tsExtension) { var diag = ts.Diagnostics.An_import_path_cannot_end_with_a_0_extension_Consider_importing_1_instead; - error(moduleReferenceLiteral, diag, tsExtension, ts.removeExtension(moduleName, tsExtension)); + error(errorNode, diag, tsExtension, ts.removeExtension(moduleName, tsExtension)); } else { - error(moduleReferenceLiteral, moduleNotFoundError, moduleName); + error(errorNode, moduleNotFoundError, moduleName); } } return undefined; @@ -18100,7 +24079,15 @@ var ts; } return false; } - function isSymbolAccessible(symbol, enclosingDeclaration, meaning) { + /** + * Check if the given symbol in given enclosing declaration is accessible and mark all associated alias to be visible if requested + * + * @param symbol a Symbol to check if accessible + * @param enclosingDeclaration a Node containing reference to the symbol + * @param meaning a SymbolFlags to check if such meaning of the symbol is accessible + * @param shouldComputeAliasToMakeVisible a boolean value to indicate whether to return aliases to be mark visible in case the symbol is accessible + */ + function isSymbolAccessible(symbol, enclosingDeclaration, meaning, shouldComputeAliasesToMakeVisible) { if (symbol && enclosingDeclaration && !(symbol.flags & 262144 /* TypeParameter */)) { var initialSymbol = symbol; var meaningToLook = meaning; @@ -18108,7 +24095,7 @@ var ts; // Symbol is accessible if it by itself is accessible var accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaningToLook, /*useOnlyExternalAliasing*/ false); if (accessibleSymbolChain) { - var hasAccessibleDeclarations = hasVisibleDeclarations(accessibleSymbolChain[0]); + var hasAccessibleDeclarations = hasVisibleDeclarations(accessibleSymbolChain[0], shouldComputeAliasesToMakeVisible); if (!hasAccessibleDeclarations) { return { accessibility: 1 /* NotAccessible */, @@ -18165,7 +24152,7 @@ var ts; function hasExternalModuleSymbol(declaration) { return ts.isAmbientModule(declaration) || (declaration.kind === 256 /* SourceFile */ && ts.isExternalOrCommonJsModule(declaration)); } - function hasVisibleDeclarations(symbol) { + function hasVisibleDeclarations(symbol, shouldComputeAliasToMakeVisible) { var aliasesToMakeVisible; if (ts.forEach(symbol.declarations, function (declaration) { return !getIsDeclarationVisible(declaration); })) { return undefined; @@ -18177,16 +24164,21 @@ var ts; // because these kind of aliases can be used to name types in declaration file var anyImportSyntax = getAnyImportSyntax(declaration); if (anyImportSyntax && - !(anyImportSyntax.flags & 1 /* Export */) && + !(ts.getModifierFlags(anyImportSyntax) & 1 /* Export */) && isDeclarationVisible(anyImportSyntax.parent)) { - getNodeLinks(declaration).isVisible = true; - if (aliasesToMakeVisible) { - if (!ts.contains(aliasesToMakeVisible, anyImportSyntax)) { - aliasesToMakeVisible.push(anyImportSyntax); + // In function "buildTypeDisplay" where we decide whether to write type-alias or serialize types, + // we want to just check if type- alias is accessible or not but we don't care about emitting those alias at that time + // since we will do the emitting later in trackSymbol. + if (shouldComputeAliasToMakeVisible) { + getNodeLinks(declaration).isVisible = true; + if (aliasesToMakeVisible) { + if (!ts.contains(aliasesToMakeVisible, anyImportSyntax)) { + aliasesToMakeVisible.push(anyImportSyntax); + } + } + else { + aliasesToMakeVisible = [anyImportSyntax]; } - } - else { - aliasesToMakeVisible = [anyImportSyntax]; } return true; } @@ -18216,7 +24208,7 @@ var ts; var firstIdentifier = getFirstIdentifier(entityName); var symbol = resolveName(enclosingDeclaration, firstIdentifier.text, meaning, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined); // Verify if the symbol is accessible - return (symbol && hasVisibleDeclarations(symbol)) || { + return (symbol && hasVisibleDeclarations(symbol, /*shouldComputeAliasToMakeVisible*/ true)) || { accessibility: 1 /* NotAccessible */, errorSymbolName: ts.getTextOfNode(firstIdentifier), errorNode: firstIdentifier @@ -18314,6 +24306,9 @@ var ts; node.parent.kind === 226 /* ModuleBlock */ && ts.isExternalModuleAugmentation(node.parent.parent); } + function literalTypeToString(type) { + return type.flags & 32 /* StringLiteral */ ? "\"" + ts.escapeString(type.text) + "\"" : type.text; + } function getSymbolDisplayBuilder() { function getNameOfSymbol(symbol) { if (symbol.declarations && symbol.declarations.length) { @@ -18386,7 +24381,7 @@ var ts; } parentSymbol = symbol; } - // const the writer know we just wrote out a symbol. The declaration emitter writer uses + // Let the writer know we just wrote out a symbol. The declaration emitter writer uses // this to determine if an import it has previously seen (and not written out) needs // to be written to the file once the walk of the tree is complete. // @@ -18394,32 +24389,32 @@ var ts; // up front (for example, during checking) could determine if we need to emit the imports // and we could then access that data during declaration emit. writer.trackSymbol(symbol, enclosingDeclaration, meaning); - function walkSymbol(symbol, meaning) { - if (symbol) { - var accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaning, !!(flags & 2 /* UseOnlyExternalAliasing */)); - if (!accessibleSymbolChain || - needsQualification(accessibleSymbolChain[0], enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning))) { - // Go up and add our parent. - walkSymbol(getParentOfSymbol(accessibleSymbolChain ? accessibleSymbolChain[0] : symbol), getQualifiedLeftMeaning(meaning)); + /** @param endOfChain Set to false for recursive calls; non-recursive calls should always output something. */ + function walkSymbol(symbol, meaning, endOfChain) { + var accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaning, !!(flags & 2 /* UseOnlyExternalAliasing */)); + if (!accessibleSymbolChain || + needsQualification(accessibleSymbolChain[0], enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning))) { + // Go up and add our parent. + var parent_8 = getParentOfSymbol(accessibleSymbolChain ? accessibleSymbolChain[0] : symbol); + if (parent_8) { + walkSymbol(parent_8, getQualifiedLeftMeaning(meaning), /*endOfChain*/ false); } - if (accessibleSymbolChain) { - for (var _i = 0, accessibleSymbolChain_1 = accessibleSymbolChain; _i < accessibleSymbolChain_1.length; _i++) { - var accessibleSymbol = accessibleSymbolChain_1[_i]; - appendParentTypeArgumentsAndSymbolName(accessibleSymbol); - } - } - else { - // If we didn't find accessible symbol chain for this symbol, break if this is external module - if (!parentSymbol && ts.forEach(symbol.declarations, hasExternalModuleSymbol)) { - return; - } - // if this is anonymous type break - if (symbol.flags & 2048 /* TypeLiteral */ || symbol.flags & 4096 /* ObjectLiteral */) { - return; - } - appendParentTypeArgumentsAndSymbolName(symbol); + } + if (accessibleSymbolChain) { + for (var _i = 0, accessibleSymbolChain_1 = accessibleSymbolChain; _i < accessibleSymbolChain_1.length; _i++) { + var accessibleSymbol = accessibleSymbolChain_1[_i]; + appendParentTypeArgumentsAndSymbolName(accessibleSymbol); } } + else if ( + // If this is the last part of outputting the symbol, always output. The cases apply only to parent symbols. + endOfChain || + // If a parent symbol is an external module, don't write it. (We prefer just `x` vs `"foo/bar".x`.) + !(!parentSymbol && ts.forEach(symbol.declarations, hasExternalModuleSymbol)) && + // If a parent symbol is an anonymous type, don't write it. + !(symbol.flags & (2048 /* TypeLiteral */ | 4096 /* ObjectLiteral */))) { + appendParentTypeArgumentsAndSymbolName(symbol); + } } // Get qualified name if the symbol is not a type parameter // and there is an enclosing declaration or we specifically @@ -18427,10 +24422,11 @@ var ts; var isTypeParameter = symbol.flags & 262144 /* TypeParameter */; var typeFormatFlag = 128 /* UseFullyQualifiedType */ & typeFlags; if (!isTypeParameter && (enclosingDeclaration || typeFormatFlag)) { - walkSymbol(symbol, meaning); - return; + walkSymbol(symbol, meaning, /*endOfChain*/ true); + } + else { + appendParentTypeArgumentsAndSymbolName(symbol); } - return appendParentTypeArgumentsAndSymbolName(symbol); } function buildTypeDisplay(type, writer, enclosingDeclaration, globalFlags, symbolStack) { var globalFlagsToPass = globalFlags & 16 /* WriteOwnNameForAnyLike */; @@ -18463,7 +24459,9 @@ var ts; // The specified symbol flags need to be reinterpreted as type flags buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, 793064 /* Type */, 0 /* None */, nextFlags); } - else if (!(flags & 512 /* InTypeAlias */) && type.flags & (2097152 /* Anonymous */ | 1572864 /* UnionOrIntersection */) && type.aliasSymbol) { + else if (!(flags & 512 /* InTypeAlias */) && type.flags & (2097152 /* Anonymous */ | 1572864 /* UnionOrIntersection */) && type.aliasSymbol && + isSymbolAccessible(type.aliasSymbol, enclosingDeclaration, 793064 /* Type */, /*shouldComputeAliasesToMakeVisible*/ false).accessibility === 0 /* Accessible */) { + // Only write out inferred type with its corresponding type-alias if type-alias is visible var typeArguments = type.aliasTypeArguments; writeSymbolTypeReference(type.aliasSymbol, typeArguments, 0, typeArguments ? typeArguments.length : 0, nextFlags); } @@ -18473,11 +24471,8 @@ var ts; else if (type.flags & 2097152 /* Anonymous */) { writeAnonymousType(type, nextFlags); } - else if (type.flags & 32 /* StringLiteral */) { - writer.writeStringLiteral("\"" + ts.escapeString(type.text) + "\""); - } - else if (type.flags & 64 /* NumberLiteral */) { - writer.writeStringLiteral(type.text); + else if (type.flags & 96 /* StringOrNumberLiteral */) { + writer.writeStringLiteral(literalTypeToString(type)); } else { // Should never get here @@ -18542,14 +24537,14 @@ var ts; while (i < length_1) { // Find group of type arguments for type parameters with the same declaring container. var start = i; - var parent_7 = getParentSymbolOfTypeParameter(outerTypeParameters[i]); + var parent_9 = getParentSymbolOfTypeParameter(outerTypeParameters[i]); do { i++; - } while (i < length_1 && getParentSymbolOfTypeParameter(outerTypeParameters[i]) === parent_7); + } while (i < length_1 && getParentSymbolOfTypeParameter(outerTypeParameters[i]) === parent_9); // When type parameters are their own type arguments for the whole group (i.e. we have // the default outer type arguments), we don't show the group. if (!ts.rangeEquals(outerTypeParameters, typeArguments, start, i)) { - writeSymbolTypeReference(parent_7, typeArguments, start, i, flags); + writeSymbolTypeReference(parent_9, typeArguments, start, i, flags); writePunctuation(writer, 21 /* DotToken */); } } @@ -18611,7 +24606,7 @@ var ts; } function shouldWriteTypeOfFunctionSymbol() { var isStaticMethodSymbol = !!(symbol.flags & 8192 /* Method */ && - ts.forEach(symbol.declarations, function (declaration) { return declaration.flags & 32 /* Static */; })); + ts.forEach(symbol.declarations, function (declaration) { return ts.getModifierFlags(declaration) & 32 /* Static */; })); var isNonLocalFunctionSymbol = !!(symbol.flags & 16 /* Function */) && (symbol.parent || ts.forEach(symbol.declarations, function (declaration) { @@ -18800,7 +24795,7 @@ var ts; } } function buildBindingElementDisplay(bindingElement, writer, enclosingDeclaration, flags, symbolStack) { - if (bindingElement.kind === 193 /* OmittedExpression */) { + if (ts.isOmittedExpression(bindingElement)) { return; } ts.Debug.assert(bindingElement.kind === 169 /* BindingElement */); @@ -18953,21 +24948,21 @@ var ts; if (ts.isExternalModuleAugmentation(node)) { return true; } - var parent_8 = getDeclarationContainer(node); + var parent_10 = getDeclarationContainer(node); // If the node is not exported or it is not ambient module element (except import declaration) - if (!(ts.getCombinedNodeFlags(node) & 1 /* Export */) && - !(node.kind !== 229 /* ImportEqualsDeclaration */ && parent_8.kind !== 256 /* SourceFile */ && ts.isInAmbientContext(parent_8))) { - return isGlobalSourceFile(parent_8); + if (!(ts.getCombinedModifierFlags(node) & 1 /* Export */) && + !(node.kind !== 229 /* ImportEqualsDeclaration */ && parent_10.kind !== 256 /* SourceFile */ && ts.isInAmbientContext(parent_10))) { + return isGlobalSourceFile(parent_10); } // Exported members/ambient module elements (exception import declaration) are visible if parent is visible - return isDeclarationVisible(parent_8); + return isDeclarationVisible(parent_10); case 145 /* PropertyDeclaration */: case 144 /* PropertySignature */: case 149 /* GetAccessor */: case 150 /* SetAccessor */: case 147 /* MethodDeclaration */: case 146 /* MethodSignature */: - if (node.flags & (8 /* Private */ | 16 /* Protected */)) { + if (ts.getModifierFlags(node) & (8 /* Private */ | 16 /* Protected */)) { // Private/protected properties/methods are not visible return false; } @@ -18996,8 +24991,9 @@ var ts; return false; // Type parameters are always visible case 141 /* TypeParameter */: - // Source file is always visible + // Source file and namespace export are always visible case 256 /* SourceFile */: + case 228 /* NamespaceExportDeclaration */: return true; // Export assignments do not create name bindings outside the module case 235 /* ExportAssignment */: @@ -19174,15 +25170,15 @@ var ts; // undefined or any type of the parent. if (!parentType || isTypeAny(parentType)) { if (declaration.initializer) { - return checkExpressionCached(declaration.initializer); + return checkDeclarationInitializer(declaration); } return parentType; } var type; if (pattern.kind === 167 /* ObjectBindingPattern */) { // Use explicitly specified property name ({ p: xxx } form), or otherwise the implied name ({ p } form) - var name_11 = declaration.propertyName || declaration.name; - if (isComputedNonLiteralName(name_11)) { + var name_14 = declaration.propertyName || declaration.name; + if (isComputedNonLiteralName(name_14)) { // computed properties with non-literal names are treated as 'any' return anyType; } @@ -19191,12 +25187,12 @@ var ts; } // Use type of the specified property, or otherwise, for a numeric name, the type of the numeric index signature, // or otherwise the type of the string index signature. - var text = getTextOfPropertyName(name_11); + var text = getTextOfPropertyName(name_14); type = getTypeOfPropertyOfType(parentType, text) || isNumericLiteralName(text) && getIndexTypeOfType(parentType, 1 /* Number */) || getIndexTypeOfType(parentType, 0 /* String */); if (!type) { - error(name_11, ts.Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(parentType), ts.declarationNameToString(name_11)); + error(name_14, ts.Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(parentType), ts.declarationNameToString(name_14)); return unknownType; } } @@ -19231,7 +25227,9 @@ var ts; if (strictNullChecks && declaration.initializer && !(getFalsyFlags(checkExpressionCached(declaration.initializer)) & 2048 /* Undefined */)) { type = getTypeWithFacts(type, 131072 /* NEUndefined */); } - return type; + return declaration.initializer ? + getUnionType([type, checkExpressionCached(declaration.initializer)], /*subtypeReduction*/ true) : + type; } function getTypeForVariableLikeDeclarationFromJSDocComment(declaration) { var jsDocType = getJSDocTypeForVariableLikeDeclarationFromJSDocComment(declaration); @@ -19269,7 +25267,7 @@ var ts; } // Return the inferred type for a variable, parameter, or property declaration function getTypeForVariableLikeDeclaration(declaration, includeOptionality) { - if (declaration.flags & 134217728 /* JavaScriptFile */) { + if (declaration.flags & 1048576 /* JavaScriptFile */) { // If this is a variable in a JavaScript file, then use the JSDoc type (if it has // one as its type), otherwise fallback to the below standard TS codepaths to // try to figure it out. @@ -19327,7 +25325,8 @@ var ts; } // Use the type of the initializer expression if one is present if (declaration.initializer) { - return addOptionality(checkExpressionCached(declaration.initializer), /*optional*/ declaration.questionToken && includeOptionality); + var type = checkDeclarationInitializer(declaration); + return addOptionality(type, /*optional*/ declaration.questionToken && includeOptionality); } // If it is a short-hand property assignment, use the type of the identifier if (declaration.kind === 254 /* ShorthandPropertyAssignment */) { @@ -19345,7 +25344,7 @@ var ts; // pattern. Otherwise, it is the type any. function getTypeFromBindingElement(element, includePatternInType, reportErrors) { if (element.initializer) { - return checkExpressionCached(element.initializer); + return checkDeclarationInitializer(element); } if (ts.isBindingPattern(element.name)) { return getTypeFromBindingPattern(element.name, includePatternInType, reportErrors); @@ -19385,11 +25384,12 @@ var ts; // Return the type implied by an array binding pattern function getTypeFromArrayBindingPattern(pattern, includePatternInType, reportErrors) { var elements = pattern.elements; - if (elements.length === 0 || elements[elements.length - 1].dotDotDotToken) { + var lastElement = ts.lastOrUndefined(elements); + if (elements.length === 0 || (!ts.isOmittedExpression(lastElement) && lastElement.dotDotDotToken)) { return languageVersion >= 2 /* ES6 */ ? createIterableType(anyType) : anyArrayType; } // If the pattern has at least one element, and no rest element, then it should imply a tuple type. - var elementTypes = ts.map(elements, function (e) { return e.kind === 193 /* OmittedExpression */ ? anyType : getTypeFromBindingElement(e, includePatternInType, reportErrors); }); + var elementTypes = ts.map(elements, function (e) { return ts.isOmittedExpression(e) ? anyType : getTypeFromBindingElement(e, includePatternInType, reportErrors); }); var result = createTupleType(elementTypes); if (includePatternInType) { result = cloneTypeReference(result); @@ -19463,7 +25463,7 @@ var ts; if (declaration.kind === 235 /* ExportAssignment */) { return links.type = checkExpression(declaration.expression); } - if (declaration.flags & 134217728 /* JavaScriptFile */ && declaration.kind === 280 /* JSDocPropertyTag */ && declaration.typeExpression) { + if (declaration.flags & 1048576 /* JavaScriptFile */ && declaration.kind === 280 /* JSDocPropertyTag */ && declaration.typeExpression) { return links.type = getTypeFromTypeNode(declaration.typeExpression.type); } // Handle variable, parameter or property @@ -19479,7 +25479,7 @@ var ts; if (declaration.kind === 187 /* BinaryExpression */ || declaration.kind === 172 /* PropertyAccessExpression */ && declaration.parent.kind === 187 /* BinaryExpression */) { // Use JS Doc type if present on parent expression statement - if (declaration.flags & 134217728 /* JavaScriptFile */) { + if (declaration.flags & 1048576 /* JavaScriptFile */) { var typeTag = ts.getJSDocTypeTag(declaration.parent); if (typeTag && typeTag.typeExpression) { return links.type = getTypeFromTypeNode(typeTag.typeExpression.type); @@ -19535,7 +25535,7 @@ var ts; if (!links.type) { var getter = ts.getDeclarationOfKind(symbol, 149 /* GetAccessor */); var setter = ts.getDeclarationOfKind(symbol, 150 /* SetAccessor */); - if (getter && getter.flags & 134217728 /* JavaScriptFile */) { + if (getter && getter.flags & 1048576 /* JavaScriptFile */) { var jsDocType = getTypeForVariableLikeDeclarationFromJSDocComment(getter); if (jsDocType) { return links.type = jsDocType; @@ -19589,7 +25589,7 @@ var ts; function getTypeOfFuncClassEnumModule(symbol) { var links = getSymbolLinks(symbol); if (!links.type) { - if (symbol.valueDeclaration.kind === 225 /* ModuleDeclaration */ && ts.isShorthandAmbientModule(symbol.valueDeclaration)) { + if (symbol.valueDeclaration.kind === 225 /* ModuleDeclaration */ && ts.isShorthandAmbientModuleSymbol(symbol)) { links.type = anyType; } else { @@ -19603,7 +25603,7 @@ var ts; function getTypeOfEnumMember(symbol) { var links = getSymbolLinks(symbol); if (!links.type) { - links.type = getDeclaredTypeOfEnum(getParentOfSymbol(symbol)); + links.type = getDeclaredTypeOfEnumMember(symbol); } return links.type; } @@ -19734,7 +25734,7 @@ var ts; function getInstantiatedConstructorsForTypeArguments(type, typeArgumentNodes) { var signatures = getConstructorsForTypeArguments(type, typeArgumentNodes); if (typeArgumentNodes) { - var typeArguments_1 = ts.map(typeArgumentNodes, getTypeFromTypeNode); + var typeArguments_1 = ts.map(typeArgumentNodes, getTypeFromTypeNodeNoAlias); signatures = ts.map(signatures, function (sig) { return getSignatureInstantiation(sig, typeArguments_1); }); } return signatures; @@ -19883,7 +25883,7 @@ var ts; for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var declaration = _a[_i]; if (declaration.kind === 222 /* InterfaceDeclaration */) { - if (declaration.flags & 16384 /* ContainsThis */) { + if (declaration.flags & 64 /* ContainsThis */) { return false; } var baseTypeNodes = ts.getInterfaceBaseTypeNodes(declaration); @@ -19994,6 +25994,13 @@ var ts; } return true; } + function createEnumLiteralType(symbol, baseType, text) { + var type = createType(256 /* EnumLiteral */); + type.symbol = symbol; + type.baseType = baseType; + type.text = text; + return type; + } function getDeclaredTypeOfEnum(symbol) { var links = getSymbolLinks(symbol); if (!links.declaredType) { @@ -20011,10 +26018,7 @@ var ts; var memberSymbol = getSymbolOfNode(member); var value = getEnumMemberValue(member); if (!memberTypes[value]) { - var memberType = memberTypes[value] = createType(256 /* EnumLiteral */); - memberType.symbol = memberSymbol; - memberType.baseType = enumType; - memberType.text = "" + value; + var memberType = memberTypes[value] = createEnumLiteralType(memberSymbol, enumType, "" + value); memberTypeList.push(memberType); } } @@ -20274,7 +26278,7 @@ var ts; return [createSignature(undefined, classType.localTypeParameters, undefined, emptyArray, classType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false)]; } var baseTypeNode = getBaseTypeNodeOfClass(classType); - var typeArguments = ts.map(baseTypeNode.typeArguments, getTypeFromTypeNode); + var typeArguments = ts.map(baseTypeNode.typeArguments, getTypeFromTypeNodeNoAlias); var typeArgCount = typeArguments ? typeArguments.length : 0; var result = []; for (var _i = 0, baseSignatures_1 = baseSignatures; _i < baseSignatures_1.length; _i++) { @@ -20493,7 +26497,7 @@ var ts; var current = _a[_i]; for (var _b = 0, _c = getPropertiesOfType(current); _b < _c.length; _b++) { var prop = _c[_b]; - getPropertyOfUnionOrIntersectionType(type, prop.name); + getUnionOrIntersectionProperty(type, prop.name); } // The properties of a union type are those that are present in all constituent types, so // we only need to check the properties of the first type @@ -20501,7 +26505,19 @@ var ts; break; } } - return type.resolvedProperties ? symbolsToArray(type.resolvedProperties) : emptyArray; + var props = type.resolvedProperties; + if (props) { + var result = []; + for (var key in props) { + var prop = props[key]; + // We need to filter out partial properties in union types + if (!(prop.flags & 268435456 /* SyntheticProperty */ && prop.isPartial)) { + result.push(prop); + } + } + return result; + } + return emptyArray; } function getPropertiesOfType(type) { type = getApparentType(type); @@ -20550,12 +26566,13 @@ var ts; // Flags we want to propagate to the result if they exist in all source symbols var commonFlags = (containingType.flags & 1048576 /* Intersection */) ? 536870912 /* Optional */ : 0 /* None */; var isReadonly = false; + var isPartial = false; for (var _i = 0, types_2 = types; _i < types_2.length; _i++) { var current = types_2[_i]; var type = getApparentType(current); if (type !== unknownType) { var prop = getPropertyOfType(type, name); - if (prop && !(getDeclarationFlagsFromSymbol(prop) & (8 /* Private */ | 16 /* Protected */))) { + if (prop && !(getDeclarationModifierFlagsFromSymbol(prop) & (8 /* Private */ | 16 /* Protected */))) { commonFlags &= prop.flags; if (!props) { props = [prop]; @@ -20568,21 +26585,20 @@ var ts; } } else if (containingType.flags & 524288 /* Union */) { - // A union type requires the property to be present in all constituent types - return undefined; + isPartial = true; } } } if (!props) { return undefined; } - if (props.length === 1) { + if (props.length === 1 && !isPartial) { return props[0]; } var propTypes = []; var declarations = []; var commonType = undefined; - var hasCommonType = true; + var hasNonUniformType = false; for (var _a = 0, props_1 = props; _a < props_1.length; _a++) { var prop = props_1[_a]; if (prop.declarations) { @@ -20593,22 +26609,25 @@ var ts; commonType = type; } else if (type !== commonType) { - hasCommonType = false; + hasNonUniformType = true; } - propTypes.push(getTypeOfSymbol(prop)); + propTypes.push(type); } - var result = createSymbol(4 /* Property */ | - 67108864 /* Transient */ | - 268435456 /* SyntheticProperty */ | - commonFlags, name); + var result = createSymbol(4 /* Property */ | 67108864 /* Transient */ | 268435456 /* SyntheticProperty */ | commonFlags, name); result.containingType = containingType; - result.hasCommonType = hasCommonType; + result.hasNonUniformType = hasNonUniformType; + result.isPartial = isPartial; result.declarations = declarations; result.isReadonly = isReadonly; result.type = containingType.flags & 524288 /* Union */ ? getUnionType(propTypes) : getIntersectionType(propTypes); return result; } - function getPropertyOfUnionOrIntersectionType(type, name) { + // Return the symbol for a given property in a union or intersection type, or undefined if the property + // does not exist in any constituent type. Note that the returned property may only be present in some + // constituents, in which case the isPartial flag is set when the containing type is union type. We need + // these partial properties when identifying discriminant properties, but otherwise they are filtered out + // and do not appear to be present in the union type. + function getUnionOrIntersectionProperty(type, name) { var properties = type.resolvedProperties || (type.resolvedProperties = ts.createMap()); var property = properties[name]; if (!property) { @@ -20619,6 +26638,11 @@ var ts; } return property; } + function getPropertyOfUnionOrIntersectionType(type, name) { + var property = getUnionOrIntersectionProperty(type, name); + // We need to filter out partial properties in union types + return property && !(property.flags & 268435456 /* SyntheticProperty */ && property.isPartial) ? property : undefined; + } /** * Return the symbol for the property with the given name in the given type. Creates synthetic union properties when * necessary, maps primitive types and type parameters are to their apparent types, and augments with properties from @@ -20698,7 +26722,7 @@ var ts; return undefined; } function getTypeParametersFromJSDocTemplate(declaration) { - if (declaration.flags & 134217728 /* JavaScriptFile */) { + if (declaration.flags & 1048576 /* JavaScriptFile */) { var templateTag = ts.getJSDocTemplateTag(declaration); if (templateTag) { return getTypeParametersFromDeclaration(templateTag.typeParameters); @@ -20728,7 +26752,7 @@ var ts; return result; } function isJSDocOptionalParameter(node) { - if (node.flags & 134217728 /* JavaScriptFile */) { + if (node.flags & 1048576 /* JavaScriptFile */) { if (node.type && node.type.kind === 268 /* JSDocOptionalType */) { return true; } @@ -20856,7 +26880,7 @@ var ts; else if (declaration.type) { return getTypeFromTypeNode(declaration.type); } - if (declaration.flags & 134217728 /* JavaScriptFile */) { + if (declaration.flags & 1048576 /* JavaScriptFile */) { var type = getReturnTypeFromJSDocComment(declaration); if (type && type !== unknownType) { return type; @@ -21015,7 +27039,7 @@ var ts; function getIndexInfoOfSymbol(symbol, kind) { var declaration = getIndexDeclarationOfSymbol(symbol, kind); if (declaration) { - return createIndexInfo(declaration.type ? getTypeFromTypeNode(declaration.type) : anyType, (declaration.flags & 64 /* Readonly */) !== 0, declaration); + return createIndexInfo(declaration.type ? getTypeFromTypeNode(declaration.type) : anyType, (ts.getModifierFlags(declaration) & 64 /* Readonly */) !== 0, declaration); } return undefined; } @@ -21125,7 +27149,7 @@ var ts; // In a type reference, the outer type parameters of the referenced class or interface are automatically // supplied as type arguments and the type reference only specifies arguments for the local type parameters // of the class or interface. - return createTypeReference(type, ts.concatenate(type.outerTypeParameters, ts.map(node.typeArguments, getTypeFromTypeNode))); + return createTypeReference(type, ts.concatenate(type.outerTypeParameters, ts.map(node.typeArguments, getTypeFromTypeNodeNoAlias))); } if (node.typeArguments) { error(node, ts.Diagnostics.Type_0_is_not_generic, typeToString(type)); @@ -21145,7 +27169,7 @@ var ts; error(node, ts.Diagnostics.Generic_type_0_requires_1_type_argument_s, symbolToString(symbol), typeParameters.length); return unknownType; } - var typeArguments = ts.map(node.typeArguments, getTypeFromTypeNode); + var typeArguments = ts.map(node.typeArguments, getTypeFromTypeNodeNoAlias); var id = getTypeListId(typeArguments); return links.instantiations[id] || (links.instantiations[id] = instantiateType(type, createTypeMapper(typeParameters, typeArguments))); } @@ -21367,7 +27391,7 @@ var ts; function getTypeFromTupleTypeNode(node) { var links = getNodeLinks(node); if (!links.resolvedType) { - links.resolvedType = createTupleType(ts.map(node.elementTypes, getTypeFromTypeNode)); + links.resolvedType = createTupleType(ts.map(node.elementTypes, getTypeFromTypeNodeNoAlias)); } return links.resolvedType; } @@ -21394,25 +27418,32 @@ var ts; return binarySearchTypes(types, type) >= 0; } function addTypeToUnion(typeSet, type) { - if (type.flags & 524288 /* Union */) { + var flags = type.flags; + if (flags & 524288 /* Union */) { addTypesToUnion(typeSet, type.types); } - else if (type.flags & 1 /* Any */) { + else if (flags & 1 /* Any */) { typeSet.containsAny = true; } - else if (!strictNullChecks && type.flags & 6144 /* Nullable */) { - if (type.flags & 2048 /* Undefined */) + else if (!strictNullChecks && flags & 6144 /* Nullable */) { + if (flags & 2048 /* Undefined */) typeSet.containsUndefined = true; - if (type.flags & 4096 /* Null */) + if (flags & 4096 /* Null */) typeSet.containsNull = true; - if (!(type.flags & 33554432 /* ContainsWideningType */)) + if (!(flags & 33554432 /* ContainsWideningType */)) typeSet.containsNonWideningType = true; } - else if (!(type.flags & 8192 /* Never */)) { + else if (!(flags & 8192 /* Never */)) { + if (flags & 2 /* String */) + typeSet.containsString = true; + if (flags & 4 /* Number */) + typeSet.containsNumber = true; + if (flags & 96 /* StringOrNumberLiteral */) + typeSet.containsStringOrNumberLiteral = true; var len = typeSet.length; var index = len && type.id > typeSet[len - 1].id ? ~len : binarySearchTypes(typeSet, type); if (index < 0) { - if (!(type.flags & 2097152 /* Anonymous */ && type.symbol && type.symbol.flags & (16 /* Function */ | 8192 /* Method */) && containsIdenticalType(typeSet, type))) { + if (!(flags & 2097152 /* Anonymous */ && type.symbol && type.symbol.flags & (16 /* Function */ | 8192 /* Method */) && containsIdenticalType(typeSet, type))) { typeSet.splice(~index, 0, type); } } @@ -21452,6 +27483,19 @@ var ts; } } } + function removeRedundantLiteralTypes(types) { + var i = types.length; + while (i > 0) { + i--; + var t = types[i]; + var remove = t.flags & 32 /* StringLiteral */ && types.containsString || + t.flags & 64 /* NumberLiteral */ && types.containsNumber || + t.flags & 96 /* StringOrNumberLiteral */ && t.flags & 16777216 /* FreshLiteral */ && containsType(types, t.regularType); + if (remove) { + ts.orderedRemoveItemAt(types, i); + } + } + } // We sort and deduplicate the constituent types based on object identity. If the subtypeReduction // flag is specified we also reduce the constituent type set to only include types that aren't subtypes // of other types. Subtype reduction is expensive for large union types and is possible only when union @@ -21474,6 +27518,9 @@ var ts; if (subtypeReduction) { removeSubtypes(typeSet); } + else if (typeSet.containsStringOrNumberLiteral) { + removeRedundantLiteralTypes(typeSet); + } if (typeSet.length === 0) { return typeSet.containsNull ? typeSet.containsNonWideningType ? nullType : nullWideningType : typeSet.containsUndefined ? typeSet.containsNonWideningType ? undefinedType : undefinedWideningType : @@ -21503,7 +27550,7 @@ var ts; function getTypeFromUnionTypeNode(node, aliasSymbol, aliasTypeArguments) { var links = getNodeLinks(node); if (!links.resolvedType) { - links.resolvedType = getUnionType(ts.map(node.types, getTypeFromTypeNode), /*subtypeReduction*/ false, aliasSymbol, aliasTypeArguments); + links.resolvedType = getUnionType(ts.map(node.types, getTypeFromTypeNodeNoAlias), /*subtypeReduction*/ false, aliasSymbol, aliasTypeArguments); } return links.resolvedType; } @@ -21557,7 +27604,7 @@ var ts; function getTypeFromIntersectionTypeNode(node, aliasSymbol, aliasTypeArguments) { var links = getNodeLinks(node); if (!links.resolvedType) { - links.resolvedType = getIntersectionType(ts.map(node.types, getTypeFromTypeNode), aliasSymbol, aliasTypeArguments); + links.resolvedType = getIntersectionType(ts.map(node.types, getTypeFromTypeNodeNoAlias), aliasSymbol, aliasTypeArguments); } return links.resolvedType; } @@ -21577,6 +27624,20 @@ var ts; type.text = text; return type; } + function getFreshTypeOfLiteralType(type) { + if (type.flags & 96 /* StringOrNumberLiteral */ && !(type.flags & 16777216 /* FreshLiteral */)) { + if (!type.freshType) { + var freshType = createLiteralType(type.flags | 16777216 /* FreshLiteral */, type.text); + freshType.regularType = type; + type.freshType = freshType; + } + return type.freshType; + } + return type; + } + function getRegularTypeOfLiteralType(type) { + return type.flags & 96 /* StringOrNumberLiteral */ && type.flags & 16777216 /* FreshLiteral */ ? type.regularType : type; + } function getLiteralTypeForText(flags, text) { var map = flags & 32 /* StringLiteral */ ? stringLiteralTypes : numericLiteralTypes; return map[text] || (map[text] = createLiteralType(flags, text)); @@ -21584,7 +27645,7 @@ var ts; function getTypeFromLiteralTypeNode(node) { var links = getNodeLinks(node); if (!links.resolvedType) { - links.resolvedType = checkExpression(node.literal); + links.resolvedType = getRegularTypeOfLiteralType(checkExpression(node.literal)); } return links.resolvedType; } @@ -21599,7 +27660,7 @@ var ts; function getTypeFromJSDocTupleType(node) { var links = getNodeLinks(node); if (!links.resolvedType) { - var types = ts.map(node.types, getTypeFromTypeNode); + var types = ts.map(node.types, getTypeFromTypeNodeNoAlias); links.resolvedType = createTupleType(types); } return links.resolvedType; @@ -21608,8 +27669,8 @@ var ts; var container = ts.getThisContainer(node, /*includeArrowFunctions*/ false); var parent = container && container.parent; if (parent && (ts.isClassLike(parent) || parent.kind === 222 /* InterfaceDeclaration */)) { - if (!(container.flags & 32 /* Static */) && - (container.kind !== 148 /* Constructor */ || ts.isNodeDescendentOf(node, container.body))) { + if (!(ts.getModifierFlags(container) & 32 /* Static */) && + (container.kind !== 148 /* Constructor */ || ts.isNodeDescendantOf(node, container.body))) { return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(parent)).thisType; } } @@ -21623,6 +27684,9 @@ var ts; } return links.resolvedType; } + function getTypeFromTypeNodeNoAlias(type) { + return getTypeFromTypeNode(type, /*aliasSymbol*/ undefined, /*aliasTypeArguments*/ undefined); + } function getTypeFromTypeNode(node, aliasSymbol, aliasTypeArguments) { switch (node.kind) { case 117 /* AnyKeyword */: @@ -21684,12 +27748,13 @@ var ts; case 272 /* JSDocThisType */: case 268 /* JSDocOptionalType */: return getTypeFromTypeNode(node.type); + case 265 /* JSDocRecordType */: + return getTypeFromTypeNode(node.literal); case 156 /* FunctionType */: case 157 /* ConstructorType */: case 159 /* TypeLiteral */: case 281 /* JSDocTypeLiteral */: case 269 /* JSDocFunctionType */: - case 265 /* JSDocRecordType */: return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node, aliasSymbol, aliasTypeArguments); // This function assumes that an identifier or qualified name is a type expression // Callers should first ensure this by calling isTypeNode @@ -21747,7 +27812,7 @@ var ts; function getInferenceMapper(context) { if (!context.mapper) { var mapper = function (t) { - var typeParameters = context.typeParameters; + var typeParameters = context.signature.typeParameters; for (var i = 0; i < typeParameters.length; i++) { if (t === typeParameters[i]) { context.inferences[i].isFixed = true; @@ -21756,7 +27821,7 @@ var ts; } return t; }; - mapper.mappedTypes = context.typeParameters; + mapper.mappedTypes = context.signature.typeParameters; mapper.context = context; context.mapper = mapper; } @@ -22172,8 +28237,14 @@ var ts; if (source === target) { return true; } - if (source.symbol.name !== target.symbol.name || !(source.symbol.flags & 256 /* RegularEnum */) || !(target.symbol.flags & 256 /* RegularEnum */)) { - return false; + var id = source.id + "," + target.id; + if (enumRelation[id] !== undefined) { + return enumRelation[id]; + } + if (source.symbol.name !== target.symbol.name || + !(source.symbol.flags & 256 /* RegularEnum */) || !(target.symbol.flags & 256 /* RegularEnum */) || + (source.flags & 524288 /* Union */) !== (target.flags & 524288 /* Union */)) { + return enumRelation[id] = false; } var targetEnumType = getTypeOfSymbol(target.symbol); for (var _i = 0, _a = getPropertiesOfType(getTypeOfSymbol(source.symbol)); _i < _a.length; _i++) { @@ -22184,11 +28255,11 @@ var ts; if (errorReporter) { errorReporter(ts.Diagnostics.Property_0_is_missing_in_type_1, property.name, typeToString(target, /*enclosingDeclaration*/ undefined, 128 /* UseFullyQualifiedType */)); } - return false; + return enumRelation[id] = false; } } } - return true; + return enumRelation[id] = true; } function isSimpleTypeRelatedTo(source, target, relation, errorReporter) { if (target.flags & 8192 /* Never */) @@ -22212,14 +28283,29 @@ var ts; if (relation === assignableRelation || relation === comparableRelation) { if (source.flags & 1 /* Any */) return true; - if (source.flags & (4 /* Number */ | 64 /* NumberLiteral */) && target.flags & 16 /* Enum */) + if ((source.flags & 4 /* Number */ | source.flags & 64 /* NumberLiteral */) && target.flags & 272 /* EnumLike */) + return true; + if (source.flags & 256 /* EnumLiteral */ && + target.flags & 256 /* EnumLiteral */ && + source.text === target.text && + isEnumTypeRelatedTo(source.baseType, target.baseType, errorReporter)) { return true; - if (source.flags & 64 /* NumberLiteral */ && target.flags & 256 /* EnumLiteral */ && source.text === target.text) + } + if (source.flags & 256 /* EnumLiteral */ && + target.flags & 16 /* Enum */ && + isEnumTypeRelatedTo(target, source.baseType, errorReporter)) { return true; + } } return false; } function isTypeRelatedTo(source, target, relation) { + if (source.flags & 96 /* StringOrNumberLiteral */ && source.flags & 16777216 /* FreshLiteral */) { + source = source.regularType; + } + if (target.flags & 96 /* StringOrNumberLiteral */ && target.flags & 16777216 /* FreshLiteral */) { + target = target.regularType; + } if (source === target || relation !== identityRelation && isSimpleTypeRelatedTo(source, target, relation)) { return true; } @@ -22299,6 +28385,12 @@ var ts; // Ternary.False if they are not related. function isRelatedTo(source, target, reportErrors, headMessage) { var result; + if (source.flags & 96 /* StringOrNumberLiteral */ && source.flags & 16777216 /* FreshLiteral */) { + source = source.regularType; + } + if (target.flags & 96 /* StringOrNumberLiteral */ && target.flags & 16777216 /* FreshLiteral */) { + target = target.regularType; + } // both types are the same - covers 'they are the same primitive type or both are Any' or the same type parameter cases if (source === target) return -1 /* True */; @@ -22307,7 +28399,7 @@ var ts; } if (isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) return -1 /* True */; - if (source.flags & 16777216 /* FreshObjectLiteral */) { + if (source.flags & 8388608 /* ObjectLiteral */ && source.flags & 16777216 /* FreshLiteral */) { if (hasExcessProperties(source, target, reportErrors)) { if (reportErrors) { reportRelationError(headMessage, source, target); @@ -22409,6 +28501,9 @@ var ts; if (source.flags & 2588672 /* ObjectType */ && target.flags & 8190 /* Primitive */) { tryElaborateErrorsForPrimitivesAndObjects(source, target); } + else if (source.symbol && source.flags & 2588672 /* ObjectType */ && globalObjectType === source) { + reportError(ts.Diagnostics.The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead); + } reportRelationError(headMessage, source, target); } return 0 /* False */; @@ -22658,8 +28753,8 @@ var ts; var result = -1 /* True */; var properties = getPropertiesOfObjectType(target); var requireOptionalProperties = relation === subtypeRelation && !(source.flags & 8388608 /* ObjectLiteral */); - for (var _i = 0, properties_1 = properties; _i < properties_1.length; _i++) { - var targetProp = properties_1[_i]; + for (var _i = 0, properties_2 = properties; _i < properties_2.length; _i++) { + var targetProp = properties_2[_i]; var sourceProp = getPropertyOfType(source, targetProp.name); if (sourceProp !== targetProp) { if (!sourceProp) { @@ -22671,8 +28766,8 @@ var ts; } } else if (!(targetProp.flags & 134217728 /* Prototype */)) { - var sourcePropFlags = getDeclarationFlagsFromSymbol(sourceProp); - var targetPropFlags = getDeclarationFlagsFromSymbol(targetProp); + var sourcePropFlags = getDeclarationModifierFlagsFromSymbol(sourceProp); + var targetPropFlags = getDeclarationModifierFlagsFromSymbol(targetProp); if (sourcePropFlags & 8 /* Private */ || targetPropFlags & 8 /* Private */) { if (sourceProp.valueDeclaration !== targetProp.valueDeclaration) { if (reportErrors) { @@ -22893,8 +28988,8 @@ var ts; if (!sourceSignature.declaration || !targetSignature.declaration) { return true; } - var sourceAccessibility = sourceSignature.declaration.flags & (8 /* Private */ | 16 /* Protected */); - var targetAccessibility = targetSignature.declaration.flags & (8 /* Private */ | 16 /* Protected */); + var sourceAccessibility = ts.getModifierFlags(sourceSignature.declaration) & 24 /* NonPublicAccessibilityModifier */; + var targetAccessibility = ts.getModifierFlags(targetSignature.declaration) & 24 /* NonPublicAccessibilityModifier */; // A public, protected and private signature is assignable to a private signature. if (targetAccessibility === 8 /* Private */) { return true; @@ -22919,7 +29014,7 @@ var ts; var symbol = type.symbol; if (symbol && symbol.flags & 32 /* Class */) { var declaration = getClassLikeDeclarationOfSymbol(symbol); - if (declaration && declaration.flags & 128 /* Abstract */) { + if (declaration && ts.getModifierFlags(declaration) & 128 /* Abstract */) { return true; } } @@ -22957,8 +29052,8 @@ var ts; if (sourceProp === targetProp) { return -1 /* True */; } - var sourcePropAccessibility = getDeclarationFlagsFromSymbol(sourceProp) & (8 /* Private */ | 16 /* Protected */); - var targetPropAccessibility = getDeclarationFlagsFromSymbol(targetProp) & (8 /* Private */ | 16 /* Protected */); + var sourcePropAccessibility = getDeclarationModifierFlagsFromSymbol(sourceProp) & 24 /* NonPublicAccessibilityModifier */; + var targetPropAccessibility = getDeclarationModifierFlagsFromSymbol(targetProp) & 24 /* NonPublicAccessibilityModifier */; if (sourcePropAccessibility !== targetPropAccessibility) { return 0 /* False */; } @@ -23059,15 +29154,35 @@ var ts; } return true; } + function literalTypesWithSameBaseType(types) { + var commonBaseType; + for (var _i = 0, types_8 = types; _i < types_8.length; _i++) { + var t = types_8[_i]; + var baseType = getBaseTypeOfLiteralType(t); + if (!commonBaseType) { + commonBaseType = baseType; + } + if (baseType === t || baseType !== commonBaseType) { + return false; + } + } + return true; + } + // When the candidate types are all literal types with the same base type, the common + // supertype is a union of those literal types. Otherwise, the common supertype is the + // first type that is a supertype of each of the other types. + function getSupertypeOrUnion(types) { + return literalTypesWithSameBaseType(types) ? getUnionType(types) : ts.forEach(types, function (t) { return isSupertypeOfEach(t, types) ? t : undefined; }); + } function getCommonSupertype(types) { if (!strictNullChecks) { - return ts.forEach(types, function (t) { return isSupertypeOfEach(t, types) ? t : undefined; }); + return getSupertypeOrUnion(types); } var primaryTypes = ts.filter(types, function (t) { return !(t.flags & 6144 /* Nullable */); }); if (!primaryTypes.length) { return getUnionType(types, /*subtypeReduction*/ true); } - var supertype = ts.forEach(primaryTypes, function (t) { return isSupertypeOfEach(t, primaryTypes) ? t : undefined; }); + var supertype = getSupertypeOrUnion(primaryTypes); return supertype && includeFalsyTypes(supertype, getFalsyFlagsOfTypes(types) & 6144 /* Nullable */); } function reportNoCommonSupertypeError(types, errorLocation, errorMessageChainHead) { @@ -23118,17 +29233,25 @@ var ts; function isUnitType(type) { return (type.flags & (480 /* Literal */ | 2048 /* Undefined */ | 4096 /* Null */)) !== 0; } - function isUnitUnionType(type) { + function isLiteralType(type) { return type.flags & 8 /* Boolean */ ? true : type.flags & 524288 /* Union */ ? type.flags & 16 /* Enum */ ? true : !ts.forEach(type.types, function (t) { return !isUnitType(t); }) : isUnitType(type); } - function getBaseTypeOfUnitType(type) { + function getBaseTypeOfLiteralType(type) { return type.flags & 32 /* StringLiteral */ ? stringType : type.flags & 64 /* NumberLiteral */ ? numberType : type.flags & 128 /* BooleanLiteral */ ? booleanType : type.flags & 256 /* EnumLiteral */ ? type.baseType : - type.flags & 524288 /* Union */ && !(type.flags & 16 /* Enum */) ? getUnionType(ts.map(type.types, getBaseTypeOfUnitType)) : + type.flags & 524288 /* Union */ && !(type.flags & 16 /* Enum */) ? getUnionType(ts.map(type.types, getBaseTypeOfLiteralType)) : + type; + } + function getWidenedLiteralType(type) { + return type.flags & 32 /* StringLiteral */ && type.flags & 16777216 /* FreshLiteral */ ? stringType : + type.flags & 64 /* NumberLiteral */ && type.flags & 16777216 /* FreshLiteral */ ? numberType : + type.flags & 128 /* BooleanLiteral */ ? booleanType : + type.flags & 256 /* EnumLiteral */ ? type.baseType : + type.flags & 524288 /* Union */ && !(type.flags & 16 /* Enum */) ? getUnionType(ts.map(type.types, getWidenedLiteralType)) : type; } /** @@ -23140,8 +29263,8 @@ var ts; } function getFalsyFlagsOfTypes(types) { var result = 0; - for (var _i = 0, types_8 = types; _i < types_8.length; _i++) { - var t = types_8[_i]; + for (var _i = 0, types_9 = types; _i < types_9.length; _i++) { + var t = types_9[_i]; result |= getFalsyFlags(t); } return result; @@ -23151,8 +29274,8 @@ var ts; // no flags for all other types (including non-falsy literal types). function getFalsyFlags(type) { return type.flags & 524288 /* Union */ ? getFalsyFlagsOfTypes(type.types) : - type.flags & 32 /* StringLiteral */ ? type === emptyStringType ? 32 /* StringLiteral */ : 0 : - type.flags & 64 /* NumberLiteral */ ? type === zeroType ? 64 /* NumberLiteral */ : 0 : + type.flags & 32 /* StringLiteral */ ? type.text === "" ? 32 /* StringLiteral */ : 0 : + type.flags & 64 /* NumberLiteral */ ? type.text === "0" ? 64 /* NumberLiteral */ : 0 : type.flags & 128 /* BooleanLiteral */ ? type === falseType ? 128 /* BooleanLiteral */ : 0 : type.flags & 7406 /* PossiblyFalsy */; } @@ -23220,7 +29343,7 @@ var ts; * Leave signatures alone since they are not subject to the check. */ function getRegularTypeOfObjectLiteral(type) { - if (!(type.flags & 16777216 /* FreshObjectLiteral */)) { + if (!(type.flags & 8388608 /* ObjectLiteral */ && type.flags & 16777216 /* FreshLiteral */)) { return type; } var regularType = type.regularType; @@ -23230,7 +29353,7 @@ var ts; var resolved = type; var members = transformTypeOfMembers(type, getRegularTypeOfObjectLiteral); var regularNew = createAnonymousType(resolved.symbol, members, resolved.callSignatures, resolved.constructSignatures, resolved.stringIndexInfo, resolved.numberIndexInfo); - regularNew.flags = resolved.flags & ~16777216 /* FreshObjectLiteral */; + regularNew.flags = resolved.flags & ~16777216 /* FreshLiteral */; type.regularType = regularNew; return regularNew; } @@ -23368,19 +29491,20 @@ var ts; callback(getTypeAtPosition(source, i), getTypeAtPosition(target, i)); } } - function createInferenceContext(typeParameters, inferUnionTypes) { - var inferences = ts.map(typeParameters, createTypeInferencesObject); + function createInferenceContext(signature, inferUnionTypes) { + var inferences = ts.map(signature.typeParameters, createTypeInferencesObject); return { - typeParameters: typeParameters, + signature: signature, inferUnionTypes: inferUnionTypes, inferences: inferences, - inferredTypes: new Array(typeParameters.length), + inferredTypes: new Array(signature.typeParameters.length), }; } function createTypeInferencesObject() { return { primary: undefined, secondary: undefined, + topLevel: true, isFixed: false, }; } @@ -23399,13 +29523,17 @@ var ts; } return type.couldContainTypeParameters; } - function inferTypes(context, source, target) { + function isTypeParameterAtTopLevel(type, typeParameter) { + return type === typeParameter || type.flags & 1572864 /* UnionOrIntersection */ && ts.forEach(type.types, function (t) { return isTypeParameterAtTopLevel(t, typeParameter); }); + } + function inferTypes(context, originalSource, originalTarget) { + var typeParameters = context.signature.typeParameters; var sourceStack; var targetStack; var depth = 0; var inferiority = 0; var visited = ts.createMap(); - inferFromTypes(source, target); + inferFromTypes(originalSource, originalTarget); function isInProcess(source, target) { for (var i = 0; i < depth; i++) { if (source === sourceStack[i] && target === targetStack[i]) { @@ -23429,17 +29557,25 @@ var ts; } return; } - // Find each target constituent type that has an identically matching source - // constituent type, and for each such target constituent type infer from the type to - // itself. When inferring from a type to itself we effectively find all type parameter - // occurrences within that type and infer themselves as their type arguments. + // Find each source constituent type that has an identically matching target constituent + // type, and for each such type infer from the type to itself. When inferring from a + // type to itself we effectively find all type parameter occurrences within that type + // and infer themselves as their type arguments. We have special handling for numeric + // and string literals because the number and string types are not represented as unions + // of all their possible values. var matchingTypes = void 0; - for (var _b = 0, _c = target.types; _b < _c.length; _b++) { + for (var _b = 0, _c = source.types; _b < _c.length; _b++) { var t = _c[_b]; - if (typeIdenticalToSomeType(t, source.types)) { + if (typeIdenticalToSomeType(t, target.types)) { (matchingTypes || (matchingTypes = [])).push(t); inferFromTypes(t, t); } + else if (t.flags & (64 /* NumberLiteral */ | 32 /* StringLiteral */)) { + var b = getBaseTypeOfLiteralType(t); + if (typeIdenticalToSomeType(b, target.types)) { + (matchingTypes || (matchingTypes = [])).push(t, b); + } + } } // Next, to improve the quality of inferences, reduce the source and target types by // removing the identically matched constituents. For example, when inferring from @@ -23459,7 +29595,6 @@ var ts; if (source.flags & 134217728 /* ContainsAnyFunctionType */) { return; } - var typeParameters = context.typeParameters; for (var i = 0; i < typeParameters.length; i++) { if (target === typeParameters[i]) { var inferences = context.inferences[i]; @@ -23476,6 +29611,9 @@ var ts; if (!ts.contains(candidates, source)) { candidates.push(source); } + if (!isTypeParameterAtTopLevel(originalTarget, target)) { + inferences.topLevel = false; + } } return; } @@ -23497,7 +29635,7 @@ var ts; // First infer to each type in union or intersection that isn't a type parameter for (var _d = 0, targetTypes_2 = targetTypes; _d < targetTypes_2.length; _d++) { var t = targetTypes_2[_d]; - if (t.flags & 16384 /* TypeParameter */ && ts.contains(context.typeParameters, t)) { + if (t.flags & 16384 /* TypeParameter */ && ts.contains(typeParameters, t)) { typeParameter = t; typeParameterCount++; } @@ -23553,8 +29691,8 @@ var ts; } function inferFromProperties(source, target) { var properties = getPropertiesOfObjectType(target); - for (var _i = 0, properties_2 = properties; _i < properties_2.length; _i++) { - var targetProp = properties_2[_i]; + for (var _i = 0, properties_3 = properties; _i < properties_3.length; _i++) { + var targetProp = properties_3[_i]; var sourceProp = getPropertyOfObjectType(source, targetProp.name); if (sourceProp) { inferFromTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp)); @@ -23571,8 +29709,11 @@ var ts; inferFromSignature(getErasedSignature(sourceSignatures[sourceLen - len + i]), getErasedSignature(targetSignatures[targetLen - len + i])); } } + function inferFromParameterTypes(source, target) { + return inferFromTypes(source, target); + } function inferFromSignature(source, target) { - forEachMatchingParameterType(source, target, inferFromTypes); + forEachMatchingParameterType(source, target, inferFromParameterTypes); if (source.typePredicate && target.typePredicate && source.typePredicate.kind === target.typePredicate.kind) { inferFromTypes(source.typePredicate.type, target.typePredicate.type); } @@ -23601,8 +29742,8 @@ var ts; } } function typeIdenticalToSomeType(type, types) { - for (var _i = 0, types_9 = types; _i < types_9.length; _i++) { - var t = types_9[_i]; + for (var _i = 0, types_10 = types; _i < types_10.length; _i++) { + var t = types_10[_i]; if (isTypeIdenticalTo(t, type)) { return true; } @@ -23627,14 +29768,27 @@ var ts; var inferences = context.inferences[index]; return inferences.primary || inferences.secondary || emptyArray; } + function hasPrimitiveConstraint(type) { + var constraint = getConstraintOfTypeParameter(type); + return constraint && maybeTypeOfKind(constraint, 8190 /* Primitive */); + } function getInferredType(context, index) { var inferredType = context.inferredTypes[index]; var inferenceSucceeded; if (!inferredType) { var inferences = getInferenceCandidates(context, index); if (inferences.length) { + // We widen inferred literal types if + // all inferences were made to top-level ocurrences of the type parameter, and + // the type parameter has no constraint or its constraint includes no primitive or literal types, and + // the type parameter was fixed during inference or does not occur at top-level in the return type. + var signature = context.signature; + var widenLiteralTypes = context.inferences[index].topLevel && + !hasPrimitiveConstraint(signature.typeParameters[index]) && + (context.inferences[index].isFixed || !isTypeParameterAtTopLevel(getReturnTypeOfSignature(signature), signature.typeParameters[index])); + var baseInferences = widenLiteralTypes ? ts.map(inferences, getWidenedLiteralType) : inferences; // Infer widened union or supertype, or the unknown type for no common supertype - var unionOrSuperType = context.inferUnionTypes ? getUnionType(inferences, /*subtypeReduction*/ true) : getCommonSupertype(inferences); + var unionOrSuperType = context.inferUnionTypes ? getUnionType(baseInferences, /*subtypeReduction*/ true) : getCommonSupertype(baseInferences); inferredType = unionOrSuperType ? getWidenedType(unionOrSuperType) : unknownType; inferenceSucceeded = !!unionOrSuperType; } @@ -23649,7 +29803,7 @@ var ts; context.inferredTypes[index] = inferredType; // Only do the constraint check if inference succeeded (to prevent cascading errors) if (inferenceSucceeded) { - var constraint = getConstraintOfTypeParameter(context.typeParameters[index]); + var constraint = getConstraintOfTypeParameter(context.signature.typeParameters[index]); if (constraint) { var instantiatedConstraint = instantiateType(constraint, getInferenceMapper(context)); if (!isTypeAssignableTo(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) { @@ -23771,21 +29925,10 @@ var ts; } function isDiscriminantProperty(type, name) { if (type && type.flags & 524288 /* Union */) { - var prop = getPropertyOfType(type, name); - if (!prop) { - // The type may be a union that includes nullable or primitive types. If filtering - // those out produces a different type, get the property from that type instead. - // Effectively, we're checking if this *could* be a discriminant property once nullable - // and primitive types are removed by other type guards. - var filteredType = getTypeWithFacts(type, 4194304 /* Discriminatable */); - if (filteredType !== type && filteredType.flags & 524288 /* Union */) { - prop = getPropertyOfType(filteredType, name); - } - } + var prop = getUnionOrIntersectionProperty(type, name); if (prop && prop.flags & 268435456 /* SyntheticProperty */) { if (prop.isDiscriminantProperty === undefined) { - prop.isDiscriminantProperty = !prop.hasCommonType && - isUnitUnionType(getTypeOfSymbol(prop)); + prop.isDiscriminantProperty = prop.hasNonUniformType && isLiteralType(getTypeOfSymbol(prop)); } return prop.isDiscriminantProperty; } @@ -23834,8 +29977,11 @@ var ts; // we remove type string. function getAssignmentReducedType(declaredType, assignedType) { if (declaredType !== assignedType) { + if (assignedType.flags & 8192 /* Never */) { + return assignedType; + } var reducedType = filterType(declaredType, function (t) { return typeMaybeAssignableTo(assignedType, t); }); - if (reducedType !== neverType) { + if (!(reducedType.flags & 8192 /* Never */)) { return reducedType; } } @@ -23843,8 +29989,8 @@ var ts; } function getTypeFactsOfTypes(types) { var result = 0 /* None */; - for (var _i = 0, types_10 = types; _i < types_10.length; _i++) { - var t = types_10[_i]; + for (var _i = 0, types_11 = types; _i < types_11.length; _i++) { + var t = types_11[_i]; result |= getTypeFacts(t); } return result; @@ -23863,14 +30009,14 @@ var ts; } if (flags & 32 /* StringLiteral */) { return strictNullChecks ? - type === emptyStringType ? 3030785 /* EmptyStringStrictFacts */ : 1982209 /* NonEmptyStringStrictFacts */ : - type === emptyStringType ? 3145473 /* EmptyStringFacts */ : 4194049 /* NonEmptyStringFacts */; + type.text === "" ? 3030785 /* EmptyStringStrictFacts */ : 1982209 /* NonEmptyStringStrictFacts */ : + type.text === "" ? 3145473 /* EmptyStringFacts */ : 4194049 /* NonEmptyStringFacts */; } if (flags & (4 /* Number */ | 16 /* Enum */)) { return strictNullChecks ? 4079234 /* NumberStrictFacts */ : 4193922 /* NumberFacts */; } if (flags & (64 /* NumberLiteral */ | 256 /* EnumLiteral */)) { - var isZero = type === zeroType || type.flags & 256 /* EnumLiteral */ && type.text === "0"; + var isZero = type.text === "0"; return strictNullChecks ? isZero ? 3030658 /* ZeroStrictFacts */ : 1982082 /* NonZeroStrictFacts */ : isZero ? 3145346 /* ZeroFacts */ : 4193922 /* NonZeroFacts */; @@ -24025,7 +30171,7 @@ var ts; } function getTypeOfSwitchClause(clause) { if (clause.kind === 249 /* CaseClause */) { - var caseType = checkExpression(clause.expression); + var caseType = getRegularTypeOfLiteralType(checkExpression(clause.expression)); return isUnitType(caseType) ? caseType : undefined; } return neverType; @@ -24087,7 +30233,7 @@ var ts; var visitedFlowStart = visitedFlowCount; var result = getTypeFromFlowType(getTypeAtFlowNode(reference.flowNode)); visitedFlowCount = visitedFlowStart; - if (reference.parent.kind === 196 /* NonNullExpression */ && getTypeWithFacts(result, 524288 /* NEUndefinedOrNull */) === neverType) { + if (reference.parent.kind === 196 /* NonNullExpression */ && getTypeWithFacts(result, 524288 /* NEUndefinedOrNull */).flags & 8192 /* Never */) { return declaredType; } return result; @@ -24155,7 +30301,8 @@ var ts; // Assignments only narrow the computed type if the declared type is a union type. Thus, we // only need to evaluate the assigned type if the declared type is a union type. if (isMatchingReference(reference, node)) { - return declaredType.flags & 524288 /* Union */ ? + var isIncrementOrDecrement = node.parent.kind === 185 /* PrefixUnaryExpression */ || node.parent.kind === 186 /* PostfixUnaryExpression */; + return declaredType.flags & 524288 /* Union */ && !isIncrementOrDecrement ? getAssignmentReducedType(declaredType, getInitialOrAssignedType(node)) : declaredType; } @@ -24172,17 +30319,18 @@ var ts; function getTypeAtFlowCondition(flow) { var flowType = getTypeAtFlowNode(flow.antecedent); var type = getTypeFromFlowType(flowType); - if (type !== neverType) { + if (!(type.flags & 8192 /* Never */)) { // If we have an antecedent type (meaning we're reachable in some way), we first // attempt to narrow the antecedent type. If that produces the never type, and if // the antecedent type is incomplete (i.e. a transient type in a loop), then we // take the type guard as an indication that control *could* reach here once we - // have the complete type. We proceed by reverting to the declared type and then - // narrow that. + // have the complete type. We proceed by switching to the silent never type which + // doesn't report errors when operators are applied to it. Note that this is the + // *only* place a silent never type is ever generated. var assumeTrue = (flow.flags & 32 /* TrueCondition */) !== 0; type = narrowType(type, flow.expression, assumeTrue); - if (type === neverType && isIncomplete(flowType)) { - type = narrowType(declaredType, flow.expression, assumeTrue); + if (type.flags & 8192 /* Never */ && isIncomplete(flowType)) { + type = silentNeverType; } } return createFlowType(type, isIncomplete(flowType)); @@ -24361,6 +30509,9 @@ var ts; return type; } function narrowTypeByEquality(type, operator, value, assumeTrue) { + if (type.flags & 1 /* Any */) { + return type; + } if (operator === 31 /* ExclamationEqualsToken */ || operator === 33 /* ExclamationEqualsEqualsToken */) { assumeTrue = !assumeTrue; } @@ -24382,9 +30533,13 @@ var ts; } if (assumeTrue) { var narrowedType = filterType(type, function (t) { return areTypesComparable(t, valueType); }); - return narrowedType !== neverType ? narrowedType : type; + return narrowedType.flags & 8192 /* Never */ ? type : narrowedType; } - return isUnitType(valueType) ? filterType(type, function (t) { return t !== valueType; }) : type; + if (isUnitType(valueType)) { + var regularType_1 = getRegularTypeOfLiteralType(valueType); + return filterType(type, function (t) { return getRegularTypeOfLiteralType(t) !== regularType_1; }); + } + return type; } function narrowTypeByTypeof(type, typeOfExpr, operator, literal, assumeTrue) { // We have '==', '!=', '====', or !==' operator with 'typeof xxx' and string literal operands @@ -24423,12 +30578,12 @@ var ts; var clauseTypes = switchTypes.slice(clauseStart, clauseEnd); var hasDefaultClause = clauseStart === clauseEnd || ts.contains(clauseTypes, neverType); var discriminantType = getUnionType(clauseTypes); - var caseType = discriminantType === neverType ? neverType : filterType(type, function (t) { return isTypeComparableTo(discriminantType, t); }); + var caseType = discriminantType.flags & 8192 /* Never */ ? neverType : filterType(type, function (t) { return isTypeComparableTo(discriminantType, t); }); if (!hasDefaultClause) { return caseType; } - var defaultType = filterType(type, function (t) { return !(isUnitType(t) && ts.contains(switchTypes, t)); }); - return caseType === neverType ? defaultType : getUnionType([caseType, defaultType]); + var defaultType = filterType(type, function (t) { return !(isUnitType(t) && ts.contains(switchTypes, getRegularTypeOfLiteralType(t))); }); + return caseType.flags & 8192 /* Never */ ? defaultType : getUnionType([caseType, defaultType]); } function narrowTypeByInstanceof(type, expr, assumeTrue) { var left = getReferenceCandidate(expr.left); @@ -24484,7 +30639,7 @@ var ts; // the candidate type. If one or more constituents remain, return a union of those. if (type.flags & 524288 /* Union */) { var assignableType = filterType(type, function (t) { return isTypeInstanceOf(t, candidate); }); - if (assignableType !== neverType) { + if (!(assignableType.flags & 8192 /* Never */)) { return assignableType; } } @@ -24494,7 +30649,7 @@ var ts; // type. Otherwise, the types are completely unrelated, so narrow to an intersection of the // two types. var targetType = type.flags & 16384 /* TypeParameter */ ? getApparentType(type) : type; - return isTypeSubtypeOf(candidate, targetType) ? candidate : + return isTypeSubtypeOf(candidate, type) ? candidate : isTypeAssignableTo(type, candidate) ? type : isTypeAssignableTo(candidate, targetType) ? candidate : getIntersectionType([type, candidate]); @@ -24647,12 +30802,15 @@ var ts; // can explicitly bound arguments objects if (symbol === argumentsSymbol) { var container = ts.getContainingFunction(node); - if (container.kind === 180 /* ArrowFunction */) { - if (languageVersion < 2 /* ES6 */) { + if (languageVersion < 2 /* ES6 */) { + if (container.kind === 180 /* ArrowFunction */) { error(node, ts.Diagnostics.The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression); } + else if (ts.hasModifier(container, 256 /* Async */)) { + error(node, ts.Diagnostics.The_arguments_object_cannot_be_referenced_in_an_async_function_or_method_in_ES3_and_ES5_Consider_using_a_standard_function_or_method); + } } - if (node.flags & 33554432 /* AwaitContext */) { + if (node.flags & 262144 /* AwaitContext */) { getNodeLinks(container).flags |= 8192 /* CaptureArguments */; } } @@ -24660,21 +30818,39 @@ var ts; markAliasSymbolAsReferenced(symbol); } var localOrExportSymbol = getExportSymbolOfValueSymbolIfExported(symbol); - // Due to the emit for class decorators, any reference to the class from inside of the class body - // must instead be rewritten to point to a temporary variable to avoid issues with the double-bind - // behavior of class names in ES6. - if (languageVersion === 2 /* ES6 */ - && localOrExportSymbol.flags & 32 /* Class */ - && localOrExportSymbol.valueDeclaration.kind === 221 /* ClassDeclaration */ - && ts.nodeIsDecorated(localOrExportSymbol.valueDeclaration)) { - var container = ts.getContainingClass(node); - while (container !== undefined) { - if (container === localOrExportSymbol.valueDeclaration && container.name !== node) { - getNodeLinks(container).flags |= 524288 /* ClassWithBodyScopedClassBinding */; - getNodeLinks(node).flags |= 1048576 /* BodyScopedClassBinding */; - break; + if (localOrExportSymbol.flags & 32 /* Class */) { + var declaration_1 = localOrExportSymbol.valueDeclaration; + // Due to the emit for class decorators, any reference to the class from inside of the class body + // must instead be rewritten to point to a temporary variable to avoid issues with the double-bind + // behavior of class names in ES6. + if (languageVersion === 2 /* ES6 */ + && declaration_1.kind === 221 /* ClassDeclaration */ + && ts.nodeIsDecorated(declaration_1)) { + var container = ts.getContainingClass(node); + while (container !== undefined) { + if (container === declaration_1 && container.name !== node) { + getNodeLinks(declaration_1).flags |= 8388608 /* ClassWithConstructorReference */; + getNodeLinks(node).flags |= 16777216 /* ConstructorReferenceInClass */; + break; + } + container = ts.getContainingClass(container); + } + } + else if (declaration_1.kind === 192 /* ClassExpression */) { + // When we emit a class expression with static members that contain a reference + // to the constructor in the initializer, we will need to substitute that + // binding with an alias as the class name is not in scope. + var container = ts.getThisContainer(node, /*includeArrowFunctions*/ false); + while (container !== undefined) { + if (container.parent === declaration_1) { + if (container.kind === 145 /* PropertyDeclaration */ && ts.hasModifier(container, 32 /* Static */)) { + getNodeLinks(declaration_1).flags |= 8388608 /* ClassWithConstructorReference */; + getNodeLinks(node).flags |= 16777216 /* ConstructorReferenceInClass */; + } + break; + } + container = ts.getThisContainer(container, /*includeArrowFunctions*/ false); } - container = ts.getContainingClass(container); } } checkCollisionWithCapturedSuperVariable(node, node); @@ -24693,6 +30869,7 @@ var ts; var isParameter = ts.getRootDeclaration(declaration).kind === 142 /* Parameter */; var declarationContainer = getControlFlowContainer(declaration); var flowContainer = getControlFlowContainer(node); + var isOuterVariable = flowContainer !== declarationContainer; // When the control flow originates in a function expression or arrow function and we are referencing // a const variable or parameter from an outer function, we extend the origin of the control flow // analysis to include the immediately enclosing function. @@ -24705,7 +30882,7 @@ var ts; // the entire control flow graph from the variable's declaration (i.e. when the flow container and // declaration container are the same). var assumeInitialized = !strictNullChecks || (type.flags & 1 /* Any */) !== 0 || isParameter || - flowContainer !== declarationContainer || ts.isInAmbientContext(declaration); + isOuterVariable || ts.isInAmbientContext(declaration); var flowType = getFlowTypeOfReference(node, type, assumeInitialized, flowContainer); // A variable is considered uninitialized when it is possible to analyze the entire control flow graph // from declaration to use, and when the variable's declared type doesn't include undefined but the @@ -24889,7 +31066,7 @@ var ts; break; case 145 /* PropertyDeclaration */: case 144 /* PropertySignature */: - if (container.flags & 32 /* Static */) { + if (ts.getModifierFlags(container) & 32 /* Static */) { error(node, ts.Diagnostics.this_cannot_be_referenced_in_a_static_property_initializer); } break; @@ -24925,7 +31102,7 @@ var ts; } if (ts.isClassLike(container.parent)) { var symbol = getSymbolOfNode(container.parent); - var type = container.flags & 32 /* Static */ ? getTypeOfSymbol(symbol) : getDeclaredTypeOfSymbol(symbol).thisType; + var type = ts.hasModifier(container, 32 /* Static */) ? getTypeOfSymbol(symbol) : getDeclaredTypeOfSymbol(symbol).thisType; return getFlowTypeOfReference(node, type, /*assumeInitialized*/ true, /*flowContainer*/ undefined); } if (ts.isInJavaScriptFile(node)) { @@ -24961,8 +31138,8 @@ var ts; var isCallExpression = node.parent.kind === 174 /* CallExpression */ && node.parent.expression === node; var container = ts.getSuperContainer(node, /*stopOnFunctions*/ true); var needToCaptureLexicalThis = false; + // adjust the container reference in case if super is used inside arrow functions with arbitrarily deep nesting if (!isCallExpression) { - // adjust the container reference in case if super is used inside arrow functions with arbitrary deep nesting while (container && container.kind === 180 /* ArrowFunction */) { container = ts.getSuperContainer(container, /*stopOnFunctions*/ true); needToCaptureLexicalThis = languageVersion < 2 /* ES6 */; @@ -24994,7 +31171,7 @@ var ts; } return unknownType; } - if ((container.flags & 32 /* Static */) || isCallExpression) { + if ((ts.getModifierFlags(container) & 32 /* Static */) || isCallExpression) { nodeCheckFlag = 512 /* SuperStatic */; } else { @@ -25057,8 +31234,8 @@ var ts; // This helper creates an object with a "value" property that wraps the `super` property or indexed access for both get and set. // This is required for destructuring assignments, as a call expression cannot be used as the target of a destructuring assignment // while a property access can. - if (container.kind === 147 /* MethodDeclaration */ && container.flags & 256 /* Async */) { - if (ts.isSuperPropertyOrElementAccess(node.parent) && ts.isAssignmentTarget(node.parent)) { + if (container.kind === 147 /* MethodDeclaration */ && ts.getModifierFlags(container) & 256 /* Async */) { + if (ts.isSuperProperty(node.parent) && ts.isAssignmentTarget(node.parent)) { getNodeLinks(container).flags |= 4096 /* AsyncMethodWithSuperBinding */; } else { @@ -25115,7 +31292,7 @@ var ts; // - In a static member function or static member accessor // topmost container must be something that is directly nested in the class declaration\object literal expression if (ts.isClassLike(container.parent) || container.parent.kind === 171 /* ObjectLiteralExpression */) { - if (container.flags & 32 /* Static */) { + if (ts.getModifierFlags(container) & 32 /* Static */) { return container.kind === 147 /* MethodDeclaration */ || container.kind === 146 /* MethodSignature */ || container.kind === 149 /* GetAccessor */ || @@ -25155,14 +31332,14 @@ var ts; if (parameter.dotDotDotToken) { var restTypes = []; for (var i = indexOfParameter; i < iife.arguments.length; i++) { - restTypes.push(getTypeOfExpression(iife.arguments[i])); + restTypes.push(getWidenedLiteralType(checkExpression(iife.arguments[i]))); } return createArrayType(getUnionType(restTypes)); } var links = getNodeLinks(iife); var cached = links.resolvedSignature; links.resolvedSignature = anySignature; - var type = checkExpression(iife.arguments[indexOfParameter]); + var type = getWidenedLiteralType(checkExpression(iife.arguments[indexOfParameter])); links.resolvedSignature = cached; return type; } @@ -25210,11 +31387,11 @@ var ts; } if (ts.isBindingPattern(declaration.parent)) { var parentDeclaration = declaration.parent.parent; - var name_12 = declaration.propertyName || declaration.name; + var name_15 = declaration.propertyName || declaration.name; if (ts.isVariableLike(parentDeclaration) && parentDeclaration.type && - !ts.isBindingPattern(name_12)) { - var text = getTextOfPropertyName(name_12); + !ts.isBindingPattern(name_15)) { + var text = getTextOfPropertyName(name_15); if (text) { return getTypeOfPropertyOfType(getTypeFromTypeNode(parentDeclaration.type), text); } @@ -25329,8 +31506,8 @@ var ts; var types = type.types; var mappedType; var mappedTypes; - for (var _i = 0, types_11 = types; _i < types_11.length; _i++) { - var current = types_11[_i]; + for (var _i = 0, types_12 = types; _i < types_12.length; _i++) { + var current = types_12[_i]; var t = mapper(current); if (t) { if (!mappedType) { @@ -25477,6 +31654,7 @@ var ts; case 187 /* BinaryExpression */: return getContextualTypeForBinaryOperand(node); case 253 /* PropertyAssignment */: + case 254 /* ShorthandPropertyAssignment */: return getContextualTypeForObjectLiteralElement(parent); case 170 /* ArrayLiteralExpression */: return getContextualTypeForElementExpression(node); @@ -25495,30 +31673,6 @@ var ts; } return undefined; } - function isLiteralTypeLocation(node) { - var parent = node.parent; - switch (parent.kind) { - case 187 /* BinaryExpression */: - switch (parent.operatorToken.kind) { - case 32 /* EqualsEqualsEqualsToken */: - case 33 /* ExclamationEqualsEqualsToken */: - case 30 /* EqualsEqualsToken */: - case 31 /* ExclamationEqualsToken */: - return true; - } - break; - case 188 /* ConditionalExpression */: - return (node === parent.whenTrue || - node === parent.whenFalse) && - isLiteralTypeLocation(parent); - case 178 /* ParenthesizedExpression */: - return isLiteralTypeLocation(parent); - case 249 /* CaseClause */: - case 166 /* LiteralType */: - return true; - } - return false; - } // If the given type is an object or union type, if that type has a single signature, and if // that signature is non-generic, return the signature. Otherwise return undefined. function getNonGenericSignature(type) { @@ -25560,8 +31714,8 @@ var ts; } var signatureList; var types = type.types; - for (var _i = 0, types_12 = types; _i < types_12.length; _i++) { - var current = types_12[_i]; + for (var _i = 0, types_13 = types; _i < types_13.length; _i++) { + var current = types_13[_i]; var signature = getNonGenericSignature(current); if (signature) { if (!signatureList) { @@ -25648,7 +31802,7 @@ var ts; } } else { - var type = checkExpression(e, contextualMapper); + var type = checkExpressionForMutableLocation(e, contextualMapper); elementTypes.push(type); } hasSpreadElement = hasSpreadElement || e.kind === 191 /* SpreadElementExpression */; @@ -25701,6 +31855,9 @@ var ts; function isTypeAnyOrAllConstituentTypesHaveKind(type, kind) { return isTypeAny(type) || isTypeOfKind(type, kind); } + function isInfinityOrNaNString(name) { + return name === "Infinity" || name === "-Infinity" || name === "NaN"; + } function isNumericLiteralName(name) { // The intent of numeric names is that // - they are names with text in a numeric form, and that @@ -25778,7 +31935,7 @@ var ts; } else { ts.Debug.assert(memberDecl.kind === 254 /* ShorthandPropertyAssignment */); - type = checkExpression(memberDecl.name, contextualMapper); + type = checkExpressionForMutableLocation(memberDecl.name, contextualMapper); } typeFlags |= type.flags; var prop = createSymbol(4 /* Property */ | 67108864 /* Transient */ | member.flags, member.name); @@ -25853,7 +32010,7 @@ var ts; var stringIndexInfo = hasComputedStringProperty ? getObjectLiteralIndexInfo(node, propertiesArray, 0 /* String */) : undefined; var numberIndexInfo = hasComputedNumberProperty ? getObjectLiteralIndexInfo(node, propertiesArray, 1 /* Number */) : undefined; var result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo); - var freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : 16777216 /* FreshObjectLiteral */; + var freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : 16777216 /* FreshLiteral */; result.flags |= 8388608 /* ObjectLiteral */ | 67108864 /* ContainsObjectLiteral */ | freshObjectLiteralFlag | (typeFlags & 234881024 /* PropagatingFlags */) | (patternWithComputedProperties ? 536870912 /* ObjectLiteralPatternWithComputedProperties */ : 0); if (inDestructuringPattern) { result.pattern = node; @@ -26286,8 +32443,11 @@ var ts; function getDeclarationKindFromSymbol(s) { return s.valueDeclaration ? s.valueDeclaration.kind : 145 /* PropertyDeclaration */; } - function getDeclarationFlagsFromSymbol(s) { - return s.valueDeclaration ? ts.getCombinedNodeFlags(s.valueDeclaration) : s.flags & 134217728 /* Prototype */ ? 4 /* Public */ | 32 /* Static */ : 0; + function getDeclarationModifierFlagsFromSymbol(s) { + return s.valueDeclaration ? ts.getCombinedModifierFlags(s.valueDeclaration) : s.flags & 134217728 /* Prototype */ ? 4 /* Public */ | 32 /* Static */ : 0; + } + function getDeclarationNodeFlagsFromSymbol(s) { + return s.valueDeclaration ? ts.getCombinedNodeFlags(s.valueDeclaration) : 0; } /** * Check whether the requested property access is valid. @@ -26298,7 +32458,7 @@ var ts; * @param prop The symbol for the right hand side of the property access. */ function checkClassPropertyAccess(node, left, type, prop) { - var flags = getDeclarationFlagsFromSymbol(prop); + var flags = getDeclarationModifierFlagsFromSymbol(prop); var declaringClass = getDeclaredTypeOfSymbol(getParentOfSymbol(prop)); var errorNode = node.kind === 172 /* PropertyAccessExpression */ || node.kind === 218 /* VariableDeclaration */ ? node.name : @@ -26327,7 +32487,7 @@ var ts; } } // Public properties are otherwise accessible. - if (!(flags & (8 /* Private */ | 16 /* Protected */))) { + if (!(flags & 24 /* NonPublicAccessibilityModifier */)) { return true; } // Property is known to be private or protected at this point @@ -26393,7 +32553,7 @@ var ts; } function checkPropertyAccessExpressionOrQualifiedName(node, left, right) { var type = checkNonNullExpression(left); - if (isTypeAny(type)) { + if (isTypeAny(type) || type === silentNeverType) { return type; } var apparentType = getApparentType(getWidenedType(type)); @@ -26404,13 +32564,13 @@ var ts; var prop = getPropertyOfType(apparentType, right.text); if (!prop) { if (right.text && !checkAndReportErrorForExtendingInterface(node)) { - error(right, ts.Diagnostics.Property_0_does_not_exist_on_type_1, ts.declarationNameToString(right), typeToString(type.flags & 268435456 /* ThisType */ ? apparentType : type)); + reportNonexistentProperty(right, type.flags & 268435456 /* ThisType */ ? apparentType : type); } return unknownType; } if (noUnusedIdentifiers && (prop.flags & 106500 /* ClassMember */) && - prop.valueDeclaration && (prop.valueDeclaration.flags & 8 /* Private */)) { + prop.valueDeclaration && (ts.getModifierFlags(prop.valueDeclaration) & 8 /* Private */)) { if (prop.flags & 16777216 /* Instantiated */) { getSymbolLinks(prop).target.isReferenced = true; } @@ -26423,9 +32583,6 @@ var ts; checkClassPropertyAccess(node, left, apparentType, prop); } var propType = getTypeOfSymbol(prop); - if (prop.flags & 8 /* EnumMember */ && isLiteralContextForType(node, propType)) { - propType = getDeclaredTypeOfSymbol(prop); - } // Only compute control flow type if this is a property access expression that isn't an // assignment target, and the referenced property was declared as a variable, property, // accessor, or optional method. @@ -26435,6 +32592,20 @@ var ts; return propType; } return getFlowTypeOfReference(node, propType, /*assumeInitialized*/ true, /*flowContainer*/ undefined); + function reportNonexistentProperty(propNode, containingType) { + var errorInfo; + if (containingType.flags & 524288 /* Union */ && !(containingType.flags & 8190 /* Primitive */)) { + for (var _i = 0, _a = containingType.types; _i < _a.length; _i++) { + var subtype = _a[_i]; + if (!getPropertyOfType(subtype, propNode.text)) { + errorInfo = ts.chainDiagnosticMessages(errorInfo, ts.Diagnostics.Property_0_does_not_exist_on_type_1, ts.declarationNameToString(propNode), typeToString(subtype)); + break; + } + } + } + errorInfo = ts.chainDiagnosticMessages(errorInfo, ts.Diagnostics.Property_0_does_not_exist_on_type_1, ts.declarationNameToString(propNode), typeToString(containingType)); + diagnostics.add(ts.createDiagnosticForNodeFromMessageChain(propNode, errorInfo)); + } } function isValidPropertyAccess(node, propertyName) { var left = node.kind === 172 /* PropertyAccessExpression */ @@ -26514,8 +32685,8 @@ var ts; // Obtain base constraint such that we can bail out if the constraint is an unknown type var objectType = getApparentType(checkNonNullExpression(node.expression)); var indexType = node.argumentExpression ? checkExpression(node.argumentExpression) : unknownType; - if (objectType === unknownType) { - return unknownType; + if (objectType === unknownType || objectType === silentNeverType) { + return objectType; } var isConstEnum = isConstEnumObjectType(objectType); if (isConstEnum && @@ -26533,15 +32704,15 @@ var ts; // - Otherwise, if IndexExpr is of type Any, the String or Number primitive type, or an enum type, the property access is of type Any. // See if we can index as a property. if (node.argumentExpression) { - var name_13 = getPropertyNameForIndexedAccess(node.argumentExpression, indexType); - if (name_13 !== undefined) { - var prop = getPropertyOfType(objectType, name_13); + var name_16 = getPropertyNameForIndexedAccess(node.argumentExpression, indexType); + if (name_16 !== undefined) { + var prop = getPropertyOfType(objectType, name_16); if (prop) { getNodeLinks(node).resolvedSymbol = prop; return getTypeOfSymbol(prop); } else if (isConstEnum) { - error(node.argumentExpression, ts.Diagnostics.Property_0_does_not_exist_on_const_enum_1, name_13, symbolToString(objectType.symbol)); + error(node.argumentExpression, ts.Diagnostics.Property_0_does_not_exist_on_const_enum_1, name_16, symbolToString(objectType.symbol)); return unknownType; } } @@ -26674,13 +32845,13 @@ var ts; for (var _i = 0, signatures_2 = signatures; _i < signatures_2.length; _i++) { var signature = signatures_2[_i]; var symbol = signature.declaration && getSymbolOfNode(signature.declaration); - var parent_9 = signature.declaration && signature.declaration.parent; + var parent_11 = signature.declaration && signature.declaration.parent; if (!lastSymbol || symbol === lastSymbol) { - if (lastParent && parent_9 === lastParent) { + if (lastParent && parent_11 === lastParent) { index++; } else { - lastParent = parent_9; + lastParent = parent_11; index = cutoffIndex; } } @@ -26688,7 +32859,7 @@ var ts; // current declaration belongs to a different symbol // set cutoffIndex so re-orderings in the future won't change result set from 0 to cutoffIndex index = cutoffIndex = result.length; - lastParent = parent_9; + lastParent = parent_11; } lastSymbol = symbol; // specialized signatures always need to be placed before non-specialized signatures regardless @@ -26797,7 +32968,7 @@ var ts; } // Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec) function instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper) { - var context = createInferenceContext(signature.typeParameters, /*inferUnionTypes*/ true); + var context = createInferenceContext(signature, /*inferUnionTypes*/ true); forEachMatchingParameterType(contextualSignature, signature, function (source, target) { // Type parameters from outer context referenced by source type are fixed by instantiation of the source type inferTypes(context, instantiateType(source, contextualMapper), target); @@ -27327,7 +33498,7 @@ var ts; else if (candidateForTypeArgumentError) { if (!isTaggedTemplate && !isDecorator && typeArguments) { var typeArguments_2 = node.typeArguments; - checkTypeArguments(candidateForTypeArgumentError, typeArguments_2, ts.map(typeArguments_2, getTypeFromTypeNode), /*reportErrors*/ true, headMessage); + checkTypeArguments(candidateForTypeArgumentError, typeArguments_2, ts.map(typeArguments_2, getTypeFromTypeNodeNoAlias), /*reportErrors*/ true, headMessage); } else { ts.Debug.assert(resultOfFailedInference.failedTypeParameterIndex >= 0); @@ -27354,7 +33525,7 @@ var ts; var candidate = candidates_1[_i]; if (hasCorrectArity(node, args, candidate)) { if (candidate.typeParameters && typeArguments) { - candidate = getSignatureInstantiation(candidate, ts.map(typeArguments, getTypeFromTypeNode)); + candidate = getSignatureInstantiation(candidate, ts.map(typeArguments, getTypeFromTypeNodeNoAlias)); } return candidate; } @@ -27379,14 +33550,14 @@ var ts; var candidate = void 0; var typeArgumentsAreValid = void 0; var inferenceContext = originalCandidate.typeParameters - ? createInferenceContext(originalCandidate.typeParameters, /*inferUnionTypes*/ false) + ? createInferenceContext(originalCandidate, /*inferUnionTypes*/ false) : undefined; while (true) { candidate = originalCandidate; if (candidate.typeParameters) { var typeArgumentTypes = void 0; if (typeArguments) { - typeArgumentTypes = ts.map(typeArguments, getTypeFromTypeNode); + typeArgumentTypes = ts.map(typeArguments, getTypeFromTypeNodeNoAlias); typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false); } else { @@ -27448,6 +33619,9 @@ var ts; return resolveUntypedCall(node); } var funcType = checkNonNullExpression(node.expression); + if (funcType === silentNeverType) { + return silentNeverSignature; + } var apparentType = getApparentType(funcType); if (apparentType === unknownType) { // Another error has already been reported @@ -27478,7 +33652,7 @@ var ts; error(node, ts.Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType)); } else { - error(node, ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature); + error(node, ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType)); } return resolveErrorCall(node); } @@ -27514,6 +33688,9 @@ var ts; } } var expressionType = checkNonNullExpression(node.expression); + if (expressionType === silentNeverType) { + return silentNeverSignature; + } // If expressionType's apparent type(section 3.8.1) is an object type with one or // more construct signatures, the expression is processed in the same manner as a // function call, but using the construct signatures as the initial set of candidate @@ -27529,7 +33706,7 @@ var ts; // In the case of a merged class-module or class-interface declaration, // only the class declaration node will have the Abstract flag set. var valueDecl = expressionType.symbol && getClassLikeDeclarationOfSymbol(expressionType.symbol); - if (valueDecl && valueDecl.flags & 128 /* Abstract */) { + if (valueDecl && ts.getModifierFlags(valueDecl) & 128 /* Abstract */) { error(node, ts.Diagnostics.Cannot_create_an_instance_of_the_abstract_class_0, ts.declarationNameToString(valueDecl.name)); return resolveErrorCall(node); } @@ -27576,9 +33753,9 @@ var ts; return true; } var declaration = signature.declaration; - var flags = declaration.flags; + var modifiers = ts.getModifierFlags(declaration); // Public constructor is accessible. - if (!(flags & (8 /* Private */ | 16 /* Protected */))) { + if (!(modifiers & 24 /* NonPublicAccessibilityModifier */)) { return true; } var declaringClassDeclaration = getClassLikeDeclarationOfSymbol(declaration.parent.symbol); @@ -27591,16 +33768,16 @@ var ts; var baseTypes = getBaseTypes(containingType); if (baseTypes.length) { var baseType = baseTypes[0]; - if (flags & 16 /* Protected */ && + if (modifiers & 16 /* Protected */ && baseType.symbol === declaration.parent.symbol) { return true; } } } - if (flags & 8 /* Private */) { + if (modifiers & 8 /* Private */) { error(node, ts.Diagnostics.Constructor_of_class_0_is_private_and_only_accessible_within_the_class_declaration, typeToString(declaringClass)); } - if (flags & 16 /* Protected */) { + if (modifiers & 16 /* Protected */) { error(node, ts.Diagnostics.Constructor_of_class_0_is_protected_and_only_accessible_within_the_class_declaration, typeToString(declaringClass)); } return false; @@ -27620,7 +33797,7 @@ var ts; return resolveUntypedCall(node); } if (!callSignatures.length) { - error(node, ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature); + error(node, ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType)); return resolveErrorCall(node); } return resolveCall(node, callSignatures, candidatesOutArray); @@ -27660,7 +33837,7 @@ var ts; var headMessage = getDiagnosticHeadMessageForDecoratorResolution(node); if (!callSignatures.length) { var errorInfo = void 0; - errorInfo = ts.chainDiagnosticMessages(errorInfo, ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature); + errorInfo = ts.chainDiagnosticMessages(errorInfo, ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType)); errorInfo = ts.chainDiagnosticMessages(errorInfo, headMessage); diagnostics.add(ts.createDiagnosticForNodeFromMessageChain(node, errorInfo)); return resolveErrorCall(node); @@ -27758,7 +33935,7 @@ var ts; return getReturnTypeOfSignature(getResolvedSignature(node)); } function checkAssertion(node) { - var exprType = getRegularTypeOfObjectLiteral(checkExpression(node.expression)); + var exprType = getRegularTypeOfObjectLiteral(getBaseTypeOfLiteralType(checkExpression(node.expression))); checkSourceElement(node.type); var targetType = getTypeFromTypeNode(node.type); if (produceDiagnostics && targetType !== unknownType) { @@ -27812,7 +33989,7 @@ var ts; if (ts.isBindingPattern(node.name)) { for (var _i = 0, _a = node.name.elements; _i < _a.length; _i++) { var element = _a[_i]; - if (element.kind !== 193 /* OmittedExpression */) { + if (!ts.isOmittedExpression(element)) { if (element.name.kind === 69 /* Identifier */) { getSymbolLinks(getSymbolOfNode(element)).type = getTypeForBindingElement(element); } @@ -27932,20 +34109,8 @@ var ts; return isAsync ? createPromiseReturnType(func, voidType) : voidType; } } - // When yield/return statements are contextually typed we allow the return type to be a union type. - // Otherwise we require the yield/return expressions to have a best common supertype. - type = contextualSignature ? getUnionType(types, /*subtypeReduction*/ true) : getCommonSupertype(types); - if (!type) { - if (funcIsGenerator) { - error(func, ts.Diagnostics.No_best_common_type_exists_among_yield_expressions); - return createIterableIteratorType(unknownType); - } - else { - error(func, ts.Diagnostics.No_best_common_type_exists_among_return_expressions); - // Defer to unioning the return types so we get a) downstream errors earlier and b) better Salsa experience - return isAsync ? createPromiseReturnType(func, getUnionType(types, /*subtypeReduction*/ true)) : getUnionType(types, /*subtypeReduction*/ true); - } - } + // Return a union of the return expression types. + type = getUnionType(types, /*subtypeReduction*/ true); if (funcIsGenerator) { type = createIterableIteratorType(type); } @@ -27953,6 +34118,9 @@ var ts; if (!contextualSignature) { reportErrorsFromWidening(func, type); } + if (isUnitType(type) && !(contextualSignature && isLiteralContextualType(getReturnTypeOfSignature(contextualSignature)))) { + type = getWidenedLiteralType(type); + } var widenedType = getWidenedType(type); // From within an async function you can return either a non-promise value or a promise. Any // Promise/A+ compatible implementation will always assimilate any foreign promise, so the @@ -27981,7 +34149,7 @@ var ts; return false; } var type = checkExpression(node.expression); - if (!isUnitUnionType(type)) { + if (!isLiteralType(type)) { return false; } var switchTypes = getSwitchClauseTypes(node); @@ -27991,7 +34159,7 @@ var ts; return eachTypeContainedIn(type, switchTypes); } function functionHasImplicitReturn(func) { - if (!(func.flags & 32768 /* HasImplicitReturn */)) { + if (!(func.flags & 128 /* HasImplicitReturn */)) { return false; } var lastStatement = ts.lastOrUndefined(func.body.statements); @@ -28016,7 +34184,7 @@ var ts; // the native Promise type by the caller. type = checkAwaitedType(type, func, ts.Diagnostics.Return_expression_in_async_function_does_not_have_a_valid_callable_then_member); } - if (type === neverType) { + if (type.flags & 8192 /* Never */) { hasReturnOfTypeNever = true; } else if (!ts.contains(aggregatedTypes, type)) { @@ -28060,8 +34228,8 @@ var ts; if (ts.nodeIsMissing(func.body) || func.body.kind !== 199 /* Block */ || !functionHasImplicitReturn(func)) { return; } - var hasExplicitReturn = func.flags & 65536 /* HasExplicitReturn */; - if (returnType === neverType) { + var hasExplicitReturn = func.flags & 256 /* HasExplicitReturn */; + if (returnType && returnType.flags & 8192 /* Never */) { error(func.type, ts.Diagnostics.A_function_returning_never_cannot_have_a_reachable_end_point); } else if (returnType && !hasExplicitReturn) { @@ -28195,8 +34363,8 @@ var ts; // Enum members // Unions and intersections of the above (unions and intersections eagerly set isReadonly on creation) return symbol.isReadonly || - symbol.flags & 4 /* Property */ && (getDeclarationFlagsFromSymbol(symbol) & 64 /* Readonly */) !== 0 || - symbol.flags & 3 /* Variable */ && (getDeclarationFlagsFromSymbol(symbol) & 2048 /* Const */) !== 0 || + symbol.flags & 4 /* Property */ && (getDeclarationModifierFlagsFromSymbol(symbol) & 64 /* Readonly */) !== 0 || + symbol.flags & 3 /* Variable */ && (getDeclarationNodeFlagsFromSymbol(symbol) & 2 /* Const */) !== 0 || symbol.flags & 98304 /* Accessor */ && !(symbol.flags & 65536 /* SetAccessor */) || (symbol.flags & 8 /* EnumMember */) !== 0; } @@ -28281,7 +34449,7 @@ var ts; function checkAwaitExpression(node) { // Grammar checking if (produceDiagnostics) { - if (!(node.flags & 33554432 /* AwaitContext */)) { + if (!(node.flags & 262144 /* AwaitContext */)) { grammarErrorOnFirstToken(node, ts.Diagnostics.await_expression_is_only_allowed_within_an_async_function); } if (isInParameterInitializerBeforeContainingFunction(node)) { @@ -28293,8 +34461,11 @@ var ts; } function checkPrefixUnaryExpression(node) { var operandType = checkExpression(node.operand); - if (node.operator === 36 /* MinusToken */ && node.operand.kind === 8 /* NumericLiteral */ && isLiteralContextForType(node, numberType)) { - return getLiteralTypeForText(64 /* NumberLiteral */, "" + -node.operand.text); + if (operandType === silentNeverType) { + return silentNeverType; + } + if (node.operator === 36 /* MinusToken */ && node.operand.kind === 8 /* NumericLiteral */) { + return getFreshTypeOfLiteralType(getLiteralTypeForText(64 /* NumberLiteral */, "" + -node.operand.text)); } switch (node.operator) { case 35 /* PlusToken */: @@ -28322,6 +34493,9 @@ var ts; } function checkPostfixUnaryExpression(node) { var operandType = checkExpression(node.operand); + if (operandType === silentNeverType) { + return silentNeverType; + } var ok = checkArithmeticOperandType(node.operand, getNonNullableType(operandType), ts.Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type); if (ok) { // run check only if former checks succeeded to avoid reporting cascading errors @@ -28337,8 +34511,8 @@ var ts; } if (type.flags & 1572864 /* UnionOrIntersection */) { var types = type.types; - for (var _i = 0, types_13 = types; _i < types_13.length; _i++) { - var t = types_13[_i]; + for (var _i = 0, types_14 = types; _i < types_14.length; _i++) { + var t = types_14[_i]; if (maybeTypeOfKind(t, kind)) { return true; } @@ -28355,8 +34529,8 @@ var ts; } if (type.flags & 524288 /* Union */) { var types = type.types; - for (var _i = 0, types_14 = types; _i < types_14.length; _i++) { - var t = types_14[_i]; + for (var _i = 0, types_15 = types; _i < types_15.length; _i++) { + var t = types_15[_i]; if (!isTypeOfKind(t, kind)) { return false; } @@ -28365,8 +34539,8 @@ var ts; } if (type.flags & 1048576 /* Intersection */) { var types = type.types; - for (var _a = 0, types_15 = types; _a < types_15.length; _a++) { - var t = types_15[_a]; + for (var _a = 0, types_16 = types; _a < types_16.length; _a++) { + var t = types_16[_a]; if (isTypeOfKind(t, kind)) { return true; } @@ -28381,6 +34555,9 @@ var ts; return (symbol.flags & 128 /* ConstEnum */) !== 0; } function checkInstanceOfExpression(left, right, leftType, rightType) { + if (leftType === silentNeverType || rightType === silentNeverType) { + return silentNeverType; + } // TypeScript 1.0 spec (April 2014): 4.15.4 // The instanceof operator requires the left operand to be of type Any, an object type, or a type parameter type, // and the right operand to be of type Any or a subtype of the 'Function' interface type. @@ -28396,6 +34573,9 @@ var ts; return booleanType; } function checkInExpression(left, right, leftType, rightType) { + if (leftType === silentNeverType || rightType === silentNeverType) { + return silentNeverType; + } // TypeScript 1.0 spec (April 2014): 4.15.5 // The in operator requires the left operand to be of type Any, the String primitive type, or the Number primitive type, // and the right operand to be of type Any, an object type, or a type parameter type. @@ -28410,22 +34590,22 @@ var ts; } function checkObjectLiteralAssignment(node, sourceType, contextualMapper) { var properties = node.properties; - for (var _i = 0, properties_3 = properties; _i < properties_3.length; _i++) { - var p = properties_3[_i]; + for (var _i = 0, properties_4 = properties; _i < properties_4.length; _i++) { + var p = properties_4[_i]; checkObjectLiteralDestructuringPropertyAssignment(sourceType, p, contextualMapper); } return sourceType; } function checkObjectLiteralDestructuringPropertyAssignment(objectLiteralType, property, contextualMapper) { if (property.kind === 253 /* PropertyAssignment */ || property.kind === 254 /* ShorthandPropertyAssignment */) { - var name_14 = property.name; - if (name_14.kind === 140 /* ComputedPropertyName */) { - checkComputedPropertyName(name_14); + var name_17 = property.name; + if (name_17.kind === 140 /* ComputedPropertyName */) { + checkComputedPropertyName(name_17); } - if (isComputedNonLiteralName(name_14)) { + if (isComputedNonLiteralName(name_17)) { return undefined; } - var text = getTextOfPropertyName(name_14); + var text = getTextOfPropertyName(name_17); var type = isTypeAny(objectLiteralType) ? objectLiteralType : getTypeOfPropertyOfType(objectLiteralType, text) || @@ -28441,7 +34621,7 @@ var ts; } } else { - error(name_14, ts.Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(objectLiteralType), ts.declarationNameToString(name_14)); + error(name_17, ts.Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(objectLiteralType), ts.declarationNameToString(name_17)); } } else { @@ -28539,6 +34719,67 @@ var ts; } return sourceType; } + /** + * This is a *shallow* check: An expression is side-effect-free if the + * evaluation of the expression *itself* cannot produce side effects. + * For example, x++ / 3 is side-effect free because the / operator + * does not have side effects. + * The intent is to "smell test" an expression for correctness in positions where + * its value is discarded (e.g. the left side of the comma operator). + */ + function isSideEffectFree(node) { + node = ts.skipParentheses(node); + switch (node.kind) { + case 69 /* Identifier */: + case 9 /* StringLiteral */: + case 10 /* RegularExpressionLiteral */: + case 176 /* TaggedTemplateExpression */: + case 189 /* TemplateExpression */: + case 11 /* NoSubstitutionTemplateLiteral */: + case 8 /* NumericLiteral */: + case 99 /* TrueKeyword */: + case 84 /* FalseKeyword */: + case 93 /* NullKeyword */: + case 135 /* UndefinedKeyword */: + case 179 /* FunctionExpression */: + case 192 /* ClassExpression */: + case 180 /* ArrowFunction */: + case 170 /* ArrayLiteralExpression */: + case 171 /* ObjectLiteralExpression */: + case 182 /* TypeOfExpression */: + case 196 /* NonNullExpression */: + case 242 /* JsxSelfClosingElement */: + case 241 /* JsxElement */: + return true; + case 188 /* ConditionalExpression */: + return isSideEffectFree(node.whenTrue) && + isSideEffectFree(node.whenFalse); + case 187 /* BinaryExpression */: + if (ts.isAssignmentOperator(node.operatorToken.kind)) { + return false; + } + return isSideEffectFree(node.left) && + isSideEffectFree(node.right); + case 185 /* PrefixUnaryExpression */: + case 186 /* PostfixUnaryExpression */: + // Unary operators ~, !, +, and - have no side effects. + // The rest do. + switch (node.operator) { + case 49 /* ExclamationToken */: + case 35 /* PlusToken */: + case 36 /* MinusToken */: + case 50 /* TildeToken */: + return true; + } + return false; + // Some forms listed here for clarity + case 183 /* VoidExpression */: // Explicit opt-out + case 177 /* TypeAssertionExpression */: // Not SEF, but can produce useful type warnings + case 195 /* AsExpression */: // Not SEF, but can produce useful type warnings + default: + return false; + } + } function isTypeEqualityComparableTo(source, target) { return (target.flags & 6144 /* Nullable */) !== 0 || isTypeComparableTo(source, target); } @@ -28582,6 +34823,9 @@ var ts; case 68 /* CaretEqualsToken */: case 46 /* AmpersandToken */: case 66 /* AmpersandEqualsToken */: + if (leftType === silentNeverType || rightType === silentNeverType) { + return silentNeverType; + } // TypeScript 1.0 spec (April 2014): 4.19.1 // These operators require their operands to be of type Any, the Number primitive type, // or an enum type. Operands of an enum type are treated @@ -28613,6 +34857,9 @@ var ts; return numberType; case 35 /* PlusToken */: case 57 /* PlusEqualsToken */: + if (leftType === silentNeverType || rightType === silentNeverType) { + return silentNeverType; + } // TypeScript 1.0 spec (April 2014): 4.19.2 // The binary + operator requires both operands to be of the Number primitive type or an enum type, // or at least one of the operands to be of type Any or the String primitive type. @@ -28666,11 +34913,11 @@ var ts; case 31 /* ExclamationEqualsToken */: case 32 /* EqualsEqualsEqualsToken */: case 33 /* ExclamationEqualsEqualsToken */: - var leftIsUnit = isUnitUnionType(leftType); - var rightIsUnit = isUnitUnionType(rightType); - if (!leftIsUnit || !rightIsUnit) { - leftType = leftIsUnit ? getBaseTypeOfUnitType(leftType) : leftType; - rightType = rightIsUnit ? getBaseTypeOfUnitType(rightType) : rightType; + var leftIsLiteral = isLiteralType(leftType); + var rightIsLiteral = isLiteralType(rightType); + if (!leftIsLiteral || !rightIsLiteral) { + leftType = leftIsLiteral ? getBaseTypeOfLiteralType(leftType) : leftType; + rightType = rightIsLiteral ? getBaseTypeOfLiteralType(rightType) : rightType; } if (!isTypeEqualityComparableTo(leftType, rightType) && !isTypeEqualityComparableTo(rightType, leftType)) { reportOperatorError(); @@ -28682,7 +34929,7 @@ var ts; return checkInExpression(left, right, leftType, rightType); case 51 /* AmpersandAmpersandToken */: return getTypeFacts(leftType) & 1048576 /* Truthy */ ? - includeFalsyTypes(rightType, getFalsyFlags(strictNullChecks ? leftType : getBaseTypeOfUnitType(rightType))) : + includeFalsyTypes(rightType, getFalsyFlags(strictNullChecks ? leftType : getBaseTypeOfLiteralType(rightType))) : leftType; case 52 /* BarBarToken */: return getTypeFacts(leftType) & 2097152 /* Falsy */ ? @@ -28692,6 +34939,9 @@ var ts; checkAssignmentOperator(rightType); return getRegularTypeOfObjectLiteral(rightType); case 24 /* CommaToken */: + if (!compilerOptions.allowUnreachableCode && isSideEffectFree(left)) { + error(left, ts.Diagnostics.Left_side_of_comma_operator_is_unused_and_has_no_side_effects); + } return rightType; } // Return true if there was no error, false if there was an error. @@ -28758,7 +35008,7 @@ var ts; function checkYieldExpression(node) { // Grammar checking if (produceDiagnostics) { - if (!(node.flags & 8388608 /* YieldContext */) || isYieldExpressionInClass(node)) { + if (!(node.flags & 65536 /* YieldContext */) || isYieldExpressionInClass(node)) { grammarErrorOnFirstToken(node, ts.Diagnostics.A_yield_expression_is_only_allowed_in_a_generator_body); } if (isInParameterInitializerBeforeContainingFunction(node)) { @@ -28799,63 +35049,19 @@ var ts; var type2 = checkExpression(node.whenFalse, contextualMapper); return getBestChoiceType(type1, type2); } - function typeContainsLiteralFromEnum(type, enumType) { - if (type.flags & 524288 /* Union */) { - for (var _i = 0, _a = type.types; _i < _a.length; _i++) { - var t = _a[_i]; - if (t.flags & 256 /* EnumLiteral */ && t.baseType === enumType) { - return true; - } - } - } - if (type.flags & 256 /* EnumLiteral */) { - return type.baseType === enumType; - } - return false; - } - function isLiteralContextForType(node, type) { - if (isLiteralTypeLocation(node)) { - return true; - } - var contextualType = getContextualType(node); - if (contextualType) { - if (contextualType.flags & 16384 /* TypeParameter */) { - var apparentType = getApparentTypeOfTypeParameter(contextualType); - // If the type parameter is constrained to the base primitive type we're checking for, - // consider this a literal context. For example, given a type parameter 'T extends string', - // this causes us to infer string literal types for T. - if (type === apparentType) { - return true; - } - contextualType = apparentType; - } - if (type.flags & 2 /* String */) { - return maybeTypeOfKind(contextualType, 32 /* StringLiteral */); - } - if (type.flags & 4 /* Number */) { - return maybeTypeOfKind(contextualType, (64 /* NumberLiteral */ | 256 /* EnumLiteral */)); - } - if (type.flags & 8 /* Boolean */) { - return maybeTypeOfKind(contextualType, 128 /* BooleanLiteral */) && !isTypeAssignableTo(booleanType, contextualType); - } - if (type.flags & 16 /* Enum */) { - return typeContainsLiteralFromEnum(contextualType, type); - } - } - return false; - } function checkLiteralExpression(node) { if (node.kind === 8 /* NumericLiteral */) { checkGrammarNumericLiteral(node); } switch (node.kind) { case 9 /* StringLiteral */: - return isLiteralContextForType(node, stringType) ? getLiteralTypeForText(32 /* StringLiteral */, node.text) : stringType; + return getFreshTypeOfLiteralType(getLiteralTypeForText(32 /* StringLiteral */, node.text)); case 8 /* NumericLiteral */: - return isLiteralContextForType(node, numberType) ? getLiteralTypeForText(64 /* NumberLiteral */, node.text) : numberType; + return getFreshTypeOfLiteralType(getLiteralTypeForText(64 /* NumberLiteral */, node.text)); case 99 /* TrueKeyword */: + return trueType; case 84 /* FalseKeyword */: - return isLiteralContextForType(node, booleanType) ? node.kind === 99 /* TrueKeyword */ ? trueType : falseType : booleanType; + return falseType; } } function checkTemplateExpression(node) { @@ -28889,6 +35095,36 @@ var ts; } return links.resolvedType; } + function isTypeAssertion(node) { + node = skipParenthesizedNodes(node); + return node.kind === 177 /* TypeAssertionExpression */ || node.kind === 195 /* AsExpression */; + } + function checkDeclarationInitializer(declaration) { + var type = checkExpressionCached(declaration.initializer); + return ts.getCombinedNodeFlags(declaration) & 2 /* Const */ || + ts.getCombinedModifierFlags(declaration) & 64 /* Readonly */ || + isTypeAssertion(declaration.initializer) ? type : getWidenedLiteralType(type); + } + function isLiteralContextualType(contextualType) { + if (contextualType) { + if (contextualType.flags & 16384 /* TypeParameter */) { + var apparentType = getApparentTypeOfTypeParameter(contextualType); + // If the type parameter is constrained to the base primitive type we're checking for, + // consider this a literal context. For example, given a type parameter 'T extends string', + // this causes us to infer string literal types for T. + if (apparentType.flags & (2 /* String */ | 4 /* Number */ | 8 /* Boolean */ | 16 /* Enum */)) { + return true; + } + contextualType = apparentType; + } + return maybeTypeOfKind(contextualType, 480 /* Literal */); + } + return false; + } + function checkExpressionForMutableLocation(node, contextualMapper) { + var type = checkExpression(node, contextualMapper); + return isTypeAssertion(node) || isLiteralContextualType(getContextualType(node)) ? type : getWidenedLiteralType(type); + } function checkPropertyAssignment(node, contextualMapper) { // Do not use hasDynamicName here, because that returns false for well known symbols. // We want to perform checkComputedPropertyName for all computed properties, including @@ -28896,7 +35132,7 @@ var ts; if (node.name.kind === 140 /* ComputedPropertyName */) { checkComputedPropertyName(node.name); } - return checkExpression(node.initializer, contextualMapper); + return checkExpressionForMutableLocation(node.initializer, contextualMapper); } function checkObjectLiteralMethod(node, contextualMapper) { // Grammar checking @@ -29055,7 +35291,7 @@ var ts; checkGrammarDecorators(node) || checkGrammarModifiers(node); checkVariableLikeDeclaration(node); var func = ts.getContainingFunction(node); - if (node.flags & 92 /* ParameterPropertyModifier */) { + if (ts.getModifierFlags(node) & 92 /* ParameterPropertyModifier */) { func = ts.getContainingFunction(node); if (!(func.kind === 148 /* Constructor */ && ts.nodeIsPresent(func.body))) { error(node, ts.Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation); @@ -29127,9 +35363,9 @@ var ts; else if (parameterName) { var hasReportedError = false; for (var _i = 0, _a = parent.parameters; _i < _a.length; _i++) { - var name_15 = _a[_i].name; - if (ts.isBindingPattern(name_15) && - checkIfTypePredicateVariableIsDeclaredInBindingPattern(name_15, parameterName, typePredicate.parameterName)) { + var name_18 = _a[_i].name; + if (ts.isBindingPattern(name_18) && + checkIfTypePredicateVariableIsDeclaredInBindingPattern(name_18, parameterName, typePredicate.parameterName)) { hasReportedError = true; break; } @@ -29149,23 +35385,27 @@ var ts; case 156 /* FunctionType */: case 147 /* MethodDeclaration */: case 146 /* MethodSignature */: - var parent_10 = node.parent; - if (node === parent_10.type) { - return parent_10; + var parent_12 = node.parent; + if (node === parent_12.type) { + return parent_12; } } } function checkIfTypePredicateVariableIsDeclaredInBindingPattern(pattern, predicateVariableNode, predicateVariableName) { for (var _i = 0, _a = pattern.elements; _i < _a.length; _i++) { - var name_16 = _a[_i].name; - if (name_16.kind === 69 /* Identifier */ && - name_16.text === predicateVariableName) { + var element = _a[_i]; + if (ts.isOmittedExpression(element)) { + continue; + } + var name_19 = element.name; + if (name_19.kind === 69 /* Identifier */ && + name_19.text === predicateVariableName) { error(predicateVariableNode, ts.Diagnostics.A_type_predicate_cannot_reference_element_0_in_a_binding_pattern, predicateVariableName); return true; } - else if (name_16.kind === 168 /* ArrayBindingPattern */ || - name_16.kind === 167 /* ObjectBindingPattern */) { - if (checkIfTypePredicateVariableIsDeclaredInBindingPattern(name_16, predicateVariableNode, predicateVariableName)) { + else if (name_19.kind === 168 /* ArrayBindingPattern */ || + name_19.kind === 167 /* ObjectBindingPattern */) { + if (checkIfTypePredicateVariableIsDeclaredInBindingPattern(name_19, predicateVariableNode, predicateVariableName)) { return true; } } @@ -29357,7 +35597,7 @@ var ts; checkFunctionOrMethodDeclaration(node); // Abstract methods cannot have an implementation. // Extra checks are to avoid reporting multiple errors relating to the "abstractness" of the node. - if (node.flags & 128 /* Abstract */ && node.body) { + if (ts.getModifierFlags(node) & 128 /* Abstract */ && node.body) { error(node, ts.Diagnostics.Method_0_cannot_have_an_implementation_because_it_is_marked_abstract, ts.declarationNameToString(node.name)); } } @@ -29406,7 +35646,7 @@ var ts; } function isInstancePropertyWithInitializer(n) { return n.kind === 145 /* PropertyDeclaration */ && - !(n.flags & 32 /* Static */) && + !(ts.getModifierFlags(n) & 32 /* Static */) && !!n.initializer; } // TS 1.0 spec (April 2014): 8.3.2 @@ -29414,6 +35654,7 @@ var ts; // constructors of derived classes must contain at least one super call somewhere in their function body. var containingClassDecl = node.parent; if (ts.getClassExtendsHeritageClauseElement(containingClassDecl)) { + captureLexicalThis(node.parent, containingClassDecl); var classExtendsNull = classDeclarationExtendsNull(containingClassDecl); var superCall = getSuperCallInConstructor(node); if (superCall) { @@ -29426,7 +35667,7 @@ var ts; // - The constructor declares parameter properties // or the containing class declares instance member variables with initializers. var superCallShouldBeFirst = ts.forEach(node.parent.members, isInstancePropertyWithInitializer) || - ts.forEach(node.parameters, function (p) { return p.flags & 92 /* ParameterPropertyModifier */; }); + ts.forEach(node.parameters, function (p) { return ts.getModifierFlags(p) & 92 /* ParameterPropertyModifier */; }); // Skip past any prologue directives to find the first statement // to ensure that it was a super call. if (superCallShouldBeFirst) { @@ -29459,8 +35700,8 @@ var ts; checkDecorators(node); checkSignatureDeclaration(node); if (node.kind === 149 /* GetAccessor */) { - if (!ts.isInAmbientContext(node) && ts.nodeIsPresent(node.body) && (node.flags & 32768 /* HasImplicitReturn */)) { - if (!(node.flags & 65536 /* HasExplicitReturn */)) { + if (!ts.isInAmbientContext(node) && ts.nodeIsPresent(node.body) && (node.flags & 128 /* HasImplicitReturn */)) { + if (!(node.flags & 256 /* HasExplicitReturn */)) { error(node.name, ts.Diagnostics.A_get_accessor_must_return_a_value); } } @@ -29477,10 +35718,10 @@ var ts; var otherKind = node.kind === 149 /* GetAccessor */ ? 150 /* SetAccessor */ : 149 /* GetAccessor */; var otherAccessor = ts.getDeclarationOfKind(node.symbol, otherKind); if (otherAccessor) { - if (((node.flags & 28 /* AccessibilityModifier */) !== (otherAccessor.flags & 28 /* AccessibilityModifier */))) { + if ((ts.getModifierFlags(node) & 28 /* AccessibilityModifier */) !== (ts.getModifierFlags(otherAccessor) & 28 /* AccessibilityModifier */)) { error(node.name, ts.Diagnostics.Getter_and_setter_accessors_do_not_agree_in_visibility); } - if (((node.flags & 128 /* Abstract */) !== (otherAccessor.flags & 128 /* Abstract */))) { + if (ts.hasModifier(node, 128 /* Abstract */) !== ts.hasModifier(otherAccessor, 128 /* Abstract */)) { error(node.name, ts.Diagnostics.Accessors_must_both_be_abstract_or_non_abstract); } // TypeScript 1.0 spec (April 2014): 4.5 @@ -29524,7 +35765,7 @@ var ts; var constraint = getConstraintOfTypeParameter(typeParameters[i]); if (constraint) { if (!typeArguments) { - typeArguments = ts.map(typeArgumentNodes, getTypeFromTypeNode); + typeArguments = ts.map(typeArgumentNodes, getTypeFromTypeNodeNoAlias); mapper = createTypeMapper(typeParameters, typeArguments); } var typeArgument = typeArguments[i]; @@ -29578,10 +35819,10 @@ var ts; ts.forEach(node.types, checkSourceElement); } function isPrivateWithinAmbient(node) { - return (node.flags & 8 /* Private */) && ts.isInAmbientContext(node); + return (ts.getModifierFlags(node) & 8 /* Private */) && ts.isInAmbientContext(node); } function getEffectiveDeclarationFlags(n, flagsToCheck) { - var flags = ts.getCombinedNodeFlags(n); + var flags = ts.getCombinedModifierFlags(n); // children of classes (even ambient classes) should not be marked as ambient or export // because those flags have no useful semantics there. if (n.parent.kind !== 222 /* InterfaceDeclaration */ && @@ -29644,7 +35885,7 @@ var ts; } } var flagsToCheck = 1 /* Export */ | 2 /* Ambient */ | 8 /* Private */ | 16 /* Protected */ | 128 /* Abstract */; - var someNodeFlags = 0; + var someNodeFlags = 0 /* None */; var allNodeFlags = flagsToCheck; var someHaveQuestionToken = false; var allHaveQuestionToken = true; @@ -29675,13 +35916,13 @@ var ts; // TODO(jfreeman): These are methods, so handle computed name case if (node.name && subsequentNode.name && node.name.text === subsequentNode.name.text) { var reportError = (node.kind === 147 /* MethodDeclaration */ || node.kind === 146 /* MethodSignature */) && - (node.flags & 32 /* Static */) !== (subsequentNode.flags & 32 /* Static */); + (ts.getModifierFlags(node) & 32 /* Static */) !== (ts.getModifierFlags(subsequentNode) & 32 /* Static */); // we can get here in two cases // 1. mixed static and instance class members // 2. something with the same name was defined before the set of overloads that prevents them from merging // here we'll report error only for the first case since for second we should already report error in binder if (reportError) { - var diagnostic = node.flags & 32 /* Static */ ? ts.Diagnostics.Function_overload_must_be_static : ts.Diagnostics.Function_overload_must_not_be_static; + var diagnostic = ts.getModifierFlags(node) & 32 /* Static */ ? ts.Diagnostics.Function_overload_must_be_static : ts.Diagnostics.Function_overload_must_not_be_static; error(errorNode_1, diagnostic); } return; @@ -29699,7 +35940,7 @@ var ts; else { // Report different errors regarding non-consecutive blocks of declarations depending on whether // the node in question is abstract. - if (node.flags & 128 /* Abstract */) { + if (ts.getModifierFlags(node) & 128 /* Abstract */) { error(errorNode, ts.Diagnostics.All_declarations_of_an_abstract_method_must_be_consecutive); } else { @@ -29767,7 +36008,7 @@ var ts; } // Abstract methods can't have an implementation -- in particular, they don't need one. if (lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body && - !(lastSeenNonAmbientDeclaration.flags & 128 /* Abstract */) && !lastSeenNonAmbientDeclaration.questionToken) { + !(ts.getModifierFlags(lastSeenNonAmbientDeclaration) & 128 /* Abstract */) && !lastSeenNonAmbientDeclaration.questionToken) { reportImplementationExpectedError(lastSeenNonAmbientDeclaration); } if (hasOverloads) { @@ -30025,7 +36266,7 @@ var ts; * @param returnType The return type of a FunctionLikeDeclaration * @param location The node on which to report the error. */ - function checkCorrectPromiseType(returnType, location) { + function checkCorrectPromiseType(returnType, location, diagnostic, typeName) { if (returnType === unknownType) { // The return type already had some other error, so we ignore and return // the unknown type. @@ -30042,7 +36283,7 @@ var ts; } // The promise type was not a valid type reference to the global promise type, so we // report an error and return the unknown type. - error(location, ts.Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type); + error(location, diagnostic, typeName); return unknownType; } /** @@ -30061,7 +36302,7 @@ var ts; function checkAsyncFunctionReturnType(node) { if (languageVersion >= 2 /* ES6 */) { var returnType = getTypeFromTypeNode(node.type); - return checkCorrectPromiseType(returnType, node.type); + return checkCorrectPromiseType(returnType, node.type, ts.Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type); } var globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType(); if (globalPromiseConstructorLikeType === emptyObjectType) { @@ -30103,17 +36344,17 @@ var ts; } var promiseConstructor = getNodeLinks(node.type).resolvedSymbol; if (!promiseConstructor || !symbolIsValue(promiseConstructor)) { + // try to fall back to global promise type. var typeName = promiseConstructor ? symbolToString(promiseConstructor) : typeToString(promiseType); - error(node, ts.Diagnostics.Type_0_is_not_a_valid_async_function_return_type, typeName); - return unknownType; + return checkCorrectPromiseType(promiseType, node.type, ts.Diagnostics.Type_0_is_not_a_valid_async_function_return_type, typeName); } // If the Promise constructor, resolved locally, is an alias symbol we should mark it as referenced. checkReturnTypeAnnotationAsExpression(node); // Validate the promise constructor type. var promiseConstructorType = getTypeOfSymbol(promiseConstructor); - if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node, ts.Diagnostics.Type_0_is_not_a_valid_async_function_return_type)) { + if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node.type, ts.Diagnostics.Type_0_is_not_a_valid_async_function_return_type)) { return unknownType; } // Verify there is no local declaration that could collide with the promise constructor. @@ -30357,7 +36598,7 @@ var ts; } function checkUnusedLocalsAndParameters(node) { if (node.parent.kind !== 222 /* InterfaceDeclaration */ && noUnusedIdentifiers && !ts.isInAmbientContext(node)) { - var _loop_1 = function(key) { + var _loop_1 = function (key) { var local = node.locals[key]; if (!local.isReferenced) { if (local.valueDeclaration && local.valueDeclaration.kind === 142 /* Parameter */) { @@ -30391,14 +36632,14 @@ var ts; for (var _i = 0, _a = node.members; _i < _a.length; _i++) { var member = _a[_i]; if (member.kind === 147 /* MethodDeclaration */ || member.kind === 145 /* PropertyDeclaration */) { - if (!member.symbol.isReferenced && member.flags & 8 /* Private */) { + if (!member.symbol.isReferenced && ts.getModifierFlags(member) & 8 /* Private */) { error(member.name, ts.Diagnostics._0_is_declared_but_never_used, member.symbol.name); } } else if (member.kind === 148 /* Constructor */) { for (var _b = 0, _c = member.parameters; _b < _c.length; _b++) { var parameter = _c[_b]; - if (!parameter.symbol.isReferenced && parameter.flags & 8 /* Private */) { + if (!parameter.symbol.isReferenced && ts.getModifierFlags(parameter) & 8 /* Private */) { error(parameter.name, ts.Diagnostics.Property_0_is_declared_but_never_used, parameter.symbol.name); } } @@ -30529,6 +36770,10 @@ var ts; } } function checkCollisionWithRequireExportsInGeneratedCode(node, name) { + // No need to check for require or exports for ES6 modules and later + if (modulekind >= ts.ModuleKind.ES6) { + return; + } if (!needCollisionCheckForIdentifier(node, name, "require") && !needCollisionCheckForIdentifier(node, name, "exports")) { return; } @@ -30553,7 +36798,7 @@ var ts; } // In case of variable declaration, node.parent is variable statement so look at the variable statement's parent var parent = getDeclarationContainer(node); - if (parent.kind === 256 /* SourceFile */ && ts.isExternalOrCommonJsModule(parent) && parent.flags & 2097152 /* HasAsyncFunctions */) { + if (parent.kind === 256 /* SourceFile */ && ts.isExternalOrCommonJsModule(parent) && parent.flags & 8192 /* HasAsyncFunctions */) { // If the declaration happens to be in external module, report error that Promise is a reserved identifier. error(name, ts.Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_a_module_containing_async_functions, ts.declarationNameToString(name), ts.declarationNameToString(name)); } @@ -30582,7 +36827,7 @@ var ts; // const x = 0; // symbol for this declaration will be 'symbol' // } // skip block-scoped variables and parameters - if ((ts.getCombinedNodeFlags(node) & 3072 /* BlockScoped */) !== 0 || ts.isParameterDeclaration(node)) { + if ((ts.getCombinedNodeFlags(node) & 3 /* BlockScoped */) !== 0 || ts.isParameterDeclaration(node)) { return; } // skip variable declarations that don't have initializers @@ -30597,7 +36842,7 @@ var ts; if (localDeclarationSymbol && localDeclarationSymbol !== symbol && localDeclarationSymbol.flags & 2 /* BlockScopedVariable */) { - if (getDeclarationFlagsFromSymbol(localDeclarationSymbol) & 3072 /* BlockScoped */) { + if (getDeclarationNodeFlagsFromSymbol(localDeclarationSymbol) & 3 /* BlockScoped */) { var varDeclList = ts.getAncestor(localDeclarationSymbol.valueDeclaration, 219 /* VariableDeclarationList */); var container = varDeclList.parent.kind === 200 /* VariableStatement */ && varDeclList.parent.parent ? varDeclList.parent.parent @@ -30614,8 +36859,8 @@ var ts; // otherwise if variable has an initializer - show error that initialization will fail // since LHS will be block scoped name instead of function scoped if (!namesShareScope) { - var name_17 = symbolToString(localDeclarationSymbol); - error(node, ts.Diagnostics.Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1, name_17, name_17); + var name_20 = symbolToString(localDeclarationSymbol); + error(node, ts.Diagnostics.Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1, name_20, name_20); } } } @@ -30668,7 +36913,7 @@ var ts; // computed property names/initializers in instance property declaration of class like entities // are executed in constructor and thus deferred if (current.parent.kind === 145 /* PropertyDeclaration */ && - !(current.parent.flags & 32 /* Static */) && + !(ts.hasModifier(current.parent, 32 /* Static */)) && ts.isClassLike(current.parent.parent)) { return; } @@ -30703,12 +36948,12 @@ var ts; checkComputedPropertyName(node.propertyName); } // check private/protected variable access - var parent_11 = node.parent.parent; - var parentType = getTypeForBindingElementParent(parent_11); - var name_18 = node.propertyName || node.name; - var property = getPropertyOfType(parentType, getTextOfPropertyName(name_18)); - if (parent_11.initializer && property && getParentOfSymbol(property)) { - checkClassPropertyAccess(parent_11, parent_11.initializer, parentType, property); + var parent_13 = node.parent.parent; + var parentType = getTypeForBindingElementParent(parent_13); + var name_21 = node.propertyName || node.name; + var property = getPropertyOfType(parentType, getTextOfPropertyName(name_21)); + if (parent_13.initializer && property && getParentOfSymbol(property)) { + checkClassPropertyAccess(parent_13, parent_13.initializer, parentType, property); } } // For a binding pattern, check contained binding elements @@ -30781,7 +37026,7 @@ var ts; 128 /* Abstract */ | 64 /* Readonly */ | 32 /* Static */; - return (left.flags & interestingFlags) === (right.flags & interestingFlags); + return (ts.getModifierFlags(left) & interestingFlags) === (ts.getModifierFlags(right) & interestingFlags); } function checkVariableDeclaration(node) { checkGrammarVariableDeclaration(node); @@ -31137,7 +37382,7 @@ var ts; } // Now that we've removed all the StringLike types, if no constituents remain, then the entire // arrayOrStringType was a string. - if (arrayType === neverType) { + if (arrayType.flags & 8192 /* Never */) { return stringType; } } @@ -31188,7 +37433,7 @@ var ts; if (func) { var signature = getSignatureFromDeclaration(func); var returnType = getReturnTypeOfSignature(signature); - if (strictNullChecks || node.expression || returnType === neverType) { + if (strictNullChecks || node.expression || returnType.flags & 8192 /* Never */) { var exprType = node.expression ? checkExpressionCached(node.expression) : undefinedType; if (func.asteriskToken) { // A generator does not need its return expressions checked against its return type. @@ -31232,12 +37477,17 @@ var ts; function checkWithStatement(node) { // Grammar checking for withStatement if (!checkGrammarStatementInAmbientContext(node)) { - if (node.flags & 33554432 /* AwaitContext */) { + if (node.flags & 262144 /* AwaitContext */) { grammarErrorOnFirstToken(node, ts.Diagnostics.with_statements_are_not_allowed_in_an_async_function_block); } } checkExpression(node.expression); - error(node.expression, ts.Diagnostics.All_symbols_within_a_with_block_will_be_resolved_to_any); + var sourceFile = ts.getSourceFileOfNode(node); + if (!hasParseDiagnostics(sourceFile)) { + var start = ts.getSpanOfTokenAtPosition(sourceFile, node.pos).start; + var end = node.statement.pos; + grammarErrorAtPos(sourceFile, start, end - start, ts.Diagnostics.The_with_statement_is_not_supported_All_symbols_in_a_with_block_will_have_type_any); + } } function checkSwitchStatement(node) { // Grammar checking @@ -31358,7 +37608,7 @@ var ts; // Only process instance properties with computed names here. // Static properties cannot be in conflict with indexers, // and properties with literal names were already checked. - if (!(member.flags & 32 /* Static */) && ts.hasDynamicName(member)) { + if (!(ts.getModifierFlags(member) & 32 /* Static */) && ts.hasDynamicName(member)) { var propType = getTypeOfSymbol(member.symbol); checkIndexConstraintForProperty(member.symbol, propType, type, declaredStringIndexer, stringIndexType, 0 /* String */); checkIndexConstraintForProperty(member.symbol, propType, type, declaredNumberIndexer, numberIndexType, 1 /* Number */); @@ -31467,7 +37717,7 @@ var ts; registerForUnusedIdentifiersCheck(node); } function checkClassDeclaration(node) { - if (!node.name && !(node.flags & 512 /* Default */)) { + if (!node.name && !(ts.getModifierFlags(node) & 512 /* Default */)) { grammarErrorOnFirstToken(node, ts.Diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name); } checkClassLikeDeclaration(node); @@ -31559,7 +37809,7 @@ var ts; var signatures = getSignaturesOfType(type, 1 /* Construct */); if (signatures.length) { var declaration = signatures[0].declaration; - if (declaration && declaration.flags & 8 /* Private */) { + if (declaration && ts.getModifierFlags(declaration) & 8 /* Private */) { var typeClassDeclaration = getClassLikeDeclarationOfSymbol(type.symbol); if (!isNodeWithinClass(node, typeClassDeclaration)) { error(node, ts.Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, node.expression.text); @@ -31598,7 +37848,7 @@ var ts; continue; } var derived = getTargetSymbol(getPropertyOfObjectType(type, base.name)); - var baseDeclarationFlags = getDeclarationFlagsFromSymbol(base); + var baseDeclarationFlags = getDeclarationModifierFlagsFromSymbol(base); ts.Debug.assert(!!derived, "derived should point to something, even if it is the base class' declaration."); if (derived) { // In order to resolve whether the inherited method was overridden in the base class or not, @@ -31610,7 +37860,7 @@ var ts; // It is an error to inherit an abstract member without implementing it or being declared abstract. // If there is no declaration for the derived class (as in the case of class expressions), // then the class cannot be declared abstract. - if (baseDeclarationFlags & 128 /* Abstract */ && (!derivedClassDecl || !(derivedClassDecl.flags & 128 /* Abstract */))) { + if (baseDeclarationFlags & 128 /* Abstract */ && (!derivedClassDecl || !(ts.getModifierFlags(derivedClassDecl) & 128 /* Abstract */))) { if (derivedClassDecl.kind === 192 /* ClassExpression */) { error(derivedClassDecl, ts.Diagnostics.Non_abstract_class_expression_does_not_implement_inherited_abstract_member_0_from_class_1, symbolToString(baseProperty), typeToString(baseType)); } @@ -31621,7 +37871,7 @@ var ts; } else { // derived overrides base. - var derivedDeclarationFlags = getDeclarationFlagsFromSymbol(derived); + var derivedDeclarationFlags = getDeclarationModifierFlagsFromSymbol(derived); if ((baseDeclarationFlags & 8 /* Private */) || (derivedDeclarationFlags & 8 /* Private */)) { // either base or derived property is private - not override, skip it continue; @@ -31700,8 +37950,8 @@ var ts; for (var _i = 0, baseTypes_2 = baseTypes; _i < baseTypes_2.length; _i++) { var base = baseTypes_2[_i]; var properties = getPropertiesOfObjectType(getTypeWithThisArgument(base, type.thisType)); - for (var _a = 0, properties_4 = properties; _a < properties_4.length; _a++) { - var prop = properties_4[_a]; + for (var _a = 0, properties_5 = properties; _a < properties_5.length; _a++) { + var prop = properties_5[_a]; var existing = seen[prop.name]; if (!existing) { seen[prop.name] = { prop: prop, containingType: base }; @@ -31779,7 +38029,7 @@ var ts; } else { var text = getTextOfPropertyName(member.name); - if (isNumericLiteralName(text)) { + if (isNumericLiteralName(text) && !isInfinityOrNaNString(text)) { error(member.name, ts.Diagnostics.An_enum_member_cannot_have_a_numeric_name); } } @@ -32134,9 +38384,9 @@ var ts; break; case 169 /* BindingElement */: case 218 /* VariableDeclaration */: - var name_19 = node.name; - if (ts.isBindingPattern(name_19)) { - for (var _b = 0, _c = name_19.elements; _b < _c.length; _b++) { + var name_22 = node.name; + if (ts.isBindingPattern(name_22)) { + for (var _b = 0, _c = name_22.elements; _b < _c.length; _b++) { var el = _c[_b]; // mark individual names in binding pattern checkModuleAugmentationElement(el, isGlobalAugmentation); @@ -32243,7 +38493,7 @@ var ts; // If we hit an import declaration in an illegal context, just bail out to avoid cascading errors. return; } - if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && (node.flags & 1023 /* Modifier */)) { + if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && ts.getModifierFlags(node) !== 0) { grammarErrorOnFirstToken(node, ts.Diagnostics.An_import_declaration_cannot_have_modifiers); } if (checkExternalImportOrExportDeclaration(node)) { @@ -32271,7 +38521,7 @@ var ts; checkGrammarDecorators(node) || checkGrammarModifiers(node); if (ts.isInternalModuleImportEqualsDeclaration(node) || checkExternalImportOrExportDeclaration(node)) { checkImportBinding(node); - if (node.flags & 1 /* Export */) { + if (ts.getModifierFlags(node) & 1 /* Export */) { markExportAsReferenced(node); } if (ts.isInternalModuleImportEqualsDeclaration(node)) { @@ -32302,7 +38552,7 @@ var ts; // If we hit an export in an illegal context, just bail out to avoid cascading errors. return; } - if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && (node.flags & 1023 /* Modifier */)) { + if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && ts.getModifierFlags(node) !== 0) { grammarErrorOnFirstToken(node, ts.Diagnostics.An_export_declaration_cannot_have_modifiers); } if (!node.moduleSpecifier || checkExternalImportOrExportDeclaration(node)) { @@ -32325,9 +38575,11 @@ var ts; } } function checkGrammarModuleElementContext(node, errorMessage) { - if (node.parent.kind !== 256 /* SourceFile */ && node.parent.kind !== 226 /* ModuleBlock */ && node.parent.kind !== 225 /* ModuleDeclaration */) { - return grammarErrorOnFirstToken(node, errorMessage); + var isInAppropriateContext = node.parent.kind === 256 /* SourceFile */ || node.parent.kind === 226 /* ModuleBlock */ || node.parent.kind === 225 /* ModuleDeclaration */; + if (!isInAppropriateContext) { + grammarErrorOnFirstToken(node, errorMessage); } + return !isInAppropriateContext; } function checkExportSpecifier(node) { checkAliasSymbol(node); @@ -32355,7 +38607,7 @@ var ts; return; } // Grammar checking - if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && (node.flags & 1023 /* Modifier */)) { + if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && ts.getModifierFlags(node) !== 0) { grammarErrorOnFirstToken(node, ts.Diagnostics.An_export_assignment_cannot_have_modifiers); } if (node.expression.kind === 69 /* Identifier */) { @@ -32671,7 +38923,7 @@ var ts; } function getSymbolsInScope(location, meaning) { var symbols = ts.createMap(); - var memberFlags = 0; + var memberFlags = 0 /* None */; if (isInsideWithStatementBody(location)) { // We cannot answer semantic questions within a with block, do not proceed any further return []; @@ -32721,7 +38973,7 @@ var ts; if (ts.introducesArgumentsExoticObject(location)) { copySymbol(argumentsSymbol, meaning); } - memberFlags = location.flags; + memberFlags = ts.getModifierFlags(location); location = location.parent; } copySymbols(globals, meaning); @@ -32857,7 +39109,7 @@ var ts; meaning |= 8388608 /* Alias */; return resolveEntityName(entityName, meaning); } - else if (ts.isExpression(entityName)) { + else if (ts.isPartOfExpression(entityName)) { if (ts.nodeIsMissing(entityName)) { // Missing entity name. return undefined; @@ -32940,7 +39192,7 @@ var ts; } // fallthrough case 95 /* SuperKeyword */: - var type = ts.isExpression(node) ? checkExpression(node) : getTypeFromTypeNode(node); + var type = ts.isPartOfExpression(node) ? checkExpression(node) : getTypeFromTypeNode(node); return type.symbol; case 165 /* ThisType */: return getTypeFromTypeNode(node).symbol; @@ -32995,10 +39247,10 @@ var ts; // We cannot answer semantic questions within a with block, do not proceed any further return unknownType; } - if (ts.isTypeNode(node)) { + if (ts.isPartOfTypeNode(node)) { return getTypeFromTypeNode(node); } - if (ts.isExpression(node)) { + if (ts.isPartOfExpression(node)) { return getTypeOfExpression(node); } if (ts.isExpressionWithTypeArgumentsInClassExtendsClause(node)) { @@ -33083,7 +39335,7 @@ var ts; if (ts.isRightSideOfQualifiedNameOrPropertyAccess(expr)) { expr = expr.parent; } - return checkExpression(expr); + return getRegularTypeOfLiteralType(checkExpression(expr)); } /** * Gets either the static or instance type of a class element, based on @@ -33091,7 +39343,7 @@ var ts; */ function getParentTypeOfClassElement(node) { var classSymbol = getSymbolOfNode(node.parent); - return node.flags & 32 /* Static */ + return ts.getModifierFlags(node) & 32 /* Static */ ? getTypeOfSymbol(classSymbol) : getDeclaredTypeOfSymbol(classSymbol); } @@ -33112,9 +39364,9 @@ var ts; function getRootSymbols(symbol) { if (symbol.flags & 268435456 /* SyntheticProperty */) { var symbols_3 = []; - var name_20 = symbol.name; + var name_23 = symbol.name; ts.forEach(getSymbolLinks(symbol).containingType.types, function (t) { - var symbol = getPropertyOfType(t, name_20); + var symbol = getPropertyOfType(t, name_23); if (symbol) { symbols_3.push(symbol); } @@ -33135,12 +39387,18 @@ var ts; } // Emitter support function isArgumentsLocalBinding(node) { - return getReferencedValueSymbol(node) === argumentsSymbol; + if (!ts.isGeneratedIdentifier(node)) { + node = ts.getParseTreeNode(node, ts.isIdentifier); + if (node) { + return getReferencedValueSymbol(node) === argumentsSymbol; + } + } + return false; } function moduleExportsSomeValue(moduleReferenceExpression) { var moduleSymbol = resolveExternalModuleName(moduleReferenceExpression.parent, moduleReferenceExpression); - if (!moduleSymbol) { - // module not found - be conservative + if (!moduleSymbol || ts.isShorthandAmbientModuleSymbol(moduleSymbol)) { + // If the module is not found or is shorthand, assume that it may export a value. return true; } var hasExportAssignment = hasExportAssignmentSymbol(moduleSymbol); @@ -33161,32 +39419,44 @@ var ts; return s && !!(s.flags & 107455 /* Value */); } } + function isNameOfModuleOrEnumDeclaration(node) { + var parent = node.parent; + return ts.isModuleOrEnumDeclaration(parent) && node === parent.name; + } // When resolved as an expression identifier, if the given node references an exported entity, return the declaration // node of the exported entity's container. Otherwise, return undefined. - function getReferencedExportContainer(node) { - var symbol = getReferencedValueSymbol(node); - if (symbol) { - if (symbol.flags & 1048576 /* ExportValue */) { - // If we reference an exported entity within the same module declaration, then whether - // we prefix depends on the kind of entity. SymbolFlags.ExportHasLocal encompasses all the - // kinds that we do NOT prefix. - var exportSymbol = getMergedSymbol(symbol.exportSymbol); - if (exportSymbol.flags & 944 /* ExportHasLocal */) { - return undefined; - } - symbol = exportSymbol; - } - var parentSymbol = getParentOfSymbol(symbol); - if (parentSymbol) { - if (parentSymbol.flags & 512 /* ValueModule */ && parentSymbol.valueDeclaration.kind === 256 /* SourceFile */) { - // If `node` accesses an export and that export isn't in the same file, then symbol is a namespace export, so return undefined. - if (parentSymbol.valueDeclaration === ts.getSourceFileOfNode(node)) { - return parentSymbol.valueDeclaration; + function getReferencedExportContainer(node, prefixLocals) { + node = ts.getParseTreeNode(node, ts.isIdentifier); + if (node) { + // When resolving the export container for the name of a module or enum + // declaration, we need to start resolution at the declaration's container. + // Otherwise, we could incorrectly resolve the export container as the + // declaration if it contains an exported member with the same name. + var symbol = getReferencedValueSymbol(node, /*startInDeclarationContainer*/ isNameOfModuleOrEnumDeclaration(node)); + if (symbol) { + if (symbol.flags & 1048576 /* ExportValue */) { + // If we reference an exported entity within the same module declaration, then whether + // we prefix depends on the kind of entity. SymbolFlags.ExportHasLocal encompasses all the + // kinds that we do NOT prefix. + var exportSymbol = getMergedSymbol(symbol.exportSymbol); + if (!prefixLocals && exportSymbol.flags & 944 /* ExportHasLocal */) { + return undefined; } + symbol = exportSymbol; } - for (var n = node.parent; n; n = n.parent) { - if ((n.kind === 225 /* ModuleDeclaration */ || n.kind === 224 /* EnumDeclaration */) && getSymbolOfNode(n) === parentSymbol) { - return n; + var parentSymbol = getParentOfSymbol(symbol); + if (parentSymbol) { + if (parentSymbol.flags & 512 /* ValueModule */ && parentSymbol.valueDeclaration.kind === 256 /* SourceFile */) { + var symbolFile = parentSymbol.valueDeclaration; + var referenceFile = ts.getSourceFileOfNode(node); + // If `node` accesses an export and that export isn't in the same file, then symbol is a namespace export, so return undefined. + var symbolIsUmdExport = symbolFile !== referenceFile; + return symbolIsUmdExport ? undefined : symbolFile; + } + for (var n = node.parent; n; n = n.parent) { + if (ts.isModuleOrEnumDeclaration(n) && getSymbolOfNode(n) === parentSymbol) { + return n; + } } } } @@ -33195,8 +39465,14 @@ var ts; // When resolved as an expression identifier, if the given node references an import, return the declaration of // that import. Otherwise, return undefined. function getReferencedImportDeclaration(node) { - var symbol = getReferencedValueSymbol(node); - return symbol && symbol.flags & 8388608 /* Alias */ ? getDeclarationOfAliasSymbol(symbol) : undefined; + node = ts.getParseTreeNode(node, ts.isIdentifier); + if (node) { + var symbol = getReferencedValueSymbol(node); + if (symbol && symbol.flags & 8388608 /* Alias */) { + return getDeclarationOfAliasSymbol(symbol); + } + } + return undefined; } function isSymbolOfDeclarationWithCollidingName(symbol) { if (symbol.flags & 418 /* BlockScoped */) { @@ -33243,32 +39519,56 @@ var ts; // a name that either hides an existing name or might hide it when compiled downlevel, // return the declaration of that entity. Otherwise, return undefined. function getReferencedDeclarationWithCollidingName(node) { - var symbol = getReferencedValueSymbol(node); - return symbol && isSymbolOfDeclarationWithCollidingName(symbol) ? symbol.valueDeclaration : undefined; + if (!ts.isGeneratedIdentifier(node)) { + node = ts.getParseTreeNode(node, ts.isIdentifier); + if (node) { + var symbol = getReferencedValueSymbol(node); + if (symbol && isSymbolOfDeclarationWithCollidingName(symbol)) { + return symbol.valueDeclaration; + } + } + } + return undefined; } // Return true if the given node is a declaration of a nested block scoped entity with a name that either hides an // existing name or might hide a name when compiled downlevel function isDeclarationWithCollidingName(node) { - return isSymbolOfDeclarationWithCollidingName(getSymbolOfNode(node)); + node = ts.getParseTreeNode(node, ts.isDeclaration); + if (node) { + var symbol = getSymbolOfNode(node); + if (symbol) { + return isSymbolOfDeclarationWithCollidingName(symbol); + } + } + return false; } function isValueAliasDeclaration(node) { + node = ts.getParseTreeNode(node); + if (node === undefined) { + // A synthesized node comes from an emit transformation and is always a value. + return true; + } switch (node.kind) { case 229 /* ImportEqualsDeclaration */: case 231 /* ImportClause */: case 232 /* NamespaceImport */: case 234 /* ImportSpecifier */: case 238 /* ExportSpecifier */: - return isAliasResolvedToValue(getSymbolOfNode(node)); + return isAliasResolvedToValue(getSymbolOfNode(node) || unknownSymbol); case 236 /* ExportDeclaration */: var exportClause = node.exportClause; return exportClause && ts.forEach(exportClause.elements, isValueAliasDeclaration); case 235 /* ExportAssignment */: - return node.expression && node.expression.kind === 69 /* Identifier */ ? isAliasResolvedToValue(getSymbolOfNode(node)) : true; + return node.expression + && node.expression.kind === 69 /* Identifier */ + ? isAliasResolvedToValue(getSymbolOfNode(node) || unknownSymbol) + : true; } return false; } function isTopLevelValueImportEqualsWithEntityName(node) { - if (node.parent.kind !== 256 /* SourceFile */ || !ts.isInternalModuleImportEqualsDeclaration(node)) { + node = ts.getParseTreeNode(node, ts.isImportEqualsDeclaration); + if (node === undefined || node.parent.kind !== 256 /* SourceFile */ || !ts.isInternalModuleImportEqualsDeclaration(node)) { // parent is not source file or it is not reference to internal module return false; } @@ -33289,9 +39589,14 @@ var ts; return isConstEnumSymbol(s) || s.constEnumOnlyModule; } function isReferencedAliasDeclaration(node, checkChildren) { + node = ts.getParseTreeNode(node); + // Purely synthesized nodes are always emitted. + if (node === undefined) { + return true; + } if (ts.isAliasSymbolDeclaration(node)) { var symbol = getSymbolOfNode(node); - if (getSymbolLinks(symbol).referenced) { + if (symbol && getSymbolLinks(symbol).referenced) { return true; } } @@ -33321,7 +39626,8 @@ var ts; return false; } function getNodeCheckFlags(node) { - return getNodeLinks(node).flags; + node = ts.getParseTreeNode(node); + return node ? getNodeLinks(node).flags : undefined; } function getEnumMemberValue(node) { computeEnumMemberValues(node.parent); @@ -33343,15 +39649,19 @@ var ts; function isFunctionType(type) { return type.flags & 2588672 /* ObjectType */ && getSignaturesOfType(type, 0 /* Call */).length > 0; } - function getTypeReferenceSerializationKind(typeName) { + function getTypeReferenceSerializationKind(typeName, location) { // Resolve the symbol as a value to ensure the type can be reached at runtime during emit. - var valueSymbol = resolveEntityName(typeName, 107455 /* Value */, /*ignoreErrors*/ true); + var valueSymbol = resolveEntityName(typeName, 107455 /* Value */, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, location); + var globalPromiseSymbol = tryGetGlobalPromiseConstructorSymbol(); + if (globalPromiseSymbol && valueSymbol === globalPromiseSymbol) { + return ts.TypeReferenceSerializationKind.Promise; + } var constructorType = valueSymbol ? getTypeOfSymbol(valueSymbol) : undefined; if (constructorType && isConstructorType(constructorType)) { return ts.TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue; } // Resolve the symbol as a type so that we can provide a more useful hint for the type serializer. - var typeSymbol = resolveEntityName(typeName, 793064 /* Type */, /*ignoreErrors*/ true); + var typeSymbol = resolveEntityName(typeName, 793064 /* Type */, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, location); // We might not be able to resolve type symbol so use unknown type in that case (eg error case) if (!typeSymbol) { return ts.TypeReferenceSerializationKind.ObjectType; @@ -33363,8 +39673,8 @@ var ts; else if (type.flags & 1 /* Any */) { return ts.TypeReferenceSerializationKind.ObjectType; } - else if (isTypeOfKind(type, 1024 /* Void */)) { - return ts.TypeReferenceSerializationKind.VoidType; + else if (isTypeOfKind(type, 1024 /* Void */ | 6144 /* Nullable */ | 8192 /* Never */)) { + return ts.TypeReferenceSerializationKind.VoidNullableOrNeverType; } else if (isTypeOfKind(type, 136 /* BooleanLike */)) { return ts.TypeReferenceSerializationKind.BooleanType; @@ -33395,7 +39705,7 @@ var ts; // Get type of the symbol if this is the valid symbol otherwise get type at location var symbol = getSymbolOfNode(declaration); var type = symbol && !(symbol.flags & (2048 /* TypeLiteral */ | 131072 /* Signature */)) - ? getTypeOfSymbol(symbol) + ? getWidenedLiteralType(getTypeOfSymbol(symbol)) : unknownType; getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags); } @@ -33416,15 +39726,44 @@ var ts; function hasGlobalName(name) { return !!globals[name]; } - function getReferencedValueSymbol(reference) { - return getNodeLinks(reference).resolvedSymbol || - resolveName(reference, reference.text, 107455 /* Value */ | 1048576 /* ExportValue */ | 8388608 /* Alias */, - /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined); + function getReferencedValueSymbol(reference, startInDeclarationContainer) { + var resolvedSymbol = getNodeLinks(reference).resolvedSymbol; + if (resolvedSymbol) { + return resolvedSymbol; + } + var location = reference; + if (startInDeclarationContainer) { + // When resolving the name of a declaration as a value, we need to start resolution + // at a point outside of the declaration. + var parent_14 = reference.parent; + if (ts.isDeclaration(parent_14) && reference === parent_14.name) { + location = getDeclarationContainer(parent_14); + } + } + return resolveName(location, reference.text, 107455 /* Value */ | 1048576 /* ExportValue */ | 8388608 /* Alias */, /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined); } function getReferencedValueDeclaration(reference) { - ts.Debug.assert(!ts.nodeIsSynthesized(reference)); - var symbol = getReferencedValueSymbol(reference); - return symbol && getExportSymbolOfValueSymbolIfExported(symbol).valueDeclaration; + if (!ts.isGeneratedIdentifier(reference)) { + reference = ts.getParseTreeNode(reference, ts.isIdentifier); + if (reference) { + var symbol = getReferencedValueSymbol(reference); + if (symbol) { + return getExportSymbolOfValueSymbolIfExported(symbol).valueDeclaration; + } + } + } + return undefined; + } + function isLiteralConstDeclaration(node) { + if (ts.isConst(node)) { + var type = getTypeOfSymbol(getSymbolOfNode(node)); + return !!(type.flags & 96 /* StringOrNumberLiteral */ && type.flags & 16777216 /* FreshLiteral */); + } + return false; + } + function writeLiteralConstValue(node, writer) { + var type = getTypeOfSymbol(getSymbolOfNode(node)); + writer.writeStringLiteral(literalTypeToString(type)); } function createResolver() { // this variable and functions that use it are deliberately moved here from the outer scope @@ -33470,7 +39809,9 @@ var ts; isArgumentsLocalBinding: isArgumentsLocalBinding, getExternalModuleFileFromDeclaration: getExternalModuleFileFromDeclaration, getTypeReferenceDirectivesForEntityName: getTypeReferenceDirectivesForEntityName, - getTypeReferenceDirectivesForSymbol: getTypeReferenceDirectivesForSymbol + getTypeReferenceDirectivesForSymbol: getTypeReferenceDirectivesForSymbol, + isLiteralConstDeclaration: isLiteralConstDeclaration, + writeLiteralConstValue: writeLiteralConstValue }; // defined here to avoid outer scope pollution function getTypeReferenceDirectivesForEntityName(node) { @@ -33520,9 +39861,9 @@ var ts; // external modules cannot define or contribute to type declaration files var current = symbol; while (true) { - var parent_12 = getParentOfSymbol(current); - if (parent_12) { - current = parent_12; + var parent_15 = getParentOfSymbol(current); + if (parent_15) { + current = parent_15; } else { break; @@ -33552,12 +39893,16 @@ var ts; } function initializeTypeChecker() { // Bind all source files and propagate errors - ts.forEach(host.getSourceFiles(), function (file) { + for (var _i = 0, _a = host.getSourceFiles(); _i < _a.length; _i++) { + var file = _a[_i]; ts.bindSourceFile(file, compilerOptions); - }); - var augmentations; + } // Initialize global symbol table - ts.forEach(host.getSourceFiles(), function (file) { + var augmentations; + var requestedExternalEmitHelpers = 0; + var firstFileRequestingExternalHelpers; + for (var _b = 0, _c = host.getSourceFiles(); _b < _c.length; _b++) { + var file = _c[_b]; if (!ts.isExternalOrCommonJsModule(file)) { mergeSymbolTable(globals, file.locals); } @@ -33576,14 +39921,23 @@ var ts; } } } - }); + if ((compilerOptions.isolatedModules || ts.isExternalModule(file)) && !file.isDeclarationFile) { + var fileRequestedExternalEmitHelpers = file.flags & 31744 /* EmitHelperFlags */; + if (fileRequestedExternalEmitHelpers) { + requestedExternalEmitHelpers |= fileRequestedExternalEmitHelpers; + if (firstFileRequestingExternalHelpers === undefined) { + firstFileRequestingExternalHelpers = file; + } + } + } + } if (augmentations) { // merge module augmentations. // this needs to be done after global symbol table is initialized to make sure that all ambient modules are indexed - for (var _i = 0, augmentations_1 = augmentations; _i < augmentations_1.length; _i++) { - var list = augmentations_1[_i]; - for (var _a = 0, list_1 = list; _a < list_1.length; _a++) { - var augmentation = list_1[_a]; + for (var _d = 0, augmentations_1 = augmentations; _d < augmentations_1.length; _d++) { + var list = augmentations_1[_d]; + for (var _e = 0, list_1 = list; _e < list_1.length; _e++) { + var augmentation = list_1[_e]; mergeModuleAugmentation(augmentation); } } @@ -33613,6 +39967,7 @@ var ts; getGlobalPromiseLikeType = ts.memoize(function () { return getGlobalType("PromiseLike", /*arity*/ 1); }); getInstantiatedGlobalPromiseLikeType = ts.memoize(createInstantiatedPromiseLikeType); getGlobalPromiseConstructorSymbol = ts.memoize(function () { return getGlobalValueSymbol("Promise"); }); + tryGetGlobalPromiseConstructorSymbol = ts.memoize(function () { return getGlobalSymbol("Promise", 107455 /* Value */, /*diagnostic*/ undefined) && getGlobalPromiseConstructorSymbol(); }); getGlobalPromiseConstructorLikeType = ts.memoize(function () { return getGlobalType("PromiseConstructorLike"); }); getGlobalThenableType = ts.memoize(createThenableType); getGlobalTemplateStringsArrayType = ts.memoize(function () { return getGlobalType("TemplateStringsArray"); }); @@ -33632,6 +39987,45 @@ var ts; var symbol = getGlobalSymbol("ReadonlyArray", 793064 /* Type */, /*diagnostic*/ undefined); globalReadonlyArrayType = symbol && getTypeOfGlobalSymbol(symbol, /*arity*/ 1); anyReadonlyArrayType = globalReadonlyArrayType ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType; + // If we have specified that we are importing helpers, we should report global + // errors if we cannot resolve the helpers external module, or if it does not have + // the necessary helpers exported. + if (compilerOptions.importHelpers && firstFileRequestingExternalHelpers) { + // Find the first reference to the helpers module. + var helpersModule = resolveExternalModule(firstFileRequestingExternalHelpers, ts.externalHelpersModuleNameText, ts.Diagnostics.Cannot_find_module_0, + /*errorNode*/ undefined); + // If we found the module, report errors if it does not have the necessary exports. + if (helpersModule) { + var exports = helpersModule.exports; + if (requestedExternalEmitHelpers & 1024 /* HasClassExtends */ && languageVersion < 2 /* ES6 */) { + verifyHelperSymbol(exports, "__extends", 107455 /* Value */); + } + if (requestedExternalEmitHelpers & 16384 /* HasJsxSpreadAttributes */ && compilerOptions.jsx !== 1 /* Preserve */) { + verifyHelperSymbol(exports, "__assign", 107455 /* Value */); + } + if (requestedExternalEmitHelpers & 2048 /* HasDecorators */) { + verifyHelperSymbol(exports, "__decorate", 107455 /* Value */); + if (compilerOptions.emitDecoratorMetadata) { + verifyHelperSymbol(exports, "__metadata", 107455 /* Value */); + } + } + if (requestedExternalEmitHelpers & 4096 /* HasParamDecorators */) { + verifyHelperSymbol(exports, "__param", 107455 /* Value */); + } + if (requestedExternalEmitHelpers & 8192 /* HasAsyncFunctions */) { + verifyHelperSymbol(exports, "__awaiter", 107455 /* Value */); + if (languageVersion < 2 /* ES6 */) { + verifyHelperSymbol(exports, "__generator", 107455 /* Value */); + } + } + } + } + } + function verifyHelperSymbol(symbols, name, meaning) { + var symbol = getSymbol(symbols, ts.escapeIdentifier(name), meaning); + if (!symbol) { + error(/*location*/ undefined, ts.Diagnostics.Module_0_has_no_exported_member_1, ts.externalHelpersModuleNameText, name); + } } function createInstantiatedPromiseLikeType() { var promiseLikeType = getGlobalPromiseLikeType(); @@ -33678,7 +40072,7 @@ var ts; return quickResult; } var lastStatic, lastPrivate, lastProtected, lastDeclare, lastAsync, lastReadonly; - var flags = 0; + var flags = 0 /* None */; for (var _i = 0, _a = node.modifiers; _i < _a.length; _i++) { var modifier = _a[_i]; if (modifier.kind !== 128 /* ReadonlyKeyword */) { @@ -33814,7 +40208,7 @@ var ts; node.kind !== 150 /* SetAccessor */) { return grammarErrorOnNode(modifier, ts.Diagnostics.abstract_modifier_can_only_appear_on_a_class_method_or_property_declaration); } - if (!(node.parent.kind === 221 /* ClassDeclaration */ && node.parent.flags & 128 /* Abstract */)) { + if (!(node.parent.kind === 221 /* ClassDeclaration */ && ts.getModifierFlags(node.parent) & 128 /* Abstract */)) { return grammarErrorOnNode(modifier, ts.Diagnostics.Abstract_methods_can_only_appear_within_an_abstract_class); } if (flags & 32 /* Static */) { @@ -33924,9 +40318,6 @@ var ts; return node.modifiers.length > 1 || node.modifiers[0].kind !== allowedModifier; } function checkGrammarAsyncModifier(node, asyncModifier) { - if (languageVersion < 2 /* ES6 */) { - return grammarErrorOnNode(asyncModifier, ts.Diagnostics.Async_functions_are_only_available_when_targeting_ECMAScript_2015_or_higher); - } switch (node.kind) { case 147 /* MethodDeclaration */: case 220 /* FunctionDeclaration */: @@ -34017,7 +40408,7 @@ var ts; if (parameter.dotDotDotToken) { return grammarErrorOnNode(parameter.dotDotDotToken, ts.Diagnostics.An_index_signature_cannot_have_a_rest_parameter); } - if (parameter.flags & 1023 /* Modifier */) { + if (ts.getModifierFlags(parameter) !== 0) { return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_cannot_have_an_accessibility_modifier); } if (parameter.questionToken) { @@ -34055,8 +40446,8 @@ var ts; function checkGrammarForOmittedArgument(node, args) { if (args) { var sourceFile = ts.getSourceFileOfNode(node); - for (var _i = 0, args_1 = args; _i < args_1.length; _i++) { - var arg = args_1[_i]; + for (var _i = 0, args_4 = args; _i < args_4.length; _i++) { + var arg = args_4[_i]; if (arg.kind === 193 /* OmittedExpression */) { return grammarErrorAtPos(sourceFile, arg.pos, 0, ts.Diagnostics.Argument_expression_expected); } @@ -34165,24 +40556,28 @@ var ts; var GetAccessor = 2; var SetAccessor = 4; var GetOrSetAccessor = GetAccessor | SetAccessor; - var _loop_2 = function(prop) { - var name_21 = prop.name; + for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { + var prop = _a[_i]; + var name_24 = prop.name; if (prop.kind === 193 /* OmittedExpression */ || - name_21.kind === 140 /* ComputedPropertyName */) { + name_24.kind === 140 /* ComputedPropertyName */) { // If the name is not a ComputedPropertyName, the grammar checking will skip it - checkGrammarComputedPropertyName(name_21); + checkGrammarComputedPropertyName(name_24); } if (prop.kind === 254 /* ShorthandPropertyAssignment */ && !inDestructuring && prop.objectAssignmentInitializer) { // having objectAssignmentInitializer is only valid in ObjectAssignmentPattern // outside of destructuring it is a syntax error - return { value: grammarErrorOnNode(prop.equalsToken, ts.Diagnostics.can_only_be_used_in_an_object_literal_property_inside_a_destructuring_assignment) }; + return grammarErrorOnNode(prop.equalsToken, ts.Diagnostics.can_only_be_used_in_an_object_literal_property_inside_a_destructuring_assignment); } // Modifiers are never allowed on properties except for 'async' on a method declaration - ts.forEach(prop.modifiers, function (mod) { - if (mod.kind !== 118 /* AsyncKeyword */ || prop.kind !== 147 /* MethodDeclaration */) { - grammarErrorOnNode(mod, ts.Diagnostics._0_modifier_cannot_be_used_here, ts.getTextOfNode(mod)); + if (prop.modifiers) { + for (var _b = 0, _c = prop.modifiers; _b < _c.length; _b++) { + var mod = _c[_b]; + if (mod.kind !== 118 /* AsyncKeyword */ || prop.kind !== 147 /* MethodDeclaration */) { + grammarErrorOnNode(mod, ts.Diagnostics._0_modifier_cannot_be_used_here, ts.getTextOfNode(mod)); + } } - }); + } // ECMA-262 11.1.5 Object Initializer // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true // a.This production is contained in strict code and IsDataDescriptor(previous) is true and @@ -34195,8 +40590,8 @@ var ts; if (prop.kind === 253 /* PropertyAssignment */ || prop.kind === 254 /* ShorthandPropertyAssignment */) { // Grammar checking for computedPropertyName and shorthandPropertyAssignment checkGrammarForInvalidQuestionMark(prop, prop.questionToken, ts.Diagnostics.An_object_member_cannot_be_declared_optional); - if (name_21.kind === 8 /* NumericLiteral */) { - checkGrammarNumericLiteral(name_21); + if (name_24.kind === 8 /* NumericLiteral */) { + checkGrammarNumericLiteral(name_24); } currentKind = Property; } @@ -34212,9 +40607,9 @@ var ts; else { ts.Debug.fail("Unexpected syntax kind:" + prop.kind); } - var effectiveName = ts.getPropertyNameForPropertyNameNode(name_21); + var effectiveName = ts.getPropertyNameForPropertyNameNode(name_24); if (effectiveName === undefined) { - return "continue"; + continue; } if (!seen[effectiveName]) { seen[effectiveName] = currentKind; @@ -34222,25 +40617,20 @@ var ts; else { var existingKind = seen[effectiveName]; if (currentKind === Property && existingKind === Property) { - grammarErrorOnNode(name_21, ts.Diagnostics.Duplicate_identifier_0, ts.getTextOfNode(name_21)); + grammarErrorOnNode(name_24, ts.Diagnostics.Duplicate_identifier_0, ts.getTextOfNode(name_24)); } else if ((currentKind & GetOrSetAccessor) && (existingKind & GetOrSetAccessor)) { if (existingKind !== GetOrSetAccessor && currentKind !== existingKind) { seen[effectiveName] = currentKind | existingKind; } else { - return { value: grammarErrorOnNode(name_21, ts.Diagnostics.An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name) }; + return grammarErrorOnNode(name_24, ts.Diagnostics.An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name); } } else { - return { value: grammarErrorOnNode(name_21, ts.Diagnostics.An_object_literal_cannot_have_property_and_accessor_with_the_same_name) }; + return grammarErrorOnNode(name_24, ts.Diagnostics.An_object_literal_cannot_have_property_and_accessor_with_the_same_name); } } - }; - for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { - var prop = _a[_i]; - var state_3 = _loop_2(prop); - if (typeof state_3 === "object") return state_3.value; } } function checkGrammarJsxElement(node) { @@ -34251,12 +40641,12 @@ var ts; continue; } var jsxAttr = attr; - var name_22 = jsxAttr.name; - if (!seen[name_22.text]) { - seen[name_22.text] = true; + var name_25 = jsxAttr.name; + if (!seen[name_25.text]) { + seen[name_25.text] = true; } else { - return grammarErrorOnNode(name_22, ts.Diagnostics.JSX_elements_cannot_have_multiple_attributes_with_the_same_name); + return grammarErrorOnNode(name_25, ts.Diagnostics.JSX_elements_cannot_have_multiple_attributes_with_the_same_name); } var initializer = jsxAttr.initializer; if (initializer && initializer.kind === 248 /* JsxExpression */ && !initializer.expression) { @@ -34313,7 +40703,7 @@ var ts; else if (ts.isInAmbientContext(accessor)) { return grammarErrorOnNode(accessor.name, ts.Diagnostics.An_accessor_cannot_be_declared_in_an_ambient_context); } - else if (accessor.body === undefined && !(accessor.flags & 128 /* Abstract */)) { + else if (accessor.body === undefined && !(ts.getModifierFlags(accessor) & 128 /* Abstract */)) { return grammarErrorAtPos(ts.getSourceFileOfNode(accessor), accessor.end - 1, ";".length, ts.Diagnostics._0_expected, "{"); } else if (accessor.typeParameters) { @@ -34464,10 +40854,27 @@ var ts; } } } + function isStringOrNumberLiteralExpression(expr) { + return expr.kind === 9 /* StringLiteral */ || expr.kind === 8 /* NumericLiteral */ || + expr.kind === 185 /* PrefixUnaryExpression */ && expr.operator === 36 /* MinusToken */ && + expr.operand.kind === 8 /* NumericLiteral */; + } function checkGrammarVariableDeclaration(node) { if (node.parent.parent.kind !== 207 /* ForInStatement */ && node.parent.parent.kind !== 208 /* ForOfStatement */) { if (ts.isInAmbientContext(node)) { if (node.initializer) { + if (ts.isConst(node) && !node.type) { + if (!isStringOrNumberLiteralExpression(node.initializer)) { + return grammarErrorOnNode(node.initializer, ts.Diagnostics.A_const_initializer_in_an_ambient_context_must_be_a_string_or_numeric_literal); + } + } + else { + // Error on equals token which immediate precedes the initializer + var equalsTokenLength = "=".length; + return grammarErrorAtPos(ts.getSourceFileOfNode(node), node.initializer.pos - equalsTokenLength, equalsTokenLength, ts.Diagnostics.Initializers_are_not_allowed_in_ambient_contexts); + } + } + if (node.initializer && !(ts.isConst(node) && isStringOrNumberLiteralExpression(node.initializer))) { // Error on equals token which immediate precedes the initializer var equalsTokenLength = "=".length; return grammarErrorAtPos(ts.getSourceFileOfNode(node), node.initializer.pos - equalsTokenLength, equalsTokenLength, ts.Diagnostics.Initializers_are_not_allowed_in_ambient_contexts); @@ -34501,7 +40908,7 @@ var ts; var elements = name.elements; for (var _i = 0, elements_2 = elements; _i < elements_2.length; _i++) { var element = elements_2[_i]; - if (element.kind !== 193 /* OmittedExpression */) { + if (!ts.isOmittedExpression(element)) { checkGrammarNameInLetOrConstDeclarations(element.name); } } @@ -34547,8 +40954,8 @@ var ts; function grammarErrorOnFirstToken(node, message, arg0, arg1, arg2) { var sourceFile = ts.getSourceFileOfNode(node); if (!hasParseDiagnostics(sourceFile)) { - var span = ts.getSpanOfTokenAtPosition(sourceFile, node.pos); - diagnostics.add(ts.createFileDiagnostic(sourceFile, span.start, span.length, message, arg0, arg1, arg2)); + var span_4 = ts.getSpanOfTokenAtPosition(sourceFile, node.pos); + diagnostics.add(ts.createFileDiagnostic(sourceFile, span_4.start, span_4.length, message, arg0, arg1, arg2)); return true; } } @@ -34621,8 +41028,7 @@ var ts; node.kind === 236 /* ExportDeclaration */ || node.kind === 235 /* ExportAssignment */ || node.kind === 228 /* NamespaceExportDeclaration */ || - (node.flags & 2 /* Ambient */) || - (node.flags & (1 /* Export */ | 512 /* Default */))) { + ts.getModifierFlags(node) & (2 /* Ambient */ | 1 /* Export */ | 512 /* Default */)) { return false; } return grammarErrorOnFirstToken(node, ts.Diagnostics.A_declare_modifier_is_required_for_a_top_level_declaration_in_a_d_ts_file); @@ -34676,11 +41082,20 @@ var ts; function grammarErrorAfterFirstToken(node, message, arg0, arg1, arg2) { var sourceFile = ts.getSourceFileOfNode(node); if (!hasParseDiagnostics(sourceFile)) { - var span = ts.getSpanOfTokenAtPosition(sourceFile, node.pos); - diagnostics.add(ts.createFileDiagnostic(sourceFile, ts.textSpanEnd(span), /*length*/ 0, message, arg0, arg1, arg2)); + var span_5 = ts.getSpanOfTokenAtPosition(sourceFile, node.pos); + diagnostics.add(ts.createFileDiagnostic(sourceFile, ts.textSpanEnd(span_5), /*length*/ 0, message, arg0, arg1, arg2)); return true; } } + function getAmbientModules() { + var result = []; + for (var sym in globals) { + if (ambientModuleSymbolRegex.test(sym)) { + result.push(globals[sym]); + } + } + return result; + } } ts.createTypeChecker = createTypeChecker; })(ts || (ts = {})); @@ -34691,12 +41106,15 @@ var ts; /// var ts; (function (ts) { + /* @internal */ + ts.compileOnSaveCommandLineOption = { name: "compileOnSave", type: "boolean" }; /* @internal */ ts.optionDeclarations = [ { name: "charset", type: "string", }, + ts.compileOnSaveCommandLineOption, { name: "declaration", shortName: "d", @@ -34716,6 +41134,7 @@ var ts; { name: "extendedDiagnostics", type: "boolean", + experimental: true }, { name: "emitBOM", @@ -34979,6 +41398,7 @@ var ts; "classic": ts.ModuleResolutionKind.Classic, }), description: ts.Diagnostics.Specify_module_resolution_strategy_Colon_node_Node_js_or_classic_TypeScript_pre_1_6, + paramType: ts.Diagnostics.STRATEGY, }, { name: "allowUnusedLabels", @@ -35092,6 +41512,7 @@ var ts; "es2017": "lib.es2017.d.ts", // Host only "dom": "lib.dom.d.ts", + "dom.iterable": "lib.dom.iterable.d.ts", "webworker": "lib.webworker.d.ts", "scripthost": "lib.scripthost.d.ts", // ES2015 Or ESNext By-feature options @@ -35119,6 +41540,11 @@ var ts; name: "strictNullChecks", type: "boolean", description: ts.Diagnostics.Enable_strict_null_checks + }, + { + name: "importHelpers", + type: "boolean", + description: ts.Diagnostics.Import_emit_helpers_from_tslib } ]; /* @internal */ @@ -35339,10 +41765,11 @@ var ts; * @param fileName The path to the config file * @param jsonText The text of the config file */ - function parseConfigFileTextToJson(fileName, jsonText) { + function parseConfigFileTextToJson(fileName, jsonText, stripComments) { + if (stripComments === void 0) { stripComments = true; } try { - var jsonTextWithoutComments = removeComments(jsonText); - return { config: /\S/.test(jsonTextWithoutComments) ? JSON.parse(jsonTextWithoutComments) : {} }; + var jsonTextToParse = stripComments ? removeComments(jsonText) : jsonText; + return { config: /\S/.test(jsonTextToParse) ? JSON.parse(jsonTextToParse) : {} }; } catch (e) { return { error: ts.createCompilerDiagnostic(ts.Diagnostics.Failed_to_parse_file_0_Colon_1, fileName, e.message) }; @@ -35389,11 +41816,11 @@ var ts; function serializeCompilerOptions(options) { var result = ts.createMap(); var optionsNameMap = getOptionNameMap().optionNameMap; - for (var name_23 in options) { - if (ts.hasProperty(options, name_23)) { + for (var name_26 in options) { + if (ts.hasProperty(options, name_26)) { // tsconfig only options cannot be specified via command line, // so we can assume that only types that can appear here string | number | boolean - switch (name_23) { + switch (name_26) { case "init": case "watch": case "version": @@ -35401,14 +41828,14 @@ var ts; case "project": break; default: - var value = options[name_23]; - var optionDefinition = optionsNameMap[name_23.toLowerCase()]; + var value = options[name_26]; + var optionDefinition = optionsNameMap[name_26.toLowerCase()]; if (optionDefinition) { var customTypeMap = getCustomTypeMapOfCommandLineOption(optionDefinition); if (!customTypeMap) { // There is no map associated with this compiler option then use the value as-is // This is the case if the value is expect to be string, number, boolean or list of string - result[name_23] = value; + result[name_26] = value; } else { if (optionDefinition.type === "list") { @@ -35417,11 +41844,11 @@ var ts; var element = _a[_i]; convertedValue.push(getNameOfCompilerOptionValue(element, customTypeMap)); } - result[name_23] = convertedValue; + result[name_26] = convertedValue; } else { // There is a typeMap associated with this command-line option so use it to map value back to its name - result[name_23] = getNameOfCompilerOptionValue(value, customTypeMap); + result[name_26] = getNameOfCompilerOptionValue(value, customTypeMap); } } } @@ -35464,22 +41891,88 @@ var ts; * @param basePath A root directory to resolve relative path entries in the config * file to. e.g. outDir */ - function parseJsonConfigFileContent(json, host, basePath, existingOptions, configFileName) { + function parseJsonConfigFileContent(json, host, basePath, existingOptions, configFileName, resolutionStack) { if (existingOptions === void 0) { existingOptions = {}; } + if (resolutionStack === void 0) { resolutionStack = []; } var errors = []; - var compilerOptions = convertCompilerOptionsFromJsonWorker(json["compilerOptions"], basePath, errors, configFileName); - var options = ts.extend(existingOptions, compilerOptions); + var getCanonicalFileName = ts.createGetCanonicalFileName(host.useCaseSensitiveFileNames); + var resolvedPath = ts.toPath(configFileName || "", basePath, getCanonicalFileName); + if (resolutionStack.indexOf(resolvedPath) >= 0) { + return { + options: {}, + fileNames: [], + typingOptions: {}, + raw: json, + errors: [ts.createCompilerDiagnostic(ts.Diagnostics.Circularity_detected_while_resolving_configuration_Colon_0, resolutionStack.concat([resolvedPath]).join(" -> "))], + wildcardDirectories: {} + }; + } + var options = convertCompilerOptionsFromJsonWorker(json["compilerOptions"], basePath, errors, configFileName); var typingOptions = convertTypingOptionsFromJsonWorker(json["typingOptions"], basePath, errors, configFileName); + if (json["extends"]) { + var _a = [undefined, undefined, undefined, {}], include = _a[0], exclude = _a[1], files = _a[2], baseOptions = _a[3]; + if (typeof json["extends"] === "string") { + _b = (tryExtendsName(json["extends"]) || [include, exclude, files, baseOptions]), include = _b[0], exclude = _b[1], files = _b[2], baseOptions = _b[3]; + } + else { + errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "extends", "string")); + } + if (include && !json["include"]) { + json["include"] = include; + } + if (exclude && !json["exclude"]) { + json["exclude"] = exclude; + } + if (files && !json["files"]) { + json["files"] = files; + } + options = ts.assign({}, baseOptions, options); + } + options = ts.extend(existingOptions, options); options.configFilePath = configFileName; - var _a = getFileNames(errors), fileNames = _a.fileNames, wildcardDirectories = _a.wildcardDirectories; + var _c = getFileNames(errors), fileNames = _c.fileNames, wildcardDirectories = _c.wildcardDirectories; + var compileOnSave = convertCompileOnSaveOptionFromJson(json, basePath, errors); return { options: options, fileNames: fileNames, typingOptions: typingOptions, raw: json, errors: errors, - wildcardDirectories: wildcardDirectories + wildcardDirectories: wildcardDirectories, + compileOnSave: compileOnSave }; + function tryExtendsName(extendedConfig) { + // If the path isn't a rooted or relative path, don't try to resolve it (we reserve the right to special case module-id like paths in the future) + if (!(ts.isRootedDiskPath(extendedConfig) || ts.startsWith(ts.normalizeSlashes(extendedConfig), "./") || ts.startsWith(ts.normalizeSlashes(extendedConfig), "../"))) { + errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.The_path_in_an_extends_options_must_be_relative_or_rooted)); + return; + } + var extendedConfigPath = ts.toPath(extendedConfig, basePath, getCanonicalFileName); + if (!host.fileExists(extendedConfigPath) && !ts.endsWith(extendedConfigPath, ".json")) { + extendedConfigPath = extendedConfigPath + ".json"; + if (!host.fileExists(extendedConfigPath)) { + errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.File_0_does_not_exist, extendedConfig)); + return; + } + } + var extendedResult = readConfigFile(extendedConfigPath, function (path) { return host.readFile(path); }); + if (extendedResult.error) { + errors.push(extendedResult.error); + return; + } + var extendedDirname = ts.getDirectoryPath(extendedConfigPath); + var relativeDifference = ts.convertToRelativePath(extendedDirname, basePath, getCanonicalFileName); + var updatePath = function (path) { return ts.isRootedDiskPath(path) ? path : ts.combinePaths(relativeDifference, path); }; + // Merge configs (copy the resolution stack so it is never reused between branches in potential diamond-problem scenarios) + var result = parseJsonConfigFileContent(extendedResult.config, host, extendedDirname, /*existingOptions*/ undefined, ts.getBaseFileName(extendedConfigPath), resolutionStack.concat([resolvedPath])); + errors.push.apply(errors, result.errors); + var _a = ts.map(["include", "exclude", "files"], function (key) { + if (!json[key] && extendedResult.config[key]) { + return ts.map(extendedResult.config[key], updatePath); + } + }), include = _a[0], exclude = _a[1], files = _a[2]; + return [include, exclude, files, result.options]; + } function getFileNames(errors) { var fileNames; if (ts.hasProperty(json, "files")) { @@ -35512,21 +42005,32 @@ var ts; errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unknown_option_excludes_Did_you_mean_exclude)); } else { - // By default, exclude common package folders + // By default, exclude common package folders and the outDir excludeSpecs = ["node_modules", "bower_components", "jspm_packages"]; - } - // Always exclude the output directory unless explicitly included - var outDir = json["compilerOptions"] && json["compilerOptions"]["outDir"]; - if (outDir) { - excludeSpecs.push(outDir); + var outDir = json["compilerOptions"] && json["compilerOptions"]["outDir"]; + if (outDir) { + excludeSpecs.push(outDir); + } } if (fileNames === undefined && includeSpecs === undefined) { includeSpecs = ["**/*"]; } return matchFileNames(fileNames, includeSpecs, excludeSpecs, basePath, options, host, errors); } + var _b; } ts.parseJsonConfigFileContent = parseJsonConfigFileContent; + function convertCompileOnSaveOptionFromJson(jsonOption, basePath, errors) { + if (!ts.hasProperty(jsonOption, ts.compileOnSaveCommandLineOption.name)) { + return false; + } + var result = convertJsonOption(ts.compileOnSaveCommandLineOption, jsonOption["compileOnSave"], basePath, errors); + if (typeof result === "boolean" && result) { + return result; + } + return false; + } + ts.convertCompileOnSaveOptionFromJson = convertCompileOnSaveOptionFromJson; function convertCompilerOptionsFromJson(jsonOptions, basePath, configFileName) { var errors = []; var options = convertCompilerOptionsFromJsonWorker(jsonOptions, basePath, errors, configFileName); @@ -35540,7 +42044,9 @@ var ts; } ts.convertTypingOptionsFromJson = convertTypingOptionsFromJson; function convertCompilerOptionsFromJsonWorker(jsonOptions, basePath, errors, configFileName) { - var options = ts.getBaseFileName(configFileName) === "jsconfig.json" ? { allowJs: true, maxNodeModuleJsDepth: 2 } : {}; + var options = ts.getBaseFileName(configFileName) === "jsconfig.json" + ? { allowJs: true, maxNodeModuleJsDepth: 2, allowSyntheticDefaultImports: true } + : {}; convertOptionsFromJson(ts.optionDeclarations, jsonOptions, basePath, options, ts.Diagnostics.Unknown_compiler_option_0, errors); return options; } @@ -35792,14 +42298,14 @@ var ts; var recursiveKeys = []; for (var _i = 0, include_1 = include; _i < include_1.length; _i++) { var file = include_1[_i]; - var name_24 = ts.normalizePath(ts.combinePaths(path, file)); - if (excludeRegex && excludeRegex.test(name_24)) { + var name_27 = ts.normalizePath(ts.combinePaths(path, file)); + if (excludeRegex && excludeRegex.test(name_27)) { continue; } - var match = wildcardDirectoryPattern.exec(name_24); + var match = wildcardDirectoryPattern.exec(name_27); if (match) { var key = useCaseSensitiveFileNames ? match[0] : match[0].toLowerCase(); - var flags = watchRecursivePattern.test(name_24) ? 1 /* Recursive */ : 0 /* None */; + var flags = watchRecursivePattern.test(name_27) ? 1 /* Recursive */ : 0 /* None */; var existingFlags = wildcardDirectories[key]; if (existingFlags === undefined || existingFlags < flags) { wildcardDirectories[key] = flags; @@ -35895,11 +42401,11 @@ var ts; return declarationDiagnostics.getDiagnostics(targetSourceFile ? targetSourceFile.fileName : undefined); function getDeclarationDiagnosticsFromFile(_a, sources, isBundledEmit) { var declarationFilePath = _a.declarationFilePath; - emitDeclarations(host, resolver, declarationDiagnostics, declarationFilePath, sources, isBundledEmit); + emitDeclarations(host, resolver, declarationDiagnostics, declarationFilePath, sources, isBundledEmit, /*emitOnlyDtsFiles*/ false); } } ts.getDeclarationDiagnostics = getDeclarationDiagnostics; - function emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFiles, isBundledEmit) { + function emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFiles, isBundledEmit, emitOnlyDtsFiles) { var newLine = host.getNewLine(); var compilerOptions = host.getCompilerOptions(); var write; @@ -35946,7 +42452,7 @@ var ts; // global file reference is added only // - if it is not bundled emit (because otherwise it would be self reference) // - and it is not already added - if (writeReferencePath(referencedFile, !isBundledEmit && !addedGlobalFileReference)) { + if (writeReferencePath(referencedFile, !isBundledEmit && !addedGlobalFileReference, emitOnlyDtsFiles)) { addedGlobalFileReference = true; } emittedReferencedFiles.push(referencedFile); @@ -36107,13807 +42613,18392 @@ var ts; } } } - function handleSymbolAccessibilityError(symbolAccessibilityResult) { - if (symbolAccessibilityResult.accessibility === 0 /* Accessible */) { - // write the aliases - if (symbolAccessibilityResult && symbolAccessibilityResult.aliasesToMakeVisible) { - writeAsynchronousModuleElements(symbolAccessibilityResult.aliasesToMakeVisible); - } + function handleSymbolAccessibilityError(symbolAccessibilityResult) { + if (symbolAccessibilityResult.accessibility === 0 /* Accessible */) { + // write the aliases + if (symbolAccessibilityResult && symbolAccessibilityResult.aliasesToMakeVisible) { + writeAsynchronousModuleElements(symbolAccessibilityResult.aliasesToMakeVisible); + } + } + else { + // Report error + reportedDeclarationError = true; + var errorInfo = writer.getSymbolAccessibilityDiagnostic(symbolAccessibilityResult); + if (errorInfo) { + if (errorInfo.typeName) { + emitterDiagnostics.add(ts.createDiagnosticForNode(symbolAccessibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, ts.getTextOfNodeFromSourceText(currentText, errorInfo.typeName), symbolAccessibilityResult.errorSymbolName, symbolAccessibilityResult.errorModuleName)); + } + else { + emitterDiagnostics.add(ts.createDiagnosticForNode(symbolAccessibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, symbolAccessibilityResult.errorSymbolName, symbolAccessibilityResult.errorModuleName)); + } + } + } + } + function trackSymbol(symbol, enclosingDeclaration, meaning) { + handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning, /*shouldComputeAliasesToMakeVisible*/ true)); + recordTypeReferenceDirectivesIfNecessary(resolver.getTypeReferenceDirectivesForSymbol(symbol, meaning)); + } + function reportInaccessibleThisError() { + if (errorNameNode) { + reportedDeclarationError = true; + emitterDiagnostics.add(ts.createDiagnosticForNode(errorNameNode, ts.Diagnostics.The_inferred_type_of_0_references_an_inaccessible_this_type_A_type_annotation_is_necessary, ts.declarationNameToString(errorNameNode))); + } + } + function writeTypeOfDeclaration(declaration, type, getSymbolAccessibilityDiagnostic) { + writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic; + write(": "); + if (type) { + // Write the type + emitType(type); + } + else { + errorNameNode = declaration.name; + resolver.writeTypeOfDeclaration(declaration, enclosingDeclaration, 2 /* UseTypeOfFunction */ | 1024 /* UseTypeAliasValue */, writer); + errorNameNode = undefined; + } + } + function writeReturnTypeAtSignature(signature, getSymbolAccessibilityDiagnostic) { + writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic; + write(": "); + if (signature.type) { + // Write the type + emitType(signature.type); + } + else { + errorNameNode = signature.name; + resolver.writeReturnTypeOfSignatureDeclaration(signature, enclosingDeclaration, 2 /* UseTypeOfFunction */ | 1024 /* UseTypeAliasValue */, writer); + errorNameNode = undefined; + } + } + function emitLines(nodes) { + for (var _i = 0, nodes_2 = nodes; _i < nodes_2.length; _i++) { + var node = nodes_2[_i]; + emit(node); + } + } + function emitSeparatedList(nodes, separator, eachNodeEmitFn, canEmitFn) { + var currentWriterPos = writer.getTextPos(); + for (var _i = 0, nodes_3 = nodes; _i < nodes_3.length; _i++) { + var node = nodes_3[_i]; + if (!canEmitFn || canEmitFn(node)) { + if (currentWriterPos !== writer.getTextPos()) { + write(separator); + } + currentWriterPos = writer.getTextPos(); + eachNodeEmitFn(node); + } + } + } + function emitCommaList(nodes, eachNodeEmitFn, canEmitFn) { + emitSeparatedList(nodes, ", ", eachNodeEmitFn, canEmitFn); + } + function writeJsDocComments(declaration) { + if (declaration) { + var jsDocComments = ts.getJsDocCommentsFromText(declaration, currentText); + ts.emitNewLineBeforeLeadingComments(currentLineMap, writer, declaration, jsDocComments); + // jsDoc comments are emitted at /*leading comment1 */space/*leading comment*/space + ts.emitComments(currentText, currentLineMap, writer, jsDocComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, ts.writeCommentRange); + } + } + function emitTypeWithNewGetSymbolAccessibilityDiagnostic(type, getSymbolAccessibilityDiagnostic) { + writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic; + emitType(type); + } + function emitType(type) { + switch (type.kind) { + case 117 /* AnyKeyword */: + case 132 /* StringKeyword */: + case 130 /* NumberKeyword */: + case 120 /* BooleanKeyword */: + case 133 /* SymbolKeyword */: + case 103 /* VoidKeyword */: + case 135 /* UndefinedKeyword */: + case 93 /* NullKeyword */: + case 127 /* NeverKeyword */: + case 165 /* ThisType */: + case 166 /* LiteralType */: + return writeTextOfNode(currentText, type); + case 194 /* ExpressionWithTypeArguments */: + return emitExpressionWithTypeArguments(type); + case 155 /* TypeReference */: + return emitTypeReference(type); + case 158 /* TypeQuery */: + return emitTypeQuery(type); + case 160 /* ArrayType */: + return emitArrayType(type); + case 161 /* TupleType */: + return emitTupleType(type); + case 162 /* UnionType */: + return emitUnionType(type); + case 163 /* IntersectionType */: + return emitIntersectionType(type); + case 164 /* ParenthesizedType */: + return emitParenType(type); + case 156 /* FunctionType */: + case 157 /* ConstructorType */: + return emitSignatureDeclarationWithJsDocComments(type); + case 159 /* TypeLiteral */: + return emitTypeLiteral(type); + case 69 /* Identifier */: + return emitEntityName(type); + case 139 /* QualifiedName */: + return emitEntityName(type); + case 154 /* TypePredicate */: + return emitTypePredicate(type); + } + function writeEntityName(entityName) { + if (entityName.kind === 69 /* Identifier */) { + writeTextOfNode(currentText, entityName); + } + else { + var left = entityName.kind === 139 /* QualifiedName */ ? entityName.left : entityName.expression; + var right = entityName.kind === 139 /* QualifiedName */ ? entityName.right : entityName.name; + writeEntityName(left); + write("."); + writeTextOfNode(currentText, right); + } + } + function emitEntityName(entityName) { + var visibilityResult = resolver.isEntityNameVisible(entityName, + // Aliases can be written asynchronously so use correct enclosing declaration + entityName.parent.kind === 229 /* ImportEqualsDeclaration */ ? entityName.parent : enclosingDeclaration); + handleSymbolAccessibilityError(visibilityResult); + recordTypeReferenceDirectivesIfNecessary(resolver.getTypeReferenceDirectivesForEntityName(entityName)); + writeEntityName(entityName); + } + function emitExpressionWithTypeArguments(node) { + if (ts.isEntityNameExpression(node.expression)) { + ts.Debug.assert(node.expression.kind === 69 /* Identifier */ || node.expression.kind === 172 /* PropertyAccessExpression */); + emitEntityName(node.expression); + if (node.typeArguments) { + write("<"); + emitCommaList(node.typeArguments, emitType); + write(">"); + } + } + } + function emitTypeReference(type) { + emitEntityName(type.typeName); + if (type.typeArguments) { + write("<"); + emitCommaList(type.typeArguments, emitType); + write(">"); + } + } + function emitTypePredicate(type) { + writeTextOfNode(currentText, type.parameterName); + write(" is "); + emitType(type.type); + } + function emitTypeQuery(type) { + write("typeof "); + emitEntityName(type.exprName); + } + function emitArrayType(type) { + emitType(type.elementType); + write("[]"); + } + function emitTupleType(type) { + write("["); + emitCommaList(type.elementTypes, emitType); + write("]"); + } + function emitUnionType(type) { + emitSeparatedList(type.types, " | ", emitType); + } + function emitIntersectionType(type) { + emitSeparatedList(type.types, " & ", emitType); + } + function emitParenType(type) { + write("("); + emitType(type.type); + write(")"); + } + function emitTypeLiteral(type) { + write("{"); + if (type.members.length) { + writeLine(); + increaseIndent(); + // write members + emitLines(type.members); + decreaseIndent(); + } + write("}"); + } + } + function emitSourceFile(node) { + currentText = node.text; + currentLineMap = ts.getLineStarts(node); + currentIdentifiers = node.identifiers; + isCurrentFileExternalModule = ts.isExternalModule(node); + enclosingDeclaration = node; + ts.emitDetachedComments(currentText, currentLineMap, writer, ts.writeCommentRange, node, newLine, true /* remove comments */); + emitLines(node.statements); + } + // Return a temp variable name to be used in `export default` statements. + // The temp name will be of the form _default_counter. + // Note that export default is only allowed at most once in a module, so we + // do not need to keep track of created temp names. + function getExportDefaultTempVariableName() { + var baseName = "_default"; + if (!(baseName in currentIdentifiers)) { + return baseName; + } + var count = 0; + while (true) { + count++; + var name_28 = baseName + "_" + count; + if (!(name_28 in currentIdentifiers)) { + return name_28; + } + } + } + function emitExportAssignment(node) { + if (node.expression.kind === 69 /* Identifier */) { + write(node.isExportEquals ? "export = " : "export default "); + writeTextOfNode(currentText, node.expression); + } + else { + // Expression + var tempVarName = getExportDefaultTempVariableName(); + if (!noDeclare) { + write("declare "); + } + write("var "); + write(tempVarName); + write(": "); + writer.getSymbolAccessibilityDiagnostic = getDefaultExportAccessibilityDiagnostic; + resolver.writeTypeOfExpression(node.expression, enclosingDeclaration, 2 /* UseTypeOfFunction */ | 1024 /* UseTypeAliasValue */, writer); + write(";"); + writeLine(); + write(node.isExportEquals ? "export = " : "export default "); + write(tempVarName); + } + write(";"); + writeLine(); + // Make all the declarations visible for the export name + if (node.expression.kind === 69 /* Identifier */) { + var nodes = resolver.collectLinkedAliases(node.expression); + // write each of these declarations asynchronously + writeAsynchronousModuleElements(nodes); + } + function getDefaultExportAccessibilityDiagnostic(diagnostic) { + return { + diagnosticMessage: ts.Diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0, + errorNode: node + }; + } + } + function isModuleElementVisible(node) { + return resolver.isDeclarationVisible(node); + } + function emitModuleElement(node, isModuleElementVisible) { + if (isModuleElementVisible) { + writeModuleElement(node); + } + else if (node.kind === 229 /* ImportEqualsDeclaration */ || + (node.parent.kind === 256 /* SourceFile */ && isCurrentFileExternalModule)) { + var isVisible = void 0; + if (asynchronousSubModuleDeclarationEmitInfo && node.parent.kind !== 256 /* SourceFile */) { + // Import declaration of another module that is visited async so lets put it in right spot + asynchronousSubModuleDeclarationEmitInfo.push({ + node: node, + outputPos: writer.getTextPos(), + indent: writer.getIndent(), + isVisible: isVisible + }); + } + else { + if (node.kind === 230 /* ImportDeclaration */) { + var importDeclaration = node; + if (importDeclaration.importClause) { + isVisible = (importDeclaration.importClause.name && resolver.isDeclarationVisible(importDeclaration.importClause)) || + isVisibleNamedBinding(importDeclaration.importClause.namedBindings); + } + } + moduleElementDeclarationEmitInfo.push({ + node: node, + outputPos: writer.getTextPos(), + indent: writer.getIndent(), + isVisible: isVisible + }); + } + } + } + function writeModuleElement(node) { + switch (node.kind) { + case 220 /* FunctionDeclaration */: + return writeFunctionDeclaration(node); + case 200 /* VariableStatement */: + return writeVariableStatement(node); + case 222 /* InterfaceDeclaration */: + return writeInterfaceDeclaration(node); + case 221 /* ClassDeclaration */: + return writeClassDeclaration(node); + case 223 /* TypeAliasDeclaration */: + return writeTypeAliasDeclaration(node); + case 224 /* EnumDeclaration */: + return writeEnumDeclaration(node); + case 225 /* ModuleDeclaration */: + return writeModuleDeclaration(node); + case 229 /* ImportEqualsDeclaration */: + return writeImportEqualsDeclaration(node); + case 230 /* ImportDeclaration */: + return writeImportDeclaration(node); + default: + ts.Debug.fail("Unknown symbol kind"); + } + } + function emitModuleElementDeclarationFlags(node) { + // If the node is parented in the current source file we need to emit export declare or just export + if (node.parent.kind === 256 /* SourceFile */) { + var modifiers = ts.getModifierFlags(node); + // If the node is exported + if (modifiers & 1 /* Export */) { + write("export "); + } + if (modifiers & 512 /* Default */) { + write("default "); + } + else if (node.kind !== 222 /* InterfaceDeclaration */ && !noDeclare) { + write("declare "); + } + } + } + function emitClassMemberDeclarationFlags(flags) { + if (flags & 8 /* Private */) { + write("private "); + } + else if (flags & 16 /* Protected */) { + write("protected "); + } + if (flags & 32 /* Static */) { + write("static "); + } + if (flags & 64 /* Readonly */) { + write("readonly "); + } + if (flags & 128 /* Abstract */) { + write("abstract "); + } + } + function writeImportEqualsDeclaration(node) { + // note usage of writer. methods instead of aliases created, just to make sure we are using + // correct writer especially to handle asynchronous alias writing + emitJsDocComments(node); + if (ts.hasModifier(node, 1 /* Export */)) { + write("export "); + } + write("import "); + writeTextOfNode(currentText, node.name); + write(" = "); + if (ts.isInternalModuleImportEqualsDeclaration(node)) { + emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.moduleReference, getImportEntityNameVisibilityError); + write(";"); + } + else { + write("require("); + emitExternalModuleSpecifier(node); + write(");"); + } + writer.writeLine(); + function getImportEntityNameVisibilityError(symbolAccessibilityResult) { + return { + diagnosticMessage: ts.Diagnostics.Import_declaration_0_is_using_private_name_1, + errorNode: node, + typeName: node.name + }; + } + } + function isVisibleNamedBinding(namedBindings) { + if (namedBindings) { + if (namedBindings.kind === 232 /* NamespaceImport */) { + return resolver.isDeclarationVisible(namedBindings); + } + else { + return ts.forEach(namedBindings.elements, function (namedImport) { return resolver.isDeclarationVisible(namedImport); }); + } + } + } + function writeImportDeclaration(node) { + emitJsDocComments(node); + if (ts.hasModifier(node, 1 /* Export */)) { + write("export "); + } + write("import "); + if (node.importClause) { + var currentWriterPos = writer.getTextPos(); + if (node.importClause.name && resolver.isDeclarationVisible(node.importClause)) { + writeTextOfNode(currentText, node.importClause.name); + } + if (node.importClause.namedBindings && isVisibleNamedBinding(node.importClause.namedBindings)) { + if (currentWriterPos !== writer.getTextPos()) { + // If the default binding was emitted, write the separated + write(", "); + } + if (node.importClause.namedBindings.kind === 232 /* NamespaceImport */) { + write("* as "); + writeTextOfNode(currentText, node.importClause.namedBindings.name); + } + else { + write("{ "); + emitCommaList(node.importClause.namedBindings.elements, emitImportOrExportSpecifier, resolver.isDeclarationVisible); + write(" }"); + } + } + write(" from "); + } + emitExternalModuleSpecifier(node); + write(";"); + writer.writeLine(); + } + function emitExternalModuleSpecifier(parent) { + // emitExternalModuleSpecifier is usually called when we emit something in the.d.ts file that will make it an external module (i.e. import/export declarations). + // the only case when it is not true is when we call it to emit correct name for module augmentation - d.ts files with just module augmentations are not considered + // external modules since they are indistinguishable from script files with ambient modules. To fix this in such d.ts files we'll emit top level 'export {}' + // so compiler will treat them as external modules. + resultHasExternalModuleIndicator = resultHasExternalModuleIndicator || parent.kind !== 225 /* ModuleDeclaration */; + var moduleSpecifier; + if (parent.kind === 229 /* ImportEqualsDeclaration */) { + var node = parent; + moduleSpecifier = ts.getExternalModuleImportEqualsDeclarationExpression(node); + } + else if (parent.kind === 225 /* ModuleDeclaration */) { + moduleSpecifier = parent.name; } else { - // Report error - reportedDeclarationError = true; - var errorInfo = writer.getSymbolAccessibilityDiagnostic(symbolAccessibilityResult); - if (errorInfo) { - if (errorInfo.typeName) { - emitterDiagnostics.add(ts.createDiagnosticForNode(symbolAccessibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, ts.getTextOfNodeFromSourceText(currentText, errorInfo.typeName), symbolAccessibilityResult.errorSymbolName, symbolAccessibilityResult.errorModuleName)); - } - else { - emitterDiagnostics.add(ts.createDiagnosticForNode(symbolAccessibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, symbolAccessibilityResult.errorSymbolName, symbolAccessibilityResult.errorModuleName)); - } + var node = parent; + moduleSpecifier = node.moduleSpecifier; + } + if (moduleSpecifier.kind === 9 /* StringLiteral */ && isBundledEmit && (compilerOptions.out || compilerOptions.outFile)) { + var moduleName = ts.getExternalModuleNameFromDeclaration(host, resolver, parent); + if (moduleName) { + write('"'); + write(moduleName); + write('"'); + return; } } + writeTextOfNode(currentText, moduleSpecifier); } - function trackSymbol(symbol, enclosingDeclaration, meaning) { - handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning)); - recordTypeReferenceDirectivesIfNecessary(resolver.getTypeReferenceDirectivesForSymbol(symbol, meaning)); - } - function reportInaccessibleThisError() { - if (errorNameNode) { - reportedDeclarationError = true; - emitterDiagnostics.add(ts.createDiagnosticForNode(errorNameNode, ts.Diagnostics.The_inferred_type_of_0_references_an_inaccessible_this_type_A_type_annotation_is_necessary, ts.declarationNameToString(errorNameNode))); + function emitImportOrExportSpecifier(node) { + if (node.propertyName) { + writeTextOfNode(currentText, node.propertyName); + write(" as "); } + writeTextOfNode(currentText, node.name); } - function writeTypeOfDeclaration(declaration, type, getSymbolAccessibilityDiagnostic) { - writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic; - write(": "); - if (type) { - // Write the type - emitType(type); + function emitExportSpecifier(node) { + emitImportOrExportSpecifier(node); + // Make all the declarations visible for the export name + var nodes = resolver.collectLinkedAliases(node.propertyName || node.name); + // write each of these declarations asynchronously + writeAsynchronousModuleElements(nodes); + } + function emitExportDeclaration(node) { + emitJsDocComments(node); + write("export "); + if (node.exportClause) { + write("{ "); + emitCommaList(node.exportClause.elements, emitExportSpecifier); + write(" }"); } else { - errorNameNode = declaration.name; - resolver.writeTypeOfDeclaration(declaration, enclosingDeclaration, 2 /* UseTypeOfFunction */, writer); - errorNameNode = undefined; + write("*"); + } + if (node.moduleSpecifier) { + write(" from "); + emitExternalModuleSpecifier(node); } + write(";"); + writer.writeLine(); } - function writeReturnTypeAtSignature(signature, getSymbolAccessibilityDiagnostic) { - writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic; - write(": "); - if (signature.type) { - // Write the type - emitType(signature.type); + function writeModuleDeclaration(node) { + emitJsDocComments(node); + emitModuleElementDeclarationFlags(node); + if (ts.isGlobalScopeAugmentation(node)) { + write("global "); } else { - errorNameNode = signature.name; - resolver.writeReturnTypeOfSignatureDeclaration(signature, enclosingDeclaration, 2 /* UseTypeOfFunction */, writer); - errorNameNode = undefined; + if (node.flags & 16 /* Namespace */) { + write("namespace "); + } + else { + write("module "); + } + if (ts.isExternalModuleAugmentation(node)) { + emitExternalModuleSpecifier(node); + } + else { + writeTextOfNode(currentText, node.name); + } } - } - function emitLines(nodes) { - for (var _i = 0, nodes_2 = nodes; _i < nodes_2.length; _i++) { - var node = nodes_2[_i]; - emit(node); + while (node.body && node.body.kind !== 226 /* ModuleBlock */) { + node = node.body; + write("."); + writeTextOfNode(currentText, node.name); + } + var prevEnclosingDeclaration = enclosingDeclaration; + if (node.body) { + enclosingDeclaration = node; + write(" {"); + writeLine(); + increaseIndent(); + emitLines(node.body.statements); + decreaseIndent(); + write("}"); + writeLine(); + enclosingDeclaration = prevEnclosingDeclaration; + } + else { + write(";"); } } - function emitSeparatedList(nodes, separator, eachNodeEmitFn, canEmitFn) { - var currentWriterPos = writer.getTextPos(); - for (var _i = 0, nodes_3 = nodes; _i < nodes_3.length; _i++) { - var node = nodes_3[_i]; - if (!canEmitFn || canEmitFn(node)) { - if (currentWriterPos !== writer.getTextPos()) { - write(separator); - } - currentWriterPos = writer.getTextPos(); - eachNodeEmitFn(node); - } + function writeTypeAliasDeclaration(node) { + var prevEnclosingDeclaration = enclosingDeclaration; + enclosingDeclaration = node; + emitJsDocComments(node); + emitModuleElementDeclarationFlags(node); + write("type "); + writeTextOfNode(currentText, node.name); + emitTypeParameters(node.typeParameters); + write(" = "); + emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError); + write(";"); + writeLine(); + enclosingDeclaration = prevEnclosingDeclaration; + function getTypeAliasDeclarationVisibilityError(symbolAccessibilityResult) { + return { + diagnosticMessage: ts.Diagnostics.Exported_type_alias_0_has_or_is_using_private_name_1, + errorNode: node.type, + typeName: node.name + }; } } - function emitCommaList(nodes, eachNodeEmitFn, canEmitFn) { - emitSeparatedList(nodes, ", ", eachNodeEmitFn, canEmitFn); + function writeEnumDeclaration(node) { + emitJsDocComments(node); + emitModuleElementDeclarationFlags(node); + if (ts.isConst(node)) { + write("const "); + } + write("enum "); + writeTextOfNode(currentText, node.name); + write(" {"); + writeLine(); + increaseIndent(); + emitLines(node.members); + decreaseIndent(); + write("}"); + writeLine(); } - function writeJsDocComments(declaration) { - if (declaration) { - var jsDocComments = ts.getJsDocCommentsFromText(declaration, currentText); - ts.emitNewLineBeforeLeadingComments(currentLineMap, writer, declaration, jsDocComments); - // jsDoc comments are emitted at /*leading comment1 */space/*leading comment*/space - ts.emitComments(currentText, currentLineMap, writer, jsDocComments, /*trailingSeparator*/ true, newLine, ts.writeCommentRange); + function emitEnumMemberDeclaration(node) { + emitJsDocComments(node); + writeTextOfNode(currentText, node.name); + var enumMemberValue = resolver.getConstantValue(node); + if (enumMemberValue !== undefined) { + write(" = "); + write(enumMemberValue.toString()); } + write(","); + writeLine(); } - function emitTypeWithNewGetSymbolAccessibilityDiagnostic(type, getSymbolAccessibilityDiagnostic) { - writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic; - emitType(type); + function isPrivateMethodTypeParameter(node) { + return node.parent.kind === 147 /* MethodDeclaration */ && ts.hasModifier(node.parent, 8 /* Private */); } - function emitType(type) { - switch (type.kind) { - case 117 /* AnyKeyword */: - case 132 /* StringKeyword */: - case 130 /* NumberKeyword */: - case 120 /* BooleanKeyword */: - case 133 /* SymbolKeyword */: - case 103 /* VoidKeyword */: - case 135 /* UndefinedKeyword */: - case 93 /* NullKeyword */: - case 127 /* NeverKeyword */: - case 165 /* ThisType */: - case 166 /* LiteralType */: - return writeTextOfNode(currentText, type); - case 194 /* ExpressionWithTypeArguments */: - return emitExpressionWithTypeArguments(type); - case 155 /* TypeReference */: - return emitTypeReference(type); - case 158 /* TypeQuery */: - return emitTypeQuery(type); - case 160 /* ArrayType */: - return emitArrayType(type); - case 161 /* TupleType */: - return emitTupleType(type); - case 162 /* UnionType */: - return emitUnionType(type); - case 163 /* IntersectionType */: - return emitIntersectionType(type); - case 164 /* ParenthesizedType */: - return emitParenType(type); - case 156 /* FunctionType */: - case 157 /* ConstructorType */: - return emitSignatureDeclarationWithJsDocComments(type); - case 159 /* TypeLiteral */: - return emitTypeLiteral(type); - case 69 /* Identifier */: - return emitEntityName(type); - case 139 /* QualifiedName */: - return emitEntityName(type); - case 154 /* TypePredicate */: - return emitTypePredicate(type); - } - function writeEntityName(entityName) { - if (entityName.kind === 69 /* Identifier */) { - writeTextOfNode(currentText, entityName); + function emitTypeParameters(typeParameters) { + function emitTypeParameter(node) { + increaseIndent(); + emitJsDocComments(node); + decreaseIndent(); + writeTextOfNode(currentText, node.name); + // If there is constraint present and this is not a type parameter of the private method emit the constraint + if (node.constraint && !isPrivateMethodTypeParameter(node)) { + write(" extends "); + if (node.parent.kind === 156 /* FunctionType */ || + node.parent.kind === 157 /* ConstructorType */ || + (node.parent.parent && node.parent.parent.kind === 159 /* TypeLiteral */)) { + ts.Debug.assert(node.parent.kind === 147 /* MethodDeclaration */ || + node.parent.kind === 146 /* MethodSignature */ || + node.parent.kind === 156 /* FunctionType */ || + node.parent.kind === 157 /* ConstructorType */ || + node.parent.kind === 151 /* CallSignature */ || + node.parent.kind === 152 /* ConstructSignature */); + emitType(node.constraint); + } + else { + emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.constraint, getTypeParameterConstraintVisibilityError); + } } - else { - var left = entityName.kind === 139 /* QualifiedName */ ? entityName.left : entityName.expression; - var right = entityName.kind === 139 /* QualifiedName */ ? entityName.right : entityName.name; - writeEntityName(left); - write("."); - writeTextOfNode(currentText, right); + function getTypeParameterConstraintVisibilityError(symbolAccessibilityResult) { + // Type parameter constraints are named by user so we should always be able to name it + var diagnosticMessage; + switch (node.parent.kind) { + case 221 /* ClassDeclaration */: + diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_class_has_or_is_using_private_name_1; + break; + case 222 /* InterfaceDeclaration */: + diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1; + break; + case 152 /* ConstructSignature */: + diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; + break; + case 151 /* CallSignature */: + diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1; + break; + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + if (ts.hasModifier(node.parent, 32 /* Static */)) { + diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1; + } + else if (node.parent.parent.kind === 221 /* ClassDeclaration */) { + diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1; + } + else { + diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1; + } + break; + case 220 /* FunctionDeclaration */: + diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_function_has_or_is_using_private_name_1; + break; + default: + ts.Debug.fail("This is unknown parent for type parameter: " + node.parent.kind); + } + return { + diagnosticMessage: diagnosticMessage, + errorNode: node, + typeName: node.name + }; } } - function emitEntityName(entityName) { - var visibilityResult = resolver.isEntityNameVisible(entityName, - // Aliases can be written asynchronously so use correct enclosing declaration - entityName.parent.kind === 229 /* ImportEqualsDeclaration */ ? entityName.parent : enclosingDeclaration); - handleSymbolAccessibilityError(visibilityResult); - recordTypeReferenceDirectivesIfNecessary(resolver.getTypeReferenceDirectivesForEntityName(entityName)); - writeEntityName(entityName); + if (typeParameters) { + write("<"); + emitCommaList(typeParameters, emitTypeParameter); + write(">"); } - function emitExpressionWithTypeArguments(node) { + } + function emitHeritageClause(typeReferences, isImplementsList) { + if (typeReferences) { + write(isImplementsList ? " implements " : " extends "); + emitCommaList(typeReferences, emitTypeOfTypeReference); + } + function emitTypeOfTypeReference(node) { if (ts.isEntityNameExpression(node.expression)) { - ts.Debug.assert(node.expression.kind === 69 /* Identifier */ || node.expression.kind === 172 /* PropertyAccessExpression */); - emitEntityName(node.expression); - if (node.typeArguments) { - write("<"); - emitCommaList(node.typeArguments, emitType); - write(">"); + emitTypeWithNewGetSymbolAccessibilityDiagnostic(node, getHeritageClauseVisibilityError); + } + else if (!isImplementsList && node.expression.kind === 93 /* NullKeyword */) { + write("null"); + } + else { + writer.getSymbolAccessibilityDiagnostic = getHeritageClauseVisibilityError; + resolver.writeBaseConstructorTypeOfClass(enclosingDeclaration, enclosingDeclaration, 2 /* UseTypeOfFunction */ | 1024 /* UseTypeAliasValue */, writer); + } + function getHeritageClauseVisibilityError(symbolAccessibilityResult) { + var diagnosticMessage; + // Heritage clause is written by user so it can always be named + if (node.parent.parent.kind === 221 /* ClassDeclaration */) { + // Class or Interface implemented/extended is inaccessible + diagnosticMessage = isImplementsList ? + ts.Diagnostics.Implements_clause_of_exported_class_0_has_or_is_using_private_name_1 : + ts.Diagnostics.Extends_clause_of_exported_class_0_has_or_is_using_private_name_1; + } + else { + // interface is inaccessible + diagnosticMessage = ts.Diagnostics.Extends_clause_of_exported_interface_0_has_or_is_using_private_name_1; } + return { + diagnosticMessage: diagnosticMessage, + errorNode: node, + typeName: node.parent.parent.name + }; } } - function emitTypeReference(type) { - emitEntityName(type.typeName); - if (type.typeArguments) { - write("<"); - emitCommaList(type.typeArguments, emitType); - write(">"); + } + function writeClassDeclaration(node) { + function emitParameterProperties(constructorDeclaration) { + if (constructorDeclaration) { + ts.forEach(constructorDeclaration.parameters, function (param) { + if (ts.hasModifier(param, 92 /* ParameterPropertyModifier */)) { + emitPropertyDeclaration(param); + } + }); } } - function emitTypePredicate(type) { - writeTextOfNode(currentText, type.parameterName); - write(" is "); - emitType(type.type); - } - function emitTypeQuery(type) { - write("typeof "); - emitEntityName(type.exprName); - } - function emitArrayType(type) { - emitType(type.elementType); - write("[]"); - } - function emitTupleType(type) { - write("["); - emitCommaList(type.elementTypes, emitType); - write("]"); + emitJsDocComments(node); + emitModuleElementDeclarationFlags(node); + if (ts.hasModifier(node, 128 /* Abstract */)) { + write("abstract "); } - function emitUnionType(type) { - emitSeparatedList(type.types, " | ", emitType); + write("class "); + writeTextOfNode(currentText, node.name); + var prevEnclosingDeclaration = enclosingDeclaration; + enclosingDeclaration = node; + emitTypeParameters(node.typeParameters); + var baseTypeNode = ts.getClassExtendsHeritageClauseElement(node); + if (baseTypeNode) { + emitHeritageClause([baseTypeNode], /*isImplementsList*/ false); } - function emitIntersectionType(type) { - emitSeparatedList(type.types, " & ", emitType); + emitHeritageClause(ts.getClassImplementsHeritageClauseElements(node), /*isImplementsList*/ true); + write(" {"); + writeLine(); + increaseIndent(); + emitParameterProperties(ts.getFirstConstructorWithBody(node)); + emitLines(node.members); + decreaseIndent(); + write("}"); + writeLine(); + enclosingDeclaration = prevEnclosingDeclaration; + } + function writeInterfaceDeclaration(node) { + emitJsDocComments(node); + emitModuleElementDeclarationFlags(node); + write("interface "); + writeTextOfNode(currentText, node.name); + var prevEnclosingDeclaration = enclosingDeclaration; + enclosingDeclaration = node; + emitTypeParameters(node.typeParameters); + emitHeritageClause(ts.getInterfaceBaseTypeNodes(node), /*isImplementsList*/ false); + write(" {"); + writeLine(); + increaseIndent(); + emitLines(node.members); + decreaseIndent(); + write("}"); + writeLine(); + enclosingDeclaration = prevEnclosingDeclaration; + } + function emitPropertyDeclaration(node) { + if (ts.hasDynamicName(node)) { + return; } - function emitParenType(type) { - write("("); - emitType(type.type); - write(")"); + emitJsDocComments(node); + emitClassMemberDeclarationFlags(ts.getModifierFlags(node)); + emitVariableDeclaration(node); + write(";"); + writeLine(); + } + function emitVariableDeclaration(node) { + // If we are emitting property it isn't moduleElement and hence we already know it needs to be emitted + // so there is no check needed to see if declaration is visible + if (node.kind !== 218 /* VariableDeclaration */ || resolver.isDeclarationVisible(node)) { + if (ts.isBindingPattern(node.name)) { + emitBindingPattern(node.name); + } + else { + // If this node is a computed name, it can only be a symbol, because we've already skipped + // it if it's not a well known symbol. In that case, the text of the name will be exactly + // what we want, namely the name expression enclosed in brackets. + writeTextOfNode(currentText, node.name); + // If optional property emit ? but in the case of parameterProperty declaration with "?" indicating optional parameter for the constructor + // we don't want to emit property declaration with "?" + if ((node.kind === 145 /* PropertyDeclaration */ || node.kind === 144 /* PropertySignature */ || + (node.kind === 142 /* Parameter */ && !ts.isParameterPropertyDeclaration(node))) && ts.hasQuestionToken(node)) { + write("?"); + } + if ((node.kind === 145 /* PropertyDeclaration */ || node.kind === 144 /* PropertySignature */) && node.parent.kind === 159 /* TypeLiteral */) { + emitTypeOfVariableDeclarationFromTypeLiteral(node); + } + else if (resolver.isLiteralConstDeclaration(node)) { + write(" = "); + resolver.writeLiteralConstValue(node, writer); + } + else if (!ts.hasModifier(node, 8 /* Private */)) { + writeTypeOfDeclaration(node, node.type, getVariableDeclarationTypeVisibilityError); + } + } } - function emitTypeLiteral(type) { - write("{"); - if (type.members.length) { - writeLine(); - increaseIndent(); - // write members - emitLines(type.members); - decreaseIndent(); + function getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult) { + if (node.kind === 218 /* VariableDeclaration */) { + return symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? + ts.Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + ts.Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Exported_variable_0_has_or_is_using_private_name_1; + } + else if (node.kind === 145 /* PropertyDeclaration */ || node.kind === 144 /* PropertySignature */) { + // TODO(jfreeman): Deal with computed properties in error reporting. + if (ts.hasModifier(node, 32 /* Static */)) { + return symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? + ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_private_name_1; + } + else if (node.parent.kind === 221 /* ClassDeclaration */) { + return symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? + ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_private_name_1; + } + else { + // Interfaces cannot have types that cannot be named + return symbolAccessibilityResult.errorModuleName ? + ts.Diagnostics.Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Property_0_of_exported_interface_has_or_is_using_private_name_1; + } } - write("}"); } - } - function emitSourceFile(node) { - currentText = node.text; - currentLineMap = ts.getLineStarts(node); - currentIdentifiers = node.identifiers; - isCurrentFileExternalModule = ts.isExternalModule(node); - enclosingDeclaration = node; - ts.emitDetachedComments(currentText, currentLineMap, writer, ts.writeCommentRange, node, newLine, true /* remove comments */); - emitLines(node.statements); - } - // Return a temp variable name to be used in `export default` statements. - // The temp name will be of the form _default_counter. - // Note that export default is only allowed at most once in a module, so we - // do not need to keep track of created temp names. - function getExportDefaultTempVariableName() { - var baseName = "_default"; - if (!(baseName in currentIdentifiers)) { - return baseName; + function getVariableDeclarationTypeVisibilityError(symbolAccessibilityResult) { + var diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult); + return diagnosticMessage !== undefined ? { + diagnosticMessage: diagnosticMessage, + errorNode: node, + typeName: node.name + } : undefined; } - var count = 0; - while (true) { - count++; - var name_25 = baseName + "_" + count; - if (!(name_25 in currentIdentifiers)) { - return name_25; + function emitBindingPattern(bindingPattern) { + // Only select non-omitted expression from the bindingPattern's elements. + // We have to do this to avoid emitting trailing commas. + // For example: + // original: var [, c,,] = [ 2,3,4] + // emitted: declare var c: number; // instead of declare var c:number, ; + var elements = []; + for (var _i = 0, _a = bindingPattern.elements; _i < _a.length; _i++) { + var element = _a[_i]; + if (element.kind !== 193 /* OmittedExpression */) { + elements.push(element); + } + } + emitCommaList(elements, emitBindingElement); + } + function emitBindingElement(bindingElement) { + function getBindingElementTypeVisibilityError(symbolAccessibilityResult) { + var diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult); + return diagnosticMessage !== undefined ? { + diagnosticMessage: diagnosticMessage, + errorNode: bindingElement, + typeName: bindingElement.name + } : undefined; + } + if (bindingElement.name) { + if (ts.isBindingPattern(bindingElement.name)) { + emitBindingPattern(bindingElement.name); + } + else { + writeTextOfNode(currentText, bindingElement.name); + writeTypeOfDeclaration(bindingElement, /*type*/ undefined, getBindingElementTypeVisibilityError); + } } } } - function emitExportAssignment(node) { - if (node.expression.kind === 69 /* Identifier */) { - write(node.isExportEquals ? "export = " : "export default "); - writeTextOfNode(currentText, node.expression); + function emitTypeOfVariableDeclarationFromTypeLiteral(node) { + // if this is property of type literal, + // or is parameter of method/call/construct/index signature of type literal + // emit only if type is specified + if (node.type) { + write(": "); + emitType(node.type); + } + } + function isVariableStatementVisible(node) { + return ts.forEach(node.declarationList.declarations, function (varDeclaration) { return resolver.isDeclarationVisible(varDeclaration); }); + } + function writeVariableStatement(node) { + emitJsDocComments(node); + emitModuleElementDeclarationFlags(node); + if (ts.isLet(node.declarationList)) { + write("let "); + } + else if (ts.isConst(node.declarationList)) { + write("const "); } else { - // Expression - var tempVarName = getExportDefaultTempVariableName(); - if (!noDeclare) { - write("declare "); - } write("var "); - write(tempVarName); - write(": "); - writer.getSymbolAccessibilityDiagnostic = getDefaultExportAccessibilityDiagnostic; - resolver.writeTypeOfExpression(node.expression, enclosingDeclaration, 2 /* UseTypeOfFunction */, writer); - write(";"); - writeLine(); - write(node.isExportEquals ? "export = " : "export default "); - write(tempVarName); } + emitCommaList(node.declarationList.declarations, emitVariableDeclaration, resolver.isDeclarationVisible); write(";"); writeLine(); - // Make all the declarations visible for the export name - if (node.expression.kind === 69 /* Identifier */) { - var nodes = resolver.collectLinkedAliases(node.expression); - // write each of these declarations asynchronously - writeAsynchronousModuleElements(nodes); + } + function emitAccessorDeclaration(node) { + if (ts.hasDynamicName(node)) { + return; } - function getDefaultExportAccessibilityDiagnostic(diagnostic) { - return { - diagnosticMessage: ts.Diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0, - errorNode: node - }; + var accessors = ts.getAllAccessorDeclarations(node.parent.members, node); + var accessorWithTypeAnnotation; + if (node === accessors.firstAccessor) { + emitJsDocComments(accessors.getAccessor); + emitJsDocComments(accessors.setAccessor); + emitClassMemberDeclarationFlags(ts.getModifierFlags(node) | (accessors.setAccessor ? 0 : 64 /* Readonly */)); + writeTextOfNode(currentText, node.name); + if (!ts.hasModifier(node, 8 /* Private */)) { + accessorWithTypeAnnotation = node; + var type = getTypeAnnotationFromAccessor(node); + if (!type) { + // couldn't get type for the first accessor, try the another one + var anotherAccessor = node.kind === 149 /* GetAccessor */ ? accessors.setAccessor : accessors.getAccessor; + type = getTypeAnnotationFromAccessor(anotherAccessor); + if (type) { + accessorWithTypeAnnotation = anotherAccessor; + } + } + writeTypeOfDeclaration(node, type, getAccessorDeclarationTypeVisibilityError); + } + write(";"); + writeLine(); } - } - function isModuleElementVisible(node) { - return resolver.isDeclarationVisible(node); - } - function emitModuleElement(node, isModuleElementVisible) { - if (isModuleElementVisible) { - writeModuleElement(node); + function getTypeAnnotationFromAccessor(accessor) { + if (accessor) { + return accessor.kind === 149 /* GetAccessor */ + ? accessor.type // Getter - return type + : accessor.parameters.length > 0 + ? accessor.parameters[0].type // Setter parameter type + : undefined; + } } - else if (node.kind === 229 /* ImportEqualsDeclaration */ || - (node.parent.kind === 256 /* SourceFile */ && isCurrentFileExternalModule)) { - var isVisible = void 0; - if (asynchronousSubModuleDeclarationEmitInfo && node.parent.kind !== 256 /* SourceFile */) { - // Import declaration of another module that is visited async so lets put it in right spot - asynchronousSubModuleDeclarationEmitInfo.push({ - node: node, - outputPos: writer.getTextPos(), - indent: writer.getIndent(), - isVisible: isVisible - }); + function getAccessorDeclarationTypeVisibilityError(symbolAccessibilityResult) { + var diagnosticMessage; + if (accessorWithTypeAnnotation.kind === 150 /* SetAccessor */) { + // Setters have to have type named and cannot infer it so, the type should always be named + if (ts.hasModifier(accessorWithTypeAnnotation.parent, 32 /* Static */)) { + diagnosticMessage = symbolAccessibilityResult.errorModuleName ? + ts.Diagnostics.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_private_name_1; + } + else { + diagnosticMessage = symbolAccessibilityResult.errorModuleName ? + ts.Diagnostics.Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_private_name_1; + } + return { + diagnosticMessage: diagnosticMessage, + errorNode: accessorWithTypeAnnotation.parameters[0], + // TODO(jfreeman): Investigate why we are passing node.name instead of node.parameters[0].name + typeName: accessorWithTypeAnnotation.name + }; } else { - if (node.kind === 230 /* ImportDeclaration */) { - var importDeclaration = node; - if (importDeclaration.importClause) { - isVisible = (importDeclaration.importClause.name && resolver.isDeclarationVisible(importDeclaration.importClause)) || - isVisibleNamedBinding(importDeclaration.importClause.namedBindings); - } + if (ts.hasModifier(accessorWithTypeAnnotation, 32 /* Static */)) { + diagnosticMessage = symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? + ts.Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : + ts.Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1 : + ts.Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_private_name_0; } - moduleElementDeclarationEmitInfo.push({ - node: node, - outputPos: writer.getTextPos(), - indent: writer.getIndent(), - isVisible: isVisible - }); + else { + diagnosticMessage = symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? + ts.Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : + ts.Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1 : + ts.Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_private_name_0; + } + return { + diagnosticMessage: diagnosticMessage, + errorNode: accessorWithTypeAnnotation.name, + typeName: undefined + }; } } } - function writeModuleElement(node) { - switch (node.kind) { - case 220 /* FunctionDeclaration */: - return writeFunctionDeclaration(node); - case 200 /* VariableStatement */: - return writeVariableStatement(node); - case 222 /* InterfaceDeclaration */: - return writeInterfaceDeclaration(node); - case 221 /* ClassDeclaration */: - return writeClassDeclaration(node); - case 223 /* TypeAliasDeclaration */: - return writeTypeAliasDeclaration(node); - case 224 /* EnumDeclaration */: - return writeEnumDeclaration(node); - case 225 /* ModuleDeclaration */: - return writeModuleDeclaration(node); - case 229 /* ImportEqualsDeclaration */: - return writeImportEqualsDeclaration(node); - case 230 /* ImportDeclaration */: - return writeImportDeclaration(node); - default: - ts.Debug.fail("Unknown symbol kind"); + function writeFunctionDeclaration(node) { + if (ts.hasDynamicName(node)) { + return; } - } - function emitModuleElementDeclarationFlags(node) { - // If the node is parented in the current source file we need to emit export declare or just export - if (node.parent.kind === 256 /* SourceFile */) { - // If the node is exported - if (node.flags & 1 /* Export */) { - write("export "); + // If we are emitting Method/Constructor it isn't moduleElement and hence already determined to be emitting + // so no need to verify if the declaration is visible + if (!resolver.isImplementationOfOverload(node)) { + emitJsDocComments(node); + if (node.kind === 220 /* FunctionDeclaration */) { + emitModuleElementDeclarationFlags(node); } - if (node.flags & 512 /* Default */) { - write("default "); + else if (node.kind === 147 /* MethodDeclaration */ || node.kind === 148 /* Constructor */) { + emitClassMemberDeclarationFlags(ts.getModifierFlags(node)); } - else if (node.kind !== 222 /* InterfaceDeclaration */ && !noDeclare) { - write("declare "); + if (node.kind === 220 /* FunctionDeclaration */) { + write("function "); + writeTextOfNode(currentText, node.name); + } + else if (node.kind === 148 /* Constructor */) { + write("constructor"); + } + else { + writeTextOfNode(currentText, node.name); + if (ts.hasQuestionToken(node)) { + write("?"); + } } + emitSignatureDeclaration(node); } } - function emitClassMemberDeclarationFlags(flags) { - if (flags & 8 /* Private */) { - write("private "); + function emitSignatureDeclarationWithJsDocComments(node) { + emitJsDocComments(node); + emitSignatureDeclaration(node); + } + function emitSignatureDeclaration(node) { + var prevEnclosingDeclaration = enclosingDeclaration; + enclosingDeclaration = node; + var closeParenthesizedFunctionType = false; + if (node.kind === 153 /* IndexSignature */) { + // Index signature can have readonly modifier + emitClassMemberDeclarationFlags(ts.getModifierFlags(node)); + write("["); } - else if (flags & 16 /* Protected */) { - write("protected "); + else { + // Construct signature or constructor type write new Signature + if (node.kind === 152 /* ConstructSignature */ || node.kind === 157 /* ConstructorType */) { + write("new "); + } + else if (node.kind === 156 /* FunctionType */) { + var currentOutput = writer.getText(); + // Do not generate incorrect type when function type with type parameters is type argument + // This could happen if user used space between two '<' making it error free + // e.g var x: A< (a: Tany)=>Tany>; + if (node.typeParameters && currentOutput.charAt(currentOutput.length - 1) === "<") { + closeParenthesizedFunctionType = true; + write("("); + } + } + emitTypeParameters(node.typeParameters); + write("("); } - if (flags & 32 /* Static */) { - write("static "); + // Parameters + emitCommaList(node.parameters, emitParameterDeclaration); + if (node.kind === 153 /* IndexSignature */) { + write("]"); } - if (flags & 64 /* Readonly */) { - write("readonly "); + else { + write(")"); } - if (flags & 128 /* Abstract */) { - write("abstract "); + // If this is not a constructor and is not private, emit the return type + var isFunctionTypeOrConstructorType = node.kind === 156 /* FunctionType */ || node.kind === 157 /* ConstructorType */; + if (isFunctionTypeOrConstructorType || node.parent.kind === 159 /* TypeLiteral */) { + // Emit type literal signature return type only if specified + if (node.type) { + write(isFunctionTypeOrConstructorType ? " => " : ": "); + emitType(node.type); + } } - } - function writeImportEqualsDeclaration(node) { - // note usage of writer. methods instead of aliases created, just to make sure we are using - // correct writer especially to handle asynchronous alias writing - emitJsDocComments(node); - if (node.flags & 1 /* Export */) { - write("export "); + else if (node.kind !== 148 /* Constructor */ && !ts.hasModifier(node, 8 /* Private */)) { + writeReturnTypeAtSignature(node, getReturnTypeVisibilityError); } - write("import "); - writeTextOfNode(currentText, node.name); - write(" = "); - if (ts.isInternalModuleImportEqualsDeclaration(node)) { - emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.moduleReference, getImportEntityNameVisibilityError); + enclosingDeclaration = prevEnclosingDeclaration; + if (!isFunctionTypeOrConstructorType) { write(";"); + writeLine(); } - else { - write("require("); - emitExternalModuleSpecifier(node); - write(");"); + else if (closeParenthesizedFunctionType) { + write(")"); } - writer.writeLine(); - function getImportEntityNameVisibilityError(symbolAccessibilityResult) { + function getReturnTypeVisibilityError(symbolAccessibilityResult) { + var diagnosticMessage; + switch (node.kind) { + case 152 /* ConstructSignature */: + // Interfaces cannot have return types that cannot be named + diagnosticMessage = symbolAccessibilityResult.errorModuleName ? + ts.Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : + ts.Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_0; + break; + case 151 /* CallSignature */: + // Interfaces cannot have return types that cannot be named + diagnosticMessage = symbolAccessibilityResult.errorModuleName ? + ts.Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : + ts.Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_private_name_0; + break; + case 153 /* IndexSignature */: + // Interfaces cannot have return types that cannot be named + diagnosticMessage = symbolAccessibilityResult.errorModuleName ? + ts.Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : + ts.Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_private_name_0; + break; + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + if (ts.hasModifier(node, 32 /* Static */)) { + diagnosticMessage = symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? + ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : + ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 : + ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_private_name_0; + } + else if (node.parent.kind === 221 /* ClassDeclaration */) { + diagnosticMessage = symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? + ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : + ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 : + ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_private_name_0; + } + else { + // Interfaces cannot have return types that cannot be named + diagnosticMessage = symbolAccessibilityResult.errorModuleName ? + ts.Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : + ts.Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_private_name_0; + } + break; + case 220 /* FunctionDeclaration */: + diagnosticMessage = symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? + ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : + ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_private_module_1 : + ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_private_name_0; + break; + default: + ts.Debug.fail("This is unknown kind for signature: " + node.kind); + } return { - diagnosticMessage: ts.Diagnostics.Import_declaration_0_is_using_private_name_1, - errorNode: node, - typeName: node.name + diagnosticMessage: diagnosticMessage, + errorNode: node.name || node }; } } - function isVisibleNamedBinding(namedBindings) { - if (namedBindings) { - if (namedBindings.kind === 232 /* NamespaceImport */) { - return resolver.isDeclarationVisible(namedBindings); - } - else { - return ts.forEach(namedBindings.elements, function (namedImport) { return resolver.isDeclarationVisible(namedImport); }); - } - } - } - function writeImportDeclaration(node) { + function emitParameterDeclaration(node) { + increaseIndent(); emitJsDocComments(node); - if (node.flags & 1 /* Export */) { - write("export "); + if (node.dotDotDotToken) { + write("..."); } - write("import "); - if (node.importClause) { - var currentWriterPos = writer.getTextPos(); - if (node.importClause.name && resolver.isDeclarationVisible(node.importClause)) { - writeTextOfNode(currentText, node.importClause.name); + if (ts.isBindingPattern(node.name)) { + // For bindingPattern, we can't simply writeTextOfNode from the source file + // because we want to omit the initializer and using writeTextOfNode will result in initializer get emitted. + // Therefore, we will have to recursively emit each element in the bindingPattern. + emitBindingPattern(node.name); + } + else { + writeTextOfNode(currentText, node.name); + } + if (resolver.isOptionalParameter(node)) { + write("?"); + } + decreaseIndent(); + if (node.parent.kind === 156 /* FunctionType */ || + node.parent.kind === 157 /* ConstructorType */ || + node.parent.parent.kind === 159 /* TypeLiteral */) { + emitTypeOfVariableDeclarationFromTypeLiteral(node); + } + else if (!ts.hasModifier(node.parent, 8 /* Private */)) { + writeTypeOfDeclaration(node, node.type, getParameterDeclarationTypeVisibilityError); + } + function getParameterDeclarationTypeVisibilityError(symbolAccessibilityResult) { + var diagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult); + return diagnosticMessage !== undefined ? { + diagnosticMessage: diagnosticMessage, + errorNode: node, + typeName: node.name + } : undefined; + } + function getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult) { + switch (node.parent.kind) { + case 148 /* Constructor */: + return symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? + ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_private_name_1; + case 152 /* ConstructSignature */: + // Interfaces cannot have parameter types that cannot be named + return symbolAccessibilityResult.errorModuleName ? + ts.Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; + case 151 /* CallSignature */: + // Interfaces cannot have parameter types that cannot be named + return symbolAccessibilityResult.errorModuleName ? + ts.Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1; + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + if (ts.hasModifier(node.parent, 32 /* Static */)) { + return symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? + ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1; + } + else if (node.parent.parent.kind === 221 /* ClassDeclaration */) { + return symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? + ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1; + } + else { + // Interfaces cannot have parameter types that cannot be named + return symbolAccessibilityResult.errorModuleName ? + ts.Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1; + } + case 220 /* FunctionDeclaration */: + return symbolAccessibilityResult.errorModuleName ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? + ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2 : + ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_private_name_1; + default: + ts.Debug.fail("This is unknown parent for parameter: " + node.parent.kind); } - if (node.importClause.namedBindings && isVisibleNamedBinding(node.importClause.namedBindings)) { - if (currentWriterPos !== writer.getTextPos()) { - // If the default binding was emitted, write the separated - write(", "); - } - if (node.importClause.namedBindings.kind === 232 /* NamespaceImport */) { - write("* as "); - writeTextOfNode(currentText, node.importClause.namedBindings.name); - } - else { - write("{ "); - emitCommaList(node.importClause.namedBindings.elements, emitImportOrExportSpecifier, resolver.isDeclarationVisible); - write(" }"); + } + function emitBindingPattern(bindingPattern) { + // We have to explicitly emit square bracket and bracket because these tokens are not store inside the node. + if (bindingPattern.kind === 167 /* ObjectBindingPattern */) { + write("{"); + emitCommaList(bindingPattern.elements, emitBindingElement); + write("}"); + } + else if (bindingPattern.kind === 168 /* ArrayBindingPattern */) { + write("["); + var elements = bindingPattern.elements; + emitCommaList(elements, emitBindingElement); + if (elements && elements.hasTrailingComma) { + write(", "); } + write("]"); } - write(" from "); - } - emitExternalModuleSpecifier(node); - write(";"); - writer.writeLine(); - } - function emitExternalModuleSpecifier(parent) { - // emitExternalModuleSpecifier is usually called when we emit something in the.d.ts file that will make it an external module (i.e. import/export declarations). - // the only case when it is not true is when we call it to emit correct name for module augmentation - d.ts files with just module augmentations are not considered - // external modules since they are indistinguishable from script files with ambient modules. To fix this in such d.ts files we'll emit top level 'export {}' - // so compiler will treat them as external modules. - resultHasExternalModuleIndicator = resultHasExternalModuleIndicator || parent.kind !== 225 /* ModuleDeclaration */; - var moduleSpecifier; - if (parent.kind === 229 /* ImportEqualsDeclaration */) { - var node = parent; - moduleSpecifier = ts.getExternalModuleImportEqualsDeclarationExpression(node); } - else if (parent.kind === 225 /* ModuleDeclaration */) { - moduleSpecifier = parent.name; - } - else { - var node = parent; - moduleSpecifier = node.moduleSpecifier; - } - if (moduleSpecifier.kind === 9 /* StringLiteral */ && isBundledEmit && (compilerOptions.out || compilerOptions.outFile)) { - var moduleName = ts.getExternalModuleNameFromDeclaration(host, resolver, parent); - if (moduleName) { - write('"'); - write(moduleName); - write('"'); - return; + function emitBindingElement(bindingElement) { + if (bindingElement.kind === 193 /* OmittedExpression */) { + // If bindingElement is an omittedExpression (i.e. containing elision), + // we will emit blank space (although this may differ from users' original code, + // it allows emitSeparatedList to write separator appropriately) + // Example: + // original: function foo([, x, ,]) {} + // emit : function foo([ , x, , ]) {} + write(" "); + } + else if (bindingElement.kind === 169 /* BindingElement */) { + if (bindingElement.propertyName) { + // bindingElement has propertyName property in the following case: + // { y: [a,b,c] ...} -> bindingPattern will have a property called propertyName for "y" + // We have to explicitly emit the propertyName before descending into its binding elements. + // Example: + // original: function foo({y: [a,b,c]}) {} + // emit : declare function foo({y: [a, b, c]}: { y: [any, any, any] }) void; + writeTextOfNode(currentText, bindingElement.propertyName); + write(": "); + } + if (bindingElement.name) { + if (ts.isBindingPattern(bindingElement.name)) { + // If it is a nested binding pattern, we will recursively descend into each element and emit each one separately. + // In the case of rest element, we will omit rest element. + // Example: + // original: function foo([a, [[b]], c] = [1,[["string"]], 3]) {} + // emit : declare function foo([a, [[b]], c]: [number, [[string]], number]): void; + // original with rest: function foo([a, ...c]) {} + // emit : declare function foo([a, ...c]): void; + emitBindingPattern(bindingElement.name); + } + else { + ts.Debug.assert(bindingElement.name.kind === 69 /* Identifier */); + // If the node is just an identifier, we will simply emit the text associated with the node's name + // Example: + // original: function foo({y = 10, x}) {} + // emit : declare function foo({y, x}: {number, any}): void; + if (bindingElement.dotDotDotToken) { + write("..."); + } + writeTextOfNode(currentText, bindingElement.name); + } + } } } - writeTextOfNode(currentText, moduleSpecifier); } - function emitImportOrExportSpecifier(node) { - if (node.propertyName) { - writeTextOfNode(currentText, node.propertyName); - write(" as "); + function emitNode(node) { + switch (node.kind) { + case 220 /* FunctionDeclaration */: + case 225 /* ModuleDeclaration */: + case 229 /* ImportEqualsDeclaration */: + case 222 /* InterfaceDeclaration */: + case 221 /* ClassDeclaration */: + case 223 /* TypeAliasDeclaration */: + case 224 /* EnumDeclaration */: + return emitModuleElement(node, isModuleElementVisible(node)); + case 200 /* VariableStatement */: + return emitModuleElement(node, isVariableStatementVisible(node)); + case 230 /* ImportDeclaration */: + // Import declaration without import clause is visible, otherwise it is not visible + return emitModuleElement(node, /*isModuleElementVisible*/ !node.importClause); + case 236 /* ExportDeclaration */: + return emitExportDeclaration(node); + case 148 /* Constructor */: + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + return writeFunctionDeclaration(node); + case 152 /* ConstructSignature */: + case 151 /* CallSignature */: + case 153 /* IndexSignature */: + return emitSignatureDeclarationWithJsDocComments(node); + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + return emitAccessorDeclaration(node); + case 145 /* PropertyDeclaration */: + case 144 /* PropertySignature */: + return emitPropertyDeclaration(node); + case 255 /* EnumMember */: + return emitEnumMemberDeclaration(node); + case 235 /* ExportAssignment */: + return emitExportAssignment(node); + case 256 /* SourceFile */: + return emitSourceFile(node); } - writeTextOfNode(currentText, node.name); - } - function emitExportSpecifier(node) { - emitImportOrExportSpecifier(node); - // Make all the declarations visible for the export name - var nodes = resolver.collectLinkedAliases(node.propertyName || node.name); - // write each of these declarations asynchronously - writeAsynchronousModuleElements(nodes); } - function emitExportDeclaration(node) { - emitJsDocComments(node); - write("export "); - if (node.exportClause) { - write("{ "); - emitCommaList(node.exportClause.elements, emitExportSpecifier); - write(" }"); + /** + * Adds the reference to referenced file, returns true if global file reference was emitted + * @param referencedFile + * @param addBundledFileReference Determines if global file reference corresponding to bundled file should be emitted or not + */ + function writeReferencePath(referencedFile, addBundledFileReference, emitOnlyDtsFiles) { + var declFileName; + var addedBundledEmitReference = false; + if (ts.isDeclarationFile(referencedFile)) { + // Declaration file, use declaration file name + declFileName = referencedFile.fileName; } else { - write("*"); - } - if (node.moduleSpecifier) { - write(" from "); - emitExternalModuleSpecifier(node); + // Get the declaration file path + ts.forEachExpectedEmitFile(host, getDeclFileName, referencedFile, emitOnlyDtsFiles); } - write(";"); - writer.writeLine(); - } - function writeModuleDeclaration(node) { - emitJsDocComments(node); - emitModuleElementDeclarationFlags(node); - if (ts.isGlobalScopeAugmentation(node)) { - write("global "); + if (declFileName) { + declFileName = ts.getRelativePathToDirectoryOrUrl(ts.getDirectoryPath(ts.normalizeSlashes(declarationFilePath)), declFileName, host.getCurrentDirectory(), host.getCanonicalFileName, + /*isAbsolutePathAnUrl*/ false); + referencesOutput += "/// " + newLine; } - else { - if (node.flags & 4096 /* Namespace */) { - write("namespace "); - } - else { - write("module "); - } - if (ts.isExternalModuleAugmentation(node)) { - emitExternalModuleSpecifier(node); - } - else { - writeTextOfNode(currentText, node.name); + return addedBundledEmitReference; + function getDeclFileName(emitFileNames, sourceFiles, isBundledEmit) { + // Dont add reference path to this file if it is a bundled emit and caller asked not emit bundled file path + if (isBundledEmit && !addBundledFileReference) { + return; } - } - while (node.body && node.body.kind !== 226 /* ModuleBlock */) { - node = node.body; - write("."); - writeTextOfNode(currentText, node.name); - } - var prevEnclosingDeclaration = enclosingDeclaration; - if (node.body) { - enclosingDeclaration = node; - write(" {"); - writeLine(); - increaseIndent(); - emitLines(node.body.statements); - decreaseIndent(); - write("}"); - writeLine(); - enclosingDeclaration = prevEnclosingDeclaration; - } - else { - write(";"); + ts.Debug.assert(!!emitFileNames.declarationFilePath || ts.isSourceFileJavaScript(referencedFile), "Declaration file is not present only for javascript files"); + declFileName = emitFileNames.declarationFilePath || emitFileNames.jsFilePath; + addedBundledEmitReference = isBundledEmit; } } - function writeTypeAliasDeclaration(node) { - var prevEnclosingDeclaration = enclosingDeclaration; - enclosingDeclaration = node; - emitJsDocComments(node); - emitModuleElementDeclarationFlags(node); - write("type "); - writeTextOfNode(currentText, node.name); - emitTypeParameters(node.typeParameters); - write(" = "); - emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError); - write(";"); - writeLine(); - enclosingDeclaration = prevEnclosingDeclaration; - function getTypeAliasDeclarationVisibilityError(symbolAccessibilityResult) { - return { - diagnosticMessage: ts.Diagnostics.Exported_type_alias_0_has_or_is_using_private_name_1, - errorNode: node.type, - typeName: node.name - }; - } + } + /* @internal */ + function writeDeclarationFile(declarationFilePath, sourceFiles, isBundledEmit, host, resolver, emitterDiagnostics, emitOnlyDtsFiles) { + var emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFiles, isBundledEmit, emitOnlyDtsFiles); + var emitSkipped = emitDeclarationResult.reportedDeclarationError || host.isEmitBlocked(declarationFilePath) || host.getCompilerOptions().noEmit; + if (!emitSkipped) { + var declarationOutput = emitDeclarationResult.referencesOutput + + getDeclarationOutput(emitDeclarationResult.synchronousDeclarationOutput, emitDeclarationResult.moduleElementDeclarationEmitInfo); + ts.writeFile(host, emitterDiagnostics, declarationFilePath, declarationOutput, host.getCompilerOptions().emitBOM, sourceFiles); } - function writeEnumDeclaration(node) { - emitJsDocComments(node); - emitModuleElementDeclarationFlags(node); - if (ts.isConst(node)) { - write("const "); - } - write("enum "); - writeTextOfNode(currentText, node.name); - write(" {"); - writeLine(); - increaseIndent(); - emitLines(node.members); - decreaseIndent(); - write("}"); - writeLine(); + return emitSkipped; + function getDeclarationOutput(synchronousDeclarationOutput, moduleElementDeclarationEmitInfo) { + var appliedSyncOutputPos = 0; + var declarationOutput = ""; + // apply asynchronous additions to the synchronous output + ts.forEach(moduleElementDeclarationEmitInfo, function (aliasEmitInfo) { + if (aliasEmitInfo.asynchronousOutput) { + declarationOutput += synchronousDeclarationOutput.substring(appliedSyncOutputPos, aliasEmitInfo.outputPos); + declarationOutput += getDeclarationOutput(aliasEmitInfo.asynchronousOutput, aliasEmitInfo.subModuleElementDeclarationEmitInfo); + appliedSyncOutputPos = aliasEmitInfo.outputPos; + } + }); + declarationOutput += synchronousDeclarationOutput.substring(appliedSyncOutputPos); + return declarationOutput; } - function emitEnumMemberDeclaration(node) { - emitJsDocComments(node); - writeTextOfNode(currentText, node.name); - var enumMemberValue = resolver.getConstantValue(node); - if (enumMemberValue !== undefined) { - write(" = "); - write(enumMemberValue.toString()); - } - write(","); - writeLine(); + } + ts.writeDeclarationFile = writeDeclarationFile; +})(ts || (ts = {})); +/// +/// +/// +/* @internal */ +var ts; +(function (ts) { + ; + /** + * This map contains information about the shape of each Node in "types.ts" pertaining to how + * each node should be traversed during a transformation. + * + * Each edge corresponds to a property in a Node subtype that should be traversed when visiting + * each child. The properties are assigned in the order in which traversal should occur. + * + * We only add entries for nodes that do not have a create/update pair defined in factory.ts + * + * NOTE: This needs to be kept up to date with changes to nodes in "types.ts". Currently, this + * map is not comprehensive. Only node edges relevant to tree transformation are + * currently defined. We may extend this to be more comprehensive, and eventually + * supplant the existing `forEachChild` implementation if performance is not + * significantly impacted. + */ + var nodeEdgeTraversalMap = ts.createMap((_a = {}, + _a[139 /* QualifiedName */] = [ + { name: "left", test: ts.isEntityName }, + { name: "right", test: ts.isIdentifier } + ], + _a[143 /* Decorator */] = [ + { name: "expression", test: ts.isLeftHandSideExpression } + ], + _a[177 /* TypeAssertionExpression */] = [ + { name: "type", test: ts.isTypeNode }, + { name: "expression", test: ts.isUnaryExpression } + ], + _a[195 /* AsExpression */] = [ + { name: "expression", test: ts.isExpression }, + { name: "type", test: ts.isTypeNode } + ], + _a[196 /* NonNullExpression */] = [ + { name: "expression", test: ts.isLeftHandSideExpression } + ], + _a[224 /* EnumDeclaration */] = [ + { name: "decorators", test: ts.isDecorator }, + { name: "modifiers", test: ts.isModifier }, + { name: "name", test: ts.isIdentifier }, + { name: "members", test: ts.isEnumMember } + ], + _a[225 /* ModuleDeclaration */] = [ + { name: "decorators", test: ts.isDecorator }, + { name: "modifiers", test: ts.isModifier }, + { name: "name", test: ts.isModuleName }, + { name: "body", test: ts.isModuleBody } + ], + _a[226 /* ModuleBlock */] = [ + { name: "statements", test: ts.isStatement } + ], + _a[229 /* ImportEqualsDeclaration */] = [ + { name: "decorators", test: ts.isDecorator }, + { name: "modifiers", test: ts.isModifier }, + { name: "name", test: ts.isIdentifier }, + { name: "moduleReference", test: ts.isModuleReference } + ], + _a[240 /* ExternalModuleReference */] = [ + { name: "expression", test: ts.isExpression, optional: true } + ], + _a[255 /* EnumMember */] = [ + { name: "name", test: ts.isPropertyName }, + { name: "initializer", test: ts.isExpression, optional: true, parenthesize: ts.parenthesizeExpressionForList } + ], + _a)); + function reduceNode(node, f, initial) { + return node ? f(initial, node) : initial; + } + /** + * Similar to `reduceLeft`, performs a reduction against each child of a node. + * NOTE: Unlike `forEachChild`, this does *not* visit every node. Only nodes added to the + * `nodeEdgeTraversalMap` above will be visited. + * + * @param node The node containing the children to reduce. + * @param f The callback function + * @param initial The initial value to supply to the reduction. + */ + function reduceEachChild(node, f, initial) { + if (node === undefined) { + return initial; } - function isPrivateMethodTypeParameter(node) { - return node.parent.kind === 147 /* MethodDeclaration */ && (node.parent.flags & 8 /* Private */); + var kind = node.kind; + // No need to visit nodes with no children. + if ((kind > 0 /* FirstToken */ && kind <= 138 /* LastToken */)) { + return initial; } - function emitTypeParameters(typeParameters) { - function emitTypeParameter(node) { - increaseIndent(); - emitJsDocComments(node); - decreaseIndent(); - writeTextOfNode(currentText, node.name); - // If there is constraint present and this is not a type parameter of the private method emit the constraint - if (node.constraint && !isPrivateMethodTypeParameter(node)) { - write(" extends "); - if (node.parent.kind === 156 /* FunctionType */ || - node.parent.kind === 157 /* ConstructorType */ || - (node.parent.parent && node.parent.parent.kind === 159 /* TypeLiteral */)) { - ts.Debug.assert(node.parent.kind === 147 /* MethodDeclaration */ || - node.parent.kind === 146 /* MethodSignature */ || - node.parent.kind === 156 /* FunctionType */ || - node.parent.kind === 157 /* ConstructorType */ || - node.parent.kind === 151 /* CallSignature */ || - node.parent.kind === 152 /* ConstructSignature */); - emitType(node.constraint); - } - else { - emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.constraint, getTypeParameterConstraintVisibilityError); - } - } - function getTypeParameterConstraintVisibilityError(symbolAccessibilityResult) { - // Type parameter constraints are named by user so we should always be able to name it - var diagnosticMessage; - switch (node.parent.kind) { - case 221 /* ClassDeclaration */: - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_class_has_or_is_using_private_name_1; - break; - case 222 /* InterfaceDeclaration */: - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1; - break; - case 152 /* ConstructSignature */: - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; - break; - case 151 /* CallSignature */: - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1; - break; - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - if (node.parent.flags & 32 /* Static */) { - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1; - } - else if (node.parent.parent.kind === 221 /* ClassDeclaration */) { - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1; - } - else { - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1; - } - break; - case 220 /* FunctionDeclaration */: - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_function_has_or_is_using_private_name_1; - break; - default: - ts.Debug.fail("This is unknown parent for type parameter: " + node.parent.kind); - } - return { - diagnosticMessage: diagnosticMessage, - errorNode: node, - typeName: node.name - }; - } - } - if (typeParameters) { - write("<"); - emitCommaList(typeParameters, emitTypeParameter); - write(">"); - } + // We do not yet support types. + if ((kind >= 154 /* TypePredicate */ && kind <= 166 /* LiteralType */)) { + return initial; } - function emitHeritageClause(typeReferences, isImplementsList) { - if (typeReferences) { - write(isImplementsList ? " implements " : " extends "); - emitCommaList(typeReferences, emitTypeOfTypeReference); - } - function emitTypeOfTypeReference(node) { - if (ts.isEntityNameExpression(node.expression)) { - emitTypeWithNewGetSymbolAccessibilityDiagnostic(node, getHeritageClauseVisibilityError); - } - else if (!isImplementsList && node.expression.kind === 93 /* NullKeyword */) { - write("null"); - } - else { - writer.getSymbolAccessibilityDiagnostic = getHeritageClauseVisibilityError; - resolver.writeBaseConstructorTypeOfClass(enclosingDeclaration, enclosingDeclaration, 2 /* UseTypeOfFunction */, writer); - } - function getHeritageClauseVisibilityError(symbolAccessibilityResult) { - var diagnosticMessage; - // Heritage clause is written by user so it can always be named - if (node.parent.parent.kind === 221 /* ClassDeclaration */) { - // Class or Interface implemented/extended is inaccessible - diagnosticMessage = isImplementsList ? - ts.Diagnostics.Implements_clause_of_exported_class_0_has_or_is_using_private_name_1 : - ts.Diagnostics.Extends_clause_of_exported_class_0_has_or_is_using_private_name_1; - } - else { - // interface is inaccessible - diagnosticMessage = ts.Diagnostics.Extends_clause_of_exported_interface_0_has_or_is_using_private_name_1; + var result = initial; + switch (node.kind) { + // Leaf nodes + case 198 /* SemicolonClassElement */: + case 201 /* EmptyStatement */: + case 193 /* OmittedExpression */: + case 217 /* DebuggerStatement */: + case 287 /* NotEmittedStatement */: + // No need to visit nodes with no children. + break; + // Names + case 140 /* ComputedPropertyName */: + result = reduceNode(node.expression, f, result); + break; + // Signature elements + case 142 /* Parameter */: + result = ts.reduceLeft(node.decorators, f, result); + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.name, f, result); + result = reduceNode(node.type, f, result); + result = reduceNode(node.initializer, f, result); + break; + case 143 /* Decorator */: + result = reduceNode(node.expression, f, result); + break; + // Type member + case 145 /* PropertyDeclaration */: + result = ts.reduceLeft(node.decorators, f, result); + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.name, f, result); + result = reduceNode(node.type, f, result); + result = reduceNode(node.initializer, f, result); + break; + case 147 /* MethodDeclaration */: + result = ts.reduceLeft(node.decorators, f, result); + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.name, f, result); + result = ts.reduceLeft(node.typeParameters, f, result); + result = ts.reduceLeft(node.parameters, f, result); + result = reduceNode(node.type, f, result); + result = reduceNode(node.body, f, result); + break; + case 148 /* Constructor */: + result = ts.reduceLeft(node.modifiers, f, result); + result = ts.reduceLeft(node.parameters, f, result); + result = reduceNode(node.body, f, result); + break; + case 149 /* GetAccessor */: + result = ts.reduceLeft(node.decorators, f, result); + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.name, f, result); + result = ts.reduceLeft(node.parameters, f, result); + result = reduceNode(node.type, f, result); + result = reduceNode(node.body, f, result); + break; + case 150 /* SetAccessor */: + result = ts.reduceLeft(node.decorators, f, result); + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.name, f, result); + result = ts.reduceLeft(node.parameters, f, result); + result = reduceNode(node.body, f, result); + break; + // Binding patterns + case 167 /* ObjectBindingPattern */: + case 168 /* ArrayBindingPattern */: + result = ts.reduceLeft(node.elements, f, result); + break; + case 169 /* BindingElement */: + result = reduceNode(node.propertyName, f, result); + result = reduceNode(node.name, f, result); + result = reduceNode(node.initializer, f, result); + break; + // Expression + case 170 /* ArrayLiteralExpression */: + result = ts.reduceLeft(node.elements, f, result); + break; + case 171 /* ObjectLiteralExpression */: + result = ts.reduceLeft(node.properties, f, result); + break; + case 172 /* PropertyAccessExpression */: + result = reduceNode(node.expression, f, result); + result = reduceNode(node.name, f, result); + break; + case 173 /* ElementAccessExpression */: + result = reduceNode(node.expression, f, result); + result = reduceNode(node.argumentExpression, f, result); + break; + case 174 /* CallExpression */: + result = reduceNode(node.expression, f, result); + result = ts.reduceLeft(node.typeArguments, f, result); + result = ts.reduceLeft(node.arguments, f, result); + break; + case 175 /* NewExpression */: + result = reduceNode(node.expression, f, result); + result = ts.reduceLeft(node.typeArguments, f, result); + result = ts.reduceLeft(node.arguments, f, result); + break; + case 176 /* TaggedTemplateExpression */: + result = reduceNode(node.tag, f, result); + result = reduceNode(node.template, f, result); + break; + case 179 /* FunctionExpression */: + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.name, f, result); + result = ts.reduceLeft(node.typeParameters, f, result); + result = ts.reduceLeft(node.parameters, f, result); + result = reduceNode(node.type, f, result); + result = reduceNode(node.body, f, result); + break; + case 180 /* ArrowFunction */: + result = ts.reduceLeft(node.modifiers, f, result); + result = ts.reduceLeft(node.typeParameters, f, result); + result = ts.reduceLeft(node.parameters, f, result); + result = reduceNode(node.type, f, result); + result = reduceNode(node.body, f, result); + break; + case 178 /* ParenthesizedExpression */: + case 181 /* DeleteExpression */: + case 182 /* TypeOfExpression */: + case 183 /* VoidExpression */: + case 184 /* AwaitExpression */: + case 190 /* YieldExpression */: + case 191 /* SpreadElementExpression */: + case 196 /* NonNullExpression */: + result = reduceNode(node.expression, f, result); + break; + case 185 /* PrefixUnaryExpression */: + case 186 /* PostfixUnaryExpression */: + result = reduceNode(node.operand, f, result); + break; + case 187 /* BinaryExpression */: + result = reduceNode(node.left, f, result); + result = reduceNode(node.right, f, result); + break; + case 188 /* ConditionalExpression */: + result = reduceNode(node.condition, f, result); + result = reduceNode(node.whenTrue, f, result); + result = reduceNode(node.whenFalse, f, result); + break; + case 189 /* TemplateExpression */: + result = reduceNode(node.head, f, result); + result = ts.reduceLeft(node.templateSpans, f, result); + break; + case 192 /* ClassExpression */: + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.name, f, result); + result = ts.reduceLeft(node.typeParameters, f, result); + result = ts.reduceLeft(node.heritageClauses, f, result); + result = ts.reduceLeft(node.members, f, result); + break; + case 194 /* ExpressionWithTypeArguments */: + result = reduceNode(node.expression, f, result); + result = ts.reduceLeft(node.typeArguments, f, result); + break; + // Misc + case 197 /* TemplateSpan */: + result = reduceNode(node.expression, f, result); + result = reduceNode(node.literal, f, result); + break; + // Element + case 199 /* Block */: + result = ts.reduceLeft(node.statements, f, result); + break; + case 200 /* VariableStatement */: + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.declarationList, f, result); + break; + case 202 /* ExpressionStatement */: + result = reduceNode(node.expression, f, result); + break; + case 203 /* IfStatement */: + result = reduceNode(node.expression, f, result); + result = reduceNode(node.thenStatement, f, result); + result = reduceNode(node.elseStatement, f, result); + break; + case 204 /* DoStatement */: + result = reduceNode(node.statement, f, result); + result = reduceNode(node.expression, f, result); + break; + case 205 /* WhileStatement */: + case 212 /* WithStatement */: + result = reduceNode(node.expression, f, result); + result = reduceNode(node.statement, f, result); + break; + case 206 /* ForStatement */: + result = reduceNode(node.initializer, f, result); + result = reduceNode(node.condition, f, result); + result = reduceNode(node.incrementor, f, result); + result = reduceNode(node.statement, f, result); + break; + case 207 /* ForInStatement */: + case 208 /* ForOfStatement */: + result = reduceNode(node.initializer, f, result); + result = reduceNode(node.expression, f, result); + result = reduceNode(node.statement, f, result); + break; + case 211 /* ReturnStatement */: + case 215 /* ThrowStatement */: + result = reduceNode(node.expression, f, result); + break; + case 213 /* SwitchStatement */: + result = reduceNode(node.expression, f, result); + result = reduceNode(node.caseBlock, f, result); + break; + case 214 /* LabeledStatement */: + result = reduceNode(node.label, f, result); + result = reduceNode(node.statement, f, result); + break; + case 216 /* TryStatement */: + result = reduceNode(node.tryBlock, f, result); + result = reduceNode(node.catchClause, f, result); + result = reduceNode(node.finallyBlock, f, result); + break; + case 218 /* VariableDeclaration */: + result = reduceNode(node.name, f, result); + result = reduceNode(node.type, f, result); + result = reduceNode(node.initializer, f, result); + break; + case 219 /* VariableDeclarationList */: + result = ts.reduceLeft(node.declarations, f, result); + break; + case 220 /* FunctionDeclaration */: + result = ts.reduceLeft(node.decorators, f, result); + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.name, f, result); + result = ts.reduceLeft(node.typeParameters, f, result); + result = ts.reduceLeft(node.parameters, f, result); + result = reduceNode(node.type, f, result); + result = reduceNode(node.body, f, result); + break; + case 221 /* ClassDeclaration */: + result = ts.reduceLeft(node.decorators, f, result); + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.name, f, result); + result = ts.reduceLeft(node.typeParameters, f, result); + result = ts.reduceLeft(node.heritageClauses, f, result); + result = ts.reduceLeft(node.members, f, result); + break; + case 227 /* CaseBlock */: + result = ts.reduceLeft(node.clauses, f, result); + break; + case 230 /* ImportDeclaration */: + result = ts.reduceLeft(node.decorators, f, result); + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.importClause, f, result); + result = reduceNode(node.moduleSpecifier, f, result); + break; + case 231 /* ImportClause */: + result = reduceNode(node.name, f, result); + result = reduceNode(node.namedBindings, f, result); + break; + case 232 /* NamespaceImport */: + result = reduceNode(node.name, f, result); + break; + case 233 /* NamedImports */: + case 237 /* NamedExports */: + result = ts.reduceLeft(node.elements, f, result); + break; + case 234 /* ImportSpecifier */: + case 238 /* ExportSpecifier */: + result = reduceNode(node.propertyName, f, result); + result = reduceNode(node.name, f, result); + break; + case 235 /* ExportAssignment */: + result = ts.reduceLeft(node.decorators, f, result); + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.expression, f, result); + break; + case 236 /* ExportDeclaration */: + result = ts.reduceLeft(node.decorators, f, result); + result = ts.reduceLeft(node.modifiers, f, result); + result = reduceNode(node.exportClause, f, result); + result = reduceNode(node.moduleSpecifier, f, result); + break; + // JSX + case 241 /* JsxElement */: + result = reduceNode(node.openingElement, f, result); + result = ts.reduceLeft(node.children, f, result); + result = reduceNode(node.closingElement, f, result); + break; + case 242 /* JsxSelfClosingElement */: + case 243 /* JsxOpeningElement */: + result = reduceNode(node.tagName, f, result); + result = ts.reduceLeft(node.attributes, f, result); + break; + case 245 /* JsxClosingElement */: + result = reduceNode(node.tagName, f, result); + break; + case 246 /* JsxAttribute */: + result = reduceNode(node.name, f, result); + result = reduceNode(node.initializer, f, result); + break; + case 247 /* JsxSpreadAttribute */: + result = reduceNode(node.expression, f, result); + break; + case 248 /* JsxExpression */: + result = reduceNode(node.expression, f, result); + break; + // Clauses + case 249 /* CaseClause */: + result = reduceNode(node.expression, f, result); + // fall-through + case 250 /* DefaultClause */: + result = ts.reduceLeft(node.statements, f, result); + break; + case 251 /* HeritageClause */: + result = ts.reduceLeft(node.types, f, result); + break; + case 252 /* CatchClause */: + result = reduceNode(node.variableDeclaration, f, result); + result = reduceNode(node.block, f, result); + break; + // Property assignments + case 253 /* PropertyAssignment */: + result = reduceNode(node.name, f, result); + result = reduceNode(node.initializer, f, result); + break; + case 254 /* ShorthandPropertyAssignment */: + result = reduceNode(node.name, f, result); + result = reduceNode(node.objectAssignmentInitializer, f, result); + break; + // Top-level nodes + case 256 /* SourceFile */: + result = ts.reduceLeft(node.statements, f, result); + break; + case 288 /* PartiallyEmittedExpression */: + result = reduceNode(node.expression, f, result); + break; + default: + var edgeTraversalPath = nodeEdgeTraversalMap[kind]; + if (edgeTraversalPath) { + for (var _i = 0, edgeTraversalPath_1 = edgeTraversalPath; _i < edgeTraversalPath_1.length; _i++) { + var edge = edgeTraversalPath_1[_i]; + var value = node[edge.name]; + if (value !== undefined) { + result = ts.isArray(value) + ? ts.reduceLeft(value, f, result) + : f(result, value); + } } - return { - diagnosticMessage: diagnosticMessage, - errorNode: node, - typeName: node.parent.parent.name - }; } - } + break; } - function writeClassDeclaration(node) { - function emitParameterProperties(constructorDeclaration) { - if (constructorDeclaration) { - ts.forEach(constructorDeclaration.parameters, function (param) { - if (param.flags & 92 /* ParameterPropertyModifier */) { - emitPropertyDeclaration(param); - } - }); - } - } - emitJsDocComments(node); - emitModuleElementDeclarationFlags(node); - if (node.flags & 128 /* Abstract */) { - write("abstract "); - } - write("class "); - writeTextOfNode(currentText, node.name); - var prevEnclosingDeclaration = enclosingDeclaration; - enclosingDeclaration = node; - emitTypeParameters(node.typeParameters); - var baseTypeNode = ts.getClassExtendsHeritageClauseElement(node); - if (baseTypeNode) { - emitHeritageClause([baseTypeNode], /*isImplementsList*/ false); - } - emitHeritageClause(ts.getClassImplementsHeritageClauseElements(node), /*isImplementsList*/ true); - write(" {"); - writeLine(); - increaseIndent(); - emitParameterProperties(ts.getFirstConstructorWithBody(node)); - emitLines(node.members); - decreaseIndent(); - write("}"); - writeLine(); - enclosingDeclaration = prevEnclosingDeclaration; + return result; + } + ts.reduceEachChild = reduceEachChild; + function visitNode(node, visitor, test, optional, lift, parenthesize, parentNode) { + if (node === undefined) { + return undefined; } - function writeInterfaceDeclaration(node) { - emitJsDocComments(node); - emitModuleElementDeclarationFlags(node); - write("interface "); - writeTextOfNode(currentText, node.name); - var prevEnclosingDeclaration = enclosingDeclaration; - enclosingDeclaration = node; - emitTypeParameters(node.typeParameters); - emitHeritageClause(ts.getInterfaceBaseTypeNodes(node), /*isImplementsList*/ false); - write(" {"); - writeLine(); - increaseIndent(); - emitLines(node.members); - decreaseIndent(); - write("}"); - writeLine(); - enclosingDeclaration = prevEnclosingDeclaration; + var visited = visitor(node); + if (visited === node) { + return node; } - function emitPropertyDeclaration(node) { - if (ts.hasDynamicName(node)) { - return; + var visitedNode; + if (visited === undefined) { + if (!optional) { + Debug.failNotOptional(); } - emitJsDocComments(node); - emitClassMemberDeclarationFlags(node.flags); - emitVariableDeclaration(node); - write(";"); - writeLine(); + return undefined; } - function emitVariableDeclaration(node) { - // If we are emitting property it isn't moduleElement and hence we already know it needs to be emitted - // so there is no check needed to see if declaration is visible - if (node.kind !== 218 /* VariableDeclaration */ || resolver.isDeclarationVisible(node)) { - if (ts.isBindingPattern(node.name)) { - emitBindingPattern(node.name); - } - else { - // If this node is a computed name, it can only be a symbol, because we've already skipped - // it if it's not a well known symbol. In that case, the text of the name will be exactly - // what we want, namely the name expression enclosed in brackets. - writeTextOfNode(currentText, node.name); - // If optional property emit ? but in the case of parameterProperty declaration with "?" indicating optional parameter for the constructor - // we don't want to emit property declaration with "?" - if ((node.kind === 145 /* PropertyDeclaration */ || node.kind === 144 /* PropertySignature */ || - (node.kind === 142 /* Parameter */ && !ts.isParameterPropertyDeclaration(node))) && ts.hasQuestionToken(node)) { - write("?"); - } - if ((node.kind === 145 /* PropertyDeclaration */ || node.kind === 144 /* PropertySignature */) && node.parent.kind === 159 /* TypeLiteral */) { - emitTypeOfVariableDeclarationFromTypeLiteral(node); - } - else if (!(node.flags & 8 /* Private */)) { - writeTypeOfDeclaration(node, node.type, getVariableDeclarationTypeVisibilityError); - } - } - } - function getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult) { - if (node.kind === 218 /* VariableDeclaration */) { - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? - ts.Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Exported_variable_0_has_or_is_using_private_name_1; - } - else if (node.kind === 145 /* PropertyDeclaration */ || node.kind === 144 /* PropertySignature */) { - // TODO(jfreeman): Deal with computed properties in error reporting. - if (node.flags & 32 /* Static */) { - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? - ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_private_name_1; - } - else if (node.parent.kind === 221 /* ClassDeclaration */) { - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? - ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_private_name_1; - } - else { - // Interfaces cannot have types that cannot be named - return symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Property_0_of_exported_interface_has_or_is_using_private_name_1; - } - } - } - function getVariableDeclarationTypeVisibilityError(symbolAccessibilityResult) { - var diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult); - return diagnosticMessage !== undefined ? { - diagnosticMessage: diagnosticMessage, - errorNode: node, - typeName: node.name - } : undefined; - } - function emitBindingPattern(bindingPattern) { - // Only select non-omitted expression from the bindingPattern's elements. - // We have to do this to avoid emitting trailing commas. - // For example: - // original: var [, c,,] = [ 2,3,4] - // emitted: declare var c: number; // instead of declare var c:number, ; - var elements = []; - for (var _i = 0, _a = bindingPattern.elements; _i < _a.length; _i++) { - var element = _a[_i]; - if (element.kind !== 193 /* OmittedExpression */) { - elements.push(element); - } - } - emitCommaList(elements, emitBindingElement); - } - function emitBindingElement(bindingElement) { - function getBindingElementTypeVisibilityError(symbolAccessibilityResult) { - var diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult); - return diagnosticMessage !== undefined ? { - diagnosticMessage: diagnosticMessage, - errorNode: bindingElement, - typeName: bindingElement.name - } : undefined; - } - if (bindingElement.name) { - if (ts.isBindingPattern(bindingElement.name)) { - emitBindingPattern(bindingElement.name); - } - else { - writeTextOfNode(currentText, bindingElement.name); - writeTypeOfDeclaration(bindingElement, /*type*/ undefined, getBindingElementTypeVisibilityError); - } - } - } + else if (ts.isArray(visited)) { + visitedNode = (lift || extractSingleNode)(visited); } - function emitTypeOfVariableDeclarationFromTypeLiteral(node) { - // if this is property of type literal, - // or is parameter of method/call/construct/index signature of type literal - // emit only if type is specified - if (node.type) { - write(": "); - emitType(node.type); - } + else { + visitedNode = visited; } - function isVariableStatementVisible(node) { - return ts.forEach(node.declarationList.declarations, function (varDeclaration) { return resolver.isDeclarationVisible(varDeclaration); }); + if (parenthesize !== undefined) { + visitedNode = parenthesize(visitedNode, parentNode); } - function writeVariableStatement(node) { - emitJsDocComments(node); - emitModuleElementDeclarationFlags(node); - if (ts.isLet(node.declarationList)) { - write("let "); - } - else if (ts.isConst(node.declarationList)) { - write("const "); - } - else { - write("var "); - } - emitCommaList(node.declarationList.declarations, emitVariableDeclaration, resolver.isDeclarationVisible); - write(";"); - writeLine(); + Debug.assertNode(visitedNode, test); + aggregateTransformFlags(visitedNode); + return visitedNode; + } + ts.visitNode = visitNode; + function visitNodes(nodes, visitor, test, start, count, parenthesize, parentNode) { + if (nodes === undefined) { + return undefined; } - function emitAccessorDeclaration(node) { - if (ts.hasDynamicName(node)) { - return; - } - var accessors = ts.getAllAccessorDeclarations(node.parent.members, node); - var accessorWithTypeAnnotation; - if (node === accessors.firstAccessor) { - emitJsDocComments(accessors.getAccessor); - emitJsDocComments(accessors.setAccessor); - emitClassMemberDeclarationFlags(node.flags | (accessors.setAccessor ? 0 : 64 /* Readonly */)); - writeTextOfNode(currentText, node.name); - if (!(node.flags & 8 /* Private */)) { - accessorWithTypeAnnotation = node; - var type = getTypeAnnotationFromAccessor(node); - if (!type) { - // couldn't get type for the first accessor, try the another one - var anotherAccessor = node.kind === 149 /* GetAccessor */ ? accessors.setAccessor : accessors.getAccessor; - type = getTypeAnnotationFromAccessor(anotherAccessor); - if (type) { - accessorWithTypeAnnotation = anotherAccessor; + var updated; + // Ensure start and count have valid values + var length = nodes.length; + if (start === undefined || start < 0) { + start = 0; + } + if (count === undefined || count > length - start) { + count = length - start; + } + if (start > 0 || count < length) { + // If we are not visiting all of the original nodes, we must always create a new array. + // Since this is a fragment of a node array, we do not copy over the previous location + // and will only copy over `hasTrailingComma` if we are including the last element. + updated = ts.createNodeArray([], /*location*/ undefined, + /*hasTrailingComma*/ nodes.hasTrailingComma && start + count === length); + } + // Visit each original node. + for (var i = 0; i < count; i++) { + var node = nodes[i + start]; + var visited = node !== undefined ? visitor(node) : undefined; + if (updated !== undefined || visited === undefined || visited !== node) { + if (updated === undefined) { + // Ensure we have a copy of `nodes`, up to the current index. + updated = ts.createNodeArray(nodes.slice(0, i), /*location*/ nodes, nodes.hasTrailingComma); + } + if (visited) { + if (ts.isArray(visited)) { + for (var _i = 0, visited_1 = visited; _i < visited_1.length; _i++) { + var visitedNode = visited_1[_i]; + visitedNode = parenthesize + ? parenthesize(visitedNode, parentNode) + : visitedNode; + Debug.assertNode(visitedNode, test); + aggregateTransformFlags(visitedNode); + updated.push(visitedNode); } } - writeTypeOfDeclaration(node, type, getAccessorDeclarationTypeVisibilityError); - } - write(";"); - writeLine(); - } - function getTypeAnnotationFromAccessor(accessor) { - if (accessor) { - return accessor.kind === 149 /* GetAccessor */ - ? accessor.type // Getter - return type - : accessor.parameters.length > 0 - ? accessor.parameters[0].type // Setter parameter type - : undefined; - } - } - function getAccessorDeclarationTypeVisibilityError(symbolAccessibilityResult) { - var diagnosticMessage; - if (accessorWithTypeAnnotation.kind === 150 /* SetAccessor */) { - // Setters have to have type named and cannot infer it so, the type should always be named - if (accessorWithTypeAnnotation.parent.flags & 32 /* Static */) { - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_private_name_1; - } - else { - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_private_name_1; - } - return { - diagnosticMessage: diagnosticMessage, - errorNode: accessorWithTypeAnnotation.parameters[0], - // TODO(jfreeman): Investigate why we are passing node.name instead of node.parameters[0].name - typeName: accessorWithTypeAnnotation.name - }; - } - else { - if (accessorWithTypeAnnotation.flags & 32 /* Static */) { - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? - ts.Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : - ts.Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_private_name_0; - } else { - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? - ts.Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : - ts.Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_private_name_0; + var visitedNode = parenthesize + ? parenthesize(visited, parentNode) + : visited; + Debug.assertNode(visitedNode, test); + aggregateTransformFlags(visitedNode); + updated.push(visitedNode); } - return { - diagnosticMessage: diagnosticMessage, - errorNode: accessorWithTypeAnnotation.name, - typeName: undefined - }; } } } - function writeFunctionDeclaration(node) { - if (ts.hasDynamicName(node)) { - return; - } - // If we are emitting Method/Constructor it isn't moduleElement and hence already determined to be emitting - // so no need to verify if the declaration is visible - if (!resolver.isImplementationOfOverload(node)) { - emitJsDocComments(node); - if (node.kind === 220 /* FunctionDeclaration */) { - emitModuleElementDeclarationFlags(node); - } - else if (node.kind === 147 /* MethodDeclaration */ || node.kind === 148 /* Constructor */) { - emitClassMemberDeclarationFlags(node.flags); - } - if (node.kind === 220 /* FunctionDeclaration */) { - write("function "); - writeTextOfNode(currentText, node.name); - } - else if (node.kind === 148 /* Constructor */) { - write("constructor"); - } - else { - writeTextOfNode(currentText, node.name); - if (ts.hasQuestionToken(node)) { - write("?"); - } - } - emitSignatureDeclaration(node); - } + return updated || nodes; + } + ts.visitNodes = visitNodes; + function visitEachChild(node, visitor, context) { + if (node === undefined) { + return undefined; } - function emitSignatureDeclarationWithJsDocComments(node) { - emitJsDocComments(node); - emitSignatureDeclaration(node); + var kind = node.kind; + // No need to visit nodes with no children. + if ((kind > 0 /* FirstToken */ && kind <= 138 /* LastToken */)) { + return node; } - function emitSignatureDeclaration(node) { - var prevEnclosingDeclaration = enclosingDeclaration; - enclosingDeclaration = node; - var closeParenthesizedFunctionType = false; - if (node.kind === 153 /* IndexSignature */) { - // Index signature can have readonly modifier - emitClassMemberDeclarationFlags(node.flags); - write("["); - } - else { - // Construct signature or constructor type write new Signature - if (node.kind === 152 /* ConstructSignature */ || node.kind === 157 /* ConstructorType */) { - write("new "); - } - else if (node.kind === 156 /* FunctionType */) { - var currentOutput = writer.getText(); - // Do not generate incorrect type when function type with type parameters is type argument - // This could happen if user used space between two '<' making it error free - // e.g var x: A< (a: Tany)=>Tany>; - if (node.typeParameters && currentOutput.charAt(currentOutput.length - 1) === "<") { - closeParenthesizedFunctionType = true; - write("("); + // We do not yet support types. + if ((kind >= 154 /* TypePredicate */ && kind <= 166 /* LiteralType */)) { + return node; + } + switch (node.kind) { + case 198 /* SemicolonClassElement */: + case 201 /* EmptyStatement */: + case 193 /* OmittedExpression */: + case 217 /* DebuggerStatement */: + // No need to visit nodes with no children. + return node; + // Names + case 140 /* ComputedPropertyName */: + return ts.updateComputedPropertyName(node, visitNode(node.expression, visitor, ts.isExpression)); + // Signature elements + case 142 /* Parameter */: + return ts.updateParameterDeclaration(node, visitNodes(node.decorators, visitor, ts.isDecorator), visitNodes(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isBindingName), visitNode(node.type, visitor, ts.isTypeNode, /*optional*/ true), visitNode(node.initializer, visitor, ts.isExpression, /*optional*/ true)); + // Type member + case 145 /* PropertyDeclaration */: + return ts.updateProperty(node, visitNodes(node.decorators, visitor, ts.isDecorator), visitNodes(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isPropertyName), visitNode(node.type, visitor, ts.isTypeNode, /*optional*/ true), visitNode(node.initializer, visitor, ts.isExpression, /*optional*/ true)); + case 147 /* MethodDeclaration */: + return ts.updateMethod(node, visitNodes(node.decorators, visitor, ts.isDecorator), visitNodes(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isPropertyName), visitNodes(node.typeParameters, visitor, ts.isTypeParameter), (context.startLexicalEnvironment(), visitNodes(node.parameters, visitor, ts.isParameter)), visitNode(node.type, visitor, ts.isTypeNode, /*optional*/ true), mergeFunctionBodyLexicalEnvironment(visitNode(node.body, visitor, ts.isFunctionBody, /*optional*/ true), context.endLexicalEnvironment())); + case 148 /* Constructor */: + return ts.updateConstructor(node, visitNodes(node.decorators, visitor, ts.isDecorator), visitNodes(node.modifiers, visitor, ts.isModifier), (context.startLexicalEnvironment(), visitNodes(node.parameters, visitor, ts.isParameter)), mergeFunctionBodyLexicalEnvironment(visitNode(node.body, visitor, ts.isFunctionBody, /*optional*/ true), context.endLexicalEnvironment())); + case 149 /* GetAccessor */: + return ts.updateGetAccessor(node, visitNodes(node.decorators, visitor, ts.isDecorator), visitNodes(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isPropertyName), (context.startLexicalEnvironment(), visitNodes(node.parameters, visitor, ts.isParameter)), visitNode(node.type, visitor, ts.isTypeNode, /*optional*/ true), mergeFunctionBodyLexicalEnvironment(visitNode(node.body, visitor, ts.isFunctionBody, /*optional*/ true), context.endLexicalEnvironment())); + case 150 /* SetAccessor */: + return ts.updateSetAccessor(node, visitNodes(node.decorators, visitor, ts.isDecorator), visitNodes(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isPropertyName), (context.startLexicalEnvironment(), visitNodes(node.parameters, visitor, ts.isParameter)), mergeFunctionBodyLexicalEnvironment(visitNode(node.body, visitor, ts.isFunctionBody, /*optional*/ true), context.endLexicalEnvironment())); + // Binding patterns + case 167 /* ObjectBindingPattern */: + return ts.updateObjectBindingPattern(node, visitNodes(node.elements, visitor, ts.isBindingElement)); + case 168 /* ArrayBindingPattern */: + return ts.updateArrayBindingPattern(node, visitNodes(node.elements, visitor, ts.isArrayBindingElement)); + case 169 /* BindingElement */: + return ts.updateBindingElement(node, visitNode(node.propertyName, visitor, ts.isPropertyName, /*optional*/ true), visitNode(node.name, visitor, ts.isBindingName), visitNode(node.initializer, visitor, ts.isExpression, /*optional*/ true)); + // Expression + case 170 /* ArrayLiteralExpression */: + return ts.updateArrayLiteral(node, visitNodes(node.elements, visitor, ts.isExpression)); + case 171 /* ObjectLiteralExpression */: + return ts.updateObjectLiteral(node, visitNodes(node.properties, visitor, ts.isObjectLiteralElementLike)); + case 172 /* PropertyAccessExpression */: + return ts.updatePropertyAccess(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.name, visitor, ts.isIdentifier)); + case 173 /* ElementAccessExpression */: + return ts.updateElementAccess(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.argumentExpression, visitor, ts.isExpression)); + case 174 /* CallExpression */: + return ts.updateCall(node, visitNode(node.expression, visitor, ts.isExpression), visitNodes(node.typeArguments, visitor, ts.isTypeNode), visitNodes(node.arguments, visitor, ts.isExpression)); + case 175 /* NewExpression */: + return ts.updateNew(node, visitNode(node.expression, visitor, ts.isExpression), visitNodes(node.typeArguments, visitor, ts.isTypeNode), visitNodes(node.arguments, visitor, ts.isExpression)); + case 176 /* TaggedTemplateExpression */: + return ts.updateTaggedTemplate(node, visitNode(node.tag, visitor, ts.isExpression), visitNode(node.template, visitor, ts.isTemplate)); + case 178 /* ParenthesizedExpression */: + return ts.updateParen(node, visitNode(node.expression, visitor, ts.isExpression)); + case 179 /* FunctionExpression */: + return ts.updateFunctionExpression(node, visitNode(node.name, visitor, ts.isPropertyName), visitNodes(node.typeParameters, visitor, ts.isTypeParameter), (context.startLexicalEnvironment(), visitNodes(node.parameters, visitor, ts.isParameter)), visitNode(node.type, visitor, ts.isTypeNode, /*optional*/ true), mergeFunctionBodyLexicalEnvironment(visitNode(node.body, visitor, ts.isFunctionBody, /*optional*/ true), context.endLexicalEnvironment())); + case 180 /* ArrowFunction */: + return ts.updateArrowFunction(node, visitNodes(node.modifiers, visitor, ts.isModifier), visitNodes(node.typeParameters, visitor, ts.isTypeParameter), (context.startLexicalEnvironment(), visitNodes(node.parameters, visitor, ts.isParameter)), visitNode(node.type, visitor, ts.isTypeNode, /*optional*/ true), mergeFunctionBodyLexicalEnvironment(visitNode(node.body, visitor, ts.isConciseBody, /*optional*/ true), context.endLexicalEnvironment())); + case 181 /* DeleteExpression */: + return ts.updateDelete(node, visitNode(node.expression, visitor, ts.isExpression)); + case 182 /* TypeOfExpression */: + return ts.updateTypeOf(node, visitNode(node.expression, visitor, ts.isExpression)); + case 183 /* VoidExpression */: + return ts.updateVoid(node, visitNode(node.expression, visitor, ts.isExpression)); + case 184 /* AwaitExpression */: + return ts.updateAwait(node, visitNode(node.expression, visitor, ts.isExpression)); + case 187 /* BinaryExpression */: + return ts.updateBinary(node, visitNode(node.left, visitor, ts.isExpression), visitNode(node.right, visitor, ts.isExpression)); + case 185 /* PrefixUnaryExpression */: + return ts.updatePrefix(node, visitNode(node.operand, visitor, ts.isExpression)); + case 186 /* PostfixUnaryExpression */: + return ts.updatePostfix(node, visitNode(node.operand, visitor, ts.isExpression)); + case 188 /* ConditionalExpression */: + return ts.updateConditional(node, visitNode(node.condition, visitor, ts.isExpression), visitNode(node.whenTrue, visitor, ts.isExpression), visitNode(node.whenFalse, visitor, ts.isExpression)); + case 189 /* TemplateExpression */: + return ts.updateTemplateExpression(node, visitNode(node.head, visitor, ts.isTemplateLiteralFragment), visitNodes(node.templateSpans, visitor, ts.isTemplateSpan)); + case 190 /* YieldExpression */: + return ts.updateYield(node, visitNode(node.expression, visitor, ts.isExpression)); + case 191 /* SpreadElementExpression */: + return ts.updateSpread(node, visitNode(node.expression, visitor, ts.isExpression)); + case 192 /* ClassExpression */: + return ts.updateClassExpression(node, visitNodes(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isIdentifier, /*optional*/ true), visitNodes(node.typeParameters, visitor, ts.isTypeParameter), visitNodes(node.heritageClauses, visitor, ts.isHeritageClause), visitNodes(node.members, visitor, ts.isClassElement)); + case 194 /* ExpressionWithTypeArguments */: + return ts.updateExpressionWithTypeArguments(node, visitNodes(node.typeArguments, visitor, ts.isTypeNode), visitNode(node.expression, visitor, ts.isExpression)); + // Misc + case 197 /* TemplateSpan */: + return ts.updateTemplateSpan(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.literal, visitor, ts.isTemplateLiteralFragment)); + // Element + case 199 /* Block */: + return ts.updateBlock(node, visitNodes(node.statements, visitor, ts.isStatement)); + case 200 /* VariableStatement */: + return ts.updateVariableStatement(node, visitNodes(node.modifiers, visitor, ts.isModifier), visitNode(node.declarationList, visitor, ts.isVariableDeclarationList)); + case 202 /* ExpressionStatement */: + return ts.updateStatement(node, visitNode(node.expression, visitor, ts.isExpression)); + case 203 /* IfStatement */: + return ts.updateIf(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.thenStatement, visitor, ts.isStatement, /*optional*/ false, liftToBlock), visitNode(node.elseStatement, visitor, ts.isStatement, /*optional*/ true, liftToBlock)); + case 204 /* DoStatement */: + return ts.updateDo(node, visitNode(node.statement, visitor, ts.isStatement, /*optional*/ false, liftToBlock), visitNode(node.expression, visitor, ts.isExpression)); + case 205 /* WhileStatement */: + return ts.updateWhile(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.statement, visitor, ts.isStatement, /*optional*/ false, liftToBlock)); + case 206 /* ForStatement */: + return ts.updateFor(node, visitNode(node.initializer, visitor, ts.isForInitializer), visitNode(node.condition, visitor, ts.isExpression), visitNode(node.incrementor, visitor, ts.isExpression), visitNode(node.statement, visitor, ts.isStatement, /*optional*/ false, liftToBlock)); + case 207 /* ForInStatement */: + return ts.updateForIn(node, visitNode(node.initializer, visitor, ts.isForInitializer), visitNode(node.expression, visitor, ts.isExpression), visitNode(node.statement, visitor, ts.isStatement, /*optional*/ false, liftToBlock)); + case 208 /* ForOfStatement */: + return ts.updateForOf(node, visitNode(node.initializer, visitor, ts.isForInitializer), visitNode(node.expression, visitor, ts.isExpression), visitNode(node.statement, visitor, ts.isStatement, /*optional*/ false, liftToBlock)); + case 209 /* ContinueStatement */: + return ts.updateContinue(node, visitNode(node.label, visitor, ts.isIdentifier, /*optional*/ true)); + case 210 /* BreakStatement */: + return ts.updateBreak(node, visitNode(node.label, visitor, ts.isIdentifier, /*optional*/ true)); + case 211 /* ReturnStatement */: + return ts.updateReturn(node, visitNode(node.expression, visitor, ts.isExpression, /*optional*/ true)); + case 212 /* WithStatement */: + return ts.updateWith(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.statement, visitor, ts.isStatement, /*optional*/ false, liftToBlock)); + case 213 /* SwitchStatement */: + return ts.updateSwitch(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.caseBlock, visitor, ts.isCaseBlock)); + case 214 /* LabeledStatement */: + return ts.updateLabel(node, visitNode(node.label, visitor, ts.isIdentifier), visitNode(node.statement, visitor, ts.isStatement, /*optional*/ false, liftToBlock)); + case 215 /* ThrowStatement */: + return ts.updateThrow(node, visitNode(node.expression, visitor, ts.isExpression)); + case 216 /* TryStatement */: + return ts.updateTry(node, visitNode(node.tryBlock, visitor, ts.isBlock), visitNode(node.catchClause, visitor, ts.isCatchClause, /*optional*/ true), visitNode(node.finallyBlock, visitor, ts.isBlock, /*optional*/ true)); + case 218 /* VariableDeclaration */: + return ts.updateVariableDeclaration(node, visitNode(node.name, visitor, ts.isBindingName), visitNode(node.type, visitor, ts.isTypeNode, /*optional*/ true), visitNode(node.initializer, visitor, ts.isExpression, /*optional*/ true)); + case 219 /* VariableDeclarationList */: + return ts.updateVariableDeclarationList(node, visitNodes(node.declarations, visitor, ts.isVariableDeclaration)); + case 220 /* FunctionDeclaration */: + return ts.updateFunctionDeclaration(node, visitNodes(node.decorators, visitor, ts.isDecorator), visitNodes(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isPropertyName), visitNodes(node.typeParameters, visitor, ts.isTypeParameter), (context.startLexicalEnvironment(), visitNodes(node.parameters, visitor, ts.isParameter)), visitNode(node.type, visitor, ts.isTypeNode, /*optional*/ true), mergeFunctionBodyLexicalEnvironment(visitNode(node.body, visitor, ts.isFunctionBody, /*optional*/ true), context.endLexicalEnvironment())); + case 221 /* ClassDeclaration */: + return ts.updateClassDeclaration(node, visitNodes(node.decorators, visitor, ts.isDecorator), visitNodes(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isIdentifier, /*optional*/ true), visitNodes(node.typeParameters, visitor, ts.isTypeParameter), visitNodes(node.heritageClauses, visitor, ts.isHeritageClause), visitNodes(node.members, visitor, ts.isClassElement)); + case 227 /* CaseBlock */: + return ts.updateCaseBlock(node, visitNodes(node.clauses, visitor, ts.isCaseOrDefaultClause)); + case 230 /* ImportDeclaration */: + return ts.updateImportDeclaration(node, visitNodes(node.decorators, visitor, ts.isDecorator), visitNodes(node.modifiers, visitor, ts.isModifier), visitNode(node.importClause, visitor, ts.isImportClause, /*optional*/ true), visitNode(node.moduleSpecifier, visitor, ts.isExpression)); + case 231 /* ImportClause */: + return ts.updateImportClause(node, visitNode(node.name, visitor, ts.isIdentifier, /*optional*/ true), visitNode(node.namedBindings, visitor, ts.isNamedImportBindings, /*optional*/ true)); + case 232 /* NamespaceImport */: + return ts.updateNamespaceImport(node, visitNode(node.name, visitor, ts.isIdentifier)); + case 233 /* NamedImports */: + return ts.updateNamedImports(node, visitNodes(node.elements, visitor, ts.isImportSpecifier)); + case 234 /* ImportSpecifier */: + return ts.updateImportSpecifier(node, visitNode(node.propertyName, visitor, ts.isIdentifier, /*optional*/ true), visitNode(node.name, visitor, ts.isIdentifier)); + case 235 /* ExportAssignment */: + return ts.updateExportAssignment(node, visitNodes(node.decorators, visitor, ts.isDecorator), visitNodes(node.modifiers, visitor, ts.isModifier), visitNode(node.expression, visitor, ts.isExpression)); + case 236 /* ExportDeclaration */: + return ts.updateExportDeclaration(node, visitNodes(node.decorators, visitor, ts.isDecorator), visitNodes(node.modifiers, visitor, ts.isModifier), visitNode(node.exportClause, visitor, ts.isNamedExports, /*optional*/ true), visitNode(node.moduleSpecifier, visitor, ts.isExpression, /*optional*/ true)); + case 237 /* NamedExports */: + return ts.updateNamedExports(node, visitNodes(node.elements, visitor, ts.isExportSpecifier)); + case 238 /* ExportSpecifier */: + return ts.updateExportSpecifier(node, visitNode(node.propertyName, visitor, ts.isIdentifier, /*optional*/ true), visitNode(node.name, visitor, ts.isIdentifier)); + // JSX + case 241 /* JsxElement */: + return ts.updateJsxElement(node, visitNode(node.openingElement, visitor, ts.isJsxOpeningElement), visitNodes(node.children, visitor, ts.isJsxChild), visitNode(node.closingElement, visitor, ts.isJsxClosingElement)); + case 242 /* JsxSelfClosingElement */: + return ts.updateJsxSelfClosingElement(node, visitNode(node.tagName, visitor, ts.isJsxTagNameExpression), visitNodes(node.attributes, visitor, ts.isJsxAttributeLike)); + case 243 /* JsxOpeningElement */: + return ts.updateJsxOpeningElement(node, visitNode(node.tagName, visitor, ts.isJsxTagNameExpression), visitNodes(node.attributes, visitor, ts.isJsxAttributeLike)); + case 245 /* JsxClosingElement */: + return ts.updateJsxClosingElement(node, visitNode(node.tagName, visitor, ts.isJsxTagNameExpression)); + case 246 /* JsxAttribute */: + return ts.updateJsxAttribute(node, visitNode(node.name, visitor, ts.isIdentifier), visitNode(node.initializer, visitor, ts.isStringLiteralOrJsxExpression)); + case 247 /* JsxSpreadAttribute */: + return ts.updateJsxSpreadAttribute(node, visitNode(node.expression, visitor, ts.isExpression)); + case 248 /* JsxExpression */: + return ts.updateJsxExpression(node, visitNode(node.expression, visitor, ts.isExpression)); + // Clauses + case 249 /* CaseClause */: + return ts.updateCaseClause(node, visitNode(node.expression, visitor, ts.isExpression), visitNodes(node.statements, visitor, ts.isStatement)); + case 250 /* DefaultClause */: + return ts.updateDefaultClause(node, visitNodes(node.statements, visitor, ts.isStatement)); + case 251 /* HeritageClause */: + return ts.updateHeritageClause(node, visitNodes(node.types, visitor, ts.isExpressionWithTypeArguments)); + case 252 /* CatchClause */: + return ts.updateCatchClause(node, visitNode(node.variableDeclaration, visitor, ts.isVariableDeclaration), visitNode(node.block, visitor, ts.isBlock)); + // Property assignments + case 253 /* PropertyAssignment */: + return ts.updatePropertyAssignment(node, visitNode(node.name, visitor, ts.isPropertyName), visitNode(node.initializer, visitor, ts.isExpression)); + case 254 /* ShorthandPropertyAssignment */: + return ts.updateShorthandPropertyAssignment(node, visitNode(node.name, visitor, ts.isIdentifier), visitNode(node.objectAssignmentInitializer, visitor, ts.isExpression)); + // Top-level nodes + case 256 /* SourceFile */: + context.startLexicalEnvironment(); + return ts.updateSourceFileNode(node, ts.createNodeArray(ts.concatenate(visitNodes(node.statements, visitor, ts.isStatement), context.endLexicalEnvironment()), node.statements)); + // Transformation nodes + case 288 /* PartiallyEmittedExpression */: + return ts.updatePartiallyEmittedExpression(node, visitNode(node.expression, visitor, ts.isExpression)); + default: + var updated = void 0; + var edgeTraversalPath = nodeEdgeTraversalMap[kind]; + if (edgeTraversalPath) { + for (var _i = 0, edgeTraversalPath_2 = edgeTraversalPath; _i < edgeTraversalPath_2.length; _i++) { + var edge = edgeTraversalPath_2[_i]; + var value = node[edge.name]; + if (value !== undefined) { + var visited = ts.isArray(value) + ? visitNodes(value, visitor, edge.test, 0, value.length, edge.parenthesize, node) + : visitNode(value, visitor, edge.test, edge.optional, edge.lift, edge.parenthesize, node); + if (updated !== undefined || visited !== value) { + if (updated === undefined) { + updated = ts.getMutableClone(node); + } + if (visited !== value) { + updated[edge.name] = visited; + } + } + } } } - emitTypeParameters(node.typeParameters); - write("("); - } - // Parameters - emitCommaList(node.parameters, emitParameterDeclaration); - if (node.kind === 153 /* IndexSignature */) { - write("]"); + return updated ? ts.updateNode(updated, node) : node; + } + // return node; + } + ts.visitEachChild = visitEachChild; + function mergeFunctionBodyLexicalEnvironment(body, declarations) { + if (body && declarations !== undefined && declarations.length > 0) { + if (ts.isBlock(body)) { + return ts.updateBlock(body, ts.createNodeArray(ts.concatenate(body.statements, declarations), body.statements)); } else { - write(")"); + return ts.createBlock(ts.createNodeArray([ts.createReturn(body, /*location*/ body)].concat(declarations), body), + /*location*/ body, + /*multiLine*/ true); + } + } + return body; + } + ts.mergeFunctionBodyLexicalEnvironment = mergeFunctionBodyLexicalEnvironment; + /** + * Lifts a NodeArray containing only Statement nodes to a block. + * + * @param nodes The NodeArray. + */ + function liftToBlock(nodes) { + Debug.assert(ts.every(nodes, ts.isStatement), "Cannot lift nodes to a Block."); + return ts.singleOrUndefined(nodes) || ts.createBlock(nodes); + } + ts.liftToBlock = liftToBlock; + /** + * Extracts the single node from a NodeArray. + * + * @param nodes The NodeArray. + */ + function extractSingleNode(nodes) { + Debug.assert(nodes.length <= 1, "Too many nodes written to output."); + return ts.singleOrUndefined(nodes); + } + /** + * Aggregates the TransformFlags for a Node and its subtree. + */ + function aggregateTransformFlags(node) { + aggregateTransformFlagsForNode(node); + return node; + } + ts.aggregateTransformFlags = aggregateTransformFlags; + /** + * Aggregates the TransformFlags for a Node and its subtree. The flags for the subtree are + * computed first, then the transform flags for the current node are computed from the subtree + * flags and the state of the current node. Finally, the transform flags of the node are + * returned, excluding any flags that should not be included in its parent node's subtree + * flags. + */ + function aggregateTransformFlagsForNode(node) { + if (node === undefined) { + return 0 /* None */; + } + else if (node.transformFlags & 536870912 /* HasComputedFlags */) { + return node.transformFlags & ~getTransformFlagsSubtreeExclusions(node.kind); + } + else { + var subtreeFlags = aggregateTransformFlagsForSubtree(node); + return ts.computeTransformFlagsForNode(node, subtreeFlags); + } + } + /** + * Aggregates the transform flags for the subtree of a node. + */ + function aggregateTransformFlagsForSubtree(node) { + // We do not transform ambient declarations or types, so there is no need to + // recursively aggregate transform flags. + if (ts.hasModifier(node, 2 /* Ambient */) || ts.isTypeNode(node)) { + return 0 /* None */; + } + // Aggregate the transform flags of each child. + return reduceEachChild(node, aggregateTransformFlagsForChildNode, 0 /* None */); + } + /** + * Aggregates the TransformFlags of a child node with the TransformFlags of its + * siblings. + */ + function aggregateTransformFlagsForChildNode(transformFlags, child) { + return transformFlags | aggregateTransformFlagsForNode(child); + } + /** + * Gets the transform flags to exclude when unioning the transform flags of a subtree. + * + * NOTE: This needs to be kept up-to-date with the exclusions used in `computeTransformFlagsForNode`. + * For performance reasons, `computeTransformFlagsForNode` uses local constant values rather + * than calling this function. + */ + function getTransformFlagsSubtreeExclusions(kind) { + if (kind >= 154 /* FirstTypeNode */ && kind <= 166 /* LastTypeNode */) { + return -3 /* TypeExcludes */; + } + switch (kind) { + case 174 /* CallExpression */: + case 175 /* NewExpression */: + case 170 /* ArrayLiteralExpression */: + return 537133909 /* ArrayLiteralOrCallOrNewExcludes */; + case 225 /* ModuleDeclaration */: + return 546335573 /* ModuleExcludes */; + case 142 /* Parameter */: + return 538968917 /* ParameterExcludes */; + case 180 /* ArrowFunction */: + return 550710101 /* ArrowFunctionExcludes */; + case 179 /* FunctionExpression */: + case 220 /* FunctionDeclaration */: + return 550726485 /* FunctionExcludes */; + case 219 /* VariableDeclarationList */: + return 538968917 /* VariableDeclarationListExcludes */; + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + return 537590613 /* ClassExcludes */; + case 148 /* Constructor */: + return 550593365 /* ConstructorExcludes */; + case 147 /* MethodDeclaration */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + return 550593365 /* MethodOrAccessorExcludes */; + case 117 /* AnyKeyword */: + case 130 /* NumberKeyword */: + case 127 /* NeverKeyword */: + case 132 /* StringKeyword */: + case 120 /* BooleanKeyword */: + case 133 /* SymbolKeyword */: + case 103 /* VoidKeyword */: + case 141 /* TypeParameter */: + case 144 /* PropertySignature */: + case 146 /* MethodSignature */: + case 151 /* CallSignature */: + case 152 /* ConstructSignature */: + case 153 /* IndexSignature */: + case 222 /* InterfaceDeclaration */: + case 223 /* TypeAliasDeclaration */: + return -3 /* TypeExcludes */; + case 171 /* ObjectLiteralExpression */: + return 537430869 /* ObjectLiteralExcludes */; + default: + return 536871765 /* NodeExcludes */; + } + } + var Debug; + (function (Debug) { + Debug.failNotOptional = Debug.shouldAssert(1 /* Normal */) + ? function (message) { return Debug.assert(false, message || "Node not optional."); } + : function (message) { }; + Debug.failBadSyntaxKind = Debug.shouldAssert(1 /* Normal */) + ? function (node, message) { return Debug.assert(false, message || "Unexpected node.", function () { return "Node " + ts.formatSyntaxKind(node.kind) + " was unexpected."; }); } + : function (node, message) { }; + Debug.assertNode = Debug.shouldAssert(1 /* Normal */) + ? function (node, test, message) { return Debug.assert(test === undefined || test(node), message || "Unexpected node.", function () { return "Node " + ts.formatSyntaxKind(node.kind) + " did not pass test '" + getFunctionName(test) + "'."; }); } + : function (node, test, message) { }; + function getFunctionName(func) { + if (typeof func !== "function") { + return ""; } - // If this is not a constructor and is not private, emit the return type - var isFunctionTypeOrConstructorType = node.kind === 156 /* FunctionType */ || node.kind === 157 /* ConstructorType */; - if (isFunctionTypeOrConstructorType || node.parent.kind === 159 /* TypeLiteral */) { - // Emit type literal signature return type only if specified - if (node.type) { - write(isFunctionTypeOrConstructorType ? " => " : ": "); - emitType(node.type); - } + else if (func.hasOwnProperty("name")) { + return func.name; } - else if (node.kind !== 148 /* Constructor */ && !(node.flags & 8 /* Private */)) { - writeReturnTypeAtSignature(node, getReturnTypeVisibilityError); + else { + var text = Function.prototype.toString.call(func); + var match = /^function\s+([\w\$]+)\s*\(/.exec(text); + return match ? match[1] : ""; } - enclosingDeclaration = prevEnclosingDeclaration; - if (!isFunctionTypeOrConstructorType) { - write(";"); - writeLine(); + } + })(Debug = ts.Debug || (ts.Debug = {})); + var _a; +})(ts || (ts = {})); +/// +/// +/*@internal*/ +var ts; +(function (ts) { + /** + * Flattens a destructuring assignment expression. + * + * @param root The destructuring assignment expression. + * @param needsValue Indicates whether the value from the right-hand-side of the + * destructuring assignment is needed as part of a larger expression. + * @param recordTempVariable A callback used to record new temporary variables. + * @param visitor An optional visitor to use to visit expressions. + */ + function flattenDestructuringAssignment(context, node, needsValue, recordTempVariable, visitor) { + if (ts.isEmptyObjectLiteralOrArrayLiteral(node.left)) { + var right = node.right; + if (ts.isDestructuringAssignment(right)) { + return flattenDestructuringAssignment(context, right, needsValue, recordTempVariable, visitor); } - else if (closeParenthesizedFunctionType) { - write(")"); + else { + return node.right; } - function getReturnTypeVisibilityError(symbolAccessibilityResult) { - var diagnosticMessage; - switch (node.kind) { - case 152 /* ConstructSignature */: - // Interfaces cannot have return types that cannot be named - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_0; - break; - case 151 /* CallSignature */: - // Interfaces cannot have return types that cannot be named - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_private_name_0; - break; - case 153 /* IndexSignature */: - // Interfaces cannot have return types that cannot be named - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_private_name_0; - break; - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - if (node.flags & 32 /* Static */) { - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? - ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : - ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_private_name_0; - } - else if (node.parent.kind === 221 /* ClassDeclaration */) { - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? - ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : - ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_private_name_0; - } - else { - // Interfaces cannot have return types that cannot be named - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_private_name_0; - } - break; - case 220 /* FunctionDeclaration */: - diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? - ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : - ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_private_name_0; - break; - default: - ts.Debug.fail("This is unknown kind for signature: " + node.kind); + } + var location = node; + var value = node.right; + var expressions = []; + if (needsValue) { + // If the right-hand value of the destructuring assignment needs to be preserved (as + // is the case when the destructuring assignmen) is part of a larger expression), + // then we need to cache the right-hand value. + // + // The source map location for the assignment should point to the entire binary + // expression. + value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, location, emitTempVariableAssignment, visitor); + } + else if (ts.nodeIsSynthesized(node)) { + // Generally, the source map location for a destructuring assignment is the root + // expression. + // + // However, if the root expression is synthesized (as in the case + // of the initializer when transforming a ForOfStatement), then the source map + // location should point to the right-hand value of the expression. + location = value; + } + flattenDestructuring(context, node, value, location, emitAssignment, emitTempVariableAssignment, visitor); + if (needsValue) { + expressions.push(value); + } + var expression = ts.inlineExpressions(expressions); + ts.aggregateTransformFlags(expression); + return expression; + function emitAssignment(name, value, location) { + var expression = ts.createAssignment(name, value, location); + // NOTE: this completely disables source maps, but aligns with the behavior of + // `emitAssignment` in the old emitter. + ts.setEmitFlags(expression, 2048 /* NoNestedSourceMaps */); + ts.aggregateTransformFlags(expression); + expressions.push(expression); + } + function emitTempVariableAssignment(value, location) { + var name = ts.createTempVariable(recordTempVariable); + emitAssignment(name, value, location); + return name; + } + } + ts.flattenDestructuringAssignment = flattenDestructuringAssignment; + /** + * Flattens binding patterns in a parameter declaration. + * + * @param node The ParameterDeclaration to flatten. + * @param value The rhs value for the binding pattern. + * @param visitor An optional visitor to use to visit expressions. + */ + function flattenParameterDestructuring(context, node, value, visitor) { + var declarations = []; + flattenDestructuring(context, node, value, node, emitAssignment, emitTempVariableAssignment, visitor); + return declarations; + function emitAssignment(name, value, location) { + var declaration = ts.createVariableDeclaration(name, /*type*/ undefined, value, location); + // NOTE: this completely disables source maps, but aligns with the behavior of + // `emitAssignment` in the old emitter. + ts.setEmitFlags(declaration, 2048 /* NoNestedSourceMaps */); + ts.aggregateTransformFlags(declaration); + declarations.push(declaration); + } + function emitTempVariableAssignment(value, location) { + var name = ts.createTempVariable(/*recordTempVariable*/ undefined); + emitAssignment(name, value, location); + return name; + } + } + ts.flattenParameterDestructuring = flattenParameterDestructuring; + /** + * Flattens binding patterns in a variable declaration. + * + * @param node The VariableDeclaration to flatten. + * @param value An optional rhs value for the binding pattern. + * @param visitor An optional visitor to use to visit expressions. + */ + function flattenVariableDestructuring(context, node, value, visitor, recordTempVariable) { + var declarations = []; + var pendingAssignments; + flattenDestructuring(context, node, value, node, emitAssignment, emitTempVariableAssignment, visitor); + return declarations; + function emitAssignment(name, value, location, original) { + if (pendingAssignments) { + pendingAssignments.push(value); + value = ts.inlineExpressions(pendingAssignments); + pendingAssignments = undefined; + } + var declaration = ts.createVariableDeclaration(name, /*type*/ undefined, value, location); + declaration.original = original; + // NOTE: this completely disables source maps, but aligns with the behavior of + // `emitAssignment` in the old emitter. + ts.setEmitFlags(declaration, 2048 /* NoNestedSourceMaps */); + declarations.push(declaration); + ts.aggregateTransformFlags(declaration); + } + function emitTempVariableAssignment(value, location) { + var name = ts.createTempVariable(recordTempVariable); + if (recordTempVariable) { + var assignment = ts.createAssignment(name, value, location); + if (pendingAssignments) { + pendingAssignments.push(assignment); + } + else { + pendingAssignments = [assignment]; } - return { - diagnosticMessage: diagnosticMessage, - errorNode: node.name || node - }; } - } - function emitParameterDeclaration(node) { - increaseIndent(); - emitJsDocComments(node); - if (node.dotDotDotToken) { - write("..."); + else { + emitAssignment(name, value, location, /*original*/ undefined); } - if (ts.isBindingPattern(node.name)) { - // For bindingPattern, we can't simply writeTextOfNode from the source file - // because we want to omit the initializer and using writeTextOfNode will result in initializer get emitted. - // Therefore, we will have to recursively emit each element in the bindingPattern. - emitBindingPattern(node.name); + return name; + } + } + ts.flattenVariableDestructuring = flattenVariableDestructuring; + /** + * Flattens binding patterns in a variable declaration and transforms them into an expression. + * + * @param node The VariableDeclaration to flatten. + * @param recordTempVariable A callback used to record new temporary variables. + * @param nameSubstitution An optional callback used to substitute binding names. + * @param visitor An optional visitor to use to visit expressions. + */ + function flattenVariableDestructuringToExpression(context, node, recordTempVariable, nameSubstitution, visitor) { + var pendingAssignments = []; + flattenDestructuring(context, node, /*value*/ undefined, node, emitAssignment, emitTempVariableAssignment, visitor); + var expression = ts.inlineExpressions(pendingAssignments); + ts.aggregateTransformFlags(expression); + return expression; + function emitAssignment(name, value, location, original) { + var left = nameSubstitution && nameSubstitution(name) || name; + emitPendingAssignment(left, value, location, original); + } + function emitTempVariableAssignment(value, location) { + var name = ts.createTempVariable(recordTempVariable); + emitPendingAssignment(name, value, location, /*original*/ undefined); + return name; + } + function emitPendingAssignment(name, value, location, original) { + var expression = ts.createAssignment(name, value, location); + expression.original = original; + // NOTE: this completely disables source maps, but aligns with the behavior of + // `emitAssignment` in the old emitter. + ts.setEmitFlags(expression, 2048 /* NoNestedSourceMaps */); + pendingAssignments.push(expression); + return expression; + } + } + ts.flattenVariableDestructuringToExpression = flattenVariableDestructuringToExpression; + function flattenDestructuring(context, root, value, location, emitAssignment, emitTempVariableAssignment, visitor) { + if (value && visitor) { + value = ts.visitNode(value, visitor, ts.isExpression); + } + if (ts.isBinaryExpression(root)) { + emitDestructuringAssignment(root.left, value, location); + } + else { + emitBindingElement(root, value); + } + function emitDestructuringAssignment(bindingTarget, value, location) { + // When emitting target = value use source map node to highlight, including any temporary assignments needed for this + var target; + if (ts.isShorthandPropertyAssignment(bindingTarget)) { + var initializer = visitor + ? ts.visitNode(bindingTarget.objectAssignmentInitializer, visitor, ts.isExpression) + : bindingTarget.objectAssignmentInitializer; + if (initializer) { + value = createDefaultValueCheck(value, initializer, location); + } + target = bindingTarget.name; + } + else if (ts.isBinaryExpression(bindingTarget) && bindingTarget.operatorToken.kind === 56 /* EqualsToken */) { + var initializer = visitor + ? ts.visitNode(bindingTarget.right, visitor, ts.isExpression) + : bindingTarget.right; + value = createDefaultValueCheck(value, initializer, location); + target = bindingTarget.left; } else { - writeTextOfNode(currentText, node.name); + target = bindingTarget; } - if (resolver.isOptionalParameter(node)) { - write("?"); + if (target.kind === 171 /* ObjectLiteralExpression */) { + emitObjectLiteralAssignment(target, value, location); } - decreaseIndent(); - if (node.parent.kind === 156 /* FunctionType */ || - node.parent.kind === 157 /* ConstructorType */ || - node.parent.parent.kind === 159 /* TypeLiteral */) { - emitTypeOfVariableDeclarationFromTypeLiteral(node); + else if (target.kind === 170 /* ArrayLiteralExpression */) { + emitArrayLiteralAssignment(target, value, location); } - else if (!(node.parent.flags & 8 /* Private */)) { - writeTypeOfDeclaration(node, node.type, getParameterDeclarationTypeVisibilityError); + else { + var name_29 = ts.getMutableClone(target); + ts.setSourceMapRange(name_29, target); + ts.setCommentRange(name_29, target); + emitAssignment(name_29, value, location, /*original*/ undefined); } - function getParameterDeclarationTypeVisibilityError(symbolAccessibilityResult) { - var diagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult); - return diagnosticMessage !== undefined ? { - diagnosticMessage: diagnosticMessage, - errorNode: node, - typeName: node.name - } : undefined; + } + function emitObjectLiteralAssignment(target, value, location) { + var properties = target.properties; + if (properties.length !== 1) { + // For anything but a single element destructuring we need to generate a temporary + // to ensure value is evaluated exactly once. + // When doing so we want to hightlight the passed in source map node since thats the one needing this temp assignment + value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, location, emitTempVariableAssignment); } - function getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult) { - switch (node.parent.kind) { - case 148 /* Constructor */: - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? - ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_private_name_1; - case 152 /* ConstructSignature */: - // Interfaces cannot have parameter types that cannot be named - return symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; - case 151 /* CallSignature */: - // Interfaces cannot have parameter types that cannot be named - return symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1; - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - if (node.parent.flags & 32 /* Static */) { - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? - ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1; - } - else if (node.parent.parent.kind === 221 /* ClassDeclaration */) { - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? - ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1; - } - else { - // Interfaces cannot have parameter types that cannot be named - return symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1; - } - case 220 /* FunctionDeclaration */: - return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? - ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_private_name_1; - default: - ts.Debug.fail("This is unknown parent for parameter: " + node.parent.kind); + for (var _i = 0, properties_6 = properties; _i < properties_6.length; _i++) { + var p = properties_6[_i]; + if (p.kind === 253 /* PropertyAssignment */ || p.kind === 254 /* ShorthandPropertyAssignment */) { + var propName = p.name; + var target_1 = p.kind === 254 /* ShorthandPropertyAssignment */ ? p : p.initializer || propName; + // Assignment for target = value.propName should highligh whole property, hence use p as source map node + emitDestructuringAssignment(target_1, createDestructuringPropertyAccess(value, propName), p); } } - function emitBindingPattern(bindingPattern) { - // We have to explicitly emit square bracket and bracket because these tokens are not store inside the node. - if (bindingPattern.kind === 167 /* ObjectBindingPattern */) { - write("{"); - emitCommaList(bindingPattern.elements, emitBindingElement); - write("}"); - } - else if (bindingPattern.kind === 168 /* ArrayBindingPattern */) { - write("["); - var elements = bindingPattern.elements; - emitCommaList(elements, emitBindingElement); - if (elements && elements.hasTrailingComma) { - write(", "); + } + function emitArrayLiteralAssignment(target, value, location) { + var elements = target.elements; + var numElements = elements.length; + if (numElements !== 1) { + // For anything but a single element destructuring we need to generate a temporary + // to ensure value is evaluated exactly once. + // When doing so we want to hightlight the passed in source map node since thats the one needing this temp assignment + value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, location, emitTempVariableAssignment); + } + for (var i = 0; i < numElements; i++) { + var e = elements[i]; + if (e.kind !== 193 /* OmittedExpression */) { + // Assignment for target = value.propName should highligh whole property, hence use e as source map node + if (e.kind !== 191 /* SpreadElementExpression */) { + emitDestructuringAssignment(e, ts.createElementAccess(value, ts.createLiteral(i)), e); + } + else if (i === numElements - 1) { + emitDestructuringAssignment(e.expression, ts.createArraySlice(value, i), e); } - write("]"); } } - function emitBindingElement(bindingElement) { - if (bindingElement.kind === 193 /* OmittedExpression */) { - // If bindingElement is an omittedExpression (i.e. containing elision), - // we will emit blank space (although this may differ from users' original code, - // it allows emitSeparatedList to write separator appropriately) - // Example: - // original: function foo([, x, ,]) {} - // emit : function foo([ , x, , ]) {} - write(" "); - } - else if (bindingElement.kind === 169 /* BindingElement */) { - if (bindingElement.propertyName) { - // bindingElement has propertyName property in the following case: - // { y: [a,b,c] ...} -> bindingPattern will have a property called propertyName for "y" - // We have to explicitly emit the propertyName before descending into its binding elements. - // Example: - // original: function foo({y: [a,b,c]}) {} - // emit : declare function foo({y: [a, b, c]}: { y: [any, any, any] }) void; - writeTextOfNode(currentText, bindingElement.propertyName); - write(": "); + } + function emitBindingElement(target, value) { + // Any temporary assignments needed to emit target = value should point to target + var initializer = visitor ? ts.visitNode(target.initializer, visitor, ts.isExpression) : target.initializer; + if (initializer) { + // Combine value and initializer + value = value ? createDefaultValueCheck(value, initializer, target) : initializer; + } + else if (!value) { + // Use 'void 0' in absence of value and initializer + value = ts.createVoidZero(); + } + var name = target.name; + if (ts.isBindingPattern(name)) { + var elements = name.elements; + var numElements = elements.length; + if (numElements !== 1) { + // For anything other than a single-element destructuring we need to generate a temporary + // to ensure value is evaluated exactly once. Additionally, if we have zero elements + // we need to emit *something* to ensure that in case a 'var' keyword was already emitted, + // so in that case, we'll intentionally create that temporary. + value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ numElements !== 0, target, emitTempVariableAssignment); + } + for (var i = 0; i < numElements; i++) { + var element = elements[i]; + if (ts.isOmittedExpression(element)) { + continue; } - if (bindingElement.name) { - if (ts.isBindingPattern(bindingElement.name)) { - // If it is a nested binding pattern, we will recursively descend into each element and emit each one separately. - // In the case of rest element, we will omit rest element. - // Example: - // original: function foo([a, [[b]], c] = [1,[["string"]], 3]) {} - // emit : declare function foo([a, [[b]], c]: [number, [[string]], number]): void; - // original with rest: function foo([a, ...c]) {} - // emit : declare function foo([a, ...c]): void; - emitBindingPattern(bindingElement.name); + else if (name.kind === 167 /* ObjectBindingPattern */) { + // Rewrite element to a declaration with an initializer that fetches property + var propName = element.propertyName || element.name; + emitBindingElement(element, createDestructuringPropertyAccess(value, propName)); + } + else { + if (!element.dotDotDotToken) { + // Rewrite element to a declaration that accesses array element at index i + emitBindingElement(element, ts.createElementAccess(value, i)); } - else { - ts.Debug.assert(bindingElement.name.kind === 69 /* Identifier */); - // If the node is just an identifier, we will simply emit the text associated with the node's name - // Example: - // original: function foo({y = 10, x}) {} - // emit : declare function foo({y, x}: {number, any}): void; - if (bindingElement.dotDotDotToken) { - write("..."); - } - writeTextOfNode(currentText, bindingElement.name); + else if (i === numElements - 1) { + emitBindingElement(element, ts.createArraySlice(value, i)); } } } } - } - function emitNode(node) { - switch (node.kind) { - case 220 /* FunctionDeclaration */: - case 225 /* ModuleDeclaration */: - case 229 /* ImportEqualsDeclaration */: - case 222 /* InterfaceDeclaration */: - case 221 /* ClassDeclaration */: - case 223 /* TypeAliasDeclaration */: - case 224 /* EnumDeclaration */: - return emitModuleElement(node, isModuleElementVisible(node)); - case 200 /* VariableStatement */: - return emitModuleElement(node, isVariableStatementVisible(node)); - case 230 /* ImportDeclaration */: - // Import declaration without import clause is visible, otherwise it is not visible - return emitModuleElement(node, /*isModuleElementVisible*/ !node.importClause); - case 236 /* ExportDeclaration */: - return emitExportDeclaration(node); - case 148 /* Constructor */: - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - return writeFunctionDeclaration(node); - case 152 /* ConstructSignature */: - case 151 /* CallSignature */: - case 153 /* IndexSignature */: - return emitSignatureDeclarationWithJsDocComments(node); - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - return emitAccessorDeclaration(node); - case 145 /* PropertyDeclaration */: - case 144 /* PropertySignature */: - return emitPropertyDeclaration(node); - case 255 /* EnumMember */: - return emitEnumMemberDeclaration(node); - case 235 /* ExportAssignment */: - return emitExportAssignment(node); - case 256 /* SourceFile */: - return emitSourceFile(node); + else { + emitAssignment(name, value, target, target); } } + function createDefaultValueCheck(value, defaultValue, location) { + value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, location, emitTempVariableAssignment); + return ts.createConditional(ts.createStrictEquality(value, ts.createVoidZero()), ts.createToken(53 /* QuestionToken */), defaultValue, ts.createToken(54 /* ColonToken */), value); + } /** - * Adds the reference to referenced file, returns true if global file reference was emitted - * @param referencedFile - * @param addBundledFileReference Determines if global file reference corresponding to bundled file should be emitted or not + * Creates either a PropertyAccessExpression or an ElementAccessExpression for the + * right-hand side of a transformed destructuring assignment. + * + * @param expression The right-hand expression that is the source of the property. + * @param propertyName The destructuring property name. */ - function writeReferencePath(referencedFile, addBundledFileReference) { - var declFileName; - var addedBundledEmitReference = false; - if (ts.isDeclarationFile(referencedFile)) { - // Declaration file, use declaration file name - declFileName = referencedFile.fileName; - } - else { - // Get the declaration file path - ts.forEachExpectedEmitFile(host, getDeclFileName, referencedFile); + function createDestructuringPropertyAccess(expression, propertyName) { + if (ts.isComputedPropertyName(propertyName)) { + return ts.createElementAccess(expression, ensureIdentifier(propertyName.expression, /*reuseIdentifierExpressions*/ false, /*location*/ propertyName, emitTempVariableAssignment)); } - if (declFileName) { - declFileName = ts.getRelativePathToDirectoryOrUrl(ts.getDirectoryPath(ts.normalizeSlashes(declarationFilePath)), declFileName, host.getCurrentDirectory(), host.getCanonicalFileName, - /*isAbsolutePathAnUrl*/ false); - referencesOutput += "/// " + newLine; + else if (ts.isLiteralExpression(propertyName)) { + var clone_2 = ts.getSynthesizedClone(propertyName); + clone_2.text = ts.unescapeIdentifier(clone_2.text); + return ts.createElementAccess(expression, clone_2); } - return addedBundledEmitReference; - function getDeclFileName(emitFileNames, sourceFiles, isBundledEmit) { - // Dont add reference path to this file if it is a bundled emit and caller asked not emit bundled file path - if (isBundledEmit && !addBundledFileReference) { - return; + else { + if (ts.isGeneratedIdentifier(propertyName)) { + var clone_3 = ts.getSynthesizedClone(propertyName); + clone_3.text = ts.unescapeIdentifier(clone_3.text); + return ts.createPropertyAccess(expression, clone_3); + } + else { + return ts.createPropertyAccess(expression, ts.createIdentifier(ts.unescapeIdentifier(propertyName.text))); } - ts.Debug.assert(!!emitFileNames.declarationFilePath || ts.isSourceFileJavaScript(referencedFile), "Declaration file is not present only for javascript files"); - declFileName = emitFileNames.declarationFilePath || emitFileNames.jsFilePath; - addedBundledEmitReference = isBundledEmit; } } } - /* @internal */ - function writeDeclarationFile(declarationFilePath, sourceFiles, isBundledEmit, host, resolver, emitterDiagnostics) { - var emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFiles, isBundledEmit); - var emitSkipped = emitDeclarationResult.reportedDeclarationError || host.isEmitBlocked(declarationFilePath) || host.getCompilerOptions().noEmit; - if (!emitSkipped) { - var declarationOutput = emitDeclarationResult.referencesOutput - + getDeclarationOutput(emitDeclarationResult.synchronousDeclarationOutput, emitDeclarationResult.moduleElementDeclarationEmitInfo); - ts.writeFile(host, emitterDiagnostics, declarationFilePath, declarationOutput, host.getCompilerOptions().emitBOM, sourceFiles); + /** + * Ensures that there exists a declared identifier whose value holds the given expression. + * This function is useful to ensure that the expression's value can be read from in subsequent expressions. + * Unless 'reuseIdentifierExpressions' is false, 'value' will be returned if it is just an identifier. + * + * @param value the expression whose value needs to be bound. + * @param reuseIdentifierExpressions true if identifier expressions can simply be returned; + * false if it is necessary to always emit an identifier. + * @param location The location to use for source maps and comments. + * @param emitTempVariableAssignment A callback used to emit a temporary variable. + * @param visitor An optional callback used to visit the value. + */ + function ensureIdentifier(value, reuseIdentifierExpressions, location, emitTempVariableAssignment, visitor) { + if (ts.isIdentifier(value) && reuseIdentifierExpressions) { + return value; } - return emitSkipped; - function getDeclarationOutput(synchronousDeclarationOutput, moduleElementDeclarationEmitInfo) { - var appliedSyncOutputPos = 0; - var declarationOutput = ""; - // apply asynchronous additions to the synchronous output - ts.forEach(moduleElementDeclarationEmitInfo, function (aliasEmitInfo) { - if (aliasEmitInfo.asynchronousOutput) { - declarationOutput += synchronousDeclarationOutput.substring(appliedSyncOutputPos, aliasEmitInfo.outputPos); - declarationOutput += getDeclarationOutput(aliasEmitInfo.asynchronousOutput, aliasEmitInfo.subModuleElementDeclarationEmitInfo); - appliedSyncOutputPos = aliasEmitInfo.outputPos; - } - }); - declarationOutput += synchronousDeclarationOutput.substring(appliedSyncOutputPos); - return declarationOutput; + else { + if (visitor) { + value = ts.visitNode(value, visitor, ts.isExpression); + } + return emitTempVariableAssignment(value, location); } } - ts.writeDeclarationFile = writeDeclarationFile; })(ts || (ts = {})); -/// -/* @internal */ +/// +/// +/// +/*@internal*/ var ts; (function (ts) { - var nullSourceMapWriter; - // Used for initialize lastEncodedSourceMapSpan and reset lastEncodedSourceMapSpan when updateLastEncodedAndRecordedSpans - var defaultLastEncodedSourceMapSpan = { - emittedLine: 1, - emittedColumn: 1, - sourceLine: 1, - sourceColumn: 1, - sourceIndex: 0 - }; - function getNullSourceMapWriter() { - if (nullSourceMapWriter === undefined) { - nullSourceMapWriter = { - getSourceMapData: function () { return undefined; }, - setSourceFile: function (sourceFile) { }, - emitStart: function (range) { }, - emitEnd: function (range, stopOverridingSpan) { }, - emitPos: function (pos) { }, - changeEmitSourcePos: function () { }, - getText: function () { return undefined; }, - getSourceMappingURL: function () { return undefined; }, - initialize: function (filePath, sourceMapFilePath, sourceFiles, isBundledEmit) { }, - reset: function () { }, - }; - } - return nullSourceMapWriter; - } - ts.getNullSourceMapWriter = getNullSourceMapWriter; - function createSourceMapWriter(host, writer) { - var compilerOptions = host.getCompilerOptions(); - var extendedDiagnostics = compilerOptions.extendedDiagnostics; + /** + * Indicates whether to emit type metadata in the new format. + */ + var USE_NEW_TYPE_METADATA_FORMAT = false; + var TypeScriptSubstitutionFlags; + (function (TypeScriptSubstitutionFlags) { + /** Enables substitutions for decorated classes. */ + TypeScriptSubstitutionFlags[TypeScriptSubstitutionFlags["ClassAliases"] = 1] = "ClassAliases"; + /** Enables substitutions for namespace exports. */ + TypeScriptSubstitutionFlags[TypeScriptSubstitutionFlags["NamespaceExports"] = 2] = "NamespaceExports"; + /** Enables substitutions for async methods with `super` calls. */ + TypeScriptSubstitutionFlags[TypeScriptSubstitutionFlags["AsyncMethodsWithSuper"] = 4] = "AsyncMethodsWithSuper"; + /* Enables substitutions for unqualified enum members */ + TypeScriptSubstitutionFlags[TypeScriptSubstitutionFlags["NonQualifiedEnumMembers"] = 8] = "NonQualifiedEnumMembers"; + })(TypeScriptSubstitutionFlags || (TypeScriptSubstitutionFlags = {})); + function transformTypeScript(context) { + var startLexicalEnvironment = context.startLexicalEnvironment, endLexicalEnvironment = context.endLexicalEnvironment, hoistVariableDeclaration = context.hoistVariableDeclaration; + var resolver = context.getEmitResolver(); + var compilerOptions = context.getCompilerOptions(); + var languageVersion = ts.getEmitScriptTarget(compilerOptions); + var moduleKind = ts.getEmitModuleKind(compilerOptions); + // Save the previous transformation hooks. + var previousOnEmitNode = context.onEmitNode; + var previousOnSubstituteNode = context.onSubstituteNode; + // Set new transformation hooks. + context.onEmitNode = onEmitNode; + context.onSubstituteNode = onSubstituteNode; + // Enable substitution for property/element access to emit const enum values. + context.enableSubstitution(172 /* PropertyAccessExpression */); + context.enableSubstitution(173 /* ElementAccessExpression */); + // These variables contain state that changes as we descend into the tree. var currentSourceFile; - var sourceMapDir; // The directory in which sourcemap will be - var stopOverridingSpan = false; - var modifyLastSourcePos = false; - // Current source map file and its index in the sources list - var sourceMapSourceIndex; - // Last recorded and encoded spans - var lastRecordedSourceMapSpan; - var lastEncodedSourceMapSpan; - var lastEncodedNameIndex; - // Source map data - var sourceMapData; - return { - getSourceMapData: function () { return sourceMapData; }, - setSourceFile: setSourceFile, - emitPos: emitPos, - emitStart: emitStart, - emitEnd: emitEnd, - changeEmitSourcePos: changeEmitSourcePos, - getText: getText, - getSourceMappingURL: getSourceMappingURL, - initialize: initialize, - reset: reset, - }; - function initialize(filePath, sourceMapFilePath, sourceFiles, isBundledEmit) { - if (sourceMapData) { - reset(); + var currentNamespace; + var currentNamespaceContainerName; + var currentScope; + var currentScopeFirstDeclarationsOfName; + var currentSourceFileExternalHelpersModuleName; + /** + * Keeps track of whether expression substitution has been enabled for specific edge cases. + * They are persisted between each SourceFile transformation and should not be reset. + */ + var enabledSubstitutions; + /** + * A map that keeps track of aliases created for classes with decorators to avoid issues + * with the double-binding behavior of classes. + */ + var classAliases; + /** + * Keeps track of whether we are within any containing namespaces when performing + * just-in-time substitution while printing an expression identifier. + */ + var applicableSubstitutions; + /** + * This keeps track of containers where `super` is valid, for use with + * just-in-time substitution for `super` expressions inside of async methods. + */ + var currentSuperContainer; + return transformSourceFile; + /** + * Transform TypeScript-specific syntax in a SourceFile. + * + * @param node A SourceFile node. + */ + function transformSourceFile(node) { + if (ts.isDeclarationFile(node)) { + return node; } - currentSourceFile = undefined; - // Current source map file and its index in the sources list - sourceMapSourceIndex = -1; - // Last recorded and encoded spans - lastRecordedSourceMapSpan = undefined; - lastEncodedSourceMapSpan = defaultLastEncodedSourceMapSpan; - lastEncodedNameIndex = 0; - // Initialize source map data - sourceMapData = { - sourceMapFilePath: sourceMapFilePath, - jsSourceMappingURL: !compilerOptions.inlineSourceMap ? ts.getBaseFileName(ts.normalizeSlashes(sourceMapFilePath)) : undefined, - sourceMapFile: ts.getBaseFileName(ts.normalizeSlashes(filePath)), - sourceMapSourceRoot: compilerOptions.sourceRoot || "", - sourceMapSources: [], - inputSourceFileNames: [], - sourceMapNames: [], - sourceMapMappings: "", - sourceMapSourcesContent: compilerOptions.inlineSources ? [] : undefined, - sourceMapDecodedMappings: [] - }; - // Normalize source root and make sure it has trailing "/" so that it can be used to combine paths with the - // relative paths of the sources list in the sourcemap - sourceMapData.sourceMapSourceRoot = ts.normalizeSlashes(sourceMapData.sourceMapSourceRoot); - if (sourceMapData.sourceMapSourceRoot.length && sourceMapData.sourceMapSourceRoot.charCodeAt(sourceMapData.sourceMapSourceRoot.length - 1) !== 47 /* slash */) { - sourceMapData.sourceMapSourceRoot += ts.directorySeparator; + return ts.visitNode(node, visitor, ts.isSourceFile); + } + /** + * Visits a node, saving and restoring state variables on the stack. + * + * @param node The node to visit. + */ + function saveStateAndInvoke(node, f) { + // Save state + var savedCurrentScope = currentScope; + var savedCurrentScopeFirstDeclarationsOfName = currentScopeFirstDeclarationsOfName; + // Handle state changes before visiting a node. + onBeforeVisitNode(node); + var visited = f(node); + // Restore state + if (currentScope !== savedCurrentScope) { + currentScopeFirstDeclarationsOfName = savedCurrentScopeFirstDeclarationsOfName; + } + currentScope = savedCurrentScope; + return visited; + } + /** + * General-purpose node visitor. + * + * @param node The node to visit. + */ + function visitor(node) { + return saveStateAndInvoke(node, visitorWorker); + } + /** + * Visits and possibly transforms any node. + * + * @param node The node to visit. + */ + function visitorWorker(node) { + if (node.kind === 256 /* SourceFile */) { + return visitSourceFile(node); } - if (compilerOptions.mapRoot) { - sourceMapDir = ts.normalizeSlashes(compilerOptions.mapRoot); - if (!isBundledEmit) { - ts.Debug.assert(sourceFiles.length === 1); - // For modules or multiple emit files the mapRoot will have directory structure like the sources - // So if src\a.ts and src\lib\b.ts are compiled together user would be moving the maps into mapRoot\a.js.map and mapRoot\lib\b.js.map - sourceMapDir = ts.getDirectoryPath(ts.getSourceFilePathInNewDir(sourceFiles[0], host, sourceMapDir)); - } - if (!ts.isRootedDiskPath(sourceMapDir) && !ts.isUrl(sourceMapDir)) { - // The relative paths are relative to the common directory - sourceMapDir = ts.combinePaths(host.getCommonSourceDirectory(), sourceMapDir); - sourceMapData.jsSourceMappingURL = ts.getRelativePathToDirectoryOrUrl(ts.getDirectoryPath(ts.normalizePath(filePath)), // get the relative sourceMapDir path based on jsFilePath - ts.combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL), // this is where user expects to see sourceMap - host.getCurrentDirectory(), host.getCanonicalFileName, - /*isAbsolutePathAnUrl*/ true); - } - else { - sourceMapData.jsSourceMappingURL = ts.combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL); - } + else if (node.transformFlags & 1 /* TypeScript */) { + // This node is explicitly marked as TypeScript, so we should transform the node. + return visitTypeScript(node); } - else { - sourceMapDir = ts.getDirectoryPath(ts.normalizePath(filePath)); + else if (node.transformFlags & 2 /* ContainsTypeScript */) { + // This node contains TypeScript, so we should visit its children. + return ts.visitEachChild(node, visitor, context); + } + return node; + } + /** + * Specialized visitor that visits the immediate children of a namespace. + * + * @param node The node to visit. + */ + function namespaceElementVisitor(node) { + return saveStateAndInvoke(node, namespaceElementVisitorWorker); + } + /** + * Specialized visitor that visits the immediate children of a namespace. + * + * @param node The node to visit. + */ + function namespaceElementVisitorWorker(node) { + if (node.kind === 236 /* ExportDeclaration */ || + node.kind === 230 /* ImportDeclaration */ || + node.kind === 231 /* ImportClause */ || + (node.kind === 229 /* ImportEqualsDeclaration */ && + node.moduleReference.kind === 240 /* ExternalModuleReference */)) { + // do not emit ES6 imports and exports since they are illegal inside a namespace + return undefined; + } + else if (node.transformFlags & 1 /* TypeScript */ || ts.hasModifier(node, 1 /* Export */)) { + // This node is explicitly marked as TypeScript, or is exported at the namespace + // level, so we should transform the node. + return visitTypeScript(node); + } + else if (node.transformFlags & 2 /* ContainsTypeScript */) { + // This node contains TypeScript, so we should visit its children. + return ts.visitEachChild(node, visitor, context); + } + return node; + } + /** + * Specialized visitor that visits the immediate children of a class with TypeScript syntax. + * + * @param node The node to visit. + */ + function classElementVisitor(node) { + return saveStateAndInvoke(node, classElementVisitorWorker); + } + /** + * Specialized visitor that visits the immediate children of a class with TypeScript syntax. + * + * @param node The node to visit. + */ + function classElementVisitorWorker(node) { + switch (node.kind) { + case 148 /* Constructor */: + // TypeScript constructors are transformed in `visitClassDeclaration`. + // We elide them here as `visitorWorker` checks transform flags, which could + // erronously include an ES6 constructor without TypeScript syntax. + return undefined; + case 145 /* PropertyDeclaration */: + case 153 /* IndexSignature */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 147 /* MethodDeclaration */: + // Fallback to the default visit behavior. + return visitorWorker(node); + case 198 /* SemicolonClassElement */: + return node; + default: + ts.Debug.failBadSyntaxKind(node); + return undefined; + } + } + /** + * Branching visitor, visits a TypeScript syntax node. + * + * @param node The node to visit. + */ + function visitTypeScript(node) { + if (ts.hasModifier(node, 2 /* Ambient */) && ts.isStatement(node)) { + // TypeScript ambient declarations are elided, but some comments may be preserved. + // See the implementation of `getLeadingComments` in comments.ts for more details. + return ts.createNotEmittedStatement(node); + } + switch (node.kind) { + case 82 /* ExportKeyword */: + case 77 /* DefaultKeyword */: + // ES6 export and default modifiers are elided when inside a namespace. + return currentNamespace ? undefined : node; + case 112 /* PublicKeyword */: + case 110 /* PrivateKeyword */: + case 111 /* ProtectedKeyword */: + case 115 /* AbstractKeyword */: + case 118 /* AsyncKeyword */: + case 74 /* ConstKeyword */: + case 122 /* DeclareKeyword */: + case 128 /* ReadonlyKeyword */: + // TypeScript accessibility and readonly modifiers are elided. + case 160 /* ArrayType */: + case 161 /* TupleType */: + case 159 /* TypeLiteral */: + case 154 /* TypePredicate */: + case 141 /* TypeParameter */: + case 117 /* AnyKeyword */: + case 120 /* BooleanKeyword */: + case 132 /* StringKeyword */: + case 130 /* NumberKeyword */: + case 127 /* NeverKeyword */: + case 103 /* VoidKeyword */: + case 133 /* SymbolKeyword */: + case 157 /* ConstructorType */: + case 156 /* FunctionType */: + case 158 /* TypeQuery */: + case 155 /* TypeReference */: + case 162 /* UnionType */: + case 163 /* IntersectionType */: + case 164 /* ParenthesizedType */: + case 165 /* ThisType */: + case 166 /* LiteralType */: + // TypeScript type nodes are elided. + case 153 /* IndexSignature */: + // TypeScript index signatures are elided. + case 143 /* Decorator */: + // TypeScript decorators are elided. They will be emitted as part of visitClassDeclaration. + case 223 /* TypeAliasDeclaration */: + // TypeScript type-only declarations are elided. + case 145 /* PropertyDeclaration */: + // TypeScript property declarations are elided. + case 148 /* Constructor */: + // TypeScript constructors are transformed in `visitClassDeclaration`. + return undefined; + case 222 /* InterfaceDeclaration */: + // TypeScript interfaces are elided, but some comments may be preserved. + // See the implementation of `getLeadingComments` in comments.ts for more details. + return ts.createNotEmittedStatement(node); + case 221 /* ClassDeclaration */: + // This is a class declaration with TypeScript syntax extensions. + // + // TypeScript class syntax extensions include: + // - decorators + // - optional `implements` heritage clause + // - parameter property assignments in the constructor + // - property declarations + // - index signatures + // - method overload signatures + // - async methods + return visitClassDeclaration(node); + case 192 /* ClassExpression */: + // This is a class expression with TypeScript syntax extensions. + // + // TypeScript class syntax extensions include: + // - decorators + // - optional `implements` heritage clause + // - parameter property assignments in the constructor + // - property declarations + // - index signatures + // - method overload signatures + // - async methods + return visitClassExpression(node); + case 251 /* HeritageClause */: + // This is a heritage clause with TypeScript syntax extensions. + // + // TypeScript heritage clause extensions include: + // - `implements` clause + return visitHeritageClause(node); + case 194 /* ExpressionWithTypeArguments */: + // TypeScript supports type arguments on an expression in an `extends` heritage clause. + return visitExpressionWithTypeArguments(node); + case 147 /* MethodDeclaration */: + // TypeScript method declarations may be 'async', and may have decorators, modifiers + // or type annotations. + return visitMethodDeclaration(node); + case 149 /* GetAccessor */: + // Get Accessors can have TypeScript modifiers, decorators, and type annotations. + return visitGetAccessor(node); + case 150 /* SetAccessor */: + // Set Accessors can have TypeScript modifiers, decorators, and type annotations. + return visitSetAccessor(node); + case 220 /* FunctionDeclaration */: + // TypeScript function declarations may be 'async' + return visitFunctionDeclaration(node); + case 179 /* FunctionExpression */: + // TypeScript function expressions may be 'async' + return visitFunctionExpression(node); + case 180 /* ArrowFunction */: + // TypeScript arrow functions may be 'async' + return visitArrowFunction(node); + case 142 /* Parameter */: + // This is a parameter declaration with TypeScript syntax extensions. + // + // TypeScript parameter declaration syntax extensions include: + // - decorators + // - accessibility modifiers + // - the question mark (?) token for optional parameters + // - type annotations + // - this parameters + return visitParameter(node); + case 178 /* ParenthesizedExpression */: + // ParenthesizedExpressions are TypeScript if their expression is a + // TypeAssertion or AsExpression + return visitParenthesizedExpression(node); + case 177 /* TypeAssertionExpression */: + case 195 /* AsExpression */: + // TypeScript type assertions are removed, but their subtrees are preserved. + return visitAssertionExpression(node); + case 196 /* NonNullExpression */: + // TypeScript non-null expressions are removed, but their subtrees are preserved. + return visitNonNullExpression(node); + case 224 /* EnumDeclaration */: + // TypeScript enum declarations do not exist in ES6 and must be rewritten. + return visitEnumDeclaration(node); + case 184 /* AwaitExpression */: + // TypeScript 'await' expressions must be transformed. + return visitAwaitExpression(node); + case 200 /* VariableStatement */: + // TypeScript namespace exports for variable statements must be transformed. + return visitVariableStatement(node); + case 225 /* ModuleDeclaration */: + // TypeScript namespace declarations must be transformed. + return visitModuleDeclaration(node); + case 229 /* ImportEqualsDeclaration */: + // TypeScript namespace or external module import. + return visitImportEqualsDeclaration(node); + default: + ts.Debug.failBadSyntaxKind(node); + return ts.visitEachChild(node, visitor, context); } } - function reset() { - currentSourceFile = undefined; - sourceMapDir = undefined; - sourceMapSourceIndex = undefined; - lastRecordedSourceMapSpan = undefined; - lastEncodedSourceMapSpan = undefined; - lastEncodedNameIndex = undefined; - sourceMapData = undefined; - } - function updateLastEncodedAndRecordedSpans() { - if (modifyLastSourcePos) { - // Reset the source pos - modifyLastSourcePos = false; - // Change Last recorded Map with last encoded emit line and character - lastRecordedSourceMapSpan.emittedLine = lastEncodedSourceMapSpan.emittedLine; - lastRecordedSourceMapSpan.emittedColumn = lastEncodedSourceMapSpan.emittedColumn; - // Pop sourceMapDecodedMappings to remove last entry - sourceMapData.sourceMapDecodedMappings.pop(); - // Point the lastEncodedSourceMapSpace to the previous encoded sourceMapSpan - // If the list is empty which indicates that we are at the beginning of the file, - // we have to reset it to default value (same value when we first initialize sourceMapWriter) - lastEncodedSourceMapSpan = sourceMapData.sourceMapDecodedMappings.length ? - sourceMapData.sourceMapDecodedMappings[sourceMapData.sourceMapDecodedMappings.length - 1] : - defaultLastEncodedSourceMapSpan; - // TODO: Update lastEncodedNameIndex - // Since we dont support this any more, lets not worry about it right now. - // When we start supporting nameIndex, we will get back to this - // Change the encoded source map - var sourceMapMappings = sourceMapData.sourceMapMappings; - var lenthToSet = sourceMapMappings.length - 1; - for (; lenthToSet >= 0; lenthToSet--) { - var currentChar = sourceMapMappings.charAt(lenthToSet); - if (currentChar === ",") { - // Separator for the entry found - break; - } - if (currentChar === ";" && lenthToSet !== 0 && sourceMapMappings.charAt(lenthToSet - 1) !== ";") { - // Last line separator found + /** + * Performs actions that should always occur immediately before visiting a node. + * + * @param node The node to visit. + */ + function onBeforeVisitNode(node) { + switch (node.kind) { + case 256 /* SourceFile */: + case 227 /* CaseBlock */: + case 226 /* ModuleBlock */: + case 199 /* Block */: + currentScope = node; + currentScopeFirstDeclarationsOfName = undefined; + break; + case 221 /* ClassDeclaration */: + case 220 /* FunctionDeclaration */: + if (ts.hasModifier(node, 2 /* Ambient */)) { break; } - } - sourceMapData.sourceMapMappings = sourceMapMappings.substr(0, Math.max(0, lenthToSet)); + recordEmittedDeclarationInScope(node); + break; } } - // Encoding for sourcemap span - function encodeLastRecordedSourceMapSpan() { - if (!lastRecordedSourceMapSpan || lastRecordedSourceMapSpan === lastEncodedSourceMapSpan) { - return; - } - var prevEncodedEmittedColumn = lastEncodedSourceMapSpan.emittedColumn; - // Line/Comma delimiters - if (lastEncodedSourceMapSpan.emittedLine === lastRecordedSourceMapSpan.emittedLine) { - // Emit comma to separate the entry - if (sourceMapData.sourceMapMappings) { - sourceMapData.sourceMapMappings += ","; - } + function visitSourceFile(node) { + currentSourceFile = node; + // If the source file requires any helpers and is an external module, and + // the importHelpers compiler option is enabled, emit a synthesized import + // statement for the helpers library. + if (node.flags & 31744 /* EmitHelperFlags */ + && compilerOptions.importHelpers + && (ts.isExternalModule(node) || compilerOptions.isolatedModules)) { + startLexicalEnvironment(); + var statements = []; + var statementOffset = ts.addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ false, visitor); + var externalHelpersModuleName = ts.createUniqueName(ts.externalHelpersModuleNameText); + var externalHelpersModuleImport = ts.createImportDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, ts.createImportClause(/*name*/ undefined, ts.createNamespaceImport(externalHelpersModuleName)), ts.createLiteral(ts.externalHelpersModuleNameText)); + externalHelpersModuleImport.parent = node; + externalHelpersModuleImport.flags &= ~8 /* Synthesized */; + statements.push(externalHelpersModuleImport); + currentSourceFileExternalHelpersModuleName = externalHelpersModuleName; + ts.addRange(statements, ts.visitNodes(node.statements, visitor, ts.isStatement, statementOffset)); + ts.addRange(statements, endLexicalEnvironment()); + currentSourceFileExternalHelpersModuleName = undefined; + node = ts.updateSourceFileNode(node, ts.createNodeArray(statements, node.statements)); + node.externalHelpersModuleName = externalHelpersModuleName; } else { - // Emit line delimiters - for (var encodedLine = lastEncodedSourceMapSpan.emittedLine; encodedLine < lastRecordedSourceMapSpan.emittedLine; encodedLine++) { - sourceMapData.sourceMapMappings += ";"; - } - prevEncodedEmittedColumn = 1; - } - // 1. Relative Column 0 based - sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.emittedColumn - prevEncodedEmittedColumn); - // 2. Relative sourceIndex - sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceIndex - lastEncodedSourceMapSpan.sourceIndex); - // 3. Relative sourceLine 0 based - sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceLine - lastEncodedSourceMapSpan.sourceLine); - // 4. Relative sourceColumn 0 based - sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceColumn - lastEncodedSourceMapSpan.sourceColumn); - // 5. Relative namePosition 0 based - if (lastRecordedSourceMapSpan.nameIndex >= 0) { - ts.Debug.assert(false, "We do not support name index right now, Make sure to update updateLastEncodedAndRecordedSpans when we start using this"); - sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.nameIndex - lastEncodedNameIndex); - lastEncodedNameIndex = lastRecordedSourceMapSpan.nameIndex; + node = ts.visitEachChild(node, visitor, context); } - lastEncodedSourceMapSpan = lastRecordedSourceMapSpan; - sourceMapData.sourceMapDecodedMappings.push(lastEncodedSourceMapSpan); + ts.setEmitFlags(node, 1 /* EmitEmitHelpers */ | ts.getEmitFlags(node)); + return node; } - function emitPos(pos) { - if (pos === -1) { - return; - } - if (extendedDiagnostics) { - ts.performance.mark("beforeSourcemap"); + /** + * Tests whether we should emit a __decorate call for a class declaration. + */ + function shouldEmitDecorateCallForClass(node) { + if (node.decorators && node.decorators.length > 0) { + return true; } - var sourceLinePos = ts.getLineAndCharacterOfPosition(currentSourceFile, pos); - // Convert the location to be one-based. - sourceLinePos.line++; - sourceLinePos.character++; - var emittedLine = writer.getLine(); - var emittedColumn = writer.getColumn(); - // If this location wasn't recorded or the location in source is going backwards, record the span - if (!lastRecordedSourceMapSpan || - lastRecordedSourceMapSpan.emittedLine !== emittedLine || - lastRecordedSourceMapSpan.emittedColumn !== emittedColumn || - (lastRecordedSourceMapSpan.sourceIndex === sourceMapSourceIndex && - (lastRecordedSourceMapSpan.sourceLine > sourceLinePos.line || - (lastRecordedSourceMapSpan.sourceLine === sourceLinePos.line && lastRecordedSourceMapSpan.sourceColumn > sourceLinePos.character)))) { - // Encode the last recordedSpan before assigning new - encodeLastRecordedSourceMapSpan(); - // New span - lastRecordedSourceMapSpan = { - emittedLine: emittedLine, - emittedColumn: emittedColumn, - sourceLine: sourceLinePos.line, - sourceColumn: sourceLinePos.character, - sourceIndex: sourceMapSourceIndex - }; - stopOverridingSpan = false; + var constructor = ts.getFirstConstructorWithBody(node); + if (constructor) { + return ts.forEach(constructor.parameters, shouldEmitDecorateCallForParameter); } - else if (!stopOverridingSpan) { - // Take the new pos instead since there is no change in emittedLine and column since last location - lastRecordedSourceMapSpan.sourceLine = sourceLinePos.line; - lastRecordedSourceMapSpan.sourceColumn = sourceLinePos.character; - lastRecordedSourceMapSpan.sourceIndex = sourceMapSourceIndex; + return false; + } + /** + * Tests whether we should emit a __decorate call for a parameter declaration. + */ + function shouldEmitDecorateCallForParameter(parameter) { + return parameter.decorators !== undefined && parameter.decorators.length > 0; + } + /** + * Transforms a class declaration with TypeScript syntax into compatible ES6. + * + * This function will only be called when one of the following conditions are met: + * - The class has decorators. + * - The class has property declarations with initializers. + * - The class contains a constructor that contains parameters with accessibility modifiers. + * - The class is an export in a TypeScript namespace. + * + * @param node The node to transform. + */ + function visitClassDeclaration(node) { + var staticProperties = getInitializedProperties(node, /*isStatic*/ true); + var hasExtendsClause = ts.getClassExtendsHeritageClauseElement(node) !== undefined; + var isDecoratedClass = shouldEmitDecorateCallForClass(node); + var classAlias; + // emit name if + // - node has a name + // - node has static initializers + // + var name = node.name; + if (!name && staticProperties.length > 0) { + name = ts.getGeneratedNameForNode(node); } - updateLastEncodedAndRecordedSpans(); - if (extendedDiagnostics) { - ts.performance.mark("afterSourcemap"); - ts.performance.measure("Source Map", "beforeSourcemap", "afterSourcemap"); + var statements = []; + if (!isDecoratedClass) { + // ${modifiers} class ${name} ${heritageClauses} { + // ${members} + // } + var classDeclaration = ts.createClassDeclaration( + /*decorators*/ undefined, ts.visitNodes(node.modifiers, visitor, ts.isModifier), name, + /*typeParameters*/ undefined, ts.visitNodes(node.heritageClauses, visitor, ts.isHeritageClause), transformClassMembers(node, hasExtendsClause), + /*location*/ node); + ts.setOriginalNode(classDeclaration, node); + // To better align with the old emitter, we should not emit a trailing source map + // entry if the class has static properties. + if (staticProperties.length > 0) { + ts.setEmitFlags(classDeclaration, 1024 /* NoTrailingSourceMap */ | ts.getEmitFlags(classDeclaration)); + } + statements.push(classDeclaration); } + else { + classAlias = addClassDeclarationHeadWithDecorators(statements, node, name, hasExtendsClause); + } + // Emit static property assignment. Because classDeclaration is lexically evaluated, + // it is safe to emit static property assignment after classDeclaration + // From ES6 specification: + // HasLexicalDeclaration (N) : Determines if the argument identifier has a binding in this environment record that was created using + // a lexical declaration such as a LexicalDeclaration or a ClassDeclaration. + if (staticProperties.length) { + addInitializedPropertyStatements(statements, node, staticProperties, getLocalName(node, /*noSourceMaps*/ true)); + } + // Write any decorators of the node. + addClassElementDecorationStatements(statements, node, /*isStatic*/ false); + addClassElementDecorationStatements(statements, node, /*isStatic*/ true); + addConstructorDecorationStatement(statements, node, classAlias); + // If the class is exported as part of a TypeScript namespace, emit the namespace export. + // Otherwise, if the class was exported at the top level and was decorated, emit an export + // declaration or export default for the class. + if (isNamespaceExport(node)) { + addExportMemberAssignment(statements, node); + } + else if (isDecoratedClass) { + if (isDefaultExternalModuleExport(node)) { + statements.push(ts.createExportAssignment( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*isExportEquals*/ false, getLocalName(node))); + } + else if (isNamedExternalModuleExport(node)) { + statements.push(createExternalModuleExport(name)); + } + } + return statements; + } + /** + * Transforms a decorated class declaration and appends the resulting statements. If + * the class requires an alias to avoid issues with double-binding, the alias is returned. + * + * @param node A ClassDeclaration node. + * @param name The name of the class. + * @param hasExtendsClause A value indicating whether + */ + function addClassDeclarationHeadWithDecorators(statements, node, name, hasExtendsClause) { + // When we emit an ES6 class that has a class decorator, we must tailor the + // emit to certain specific cases. + // + // In the simplest case, we emit the class declaration as a let declaration, and + // evaluate decorators after the close of the class body: + // + // [Example 1] + // --------------------------------------------------------------------- + // TypeScript | Javascript + // --------------------------------------------------------------------- + // @dec | let C = class C { + // class C { | } + // } | C = __decorate([dec], C); + // --------------------------------------------------------------------- + // @dec | let C = class C { + // export class C { | } + // } | C = __decorate([dec], C); + // | export { C }; + // --------------------------------------------------------------------- + // + // If a class declaration contains a reference to itself *inside* of the class body, + // this introduces two bindings to the class: One outside of the class body, and one + // inside of the class body. If we apply decorators as in [Example 1] above, there + // is the possibility that the decorator `dec` will return a new value for the + // constructor, which would result in the binding inside of the class no longer + // pointing to the same reference as the binding outside of the class. + // + // As a result, we must instead rewrite all references to the class *inside* of the + // class body to instead point to a local temporary alias for the class: + // + // [Example 2] + // --------------------------------------------------------------------- + // TypeScript | Javascript + // --------------------------------------------------------------------- + // @dec | let C_1 = class C { + // class C { | static x() { return C_1.y; } + // static x() { return C.y; } | } + // static y = 1; | let C = C_1; + // } | C.y = 1; + // | C = C_1 = __decorate([dec], C); + // --------------------------------------------------------------------- + // @dec | let C_1 = class C { + // export class C { | static x() { return C_1.y; } + // static x() { return C.y; } | } + // static y = 1; | let C = C_1; + // } | C.y = 1; + // | C = C_1 = __decorate([dec], C); + // | export { C }; + // --------------------------------------------------------------------- + // + // If a class declaration is the default export of a module, we instead emit + // the export after the decorated declaration: + // + // [Example 3] + // --------------------------------------------------------------------- + // TypeScript | Javascript + // --------------------------------------------------------------------- + // @dec | let default_1 = class { + // export default class { | } + // } | default_1 = __decorate([dec], default_1); + // | export default default_1; + // --------------------------------------------------------------------- + // @dec | let C = class C { + // export default class C { | } + // } | C = __decorate([dec], C); + // | export default C; + // --------------------------------------------------------------------- + // + // If the class declaration is the default export and a reference to itself + // inside of the class body, we must emit both an alias for the class *and* + // move the export after the declaration: + // + // [Example 4] + // --------------------------------------------------------------------- + // TypeScript | Javascript + // --------------------------------------------------------------------- + // @dec | let C_1 = class C { + // export default class C { | static x() { return C_1.y; } + // static x() { return C.y; } | } + // static y = 1; | let C = C_1; + // } | C.y = 1; + // | C = C_1 = __decorate([dec], C); + // | export default C; + // --------------------------------------------------------------------- + // + var location = ts.moveRangePastDecorators(node); + // ... = class ${name} ${heritageClauses} { + // ${members} + // } + var classExpression = ts.setOriginalNode(ts.createClassExpression( + /*modifiers*/ undefined, name, + /*typeParameters*/ undefined, ts.visitNodes(node.heritageClauses, visitor, ts.isHeritageClause), transformClassMembers(node, hasExtendsClause), + /*location*/ location), node); + if (!name) { + name = ts.getGeneratedNameForNode(node); + } + // Record an alias to avoid class double-binding. + var classAlias; + if (resolver.getNodeCheckFlags(node) & 8388608 /* ClassWithConstructorReference */) { + enableSubstitutionForClassAliases(); + classAlias = ts.createUniqueName(node.name && !ts.isGeneratedIdentifier(node.name) ? node.name.text : "default"); + classAliases[ts.getOriginalNodeId(node)] = classAlias; + } + var declaredName = getDeclarationName(node, /*allowComments*/ true); + // let ${name} = ${classExpression} where name is either declaredName if the class doesn't contain self-reference + // or decoratedClassAlias if the class contain self-reference. + var transformedClassExpression = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createLetDeclarationList([ + ts.createVariableDeclaration(classAlias || declaredName, + /*type*/ undefined, classExpression) + ]), + /*location*/ location); + ts.setCommentRange(transformedClassExpression, node); + statements.push(ts.setOriginalNode( + /*node*/ transformedClassExpression, + /*original*/ node)); + if (classAlias) { + // We emit the class alias as a `let` declaration here so that it has the same + // TDZ as the class. + // let ${declaredName} = ${decoratedClassAlias} + statements.push(ts.setOriginalNode(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createLetDeclarationList([ + ts.createVariableDeclaration(declaredName, + /*type*/ undefined, classAlias) + ]), + /*location*/ location), + /*original*/ node)); + } + return classAlias; + } + /** + * Transforms a class expression with TypeScript syntax into compatible ES6. + * + * This function will only be called when one of the following conditions are met: + * - The class has property declarations with initializers. + * - The class contains a constructor that contains parameters with accessibility modifiers. + * + * @param node The node to transform. + */ + function visitClassExpression(node) { + var staticProperties = getInitializedProperties(node, /*isStatic*/ true); + var heritageClauses = ts.visitNodes(node.heritageClauses, visitor, ts.isHeritageClause); + var members = transformClassMembers(node, heritageClauses !== undefined); + var classExpression = ts.setOriginalNode(ts.createClassExpression( + /*modifiers*/ undefined, node.name, + /*typeParameters*/ undefined, heritageClauses, members, + /*location*/ node), node); + if (staticProperties.length > 0) { + var expressions = []; + var temp = ts.createTempVariable(hoistVariableDeclaration); + if (resolver.getNodeCheckFlags(node) & 8388608 /* ClassWithConstructorReference */) { + // record an alias as the class name is not in scope for statics. + enableSubstitutionForClassAliases(); + classAliases[ts.getOriginalNodeId(node)] = ts.getSynthesizedClone(temp); + } + // To preserve the behavior of the old emitter, we explicitly indent + // the body of a class with static initializers. + ts.setEmitFlags(classExpression, 524288 /* Indented */ | ts.getEmitFlags(classExpression)); + expressions.push(ts.startOnNewLine(ts.createAssignment(temp, classExpression))); + ts.addRange(expressions, generateInitializedPropertyExpressions(node, staticProperties, temp)); + expressions.push(ts.startOnNewLine(temp)); + return ts.inlineExpressions(expressions); + } + return classExpression; } - function getStartPos(range) { - var rangeHasDecorators = !!range.decorators; - return range.pos !== -1 ? ts.skipTrivia(currentSourceFile.text, rangeHasDecorators ? range.decorators.end : range.pos) : -1; + /** + * Transforms the members of a class. + * + * @param node The current class. + * @param hasExtendsClause A value indicating whether the class has an extends clause. + */ + function transformClassMembers(node, hasExtendsClause) { + var members = []; + var constructor = transformConstructor(node, hasExtendsClause); + if (constructor) { + members.push(constructor); + } + ts.addRange(members, ts.visitNodes(node.members, classElementVisitor, ts.isClassElement)); + return ts.createNodeArray(members, /*location*/ node.members); } - function emitStart(range) { - emitPos(getStartPos(range)); + /** + * Transforms (or creates) a constructor for a class. + * + * @param node The current class. + * @param hasExtendsClause A value indicating whether the class has an extends clause. + */ + function transformConstructor(node, hasExtendsClause) { + // Check if we have property assignment inside class declaration. + // If there is a property assignment, we need to emit constructor whether users define it or not + // If there is no property assignment, we can omit constructor if users do not define it + var hasInstancePropertyWithInitializer = ts.forEach(node.members, isInstanceInitializedProperty); + var hasParameterPropertyAssignments = node.transformFlags & 131072 /* ContainsParameterPropertyAssignments */; + var constructor = ts.getFirstConstructorWithBody(node); + // If the class does not contain nodes that require a synthesized constructor, + // accept the current constructor if it exists. + if (!hasInstancePropertyWithInitializer && !hasParameterPropertyAssignments) { + return ts.visitEachChild(constructor, visitor, context); + } + var parameters = transformConstructorParameters(constructor); + var body = transformConstructorBody(node, constructor, hasExtendsClause, parameters); + // constructor(${parameters}) { + // ${body} + // } + return ts.startOnNewLine(ts.setOriginalNode(ts.createConstructor( + /*decorators*/ undefined, + /*modifiers*/ undefined, parameters, body, + /*location*/ constructor || node), constructor)); } - function emitEnd(range, stopOverridingEnd) { - emitPos(range.end); - stopOverridingSpan = stopOverridingEnd; + /** + * Transforms (or creates) the parameters for the constructor of a class with + * parameter property assignments or instance property initializers. + * + * @param constructor The constructor declaration. + * @param hasExtendsClause A value indicating whether the class has an extends clause. + */ + function transformConstructorParameters(constructor) { + // The ES2015 spec specifies in 14.5.14. Runtime Semantics: ClassDefinitionEvaluation: + // If constructor is empty, then + // If ClassHeritag_eopt is present and protoParent is not null, then + // Let constructor be the result of parsing the source text + // constructor(...args) { super (...args);} + // using the syntactic grammar with the goal symbol MethodDefinition[~Yield]. + // Else, + // Let constructor be the result of parsing the source text + // constructor( ){ } + // using the syntactic grammar with the goal symbol MethodDefinition[~Yield]. + // + // While we could emit the '...args' rest parameter, certain later tools in the pipeline might + // downlevel the '...args' portion less efficiently by naively copying the contents of 'arguments' to an array. + // Instead, we'll avoid using a rest parameter and spread into the super call as + // 'super(...arguments)' instead of 'super(...args)', as you can see in "transformConstructorBody". + return constructor + ? ts.visitNodes(constructor.parameters, visitor, ts.isParameter) + : []; } - function changeEmitSourcePos() { - ts.Debug.assert(!modifyLastSourcePos); - modifyLastSourcePos = true; + /** + * Transforms (or creates) a constructor body for a class with parameter property + * assignments or instance property initializers. + * + * @param node The current class. + * @param constructor The current class constructor. + * @param hasExtendsClause A value indicating whether the class has an extends clause. + * @param parameters The transformed parameters for the constructor. + */ + function transformConstructorBody(node, constructor, hasExtendsClause, parameters) { + var statements = []; + var indexOfFirstStatement = 0; + // The body of a constructor is a new lexical environment + startLexicalEnvironment(); + if (constructor) { + indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(constructor, statements); + // Add parameters with property assignments. Transforms this: + // + // constructor (public x, public y) { + // } + // + // Into this: + // + // constructor (x, y) { + // this.x = x; + // this.y = y; + // } + // + var propertyAssignments = getParametersWithPropertyAssignments(constructor); + ts.addRange(statements, ts.map(propertyAssignments, transformParameterWithPropertyAssignment)); + } + else if (hasExtendsClause) { + // Add a synthetic `super` call: + // + // super(...arguments); + // + statements.push(ts.createStatement(ts.createCall(ts.createSuper(), + /*typeArguments*/ undefined, [ts.createSpread(ts.createIdentifier("arguments"))]))); + } + // Add the property initializers. Transforms this: + // + // public x = 1; + // + // Into this: + // + // constructor() { + // this.x = 1; + // } + // + var properties = getInitializedProperties(node, /*isStatic*/ false); + addInitializedPropertyStatements(statements, node, properties, ts.createThis()); + if (constructor) { + // The class already had a constructor, so we should add the existing statements, skipping the initial super call. + ts.addRange(statements, ts.visitNodes(constructor.body.statements, visitor, ts.isStatement, indexOfFirstStatement)); + } + // End the lexical environment. + ts.addRange(statements, endLexicalEnvironment()); + return ts.setMultiLine(ts.createBlock(ts.createNodeArray(statements, + /*location*/ constructor ? constructor.body.statements : node.members), + /*location*/ constructor ? constructor.body : undefined), true); } - function setSourceFile(sourceFile) { - currentSourceFile = sourceFile; - // Add the file to tsFilePaths - // If sourceroot option: Use the relative path corresponding to the common directory path - // otherwise source locations relative to map file location - var sourcesDirectoryPath = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir; - var source = ts.getRelativePathToDirectoryOrUrl(sourcesDirectoryPath, currentSourceFile.fileName, host.getCurrentDirectory(), host.getCanonicalFileName, - /*isAbsolutePathAnUrl*/ true); - sourceMapSourceIndex = ts.indexOf(sourceMapData.sourceMapSources, source); - if (sourceMapSourceIndex === -1) { - sourceMapSourceIndex = sourceMapData.sourceMapSources.length; - sourceMapData.sourceMapSources.push(source); - // The one that can be used from program to get the actual source file - sourceMapData.inputSourceFileNames.push(sourceFile.fileName); - if (compilerOptions.inlineSources) { - sourceMapData.sourceMapSourcesContent.push(sourceFile.text); + /** + * Adds super call and preceding prologue directives into the list of statements. + * + * @param ctor The constructor node. + * @returns index of the statement that follows super call + */ + function addPrologueDirectivesAndInitialSuperCall(ctor, result) { + if (ctor.body) { + var statements = ctor.body.statements; + // add prologue directives to the list (if any) + var index = ts.addPrologueDirectives(result, statements, /*ensureUseStrict*/ false, visitor); + if (index === statements.length) { + // list contains nothing but prologue directives (or empty) - exit + return index; + } + var statement = statements[index]; + if (statement.kind === 202 /* ExpressionStatement */ && ts.isSuperCallExpression(statement.expression)) { + result.push(ts.visitNode(statement, visitor, ts.isStatement)); + return index + 1; } + return index; } + return 0; } - function getText() { - encodeLastRecordedSourceMapSpan(); - return ts.stringify({ - version: 3, - file: sourceMapData.sourceMapFile, - sourceRoot: sourceMapData.sourceMapSourceRoot, - sources: sourceMapData.sourceMapSources, - names: sourceMapData.sourceMapNames, - mappings: sourceMapData.sourceMapMappings, - sourcesContent: sourceMapData.sourceMapSourcesContent, - }); + /** + * Gets all parameters of a constructor that should be transformed into property assignments. + * + * @param node The constructor node. + */ + function getParametersWithPropertyAssignments(node) { + return ts.filter(node.parameters, isParameterWithPropertyAssignment); } - function getSourceMappingURL() { - if (compilerOptions.inlineSourceMap) { - // Encode the sourceMap into the sourceMap url - var base64SourceMapText = ts.convertToBase64(getText()); - return sourceMapData.jsSourceMappingURL = "data:application/json;base64," + base64SourceMapText; - } - else { - return sourceMapData.jsSourceMappingURL; - } + /** + * Determines whether a parameter should be transformed into a property assignment. + * + * @param parameter The parameter node. + */ + function isParameterWithPropertyAssignment(parameter) { + return ts.hasModifier(parameter, 92 /* ParameterPropertyModifier */) + && ts.isIdentifier(parameter.name); } - } - ts.createSourceMapWriter = createSourceMapWriter; - var base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - function base64FormatEncode(inValue) { - if (inValue < 64) { - return base64Chars.charAt(inValue); + /** + * Transforms a parameter into a property assignment statement. + * + * @param node The parameter declaration. + */ + function transformParameterWithPropertyAssignment(node) { + ts.Debug.assert(ts.isIdentifier(node.name)); + var name = node.name; + var propertyName = ts.getMutableClone(name); + ts.setEmitFlags(propertyName, 49152 /* NoComments */ | 1536 /* NoSourceMap */); + var localName = ts.getMutableClone(name); + ts.setEmitFlags(localName, 49152 /* NoComments */); + return ts.startOnNewLine(ts.createStatement(ts.createAssignment(ts.createPropertyAccess(ts.createThis(), propertyName, + /*location*/ node.name), localName), + /*location*/ ts.moveRangePos(node, -1))); } - throw TypeError(inValue + ": not a 64 based value"); - } - function base64VLQFormatEncode(inValue) { - // Add a new least significant bit that has the sign of the value. - // if negative number the least significant bit that gets added to the number has value 1 - // else least significant bit value that gets added is 0 - // eg. -1 changes to binary : 01 [1] => 3 - // +1 changes to binary : 01 [0] => 2 - if (inValue < 0) { - inValue = ((-inValue) << 1) + 1; + /** + * Gets all property declarations with initializers on either the static or instance side of a class. + * + * @param node The class node. + * @param isStatic A value indicating whether to get properties from the static or instance side of the class. + */ + function getInitializedProperties(node, isStatic) { + return ts.filter(node.members, isStatic ? isStaticInitializedProperty : isInstanceInitializedProperty); } - else { - inValue = inValue << 1; + /** + * Gets a value indicating whether a class element is a static property declaration with an initializer. + * + * @param member The class element node. + */ + function isStaticInitializedProperty(member) { + return isInitializedProperty(member, /*isStatic*/ true); } - // Encode 5 bits at a time starting from least significant bits - var encodedStr = ""; - do { - var currentDigit = inValue & 31; // 11111 - inValue = inValue >> 5; - if (inValue > 0) { - // There are still more digits to decode, set the msb (6th bit) - currentDigit = currentDigit | 32; + /** + * Gets a value indicating whether a class element is an instance property declaration with an initializer. + * + * @param member The class element node. + */ + function isInstanceInitializedProperty(member) { + return isInitializedProperty(member, /*isStatic*/ false); + } + /** + * Gets a value indicating whether a class element is either a static or an instance property declaration with an initializer. + * + * @param member The class element node. + * @param isStatic A value indicating whether the member should be a static or instance member. + */ + function isInitializedProperty(member, isStatic) { + return member.kind === 145 /* PropertyDeclaration */ + && isStatic === ts.hasModifier(member, 32 /* Static */) + && member.initializer !== undefined; + } + /** + * Generates assignment statements for property initializers. + * + * @param node The class node. + * @param properties An array of property declarations to transform. + * @param receiver The receiver on which each property should be assigned. + */ + function addInitializedPropertyStatements(statements, node, properties, receiver) { + for (var _i = 0, properties_7 = properties; _i < properties_7.length; _i++) { + var property = properties_7[_i]; + var statement = ts.createStatement(transformInitializedProperty(node, property, receiver)); + ts.setSourceMapRange(statement, ts.moveRangePastModifiers(property)); + ts.setCommentRange(statement, property); + statements.push(statement); } - encodedStr = encodedStr + base64FormatEncode(currentDigit); - } while (inValue > 0); - return encodedStr; - } -})(ts || (ts = {})); -/// -/// -/// -/* @internal */ -var ts; -(function (ts) { - function getResolvedExternalModuleName(host, file) { - return file.moduleName || ts.getExternalModuleNameFromPath(host, file.fileName); - } - ts.getResolvedExternalModuleName = getResolvedExternalModuleName; - function getExternalModuleNameFromDeclaration(host, resolver, declaration) { - var file = resolver.getExternalModuleFileFromDeclaration(declaration); - if (!file || ts.isDeclarationFile(file)) { - return undefined; } - return getResolvedExternalModuleName(host, file); - } - ts.getExternalModuleNameFromDeclaration = getExternalModuleNameFromDeclaration; - var Jump; - (function (Jump) { - Jump[Jump["Break"] = 2] = "Break"; - Jump[Jump["Continue"] = 4] = "Continue"; - Jump[Jump["Return"] = 8] = "Return"; - })(Jump || (Jump = {})); - var entities = ts.createMap({ - "quot": 0x0022, - "amp": 0x0026, - "apos": 0x0027, - "lt": 0x003C, - "gt": 0x003E, - "nbsp": 0x00A0, - "iexcl": 0x00A1, - "cent": 0x00A2, - "pound": 0x00A3, - "curren": 0x00A4, - "yen": 0x00A5, - "brvbar": 0x00A6, - "sect": 0x00A7, - "uml": 0x00A8, - "copy": 0x00A9, - "ordf": 0x00AA, - "laquo": 0x00AB, - "not": 0x00AC, - "shy": 0x00AD, - "reg": 0x00AE, - "macr": 0x00AF, - "deg": 0x00B0, - "plusmn": 0x00B1, - "sup2": 0x00B2, - "sup3": 0x00B3, - "acute": 0x00B4, - "micro": 0x00B5, - "para": 0x00B6, - "middot": 0x00B7, - "cedil": 0x00B8, - "sup1": 0x00B9, - "ordm": 0x00BA, - "raquo": 0x00BB, - "frac14": 0x00BC, - "frac12": 0x00BD, - "frac34": 0x00BE, - "iquest": 0x00BF, - "Agrave": 0x00C0, - "Aacute": 0x00C1, - "Acirc": 0x00C2, - "Atilde": 0x00C3, - "Auml": 0x00C4, - "Aring": 0x00C5, - "AElig": 0x00C6, - "Ccedil": 0x00C7, - "Egrave": 0x00C8, - "Eacute": 0x00C9, - "Ecirc": 0x00CA, - "Euml": 0x00CB, - "Igrave": 0x00CC, - "Iacute": 0x00CD, - "Icirc": 0x00CE, - "Iuml": 0x00CF, - "ETH": 0x00D0, - "Ntilde": 0x00D1, - "Ograve": 0x00D2, - "Oacute": 0x00D3, - "Ocirc": 0x00D4, - "Otilde": 0x00D5, - "Ouml": 0x00D6, - "times": 0x00D7, - "Oslash": 0x00D8, - "Ugrave": 0x00D9, - "Uacute": 0x00DA, - "Ucirc": 0x00DB, - "Uuml": 0x00DC, - "Yacute": 0x00DD, - "THORN": 0x00DE, - "szlig": 0x00DF, - "agrave": 0x00E0, - "aacute": 0x00E1, - "acirc": 0x00E2, - "atilde": 0x00E3, - "auml": 0x00E4, - "aring": 0x00E5, - "aelig": 0x00E6, - "ccedil": 0x00E7, - "egrave": 0x00E8, - "eacute": 0x00E9, - "ecirc": 0x00EA, - "euml": 0x00EB, - "igrave": 0x00EC, - "iacute": 0x00ED, - "icirc": 0x00EE, - "iuml": 0x00EF, - "eth": 0x00F0, - "ntilde": 0x00F1, - "ograve": 0x00F2, - "oacute": 0x00F3, - "ocirc": 0x00F4, - "otilde": 0x00F5, - "ouml": 0x00F6, - "divide": 0x00F7, - "oslash": 0x00F8, - "ugrave": 0x00F9, - "uacute": 0x00FA, - "ucirc": 0x00FB, - "uuml": 0x00FC, - "yacute": 0x00FD, - "thorn": 0x00FE, - "yuml": 0x00FF, - "OElig": 0x0152, - "oelig": 0x0153, - "Scaron": 0x0160, - "scaron": 0x0161, - "Yuml": 0x0178, - "fnof": 0x0192, - "circ": 0x02C6, - "tilde": 0x02DC, - "Alpha": 0x0391, - "Beta": 0x0392, - "Gamma": 0x0393, - "Delta": 0x0394, - "Epsilon": 0x0395, - "Zeta": 0x0396, - "Eta": 0x0397, - "Theta": 0x0398, - "Iota": 0x0399, - "Kappa": 0x039A, - "Lambda": 0x039B, - "Mu": 0x039C, - "Nu": 0x039D, - "Xi": 0x039E, - "Omicron": 0x039F, - "Pi": 0x03A0, - "Rho": 0x03A1, - "Sigma": 0x03A3, - "Tau": 0x03A4, - "Upsilon": 0x03A5, - "Phi": 0x03A6, - "Chi": 0x03A7, - "Psi": 0x03A8, - "Omega": 0x03A9, - "alpha": 0x03B1, - "beta": 0x03B2, - "gamma": 0x03B3, - "delta": 0x03B4, - "epsilon": 0x03B5, - "zeta": 0x03B6, - "eta": 0x03B7, - "theta": 0x03B8, - "iota": 0x03B9, - "kappa": 0x03BA, - "lambda": 0x03BB, - "mu": 0x03BC, - "nu": 0x03BD, - "xi": 0x03BE, - "omicron": 0x03BF, - "pi": 0x03C0, - "rho": 0x03C1, - "sigmaf": 0x03C2, - "sigma": 0x03C3, - "tau": 0x03C4, - "upsilon": 0x03C5, - "phi": 0x03C6, - "chi": 0x03C7, - "psi": 0x03C8, - "omega": 0x03C9, - "thetasym": 0x03D1, - "upsih": 0x03D2, - "piv": 0x03D6, - "ensp": 0x2002, - "emsp": 0x2003, - "thinsp": 0x2009, - "zwnj": 0x200C, - "zwj": 0x200D, - "lrm": 0x200E, - "rlm": 0x200F, - "ndash": 0x2013, - "mdash": 0x2014, - "lsquo": 0x2018, - "rsquo": 0x2019, - "sbquo": 0x201A, - "ldquo": 0x201C, - "rdquo": 0x201D, - "bdquo": 0x201E, - "dagger": 0x2020, - "Dagger": 0x2021, - "bull": 0x2022, - "hellip": 0x2026, - "permil": 0x2030, - "prime": 0x2032, - "Prime": 0x2033, - "lsaquo": 0x2039, - "rsaquo": 0x203A, - "oline": 0x203E, - "frasl": 0x2044, - "euro": 0x20AC, - "image": 0x2111, - "weierp": 0x2118, - "real": 0x211C, - "trade": 0x2122, - "alefsym": 0x2135, - "larr": 0x2190, - "uarr": 0x2191, - "rarr": 0x2192, - "darr": 0x2193, - "harr": 0x2194, - "crarr": 0x21B5, - "lArr": 0x21D0, - "uArr": 0x21D1, - "rArr": 0x21D2, - "dArr": 0x21D3, - "hArr": 0x21D4, - "forall": 0x2200, - "part": 0x2202, - "exist": 0x2203, - "empty": 0x2205, - "nabla": 0x2207, - "isin": 0x2208, - "notin": 0x2209, - "ni": 0x220B, - "prod": 0x220F, - "sum": 0x2211, - "minus": 0x2212, - "lowast": 0x2217, - "radic": 0x221A, - "prop": 0x221D, - "infin": 0x221E, - "ang": 0x2220, - "and": 0x2227, - "or": 0x2228, - "cap": 0x2229, - "cup": 0x222A, - "int": 0x222B, - "there4": 0x2234, - "sim": 0x223C, - "cong": 0x2245, - "asymp": 0x2248, - "ne": 0x2260, - "equiv": 0x2261, - "le": 0x2264, - "ge": 0x2265, - "sub": 0x2282, - "sup": 0x2283, - "nsub": 0x2284, - "sube": 0x2286, - "supe": 0x2287, - "oplus": 0x2295, - "otimes": 0x2297, - "perp": 0x22A5, - "sdot": 0x22C5, - "lceil": 0x2308, - "rceil": 0x2309, - "lfloor": 0x230A, - "rfloor": 0x230B, - "lang": 0x2329, - "rang": 0x232A, - "loz": 0x25CA, - "spades": 0x2660, - "clubs": 0x2663, - "hearts": 0x2665, - "diams": 0x2666 - }); - // Flags enum to track count of temp variables and a few dedicated names - var TempFlags; - (function (TempFlags) { - TempFlags[TempFlags["Auto"] = 0] = "Auto"; - TempFlags[TempFlags["CountMask"] = 268435455] = "CountMask"; - TempFlags[TempFlags["_i"] = 268435456] = "_i"; - })(TempFlags || (TempFlags = {})); - var CopyDirection; - (function (CopyDirection) { - CopyDirection[CopyDirection["ToOriginal"] = 0] = "ToOriginal"; - CopyDirection[CopyDirection["ToOutParameter"] = 1] = "ToOutParameter"; - })(CopyDirection || (CopyDirection = {})); - // targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature - function emitFiles(resolver, host, targetSourceFile) { - // emit output for the __extends helper function - var extendsHelper = "\nvar __extends = (this && this.__extends) || function (d, b) {\n for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n};"; - var assignHelper = "\nvar __assign = (this && this.__assign) || Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n};"; - // emit output for the __decorate helper function - var decorateHelper = "\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};"; - // emit output for the __metadata helper function - var metadataHelper = "\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};"; - // emit output for the __param helper function - var paramHelper = "\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};"; - var awaiterHelper = "\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments)).next());\n });\n};"; - var compilerOptions = host.getCompilerOptions(); - var languageVersion = ts.getEmitScriptTarget(compilerOptions); - var modulekind = ts.getEmitModuleKind(compilerOptions); - var sourceMapDataList = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? [] : undefined; - var emittedFilesList = compilerOptions.listEmittedFiles ? [] : undefined; - var emitterDiagnostics = ts.createDiagnosticCollection(); - var emitSkipped = false; - var newLine = host.getNewLine(); - var emitJavaScript = createFileEmitter(); - ts.forEachExpectedEmitFile(host, emitFile, targetSourceFile); - return { - emitSkipped: emitSkipped, - diagnostics: emitterDiagnostics.getDiagnostics(), - emittedFiles: emittedFilesList, - sourceMaps: sourceMapDataList - }; - function isUniqueLocalName(name, container) { - for (var node = container; ts.isNodeDescendentOf(node, container); node = node.nextContainer) { - if (node.locals && name in node.locals) { - // We conservatively include alias symbols to cover cases where they're emitted as locals - if (node.locals[name].flags & (107455 /* Value */ | 1048576 /* ExportValue */ | 8388608 /* Alias */)) { - return false; + /** + * Generates assignment expressions for property initializers. + * + * @param node The class node. + * @param properties An array of property declarations to transform. + * @param receiver The receiver on which each property should be assigned. + */ + function generateInitializedPropertyExpressions(node, properties, receiver) { + var expressions = []; + for (var _i = 0, properties_8 = properties; _i < properties_8.length; _i++) { + var property = properties_8[_i]; + var expression = transformInitializedProperty(node, property, receiver); + expression.startsOnNewLine = true; + ts.setSourceMapRange(expression, ts.moveRangePastModifiers(property)); + ts.setCommentRange(expression, property); + expressions.push(expression); + } + return expressions; + } + /** + * Transforms a property initializer into an assignment statement. + * + * @param node The class containing the property. + * @param property The property declaration. + * @param receiver The object receiving the property assignment. + */ + function transformInitializedProperty(node, property, receiver) { + var propertyName = visitPropertyNameOfClassElement(property); + var initializer = ts.visitNode(property.initializer, visitor, ts.isExpression); + var memberAccess = ts.createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName); + return ts.createAssignment(memberAccess, initializer); + } + /** + * Gets either the static or instance members of a class that are decorated, or have + * parameters that are decorated. + * + * @param node The class containing the member. + * @param isStatic A value indicating whether to retrieve static or instance members of + * the class. + */ + function getDecoratedClassElements(node, isStatic) { + return ts.filter(node.members, isStatic ? isStaticDecoratedClassElement : isInstanceDecoratedClassElement); + } + /** + * Determines whether a class member is a static member of a class that is decorated, or + * has parameters that are decorated. + * + * @param member The class member. + */ + function isStaticDecoratedClassElement(member) { + return isDecoratedClassElement(member, /*isStatic*/ true); + } + /** + * Determines whether a class member is an instance member of a class that is decorated, + * or has parameters that are decorated. + * + * @param member The class member. + */ + function isInstanceDecoratedClassElement(member) { + return isDecoratedClassElement(member, /*isStatic*/ false); + } + /** + * Determines whether a class member is either a static or an instance member of a class + * that is decorated, or has parameters that are decorated. + * + * @param member The class member. + */ + function isDecoratedClassElement(member, isStatic) { + return ts.nodeOrChildIsDecorated(member) + && isStatic === ts.hasModifier(member, 32 /* Static */); + } + /** + * Gets an array of arrays of decorators for the parameters of a function-like node. + * The offset into the result array should correspond to the offset of the parameter. + * + * @param node The function-like node. + */ + function getDecoratorsOfParameters(node) { + var decorators; + if (node) { + var parameters = node.parameters; + for (var i = 0; i < parameters.length; i++) { + var parameter = parameters[i]; + if (decorators || parameter.decorators) { + if (!decorators) { + decorators = new Array(parameters.length); + } + decorators[i] = parameter.decorators; } } } - return true; + return decorators; } - function setLabeledJump(state, isBreak, labelText, labelMarker) { - if (isBreak) { - if (!state.labeledNonLocalBreaks) { - state.labeledNonLocalBreaks = ts.createMap(); - } - state.labeledNonLocalBreaks[labelText] = labelMarker; + /** + * Gets an AllDecorators object containing the decorators for the class and the decorators for the + * parameters of the constructor of the class. + * + * @param node The class node. + */ + function getAllDecoratorsOfConstructor(node) { + var decorators = node.decorators; + var parameters = getDecoratorsOfParameters(ts.getFirstConstructorWithBody(node)); + if (!decorators && !parameters) { + return undefined; } - else { - if (!state.labeledNonLocalContinues) { - state.labeledNonLocalContinues = ts.createMap(); - } - state.labeledNonLocalContinues[labelText] = labelMarker; + return { + decorators: decorators, + parameters: parameters + }; + } + /** + * Gets an AllDecorators object containing the decorators for the member and its parameters. + * + * @param node The class node that contains the member. + * @param member The class member. + */ + function getAllDecoratorsOfClassElement(node, member) { + switch (member.kind) { + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + return getAllDecoratorsOfAccessors(node, member); + case 147 /* MethodDeclaration */: + return getAllDecoratorsOfMethod(member); + case 145 /* PropertyDeclaration */: + return getAllDecoratorsOfProperty(member); + default: + return undefined; } } - function hoistVariableDeclarationFromLoop(state, declaration) { - if (!state.hoistedLocalVariables) { - state.hoistedLocalVariables = []; + /** + * Gets an AllDecorators object containing the decorators for the accessor and its parameters. + * + * @param node The class node that contains the accessor. + * @param accessor The class accessor member. + */ + function getAllDecoratorsOfAccessors(node, accessor) { + if (!accessor.body) { + return undefined; } - visit(declaration.name); - function visit(node) { - if (node.kind === 69 /* Identifier */) { - state.hoistedLocalVariables.push(node); - } - else { - for (var _a = 0, _b = node.elements; _a < _b.length; _a++) { - var element = _b[_a]; - visit(element.name); - } - } + var _a = ts.getAllAccessorDeclarations(node.members, accessor), firstAccessor = _a.firstAccessor, secondAccessor = _a.secondAccessor, setAccessor = _a.setAccessor; + if (accessor !== firstAccessor) { + return undefined; } + var decorators = firstAccessor.decorators || (secondAccessor && secondAccessor.decorators); + var parameters = getDecoratorsOfParameters(setAccessor); + if (!decorators && !parameters) { + return undefined; + } + return { decorators: decorators, parameters: parameters }; } - function createFileEmitter() { - var writer = ts.createTextWriter(newLine); - var write = writer.write, writeTextOfNode = writer.writeTextOfNode, writeLine = writer.writeLine, increaseIndent = writer.increaseIndent, decreaseIndent = writer.decreaseIndent; - var sourceMap = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? ts.createSourceMapWriter(host, writer) : ts.getNullSourceMapWriter(); - var setSourceFile = sourceMap.setSourceFile, emitStart = sourceMap.emitStart, emitEnd = sourceMap.emitEnd, emitPos = sourceMap.emitPos; - var currentSourceFile; - var currentText; - var currentLineMap; - var currentFileIdentifiers; - var renamedDependencies; - var isEs6Module; - var isCurrentFileExternalModule; - // name of an exporter function if file is a System external module - // System.register([...], function () {...}) - // exporting in System modules looks like: - // export var x; ... x = 1 - // => - // var x;... exporter("x", x = 1) - var exportFunctionForFile; - var contextObjectForFile; - var generatedNameSet; - var nodeToGeneratedName; - var computedPropertyNamesToGeneratedNames; - var decoratedClassAliases; - var convertedLoopState; - var extendsEmitted; - var assignEmitted; - var decorateEmitted; - var paramEmitted; - var awaiterEmitted; - var tempFlags = 0; - var tempVariables; - var tempParameters; - var externalImports; - var exportSpecifiers; - var exportEquals; - var hasExportStarsToExportValues; - var detachedCommentsInfo; - /** Sourcemap data that will get encoded */ - var sourceMapData; - /** Is the file being emitted into its own file */ - var isOwnFileEmit; - /** If removeComments is true, no leading-comments needed to be emitted **/ - var emitLeadingCommentsOfPosition = compilerOptions.removeComments ? function (pos) { } : emitLeadingCommentsOfPositionWorker; - var setSourceMapWriterEmit = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? changeSourceMapEmit : function (writer) { }; - var moduleEmitDelegates = ts.createMap((_a = {}, - _a[ts.ModuleKind.ES6] = emitES6Module, - _a[ts.ModuleKind.AMD] = emitAMDModule, - _a[ts.ModuleKind.System] = emitSystemModule, - _a[ts.ModuleKind.UMD] = emitUMDModule, - _a[ts.ModuleKind.CommonJS] = emitCommonJSModule, - _a - )); - var bundleEmitDelegates = ts.createMap((_b = {}, - _b[ts.ModuleKind.ES6] = function () { }, - _b[ts.ModuleKind.AMD] = emitAMDModule, - _b[ts.ModuleKind.System] = emitSystemModule, - _b[ts.ModuleKind.UMD] = function () { }, - _b[ts.ModuleKind.CommonJS] = function () { }, - _b - )); - return doEmit; - function doEmit(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit) { - sourceMap.initialize(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit); - generatedNameSet = ts.createMap(); - nodeToGeneratedName = []; - decoratedClassAliases = []; - isOwnFileEmit = !isBundledEmit; - // Emit helpers from all the files - if (isBundledEmit && modulekind) { - ts.forEach(sourceFiles, emitEmitHelpers); - } - // Do not call emit directly. It does not set the currentSourceFile. - ts.forEach(sourceFiles, emitSourceFile); - writeLine(); - var sourceMappingURL = sourceMap.getSourceMappingURL(); - if (sourceMappingURL) { - write("//# " + "sourceMappingURL" + "=" + sourceMappingURL); // Sometimes tools can sometimes see this line as a source mapping url comment - } - writeEmittedFiles(writer.getText(), jsFilePath, sourceMapFilePath, /*writeByteOrderMark*/ compilerOptions.emitBOM, sourceFiles); - // reset the state - sourceMap.reset(); - writer.reset(); - currentSourceFile = undefined; - currentText = undefined; - currentLineMap = undefined; - exportFunctionForFile = undefined; - contextObjectForFile = undefined; - generatedNameSet = undefined; - nodeToGeneratedName = undefined; - decoratedClassAliases = undefined; - computedPropertyNamesToGeneratedNames = undefined; - convertedLoopState = undefined; - extendsEmitted = false; - decorateEmitted = false; - paramEmitted = false; - awaiterEmitted = false; - assignEmitted = false; - tempFlags = 0; - tempVariables = undefined; - tempParameters = undefined; - externalImports = undefined; - exportSpecifiers = undefined; - exportEquals = undefined; - hasExportStarsToExportValues = undefined; - detachedCommentsInfo = undefined; - sourceMapData = undefined; - isEs6Module = false; - renamedDependencies = undefined; - isCurrentFileExternalModule = false; - } - function emitSourceFile(sourceFile) { - currentSourceFile = sourceFile; - currentText = sourceFile.text; - currentLineMap = ts.getLineStarts(sourceFile); - exportFunctionForFile = undefined; - contextObjectForFile = undefined; - isEs6Module = sourceFile.symbol && sourceFile.symbol.exports && !!sourceFile.symbol.exports["___esModule"]; - renamedDependencies = sourceFile.renamedDependencies; - currentFileIdentifiers = sourceFile.identifiers; - isCurrentFileExternalModule = ts.isExternalModule(sourceFile); - setSourceFile(sourceFile); - emitNodeWithCommentsAndWithoutSourcemap(sourceFile); - } - function isUniqueName(name) { - return !resolver.hasGlobalName(name) && - !(name in currentFileIdentifiers) && - !(name in generatedNameSet); - } - // Return the next available name in the pattern _a ... _z, _0, _1, ... - // TempFlags._i or TempFlags._n may be used to express a preference for that dedicated name. - // Note that names generated by makeTempVariableName and makeUniqueName will never conflict. - function makeTempVariableName(flags) { - if (flags && !(tempFlags & flags)) { - var name_26 = flags === 268435456 /* _i */ ? "_i" : "_n"; - if (isUniqueName(name_26)) { - tempFlags |= flags; - return name_26; - } - } - while (true) { - var count = tempFlags & 268435455 /* CountMask */; - tempFlags++; - // Skip over 'i' and 'n' - if (count !== 8 && count !== 13) { - var name_27 = count < 26 ? "_" + String.fromCharCode(97 /* a */ + count) : "_" + (count - 26); - if (isUniqueName(name_27)) { - return name_27; - } - } - } + /** + * Gets an AllDecorators object containing the decorators for the method and its parameters. + * + * @param method The class method member. + */ + function getAllDecoratorsOfMethod(method) { + if (!method.body) { + return undefined; } - // Generate a name that is unique within the current file and doesn't conflict with any names - // in global scope. The name is formed by adding an '_n' suffix to the specified base name, - // where n is a positive integer. Note that names generated by makeTempVariableName and - // makeUniqueName are guaranteed to never conflict. - function makeUniqueName(baseName) { - // Find the first unique 'name_n', where n is a positive number - if (baseName.charCodeAt(baseName.length - 1) !== 95 /* _ */) { - baseName += "_"; - } - var i = 1; - while (true) { - var generatedName = baseName + i; - if (isUniqueName(generatedName)) { - return generatedNameSet[generatedName] = generatedName; - } - i++; - } + var decorators = method.decorators; + var parameters = getDecoratorsOfParameters(method); + if (!decorators && !parameters) { + return undefined; } - function generateNameForModuleOrEnum(node) { - var name = node.name.text; - // Use module/enum name itself if it is unique, otherwise make a unique variation - return isUniqueLocalName(name, node) ? name : makeUniqueName(name); + return { decorators: decorators, parameters: parameters }; + } + /** + * Gets an AllDecorators object containing the decorators for the property. + * + * @param property The class property member. + */ + function getAllDecoratorsOfProperty(property) { + var decorators = property.decorators; + if (!decorators) { + return undefined; } - function generateNameForImportOrExportDeclaration(node) { - var expr = ts.getExternalModuleName(node); - var baseName = expr.kind === 9 /* StringLiteral */ ? - ts.escapeIdentifier(ts.makeIdentifierFromModuleName(expr.text)) : "module"; - return makeUniqueName(baseName); + return { decorators: decorators }; + } + /** + * Transforms all of the decorators for a declaration into an array of expressions. + * + * @param node The declaration node. + * @param allDecorators An object containing all of the decorators for the declaration. + */ + function transformAllDecoratorsOfDeclaration(node, allDecorators) { + if (!allDecorators) { + return undefined; } - function generateNameForExportDefault() { - return makeUniqueName("default"); + var decoratorExpressions = []; + ts.addRange(decoratorExpressions, ts.map(allDecorators.decorators, transformDecorator)); + ts.addRange(decoratorExpressions, ts.flatMap(allDecorators.parameters, transformDecoratorsOfParameter)); + addTypeMetadata(node, decoratorExpressions); + return decoratorExpressions; + } + /** + * Generates statements used to apply decorators to either the static or instance members + * of a class. + * + * @param node The class node. + * @param isStatic A value indicating whether to generate statements for static or + * instance members. + */ + function addClassElementDecorationStatements(statements, node, isStatic) { + ts.addRange(statements, ts.map(generateClassElementDecorationExpressions(node, isStatic), expressionToStatement)); + } + /** + * Generates expressions used to apply decorators to either the static or instance members + * of a class. + * + * @param node The class node. + * @param isStatic A value indicating whether to generate expressions for static or + * instance members. + */ + function generateClassElementDecorationExpressions(node, isStatic) { + var members = getDecoratedClassElements(node, isStatic); + var expressions; + for (var _i = 0, members_2 = members; _i < members_2.length; _i++) { + var member = members_2[_i]; + var expression = generateClassElementDecorationExpression(node, member); + if (expression) { + if (!expressions) { + expressions = [expression]; + } + else { + expressions.push(expression); + } + } } - function generateNameForClassExpression() { - return makeUniqueName("class"); + return expressions; + } + /** + * Generates an expression used to evaluate class element decorators at runtime. + * + * @param node The class node that contains the member. + * @param member The class member. + */ + function generateClassElementDecorationExpression(node, member) { + var allDecorators = getAllDecoratorsOfClassElement(node, member); + var decoratorExpressions = transformAllDecoratorsOfDeclaration(member, allDecorators); + if (!decoratorExpressions) { + return undefined; } - function generateNameForNode(node) { - switch (node.kind) { - case 69 /* Identifier */: - return makeUniqueName(node.text); - case 225 /* ModuleDeclaration */: - case 224 /* EnumDeclaration */: - return generateNameForModuleOrEnum(node); - case 230 /* ImportDeclaration */: - case 236 /* ExportDeclaration */: - return generateNameForImportOrExportDeclaration(node); - case 220 /* FunctionDeclaration */: - case 221 /* ClassDeclaration */: - case 235 /* ExportAssignment */: - return generateNameForExportDefault(); - case 192 /* ClassExpression */: - return generateNameForClassExpression(); - default: - ts.Debug.fail(); - } + // Emit the call to __decorate. Given the following: + // + // class C { + // @dec method(@dec2 x) {} + // @dec get accessor() {} + // @dec prop; + // } + // + // The emit for a method is: + // + // __decorate([ + // dec, + // __param(0, dec2), + // __metadata("design:type", Function), + // __metadata("design:paramtypes", [Object]), + // __metadata("design:returntype", void 0) + // ], C.prototype, "method", undefined); + // + // The emit for an accessor is: + // + // __decorate([ + // dec + // ], C.prototype, "accessor", undefined); + // + // The emit for a property is: + // + // __decorate([ + // dec + // ], C.prototype, "prop"); + // + var prefix = getClassMemberPrefix(node, member); + var memberName = getExpressionForPropertyName(member, /*generateNameForComputedPropertyName*/ true); + var descriptor = languageVersion > 0 /* ES3 */ + ? member.kind === 145 /* PropertyDeclaration */ + ? ts.createVoidZero() + : ts.createNull() + : undefined; + var helper = ts.createDecorateHelper(currentSourceFileExternalHelpersModuleName, decoratorExpressions, prefix, memberName, descriptor, ts.moveRangePastDecorators(member)); + ts.setEmitFlags(helper, 49152 /* NoComments */); + return helper; + } + /** + * Generates a __decorate helper call for a class constructor. + * + * @param node The class node. + */ + function addConstructorDecorationStatement(statements, node, decoratedClassAlias) { + var expression = generateConstructorDecorationExpression(node, decoratedClassAlias); + if (expression) { + statements.push(ts.setOriginalNode(ts.createStatement(expression), node)); } - function getGeneratedNameForNode(node) { - var id = ts.getNodeId(node); - return nodeToGeneratedName[id] || (nodeToGeneratedName[id] = ts.unescapeIdentifier(generateNameForNode(node))); + } + /** + * Generates a __decorate helper call for a class constructor. + * + * @param node The class node. + */ + function generateConstructorDecorationExpression(node, decoratedClassAlias) { + var allDecorators = getAllDecoratorsOfConstructor(node); + var decoratorExpressions = transformAllDecoratorsOfDeclaration(node, allDecorators); + if (!decoratorExpressions) { + return undefined; } - /** Write emitted output to disk */ - function writeEmittedFiles(emitOutput, jsFilePath, sourceMapFilePath, writeByteOrderMark, sourceFiles) { - if (compilerOptions.sourceMap && !compilerOptions.inlineSourceMap) { - ts.writeFile(host, emitterDiagnostics, sourceMapFilePath, sourceMap.getText(), /*writeByteOrderMark*/ false, sourceFiles); - } - if (sourceMapDataList) { - sourceMapDataList.push(sourceMap.getSourceMapData()); - } - ts.writeFile(host, emitterDiagnostics, jsFilePath, emitOutput, writeByteOrderMark, sourceFiles); + // Emit the call to __decorate. Given the class: + // + // @dec + // class C { + // } + // + // The emit for the class is: + // + // C = C_1 = __decorate([dec], C); + // + if (decoratedClassAlias) { + var expression = ts.createAssignment(decoratedClassAlias, ts.createDecorateHelper(currentSourceFileExternalHelpersModuleName, decoratorExpressions, getDeclarationName(node))); + var result = ts.createAssignment(getDeclarationName(node), expression, ts.moveRangePastDecorators(node)); + ts.setEmitFlags(result, 49152 /* NoComments */); + return result; } - // Create a temporary variable with a unique unused name. - function createTempVariable(flags) { - var result = ts.createSynthesizedNode(69 /* Identifier */); - result.text = makeTempVariableName(flags); + else { + var result = ts.createAssignment(getDeclarationName(node), ts.createDecorateHelper(currentSourceFileExternalHelpersModuleName, decoratorExpressions, getDeclarationName(node)), ts.moveRangePastDecorators(node)); + ts.setEmitFlags(result, 49152 /* NoComments */); return result; } - function recordTempDeclaration(name) { - if (!tempVariables) { - tempVariables = []; + } + /** + * Transforms a decorator into an expression. + * + * @param decorator The decorator node. + */ + function transformDecorator(decorator) { + return ts.visitNode(decorator.expression, visitor, ts.isExpression); + } + /** + * Transforms the decorators of a parameter. + * + * @param decorators The decorators for the parameter at the provided offset. + * @param parameterOffset The offset of the parameter. + */ + function transformDecoratorsOfParameter(decorators, parameterOffset) { + var expressions; + if (decorators) { + expressions = []; + for (var _i = 0, decorators_1 = decorators; _i < decorators_1.length; _i++) { + var decorator = decorators_1[_i]; + var helper = ts.createParamHelper(currentSourceFileExternalHelpersModuleName, transformDecorator(decorator), parameterOffset, + /*location*/ decorator.expression); + ts.setEmitFlags(helper, 49152 /* NoComments */); + expressions.push(helper); } - tempVariables.push(name); } - function createAndRecordTempVariable(flags) { - var temp = createTempVariable(flags); - recordTempDeclaration(temp); - return temp; + return expressions; + } + /** + * Adds optional type metadata for a declaration. + * + * @param node The declaration node. + * @param decoratorExpressions The destination array to which to add new decorator expressions. + */ + function addTypeMetadata(node, decoratorExpressions) { + if (USE_NEW_TYPE_METADATA_FORMAT) { + addNewTypeMetadata(node, decoratorExpressions); } - function emitTempDeclarations(newLine) { - if (tempVariables) { - if (newLine) { - writeLine(); - } - else { - write(" "); - } - write("var "); - emitCommaList(tempVariables); - write(";"); - } - } - /** Emit the text for the given token that comes after startPos - * This by default writes the text provided with the given tokenKind - * but if optional emitFn callback is provided the text is emitted using the callback instead of default text - * @param tokenKind the kind of the token to search and emit - * @param startPos the position in the source to start searching for the token - * @param emitFn if given will be invoked to emit the text instead of actual token emit */ - function emitToken(tokenKind, startPos, emitFn) { - var tokenStartPos = ts.skipTrivia(currentText, startPos); - emitPos(tokenStartPos); - var tokenString = ts.tokenToString(tokenKind); - if (emitFn) { - emitFn(); - } - else { - write(tokenString); - } - var tokenEndPos = tokenStartPos + tokenString.length; - emitPos(tokenEndPos); - return tokenEndPos; + else { + addOldTypeMetadata(node, decoratorExpressions); } - function emitOptional(prefix, node) { - if (node) { - write(prefix); - emit(node); + } + function addOldTypeMetadata(node, decoratorExpressions) { + if (compilerOptions.emitDecoratorMetadata) { + if (shouldAddTypeMetadata(node)) { + decoratorExpressions.push(ts.createMetadataHelper(currentSourceFileExternalHelpersModuleName, "design:type", serializeTypeOfNode(node))); } - } - function emitParenthesizedIf(node, parenthesized) { - if (parenthesized) { - write("("); + if (shouldAddParamTypesMetadata(node)) { + decoratorExpressions.push(ts.createMetadataHelper(currentSourceFileExternalHelpersModuleName, "design:paramtypes", serializeParameterTypesOfNode(node))); } - emit(node); - if (parenthesized) { - write(")"); + if (shouldAddReturnTypeMetadata(node)) { + decoratorExpressions.push(ts.createMetadataHelper(currentSourceFileExternalHelpersModuleName, "design:returntype", serializeReturnTypeOfNode(node))); } } - function emitLinePreservingList(parent, nodes, allowTrailingComma, spacesBetweenBraces) { - ts.Debug.assert(nodes.length > 0); - increaseIndent(); - if (nodeStartPositionsAreOnSameLine(parent, nodes[0])) { - if (spacesBetweenBraces) { - write(" "); - } - } - else { - writeLine(); - } - for (var i = 0, n = nodes.length; i < n; i++) { - if (i) { - if (nodeEndIsOnSameLineAsNodeStart(nodes[i - 1], nodes[i])) { - write(", "); - } - else { - write(","); - writeLine(); - } - } - emit(nodes[i]); + } + function addNewTypeMetadata(node, decoratorExpressions) { + if (compilerOptions.emitDecoratorMetadata) { + var properties = void 0; + if (shouldAddTypeMetadata(node)) { + (properties || (properties = [])).push(ts.createPropertyAssignment("type", ts.createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, /*equalsGreaterThanToken*/ undefined, serializeTypeOfNode(node)))); } - if (nodes.hasTrailingComma && allowTrailingComma) { - write(","); + if (shouldAddParamTypesMetadata(node)) { + (properties || (properties = [])).push(ts.createPropertyAssignment("paramTypes", ts.createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, /*equalsGreaterThanToken*/ undefined, serializeParameterTypesOfNode(node)))); } - decreaseIndent(); - if (nodeEndPositionsAreOnSameLine(parent, ts.lastOrUndefined(nodes))) { - if (spacesBetweenBraces) { - write(" "); - } + if (shouldAddReturnTypeMetadata(node)) { + (properties || (properties = [])).push(ts.createPropertyAssignment("returnType", ts.createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, /*equalsGreaterThanToken*/ undefined, serializeReturnTypeOfNode(node)))); } - else { - writeLine(); + if (properties) { + decoratorExpressions.push(ts.createMetadataHelper(currentSourceFileExternalHelpersModuleName, "design:typeinfo", ts.createObjectLiteral(properties, /*location*/ undefined, /*multiLine*/ true))); } } - function emitList(nodes, start, count, multiLine, trailingComma, leadingComma, noTrailingNewLine, emitNode) { - if (!emitNode) { - emitNode = emit; - } - for (var i = 0; i < count; i++) { - if (multiLine) { - if (i || leadingComma) { - write(","); - } - writeLine(); + } + /** + * Determines whether to emit the "design:type" metadata based on the node's kind. + * The caller should have already tested whether the node has decorators and whether the + * emitDecoratorMetadata compiler option is set. + * + * @param node The node to test. + */ + function shouldAddTypeMetadata(node) { + var kind = node.kind; + return kind === 147 /* MethodDeclaration */ + || kind === 149 /* GetAccessor */ + || kind === 150 /* SetAccessor */ + || kind === 145 /* PropertyDeclaration */; + } + /** + * Determines whether to emit the "design:returntype" metadata based on the node's kind. + * The caller should have already tested whether the node has decorators and whether the + * emitDecoratorMetadata compiler option is set. + * + * @param node The node to test. + */ + function shouldAddReturnTypeMetadata(node) { + return node.kind === 147 /* MethodDeclaration */; + } + /** + * Determines whether to emit the "design:paramtypes" metadata based on the node's kind. + * The caller should have already tested whether the node has decorators and whether the + * emitDecoratorMetadata compiler option is set. + * + * @param node The node to test. + */ + function shouldAddParamTypesMetadata(node) { + var kind = node.kind; + return kind === 221 /* ClassDeclaration */ + || kind === 192 /* ClassExpression */ + || kind === 147 /* MethodDeclaration */ + || kind === 149 /* GetAccessor */ + || kind === 150 /* SetAccessor */; + } + /** + * Serializes the type of a node for use with decorator type metadata. + * + * @param node The node that should have its type serialized. + */ + function serializeTypeOfNode(node) { + switch (node.kind) { + case 145 /* PropertyDeclaration */: + case 142 /* Parameter */: + case 149 /* GetAccessor */: + return serializeTypeNode(node.type); + case 150 /* SetAccessor */: + return serializeTypeNode(ts.getSetAccessorTypeAnnotationNode(node)); + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + case 147 /* MethodDeclaration */: + return ts.createIdentifier("Function"); + default: + return ts.createVoidZero(); + } + } + /** + * Gets the most likely element type for a TypeNode. This is not an exhaustive test + * as it assumes a rest argument can only be an array type (either T[], or Array). + * + * @param node The type node. + */ + function getRestParameterElementType(node) { + if (node && node.kind === 160 /* ArrayType */) { + return node.elementType; + } + else if (node && node.kind === 155 /* TypeReference */) { + return ts.singleOrUndefined(node.typeArguments); + } + else { + return undefined; + } + } + /** + * Serializes the types of the parameters of a node for use with decorator type metadata. + * + * @param node The node that should have its parameter types serialized. + */ + function serializeParameterTypesOfNode(node) { + var valueDeclaration = ts.isClassLike(node) + ? ts.getFirstConstructorWithBody(node) + : ts.isFunctionLike(node) && ts.nodeIsPresent(node.body) + ? node + : undefined; + var expressions = []; + if (valueDeclaration) { + var parameters = valueDeclaration.parameters; + var numParameters = parameters.length; + for (var i = 0; i < numParameters; i++) { + var parameter = parameters[i]; + if (i === 0 && ts.isIdentifier(parameter.name) && parameter.name.text === "this") { + continue; + } + if (parameter.dotDotDotToken) { + expressions.push(serializeTypeNode(getRestParameterElementType(parameter.type))); } else { - if (i || leadingComma) { - write(", "); - } + expressions.push(serializeTypeOfNode(parameter)); } - var node = nodes[start + i]; - // This emitting is to make sure we emit following comment properly - // ...(x, /*comment1*/ y)... - // ^ => node.pos - // "comment1" is not considered leading comment for "y" but rather - // considered as trailing comment of the previous node. - emitTrailingCommentsOfPosition(node.pos); - emitNode(node); - leadingComma = true; - } - if (trailingComma) { - write(","); - } - if (multiLine && !noTrailingNewLine) { - writeLine(); } - return count; } - function emitCommaList(nodes) { - if (nodes) { - emitList(nodes, 0, nodes.length, /*multiLine*/ false, /*trailingComma*/ false); - } + return ts.createArrayLiteral(expressions); + } + /** + * Serializes the return type of a node for use with decorator type metadata. + * + * @param node The node that should have its return type serialized. + */ + function serializeReturnTypeOfNode(node) { + if (ts.isFunctionLike(node) && node.type) { + return serializeTypeNode(node.type); } - function emitLines(nodes) { - emitLinesStartingAt(nodes, /*startIndex*/ 0); + else if (ts.isAsyncFunctionLike(node)) { + return ts.createIdentifier("Promise"); } - function emitLinesStartingAt(nodes, startIndex) { - for (var i = startIndex; i < nodes.length; i++) { - writeLine(); - emit(nodes[i]); - } + return ts.createVoidZero(); + } + /** + * Serializes a type node for use with decorator type metadata. + * + * Types are serialized in the following fashion: + * - Void types point to "undefined" (e.g. "void 0") + * - Function and Constructor types point to the global "Function" constructor. + * - Interface types with a call or construct signature types point to the global + * "Function" constructor. + * - Array and Tuple types point to the global "Array" constructor. + * - Type predicates and booleans point to the global "Boolean" constructor. + * - String literal types and strings point to the global "String" constructor. + * - Enum and number types point to the global "Number" constructor. + * - Symbol types point to the global "Symbol" constructor. + * - Type references to classes (or class-like variables) point to the constructor for the class. + * - Anything else points to the global "Object" constructor. + * + * @param node The type node to serialize. + */ + function serializeTypeNode(node) { + if (node === undefined) { + return ts.createIdentifier("Object"); } - function isBinaryOrOctalIntegerLiteral(node, text) { - if (node.kind === 8 /* NumericLiteral */ && text.length > 1) { - switch (text.charCodeAt(1)) { - case 98 /* b */: - case 66 /* B */: - case 111 /* o */: - case 79 /* O */: - return true; + switch (node.kind) { + case 103 /* VoidKeyword */: + return ts.createVoidZero(); + case 164 /* ParenthesizedType */: + return serializeTypeNode(node.type); + case 156 /* FunctionType */: + case 157 /* ConstructorType */: + return ts.createIdentifier("Function"); + case 160 /* ArrayType */: + case 161 /* TupleType */: + return ts.createIdentifier("Array"); + case 154 /* TypePredicate */: + case 120 /* BooleanKeyword */: + return ts.createIdentifier("Boolean"); + case 132 /* StringKeyword */: + return ts.createIdentifier("String"); + case 166 /* LiteralType */: + switch (node.literal.kind) { + case 9 /* StringLiteral */: + return ts.createIdentifier("String"); + case 8 /* NumericLiteral */: + return ts.createIdentifier("Number"); + case 99 /* TrueKeyword */: + case 84 /* FalseKeyword */: + return ts.createIdentifier("Boolean"); + default: + ts.Debug.failBadSyntaxKind(node.literal); + break; } - } - return false; + break; + case 130 /* NumberKeyword */: + return ts.createIdentifier("Number"); + case 133 /* SymbolKeyword */: + return languageVersion < 2 /* ES6 */ + ? getGlobalSymbolNameWithFallback() + : ts.createIdentifier("Symbol"); + case 155 /* TypeReference */: + return serializeTypeReferenceNode(node); + case 158 /* TypeQuery */: + case 159 /* TypeLiteral */: + case 162 /* UnionType */: + case 163 /* IntersectionType */: + case 117 /* AnyKeyword */: + case 165 /* ThisType */: + break; + default: + ts.Debug.failBadSyntaxKind(node); + break; } - function emitLiteral(node) { - var text = getLiteralText(node); - if ((compilerOptions.sourceMap || compilerOptions.inlineSourceMap) && (node.kind === 9 /* StringLiteral */ || ts.isTemplateLiteralKind(node.kind))) { - writer.writeLiteral(text); - } - else if (languageVersion < 2 /* ES6 */ && isBinaryOrOctalIntegerLiteral(node, text)) { - write(node.text); - } - else { - write(text); - } + return ts.createIdentifier("Object"); + } + /** + * Serializes a TypeReferenceNode to an appropriate JS constructor value for use with + * decorator type metadata. + * + * @param node The type reference node. + */ + function serializeTypeReferenceNode(node) { + switch (resolver.getTypeReferenceSerializationKind(node.typeName, currentScope)) { + case ts.TypeReferenceSerializationKind.Unknown: + var serialized = serializeEntityNameAsExpression(node.typeName, /*useFallback*/ true); + var temp = ts.createTempVariable(hoistVariableDeclaration); + return ts.createLogicalOr(ts.createLogicalAnd(ts.createStrictEquality(ts.createTypeOf(ts.createAssignment(temp, serialized)), ts.createLiteral("function")), temp), ts.createIdentifier("Object")); + case ts.TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue: + return serializeEntityNameAsExpression(node.typeName, /*useFallback*/ false); + case ts.TypeReferenceSerializationKind.VoidNullableOrNeverType: + return ts.createVoidZero(); + case ts.TypeReferenceSerializationKind.BooleanType: + return ts.createIdentifier("Boolean"); + case ts.TypeReferenceSerializationKind.NumberLikeType: + return ts.createIdentifier("Number"); + case ts.TypeReferenceSerializationKind.StringLikeType: + return ts.createIdentifier("String"); + case ts.TypeReferenceSerializationKind.ArrayLikeType: + return ts.createIdentifier("Array"); + case ts.TypeReferenceSerializationKind.ESSymbolType: + return languageVersion < 2 /* ES6 */ + ? getGlobalSymbolNameWithFallback() + : ts.createIdentifier("Symbol"); + case ts.TypeReferenceSerializationKind.TypeWithCallSignature: + return ts.createIdentifier("Function"); + case ts.TypeReferenceSerializationKind.Promise: + return ts.createIdentifier("Promise"); + case ts.TypeReferenceSerializationKind.ObjectType: + default: + return ts.createIdentifier("Object"); } - function getLiteralText(node) { - // Any template literal or string literal with an extended escape - // (e.g. "\u{0067}") will need to be downleveled as a escaped string literal. - if (languageVersion < 2 /* ES6 */ && (ts.isTemplateLiteralKind(node.kind) || node.hasExtendedUnicodeEscape)) { - return getQuotedEscapedLiteralText('"', node.text, '"'); - } - // If we don't need to downlevel and we can reach the original source text using - // the node's parent reference, then simply get the text as it was originally written. - if (node.parent) { - return ts.getTextOfNodeFromSourceText(currentText, node); - } - // If we can't reach the original source text, use the canonical form if it's a number, - // or an escaped quoted form of the original text if it's string-like. - switch (node.kind) { - case 9 /* StringLiteral */: - return getQuotedEscapedLiteralText('"', node.text, '"'); - case 11 /* NoSubstitutionTemplateLiteral */: - return getQuotedEscapedLiteralText("`", node.text, "`"); - case 12 /* TemplateHead */: - return getQuotedEscapedLiteralText("`", node.text, "${"); - case 13 /* TemplateMiddle */: - return getQuotedEscapedLiteralText("}", node.text, "${"); - case 14 /* TemplateTail */: - return getQuotedEscapedLiteralText("}", node.text, "`"); - case 8 /* NumericLiteral */: - return node.text; - } - ts.Debug.fail("Literal kind '" + node.kind + "' not accounted for."); - } - function getQuotedEscapedLiteralText(leftQuote, text, rightQuote) { - return leftQuote + ts.escapeNonAsciiCharacters(ts.escapeString(text)) + rightQuote; - } - function emitDownlevelRawTemplateLiteral(node) { - // Find original source text, since we need to emit the raw strings of the tagged template. - // The raw strings contain the (escaped) strings of what the user wrote. - // Examples: `\n` is converted to "\\n", a template string with a newline to "\n". - var text = ts.getTextOfNodeFromSourceText(currentText, node); - // text contains the original source, it will also contain quotes ("`"), dollar signs and braces ("${" and "}"), - // thus we need to remove those characters. - // First template piece starts with "`", others with "}" - // Last template piece ends with "`", others with "${" - var isLast = node.kind === 11 /* NoSubstitutionTemplateLiteral */ || node.kind === 14 /* TemplateTail */; - text = text.substring(1, text.length - (isLast ? 1 : 2)); - // Newline normalization: - // ES6 Spec 11.8.6.1 - Static Semantics of TV's and TRV's - // and LineTerminatorSequences are normalized to for both TV and TRV. - text = text.replace(/\r\n?/g, "\n"); - text = ts.escapeString(text); - write("\"" + text + "\""); - } - function emitDownlevelTaggedTemplateArray(node, literalEmitter) { - write("["); - if (node.template.kind === 11 /* NoSubstitutionTemplateLiteral */) { - literalEmitter(node.template); - } - else { - literalEmitter(node.template.head); - ts.forEach(node.template.templateSpans, function (child) { - write(", "); - literalEmitter(child.literal); - }); - } - write("]"); + } + /** + * Serializes an entity name as an expression for decorator type metadata. + * + * @param node The entity name to serialize. + * @param useFallback A value indicating whether to use logical operators to test for the + * entity name at runtime. + */ + function serializeEntityNameAsExpression(node, useFallback) { + switch (node.kind) { + case 69 /* Identifier */: + // Create a clone of the name with a new parent, and treat it as if it were + // a source tree node for the purposes of the checker. + var name_30 = ts.getMutableClone(node); + name_30.flags &= ~8 /* Synthesized */; + name_30.original = undefined; + name_30.parent = currentScope; + if (useFallback) { + return ts.createLogicalAnd(ts.createStrictInequality(ts.createTypeOf(name_30), ts.createLiteral("undefined")), name_30); + } + return name_30; + case 139 /* QualifiedName */: + return serializeQualifiedNameAsExpression(node, useFallback); } - function emitDownlevelTaggedTemplate(node) { - var tempVariable = createAndRecordTempVariable(0 /* Auto */); - write("("); - emit(tempVariable); - write(" = "); - emitDownlevelTaggedTemplateArray(node, emit); - write(", "); - emit(tempVariable); - write(".raw = "); - emitDownlevelTaggedTemplateArray(node, emitDownlevelRawTemplateLiteral); - write(", "); - emitParenthesizedIf(node.tag, needsParenthesisForPropertyAccessOrInvocation(node.tag)); - write("("); - emit(tempVariable); - // Now we emit the expressions - if (node.template.kind === 189 /* TemplateExpression */) { - ts.forEach(node.template.templateSpans, function (templateSpan) { - write(", "); - var needsParens = templateSpan.expression.kind === 187 /* BinaryExpression */ - && templateSpan.expression.operatorToken.kind === 24 /* CommaToken */; - emitParenthesizedIf(templateSpan.expression, needsParens); - }); - } - write("))"); + } + /** + * Serializes an qualified name as an expression for decorator type metadata. + * + * @param node The qualified name to serialize. + * @param useFallback A value indicating whether to use logical operators to test for the + * qualified name at runtime. + */ + function serializeQualifiedNameAsExpression(node, useFallback) { + var left; + if (node.left.kind === 69 /* Identifier */) { + left = serializeEntityNameAsExpression(node.left, useFallback); } - function emitTemplateExpression(node) { - // In ES6 mode and above, we can simply emit each portion of a template in order, but in - // ES3 & ES5 we must convert the template expression into a series of string concatenations. - if (languageVersion >= 2 /* ES6 */) { - ts.forEachChild(node, emit); - return; - } - var emitOuterParens = ts.isExpression(node.parent) - && templateNeedsParens(node, node.parent); - if (emitOuterParens) { - write("("); - } - var headEmitted = false; - if (shouldEmitTemplateHead()) { - emitLiteral(node.head); - headEmitted = true; - } - for (var i = 0, n = node.templateSpans.length; i < n; i++) { - var templateSpan = node.templateSpans[i]; - // Check if the expression has operands and binds its operands less closely than binary '+'. - // If it does, we need to wrap the expression in parentheses. Otherwise, something like - // `abc${ 1 << 2 }` - // becomes - // "abc" + 1 << 2 + "" - // which is really - // ("abc" + 1) << (2 + "") - // rather than - // "abc" + (1 << 2) + "" - var needsParens = templateSpan.expression.kind !== 178 /* ParenthesizedExpression */ - && comparePrecedenceToBinaryPlus(templateSpan.expression) !== 1 /* GreaterThan */; - if (i > 0 || headEmitted) { - // If this is the first span and the head was not emitted, then this templateSpan's - // expression will be the first to be emitted. Don't emit the preceding ' + ' in that - // case. - write(" + "); - } - emitParenthesizedIf(templateSpan.expression, needsParens); - // Only emit if the literal is non-empty. - // The binary '+' operator is left-associative, so the first string concatenation - // with the head will force the result up to this point to be a string. - // Emitting a '+ ""' has no semantic effect for middles and tails. - if (templateSpan.literal.text.length !== 0) { - write(" + "); - emitLiteral(templateSpan.literal); - } - } - if (emitOuterParens) { - write(")"); - } - function shouldEmitTemplateHead() { - // If this expression has an empty head literal and the first template span has a non-empty - // literal, then emitting the empty head literal is not necessary. - // `${ foo } and ${ bar }` - // can be emitted as - // foo + " and " + bar - // This is because it is only required that one of the first two operands in the emit - // output must be a string literal, so that the other operand and all following operands - // are forced into strings. - // - // If the first template span has an empty literal, then the head must still be emitted. - // `${ foo }${ bar }` - // must still be emitted as - // "" + foo + bar - // There is always atleast one templateSpan in this code path, since - // NoSubstitutionTemplateLiterals are directly emitted via emitLiteral() - ts.Debug.assert(node.templateSpans.length !== 0); - return node.head.text.length !== 0 || node.templateSpans[0].literal.text.length === 0; - } - function templateNeedsParens(template, parent) { - switch (parent.kind) { - case 174 /* CallExpression */: - case 175 /* NewExpression */: - return parent.expression === template; - case 176 /* TaggedTemplateExpression */: - case 178 /* ParenthesizedExpression */: - return false; - default: - return comparePrecedenceToBinaryPlus(parent) !== -1 /* LessThan */; - } - } - /** - * Returns whether the expression has lesser, greater, - * or equal precedence to the binary '+' operator - */ - function comparePrecedenceToBinaryPlus(expression) { - // All binary expressions have lower precedence than '+' apart from '*', '/', and '%' - // which have greater precedence and '-' which has equal precedence. - // All unary operators have a higher precedence apart from yield. - // Arrow functions and conditionals have a lower precedence, - // although we convert the former into regular function expressions in ES5 mode, - // and in ES6 mode this function won't get called anyway. - // - // TODO (drosen): Note that we need to account for the upcoming 'yield' and - // spread ('...') unary operators that are anticipated for ES6. - switch (expression.kind) { - case 187 /* BinaryExpression */: - switch (expression.operatorToken.kind) { - case 37 /* AsteriskToken */: - case 39 /* SlashToken */: - case 40 /* PercentToken */: - return 1 /* GreaterThan */; - case 35 /* PlusToken */: - case 36 /* MinusToken */: - return 0 /* EqualTo */; - default: - return -1 /* LessThan */; - } - case 190 /* YieldExpression */: - case 188 /* ConditionalExpression */: - return -1 /* LessThan */; - default: - return 1 /* GreaterThan */; - } - } + else if (useFallback) { + var temp = ts.createTempVariable(hoistVariableDeclaration); + left = ts.createLogicalAnd(ts.createAssignment(temp, serializeEntityNameAsExpression(node.left, /*useFallback*/ true)), temp); } - function emitTemplateSpan(span) { - emit(span.expression); - emit(span.literal); + else { + left = serializeEntityNameAsExpression(node.left, /*useFallback*/ false); } - function jsxEmitReact(node) { - /// Emit a tag name, which is either '"div"' for lower-cased names, or - /// 'Div' for upper-cased or dotted names - function emitTagName(name) { - if (name.kind === 69 /* Identifier */ && ts.isIntrinsicJsxName(name.text)) { - write('"'); - emit(name); - write('"'); - } - else { - emit(name); - } - } - /// Emit an attribute name, which is quoted if it needs to be quoted. Because - /// these emit into an object literal property name, we don't need to be worried - /// about keywords, just non-identifier characters - function emitAttributeName(name) { - if (/^[A-Za-z_]\w*$/.test(name.text)) { - emit(name); - } - else { - write('"'); - emit(name); - write('"'); - } - } - /// Emit an name/value pair for an attribute (e.g. "x: 3") - function emitJsxAttribute(node) { - emitAttributeName(node.name); - write(": "); - if (node.initializer) { - emit(node.initializer); - } - else { - write("true"); - } - } - function emitJsxElement(openingNode, children) { - var syntheticReactRef = ts.createSynthesizedNode(69 /* Identifier */); - syntheticReactRef.text = compilerOptions.reactNamespace ? compilerOptions.reactNamespace : "React"; - syntheticReactRef.parent = openingNode; - // Call React.createElement(tag, ... - emitLeadingComments(openingNode); - emitExpressionIdentifier(syntheticReactRef); - write(".createElement("); - emitTagName(openingNode.tagName); - write(", "); - // Attribute list - if (openingNode.attributes.length === 0) { - // When there are no attributes, React wants "null" - write("null"); - } - else { - // Either emit one big object literal (no spread attribs), or - // a call to the __assign helper - var attrs = openingNode.attributes; - if (ts.forEach(attrs, function (attr) { return attr.kind === 247 /* JsxSpreadAttribute */; })) { - write("__assign("); - var haveOpenedObjectLiteral = false; - for (var i = 0; i < attrs.length; i++) { - if (attrs[i].kind === 247 /* JsxSpreadAttribute */) { - // If this is the first argument, we need to emit a {} as the first argument - if (i === 0) { - write("{}, "); - } - if (haveOpenedObjectLiteral) { - write("}"); - haveOpenedObjectLiteral = false; - } - if (i > 0) { - write(", "); - } - emit(attrs[i].expression); - } - else { - ts.Debug.assert(attrs[i].kind === 246 /* JsxAttribute */); - if (haveOpenedObjectLiteral) { - write(", "); - } - else { - haveOpenedObjectLiteral = true; - if (i > 0) { - write(", "); - } - write("{"); - } - emitJsxAttribute(attrs[i]); - } - } - if (haveOpenedObjectLiteral) - write("}"); - write(")"); // closing paren to React.__spread( - } - else { - // One object literal with all the attributes in them - write("{"); - for (var i = 0, n = attrs.length; i < n; i++) { - if (i > 0) { - write(", "); - } - emitJsxAttribute(attrs[i]); - } - write("}"); - } - } - // Children - if (children) { - var firstChild = void 0; - var multipleEmittableChildren = false; - for (var i = 0, n = children.length; i < n; i++) { - var jsxChild = children[i]; - if (isJsxChildEmittable(jsxChild)) { - // we need to decide whether to emit in single line or multiple lines as indented list - // store firstChild reference, if we see another emittable child, then emit accordingly - if (!firstChild) { - write(", "); - firstChild = jsxChild; - } - else { - // more than one emittable child, emit indented list - if (!multipleEmittableChildren) { - multipleEmittableChildren = true; - increaseIndent(); - writeLine(); - emit(firstChild); - } - write(", "); - writeLine(); - emit(jsxChild); - } - } - } - if (multipleEmittableChildren) { - decreaseIndent(); - } - else if (firstChild) { - if (firstChild.kind !== 241 /* JsxElement */ && firstChild.kind !== 242 /* JsxSelfClosingElement */) { - emit(firstChild); - } - else { - // If the only child is jsx element, put it on a new indented line - increaseIndent(); - writeLine(); - emit(firstChild); - writeLine(); - decreaseIndent(); - } - } - } - // Closing paren - write(")"); // closes "React.createElement(" - emitTrailingComments(openingNode); - } - if (node.kind === 241 /* JsxElement */) { - emitJsxElement(node.openingElement, node.children); - } - else { - ts.Debug.assert(node.kind === 242 /* JsxSelfClosingElement */); - emitJsxElement(node); - } + return ts.createPropertyAccess(left, node.right); + } + /** + * Gets an expression that points to the global "Symbol" constructor at runtime if it is + * available. + */ + function getGlobalSymbolNameWithFallback() { + return ts.createConditional(ts.createStrictEquality(ts.createTypeOf(ts.createIdentifier("Symbol")), ts.createLiteral("function")), ts.createToken(53 /* QuestionToken */), ts.createIdentifier("Symbol"), ts.createToken(54 /* ColonToken */), ts.createIdentifier("Object")); + } + /** + * Gets an expression that represents a property name. For a computed property, a + * name is generated for the node. + * + * @param member The member whose name should be converted into an expression. + */ + function getExpressionForPropertyName(member, generateNameForComputedPropertyName) { + var name = member.name; + if (ts.isComputedPropertyName(name)) { + return generateNameForComputedPropertyName + ? ts.getGeneratedNameForNode(name) + : name.expression; } - function jsxEmitPreserve(node) { - function emitJsxAttribute(node) { - emit(node.name); - if (node.initializer) { - write("="); - emit(node.initializer); - } - } - function emitJsxSpreadAttribute(node) { - write("{..."); - emit(node.expression); - write("}"); - } - function emitAttributes(attribs) { - for (var i = 0, n = attribs.length; i < n; i++) { - if (i > 0) { - write(" "); - } - if (attribs[i].kind === 247 /* JsxSpreadAttribute */) { - emitJsxSpreadAttribute(attribs[i]); - } - else { - ts.Debug.assert(attribs[i].kind === 246 /* JsxAttribute */); - emitJsxAttribute(attribs[i]); - } - } - } - function emitJsxOpeningOrSelfClosingElement(node) { - write("<"); - emit(node.tagName); - if (node.attributes.length > 0 || (node.kind === 242 /* JsxSelfClosingElement */)) { - write(" "); - } - emitAttributes(node.attributes); - if (node.kind === 242 /* JsxSelfClosingElement */) { - write("/>"); - } - else { - write(">"); - } - } - function emitJsxClosingElement(node) { - write(""); - } - function emitJsxElement(node) { - emitJsxOpeningOrSelfClosingElement(node.openingElement); - for (var i = 0, n = node.children.length; i < n; i++) { - emit(node.children[i]); - } - emitJsxClosingElement(node.closingElement); - } - if (node.kind === 241 /* JsxElement */) { - emitJsxElement(node); - } - else { - ts.Debug.assert(node.kind === 242 /* JsxSelfClosingElement */); - emitJsxOpeningOrSelfClosingElement(node); - } + else if (ts.isIdentifier(name)) { + return ts.createLiteral(name.text); } - // This function specifically handles numeric/string literals for enum and accessor 'identifiers'. - // In a sense, it does not actually emit identifiers as much as it declares a name for a specific property. - // For example, this is utilized when feeding in a result to Object.defineProperty. - function emitExpressionForPropertyName(node) { - ts.Debug.assert(node.kind !== 169 /* BindingElement */); - if (node.kind === 9 /* StringLiteral */) { - emitLiteral(node); - } - else if (node.kind === 140 /* ComputedPropertyName */) { - // if this is a decorated computed property, we will need to capture the result - // of the property expression so that we can apply decorators later. This is to ensure - // we don't introduce unintended side effects: - // - // class C { - // [_a = x]() { } - // } - // - // The emit for the decorated computed property decorator is: - // - // __decorate([dec], C.prototype, _a, Object.getOwnPropertyDescriptor(C.prototype, _a)); - // - if (ts.nodeIsDecorated(node.parent)) { - if (!computedPropertyNamesToGeneratedNames) { - computedPropertyNamesToGeneratedNames = []; - } - var generatedName = computedPropertyNamesToGeneratedNames[ts.getNodeId(node)]; - if (generatedName) { - // we have already generated a variable for this node, write that value instead. - write(generatedName); - return; - } - generatedName = createAndRecordTempVariable(0 /* Auto */).text; - computedPropertyNamesToGeneratedNames[ts.getNodeId(node)] = generatedName; - write(generatedName); - write(" = "); - } - emit(node.expression); - } - else { - write('"'); - if (node.kind === 8 /* NumericLiteral */) { - write(node.text); - } - else { - writeTextOfNode(currentText, node); - } - write('"'); - } + else { + return ts.getSynthesizedClone(name); } - function isExpressionIdentifier(node) { - var parent = node.parent; - switch (parent.kind) { - case 170 /* ArrayLiteralExpression */: - case 195 /* AsExpression */: - case 184 /* AwaitExpression */: - case 187 /* BinaryExpression */: - case 174 /* CallExpression */: - case 249 /* CaseClause */: - case 140 /* ComputedPropertyName */: - case 188 /* ConditionalExpression */: - case 143 /* Decorator */: - case 181 /* DeleteExpression */: - case 204 /* DoStatement */: - case 173 /* ElementAccessExpression */: - case 235 /* ExportAssignment */: - case 202 /* ExpressionStatement */: - case 194 /* ExpressionWithTypeArguments */: - case 206 /* ForStatement */: - case 207 /* ForInStatement */: - case 208 /* ForOfStatement */: - case 203 /* IfStatement */: - case 245 /* JsxClosingElement */: - case 242 /* JsxSelfClosingElement */: - case 243 /* JsxOpeningElement */: - case 247 /* JsxSpreadAttribute */: - case 248 /* JsxExpression */: - case 175 /* NewExpression */: - case 196 /* NonNullExpression */: - case 178 /* ParenthesizedExpression */: - case 186 /* PostfixUnaryExpression */: - case 185 /* PrefixUnaryExpression */: - case 211 /* ReturnStatement */: - case 254 /* ShorthandPropertyAssignment */: - case 191 /* SpreadElementExpression */: - case 213 /* SwitchStatement */: - case 176 /* TaggedTemplateExpression */: - case 197 /* TemplateSpan */: - case 215 /* ThrowStatement */: - case 177 /* TypeAssertionExpression */: - case 182 /* TypeOfExpression */: - case 183 /* VoidExpression */: - case 205 /* WhileStatement */: - case 212 /* WithStatement */: - case 190 /* YieldExpression */: - return true; - case 169 /* BindingElement */: - case 255 /* EnumMember */: - case 142 /* Parameter */: - case 253 /* PropertyAssignment */: - case 145 /* PropertyDeclaration */: - case 218 /* VariableDeclaration */: - return parent.initializer === node; - case 172 /* PropertyAccessExpression */: - return parent.expression === node; - case 180 /* ArrowFunction */: - case 179 /* FunctionExpression */: - return parent.body === node; - case 229 /* ImportEqualsDeclaration */: - return parent.moduleReference === node; - case 139 /* QualifiedName */: - return parent.left === node; + } + /** + * Visits the property name of a class element, for use when emitting property + * initializers. For a computed property on a node with decorators, a temporary + * value is stored for later use. + * + * @param member The member whose name should be visited. + */ + function visitPropertyNameOfClassElement(member) { + var name = member.name; + if (ts.isComputedPropertyName(name)) { + var expression = ts.visitNode(name.expression, visitor, ts.isExpression); + if (member.decorators) { + var generatedName = ts.getGeneratedNameForNode(name); + hoistVariableDeclaration(generatedName); + expression = ts.createAssignment(generatedName, expression); } - return false; + return ts.setOriginalNode(ts.createComputedPropertyName(expression, /*location*/ name), name); } - function emitExpressionIdentifier(node) { - var container = resolver.getReferencedExportContainer(node); - if (container) { - if (container.kind === 256 /* SourceFile */) { - // Identifier references module export - if (modulekind !== ts.ModuleKind.ES6 && modulekind !== ts.ModuleKind.System) { - write("exports."); - } - } - else { - // Identifier references namespace export - write(getGeneratedNameForNode(container)); - write("."); - } - } - else { - if (modulekind !== ts.ModuleKind.ES6) { - var declaration = resolver.getReferencedImportDeclaration(node); - if (declaration) { - if (declaration.kind === 231 /* ImportClause */) { - // Identifier references default import - write(getGeneratedNameForNode(declaration.parent)); - write(languageVersion === 0 /* ES3 */ ? '["default"]' : ".default"); - return; - } - else if (declaration.kind === 234 /* ImportSpecifier */) { - // Identifier references named import - write(getGeneratedNameForNode(declaration.parent.parent.parent)); - var name_28 = declaration.propertyName || declaration.name; - var identifier = ts.getTextOfNodeFromSourceText(currentText, name_28); - if (languageVersion === 0 /* ES3 */ && identifier === "default") { - write('["default"]'); - } - else { - write("."); - write(identifier); - } - return; - } - } - } - if (languageVersion < 2 /* ES6 */) { - var declaration = resolver.getReferencedDeclarationWithCollidingName(node); - if (declaration) { - write(getGeneratedNameForNode(declaration.name)); - return; - } - } - else if (resolver.getNodeCheckFlags(node) & 1048576 /* BodyScopedClassBinding */) { - // Due to the emit for class decorators, any reference to the class from inside of the class body - // must instead be rewritten to point to a temporary variable to avoid issues with the double-bind - // behavior of class names in ES6. - var declaration = resolver.getReferencedValueDeclaration(node); - if (declaration) { - var classAlias = decoratedClassAliases[ts.getNodeId(declaration)]; - if (classAlias !== undefined) { - write(classAlias); - return; - } - } - } - } - if (ts.nodeIsSynthesized(node)) { - write(node.text); - } - else { - writeTextOfNode(currentText, node); - } + else { + return name; } - function isNameOfNestedBlockScopedRedeclarationOrCapturedBinding(node) { - if (languageVersion < 2 /* ES6 */) { - var parent_13 = node.parent; - switch (parent_13.kind) { - case 169 /* BindingElement */: - case 221 /* ClassDeclaration */: - case 224 /* EnumDeclaration */: - case 218 /* VariableDeclaration */: - return parent_13.name === node && resolver.isDeclarationWithCollidingName(parent_13); - } - } - return false; + } + /** + * Transforms a HeritageClause with TypeScript syntax. + * + * This function will only be called when one of the following conditions are met: + * - The node is a non-`extends` heritage clause that should be elided. + * - The node is an `extends` heritage clause that should be visited, but only allow a single type. + * + * @param node The HeritageClause to transform. + */ + function visitHeritageClause(node) { + if (node.token === 83 /* ExtendsKeyword */) { + var types = ts.visitNodes(node.types, visitor, ts.isExpressionWithTypeArguments, 0, 1); + return ts.createHeritageClause(83 /* ExtendsKeyword */, types, node); } - function getClassExpressionInPropertyAccessInStaticPropertyDeclaration(node) { - if (languageVersion >= 2 /* ES6 */) { - var parent_14 = node.parent; - if (parent_14.kind === 172 /* PropertyAccessExpression */ && parent_14.expression === node) { - parent_14 = parent_14.parent; - while (parent_14 && parent_14.kind !== 145 /* PropertyDeclaration */) { - parent_14 = parent_14.parent; - } - return parent_14 && parent_14.kind === 145 /* PropertyDeclaration */ && (parent_14.flags & 32 /* Static */) !== 0 && - parent_14.parent.kind === 192 /* ClassExpression */ ? parent_14.parent : undefined; - } - } + return undefined; + } + /** + * Transforms an ExpressionWithTypeArguments with TypeScript syntax. + * + * This function will only be called when one of the following conditions are met: + * - The node contains type arguments that should be elided. + * + * @param node The ExpressionWithTypeArguments to transform. + */ + function visitExpressionWithTypeArguments(node) { + var expression = ts.visitNode(node.expression, visitor, ts.isLeftHandSideExpression); + return ts.createExpressionWithTypeArguments( + /*typeArguments*/ undefined, expression, node); + } + /** + * Determines whether to emit a function-like declaration. We should not emit the + * declaration if it does not have a body. + * + * @param node The declaration node. + */ + function shouldEmitFunctionLikeDeclaration(node) { + return !ts.nodeIsMissing(node.body); + } + /** + * Visits a method declaration of a class. + * + * This function will be called when one of the following conditions are met: + * - The node is an overload + * - The node is marked as abstract, async, public, private, protected, or readonly + * - The node has both a decorator and a computed property name + * + * @param node The method node. + */ + function visitMethodDeclaration(node) { + if (!shouldEmitFunctionLikeDeclaration(node)) { return undefined; } - function emitIdentifier(node) { - if (convertedLoopState) { - if (node.text == "arguments" && resolver.isArgumentsLocalBinding(node)) { - // in converted loop body arguments cannot be used directly. - var name_29 = convertedLoopState.argumentsName || (convertedLoopState.argumentsName = makeUniqueName("arguments")); - write(name_29); - return; - } - } - if (!node.parent) { - write(node.text); - } - else if (isExpressionIdentifier(node)) { - var classExpression = getClassExpressionInPropertyAccessInStaticPropertyDeclaration(node); - if (classExpression) { - var declaration = resolver.getReferencedValueDeclaration(node); - if (declaration === classExpression) { - write(getGeneratedNameForNode(declaration.name)); - return; - } - } - emitExpressionIdentifier(node); - } - else if (isNameOfNestedBlockScopedRedeclarationOrCapturedBinding(node)) { - write(getGeneratedNameForNode(node)); - } - else if (ts.nodeIsSynthesized(node)) { - write(node.text); - } - else { - writeTextOfNode(currentText, node); - } + var method = ts.createMethod( + /*decorators*/ undefined, ts.visitNodes(node.modifiers, visitor, ts.isModifier), node.asteriskToken, visitPropertyNameOfClassElement(node), + /*typeParameters*/ undefined, ts.visitNodes(node.parameters, visitor, ts.isParameter), + /*type*/ undefined, transformFunctionBody(node), + /*location*/ node); + // While we emit the source map for the node after skipping decorators and modifiers, + // we need to emit the comments for the original range. + ts.setCommentRange(method, node); + ts.setSourceMapRange(method, ts.moveRangePastDecorators(node)); + ts.setOriginalNode(method, node); + return method; + } + /** + * Determines whether to emit an accessor declaration. We should not emit the + * declaration if it does not have a body and is abstract. + * + * @param node The declaration node. + */ + function shouldEmitAccessorDeclaration(node) { + return !(ts.nodeIsMissing(node.body) && ts.hasModifier(node, 128 /* Abstract */)); + } + /** + * Visits a get accessor declaration of a class. + * + * This function will be called when one of the following conditions are met: + * - The node is marked as abstract, public, private, or protected + * - The node has both a decorator and a computed property name + * + * @param node The get accessor node. + */ + function visitGetAccessor(node) { + if (!shouldEmitAccessorDeclaration(node)) { + return undefined; } - function emitThis(node) { - if (resolver.getNodeCheckFlags(node) & 2 /* LexicalThis */) { - write("_this"); - } - else if (convertedLoopState) { - write(convertedLoopState.thisName || (convertedLoopState.thisName = makeUniqueName("this"))); + var accessor = ts.createGetAccessor( + /*decorators*/ undefined, ts.visitNodes(node.modifiers, visitor, ts.isModifier), visitPropertyNameOfClassElement(node), ts.visitNodes(node.parameters, visitor, ts.isParameter), + /*type*/ undefined, node.body ? ts.visitEachChild(node.body, visitor, context) : ts.createBlock([]), + /*location*/ node); + // While we emit the source map for the node after skipping decorators and modifiers, + // we need to emit the comments for the original range. + ts.setCommentRange(accessor, node); + ts.setSourceMapRange(accessor, ts.moveRangePastDecorators(node)); + ts.setOriginalNode(accessor, node); + return accessor; + } + /** + * Visits a set accessor declaration of a class. + * + * This function will be called when one of the following conditions are met: + * - The node is marked as abstract, public, private, or protected + * - The node has both a decorator and a computed property name + * + * @param node The set accessor node. + */ + function visitSetAccessor(node) { + if (!shouldEmitAccessorDeclaration(node)) { + return undefined; + } + var accessor = ts.createSetAccessor( + /*decorators*/ undefined, ts.visitNodes(node.modifiers, visitor, ts.isModifier), visitPropertyNameOfClassElement(node), ts.visitNodes(node.parameters, visitor, ts.isParameter), node.body ? ts.visitEachChild(node.body, visitor, context) : ts.createBlock([]), + /*location*/ node); + // While we emit the source map for the node after skipping decorators and modifiers, + // we need to emit the comments for the original range. + ts.setCommentRange(accessor, node); + ts.setSourceMapRange(accessor, ts.moveRangePastDecorators(node)); + ts.setOriginalNode(accessor, node); + return accessor; + } + /** + * Visits a function declaration. + * + * This function will be called when one of the following conditions are met: + * - The node is an overload + * - The node is marked async + * - The node is exported from a TypeScript namespace + * + * @param node The function node. + */ + function visitFunctionDeclaration(node) { + if (!shouldEmitFunctionLikeDeclaration(node)) { + return ts.createNotEmittedStatement(node); + } + var func = ts.createFunctionDeclaration( + /*decorators*/ undefined, ts.visitNodes(node.modifiers, visitor, ts.isModifier), node.asteriskToken, node.name, + /*typeParameters*/ undefined, ts.visitNodes(node.parameters, visitor, ts.isParameter), + /*type*/ undefined, transformFunctionBody(node), + /*location*/ node); + ts.setOriginalNode(func, node); + if (isNamespaceExport(node)) { + var statements = [func]; + addExportMemberAssignment(statements, node); + return statements; + } + return func; + } + /** + * Visits a function expression node. + * + * This function will be called when one of the following conditions are met: + * - The node is marked async + * + * @param node The function expression node. + */ + function visitFunctionExpression(node) { + if (ts.nodeIsMissing(node.body)) { + return ts.createOmittedExpression(); + } + var func = ts.createFunctionExpression(node.asteriskToken, node.name, + /*typeParameters*/ undefined, ts.visitNodes(node.parameters, visitor, ts.isParameter), + /*type*/ undefined, transformFunctionBody(node), + /*location*/ node); + ts.setOriginalNode(func, node); + return func; + } + /** + * @remarks + * This function will be called when one of the following conditions are met: + * - The node is marked async + */ + function visitArrowFunction(node) { + var func = ts.createArrowFunction( + /*modifiers*/ undefined, + /*typeParameters*/ undefined, ts.visitNodes(node.parameters, visitor, ts.isParameter), + /*type*/ undefined, node.equalsGreaterThanToken, transformConciseBody(node), + /*location*/ node); + ts.setOriginalNode(func, node); + return func; + } + function transformFunctionBody(node) { + if (ts.isAsyncFunctionLike(node)) { + return transformAsyncFunctionBody(node); + } + return transformFunctionBodyWorker(node.body); + } + function transformFunctionBodyWorker(body, start) { + if (start === void 0) { start = 0; } + var savedCurrentScope = currentScope; + currentScope = body; + startLexicalEnvironment(); + var statements = ts.visitNodes(body.statements, visitor, ts.isStatement, start); + var visited = ts.updateBlock(body, statements); + var declarations = endLexicalEnvironment(); + currentScope = savedCurrentScope; + return ts.mergeFunctionBodyLexicalEnvironment(visited, declarations); + } + function transformConciseBody(node) { + if (ts.isAsyncFunctionLike(node)) { + return transformAsyncFunctionBody(node); + } + return transformConciseBodyWorker(node.body, /*forceBlockFunctionBody*/ false); + } + function transformConciseBodyWorker(body, forceBlockFunctionBody) { + if (ts.isBlock(body)) { + return transformFunctionBodyWorker(body); + } + else { + startLexicalEnvironment(); + var visited = ts.visitNode(body, visitor, ts.isConciseBody); + var declarations = endLexicalEnvironment(); + var merged = ts.mergeFunctionBodyLexicalEnvironment(visited, declarations); + if (forceBlockFunctionBody && !ts.isBlock(merged)) { + return ts.createBlock([ + ts.createReturn(merged) + ]); } else { - write("this"); + return merged; } } - function emitSuper(node) { - if (languageVersion >= 2 /* ES6 */) { - write("super"); + } + function getPromiseConstructor(type) { + var typeName = ts.getEntityNameFromTypeNode(type); + if (typeName && ts.isEntityName(typeName)) { + var serializationKind = resolver.getTypeReferenceSerializationKind(typeName); + if (serializationKind === ts.TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue + || serializationKind === ts.TypeReferenceSerializationKind.Unknown) { + return typeName; } - else { - var flags = resolver.getNodeCheckFlags(node); - if (flags & 256 /* SuperInstance */) { - write("_super.prototype"); + } + return undefined; + } + function transformAsyncFunctionBody(node) { + var promiseConstructor = languageVersion < 2 /* ES6 */ ? getPromiseConstructor(node.type) : undefined; + var isArrowFunction = node.kind === 180 /* ArrowFunction */; + var hasLexicalArguments = (resolver.getNodeCheckFlags(node) & 8192 /* CaptureArguments */) !== 0; + // An async function is emit as an outer function that calls an inner + // generator function. To preserve lexical bindings, we pass the current + // `this` and `arguments` objects to `__awaiter`. The generator function + // passed to `__awaiter` is executed inside of the callback to the + // promise constructor. + if (!isArrowFunction) { + var statements = []; + var statementOffset = ts.addPrologueDirectives(statements, node.body.statements, /*ensureUseStrict*/ false, visitor); + statements.push(ts.createReturn(ts.createAwaiterHelper(currentSourceFileExternalHelpersModuleName, hasLexicalArguments, promiseConstructor, transformFunctionBodyWorker(node.body, statementOffset)))); + var block = ts.createBlock(statements, /*location*/ node.body, /*multiLine*/ true); + // Minor optimization, emit `_super` helper to capture `super` access in an arrow. + // This step isn't needed if we eventually transform this to ES5. + if (languageVersion >= 2 /* ES6 */) { + if (resolver.getNodeCheckFlags(node) & 4096 /* AsyncMethodWithSuperBinding */) { + enableSubstitutionForAsyncMethodsWithSuper(); + ts.setEmitFlags(block, 8 /* EmitAdvancedSuperHelper */); } - else { - write("_super"); + else if (resolver.getNodeCheckFlags(node) & 2048 /* AsyncMethodWithSuper */) { + enableSubstitutionForAsyncMethodsWithSuper(); + ts.setEmitFlags(block, 4 /* EmitSuperHelper */); } } + return block; } - function emitObjectBindingPattern(node) { - write("{ "); - var elements = node.elements; - emitList(elements, 0, elements.length, /*multiLine*/ false, /*trailingComma*/ elements.hasTrailingComma); - write(" }"); + else { + return ts.createAwaiterHelper(currentSourceFileExternalHelpersModuleName, hasLexicalArguments, promiseConstructor, transformConciseBodyWorker(node.body, /*forceBlockFunctionBody*/ true)); } - function emitArrayBindingPattern(node) { - write("["); - var elements = node.elements; - emitList(elements, 0, elements.length, /*multiLine*/ false, /*trailingComma*/ elements.hasTrailingComma); - write("]"); + } + /** + * Visits a parameter declaration node. + * + * This function will be called when one of the following conditions are met: + * - The node has an accessibility modifier. + * - The node has a questionToken. + * - The node's kind is ThisKeyword. + * + * @param node The parameter declaration node. + */ + function visitParameter(node) { + if (node.name && ts.isIdentifier(node.name) && node.name.originalKeywordKind === 97 /* ThisKeyword */) { + return undefined; } - function emitBindingElement(node) { - if (node.propertyName) { - emit(node.propertyName); - write(": "); - } - if (node.dotDotDotToken) { - write("..."); - } - if (ts.isBindingPattern(node.name)) { - emit(node.name); - } - else { - emitModuleMemberName(node); + var parameter = ts.createParameterDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, node.dotDotDotToken, ts.visitNode(node.name, visitor, ts.isBindingName), + /*questionToken*/ undefined, + /*type*/ undefined, ts.visitNode(node.initializer, visitor, ts.isExpression), + /*location*/ ts.moveRangePastModifiers(node)); + // While we emit the source map for the node after skipping decorators and modifiers, + // we need to emit the comments for the original range. + ts.setOriginalNode(parameter, node); + ts.setCommentRange(parameter, node); + ts.setSourceMapRange(parameter, ts.moveRangePastModifiers(node)); + ts.setEmitFlags(parameter.name, 1024 /* NoTrailingSourceMap */); + return parameter; + } + /** + * Visits a variable statement in a namespace. + * + * This function will be called when one of the following conditions are met: + * - The node is exported from a TypeScript namespace. + */ + function visitVariableStatement(node) { + if (isNamespaceExport(node)) { + var variables = ts.getInitializedVariables(node.declarationList); + if (variables.length === 0) { + // elide statement if there are no initialized variables. + return undefined; } - emitOptional(" = ", node.initializer); + return ts.createStatement(ts.inlineExpressions(ts.map(variables, transformInitializedVariable)), + /*location*/ node); } - function emitSpreadElementExpression(node) { - write("..."); - emit(node.expression); - } - function emitYieldExpression(node) { - write(ts.tokenToString(114 /* YieldKeyword */)); - if (node.asteriskToken) { - write("*"); - } - if (node.expression) { - write(" "); - emit(node.expression); - } + else { + return ts.visitEachChild(node, visitor, context); } - function emitAwaitExpression(node) { - var needsParenthesis = needsParenthesisForAwaitExpressionAsYield(node); - if (needsParenthesis) { - write("("); - } - write(ts.tokenToString(114 /* YieldKeyword */)); - write(" "); - emit(node.expression); - if (needsParenthesis) { - write(")"); - } + } + function transformInitializedVariable(node) { + var name = node.name; + if (ts.isBindingPattern(name)) { + return ts.flattenVariableDestructuringToExpression(context, node, hoistVariableDeclaration, getNamespaceMemberNameWithSourceMapsAndWithoutComments, visitor); } - function needsParenthesisForAwaitExpressionAsYield(node) { - if (node.parent.kind === 187 /* BinaryExpression */ && !ts.isAssignmentOperator(node.parent.operatorToken.kind)) { - return true; - } - else if (node.parent.kind === 188 /* ConditionalExpression */ && node.parent.condition === node) { - return true; - } - else if (node.parent.kind === 185 /* PrefixUnaryExpression */ || node.parent.kind === 181 /* DeleteExpression */ || - node.parent.kind === 182 /* TypeOfExpression */ || node.parent.kind === 183 /* VoidExpression */) { - return true; - } - return false; + else { + return ts.createAssignment(getNamespaceMemberNameWithSourceMapsAndWithoutComments(name), ts.visitNode(node.initializer, visitor, ts.isExpression), + /*location*/ node); } - function needsParenthesisForPropertyAccessOrInvocation(node) { - switch (node.kind) { - case 69 /* Identifier */: - case 170 /* ArrayLiteralExpression */: - case 172 /* PropertyAccessExpression */: - case 173 /* ElementAccessExpression */: - case 174 /* CallExpression */: - case 178 /* ParenthesizedExpression */: - // This list is not exhaustive and only includes those cases that are relevant - // to the check in emitArrayLiteral. More cases can be added as needed. - return false; - } - return true; + } + /** + * Visits an await expression. + * + * This function will be called any time a TypeScript await expression is encountered. + * + * @param node The await expression node. + */ + function visitAwaitExpression(node) { + return ts.setOriginalNode(ts.createYield( + /*asteriskToken*/ undefined, ts.visitNode(node.expression, visitor, ts.isExpression), + /*location*/ node), node); + } + /** + * Visits a parenthesized expression that contains either a type assertion or an `as` + * expression. + * + * @param node The parenthesized expression node. + */ + function visitParenthesizedExpression(node) { + var innerExpression = ts.skipOuterExpressions(node.expression, ~2 /* Assertions */); + if (ts.isAssertionExpression(innerExpression)) { + // Make sure we consider all nested cast expressions, e.g.: + // (-A).x; + var expression = ts.visitNode(node.expression, visitor, ts.isExpression); + // We have an expression of the form: (SubExpr). Emitting this as (SubExpr) + // is really not desirable. We would like to emit the subexpression as-is. Omitting + // the parentheses, however, could cause change in the semantics of the generated + // code if the casted expression has a lower precedence than the rest of the + // expression. + // + // Due to the auto-parenthesization rules used by the visitor and factory functions + // we can safely elide the parentheses here, as a new synthetic + // ParenthesizedExpression will be inserted if we remove parentheses too + // aggressively. + // + // To preserve comments, we return a "PartiallyEmittedExpression" here which will + // preserve the position information of the original expression. + return ts.createPartiallyEmittedExpression(expression, node); } - function emitListWithSpread(elements, needsUniqueCopy, multiLine, trailingComma, useConcat) { - var pos = 0; - var group = 0; - var length = elements.length; - while (pos < length) { - // Emit using the pattern .concat(, , ...) - if (group === 1 && useConcat) { - write(".concat("); - } - else if (group > 0) { - write(", "); - } - var e = elements[pos]; - if (e.kind === 191 /* SpreadElementExpression */) { - e = e.expression; - emitParenthesizedIf(e, /*parenthesized*/ group === 0 && needsParenthesisForPropertyAccessOrInvocation(e)); - pos++; - if (pos === length && group === 0 && needsUniqueCopy && e.kind !== 170 /* ArrayLiteralExpression */) { - write(".slice()"); - } - } - else { - var i = pos; - while (i < length && elements[i].kind !== 191 /* SpreadElementExpression */) { - i++; - } - write("["); - if (multiLine) { - increaseIndent(); - } - emitList(elements, pos, i - pos, multiLine, trailingComma && i === length); - if (multiLine) { - decreaseIndent(); - } - write("]"); - pos = i; - } - group++; - } - if (group > 1) { - if (useConcat) { - write(")"); - } - } + return ts.visitEachChild(node, visitor, context); + } + function visitAssertionExpression(node) { + var expression = ts.visitNode(node.expression, visitor, ts.isExpression); + return ts.createPartiallyEmittedExpression(expression, node); + } + function visitNonNullExpression(node) { + var expression = ts.visitNode(node.expression, visitor, ts.isLeftHandSideExpression); + return ts.createPartiallyEmittedExpression(expression, node); + } + /** + * Determines whether to emit an enum declaration. + * + * @param node The enum declaration node. + */ + function shouldEmitEnumDeclaration(node) { + return !ts.isConst(node) + || compilerOptions.preserveConstEnums + || compilerOptions.isolatedModules; + } + function shouldEmitVarForEnumDeclaration(node) { + return isFirstEmittedDeclarationInScope(node) + && (!ts.hasModifier(node, 1 /* Export */) + || isES6ExportedDeclaration(node)); + } + /* + * Adds a trailing VariableStatement for an enum or module declaration. + */ + function addVarForEnumExportedFromNamespace(statements, node) { + var statement = ts.createVariableStatement( + /*modifiers*/ undefined, [ts.createVariableDeclaration(getDeclarationName(node), + /*type*/ undefined, getExportName(node))]); + ts.setSourceMapRange(statement, node); + statements.push(statement); + } + /** + * Visits an enum declaration. + * + * This function will be called any time a TypeScript enum is encountered. + * + * @param node The enum declaration node. + */ + function visitEnumDeclaration(node) { + if (!shouldEmitEnumDeclaration(node)) { + return undefined; } - function isSpreadElementExpression(node) { - return node.kind === 191 /* SpreadElementExpression */; + var statements = []; + // We request to be advised when the printer is about to print this node. This allows + // us to set up the correct state for later substitutions. + var emitFlags = 64 /* AdviseOnEmitNode */; + // If needed, we should emit a variable declaration for the enum. If we emit + // a leading variable declaration, we should not emit leading comments for the + // enum body. + recordEmittedDeclarationInScope(node); + if (shouldEmitVarForEnumDeclaration(node)) { + addVarForEnumOrModuleDeclaration(statements, node); + // We should still emit the comments if we are emitting a system module. + if (moduleKind !== ts.ModuleKind.System || currentScope !== currentSourceFile) { + emitFlags |= 16384 /* NoLeadingComments */; + } + } + // `parameterName` is the declaration name used inside of the enum. + var parameterName = getNamespaceParameterName(node); + // `containerName` is the expression used inside of the enum for assignments. + var containerName = getNamespaceContainerName(node); + // `exportName` is the expression used within this node's container for any exported references. + var exportName = getExportName(node); + // (function (x) { + // x[x["y"] = 0] = "y"; + // ... + // })(x || (x = {})); + var enumStatement = ts.createStatement(ts.createCall(ts.createFunctionExpression( + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ts.createParameter(parameterName)], + /*type*/ undefined, transformEnumBody(node, containerName)), + /*typeArguments*/ undefined, [ts.createLogicalOr(exportName, ts.createAssignment(exportName, ts.createObjectLiteral()))]), + /*location*/ node); + ts.setOriginalNode(enumStatement, node); + ts.setEmitFlags(enumStatement, emitFlags); + statements.push(enumStatement); + if (isNamespaceExport(node)) { + addVarForEnumExportedFromNamespace(statements, node); + } + return statements; + } + /** + * Transforms the body of an enum declaration. + * + * @param node The enum declaration node. + */ + function transformEnumBody(node, localName) { + var savedCurrentNamespaceLocalName = currentNamespaceContainerName; + currentNamespaceContainerName = localName; + var statements = []; + startLexicalEnvironment(); + ts.addRange(statements, ts.map(node.members, transformEnumMember)); + ts.addRange(statements, endLexicalEnvironment()); + currentNamespaceContainerName = savedCurrentNamespaceLocalName; + return ts.createBlock(ts.createNodeArray(statements, /*location*/ node.members), + /*location*/ undefined, + /*multiLine*/ true); + } + /** + * Transforms an enum member into a statement. + * + * @param member The enum member node. + */ + function transformEnumMember(member) { + // enums don't support computed properties + // we pass false as 'generateNameForComputedPropertyName' for a backward compatibility purposes + // old emitter always generate 'expression' part of the name as-is. + var name = getExpressionForPropertyName(member, /*generateNameForComputedPropertyName*/ false); + return ts.createStatement(ts.createAssignment(ts.createElementAccess(currentNamespaceContainerName, ts.createAssignment(ts.createElementAccess(currentNamespaceContainerName, name), transformEnumMemberDeclarationValue(member))), name, + /*location*/ member), + /*location*/ member); + } + /** + * Transforms the value of an enum member. + * + * @param member The enum member node. + */ + function transformEnumMemberDeclarationValue(member) { + var value = resolver.getConstantValue(member); + if (value !== undefined) { + return ts.createLiteral(value); } - function emitArrayLiteral(node) { - var elements = node.elements; - if (elements.length === 0) { - write("[]"); - } - else if (languageVersion >= 2 /* ES6 */ || !ts.forEach(elements, isSpreadElementExpression)) { - write("["); - emitLinePreservingList(node, node.elements, elements.hasTrailingComma, /*spacesBetweenBraces*/ false); - write("]"); + else { + enableSubstitutionForNonQualifiedEnumMembers(); + if (member.initializer) { + return ts.visitNode(member.initializer, visitor, ts.isExpression); } else { - emitListWithSpread(elements, /*needsUniqueCopy*/ true, /*multiLine*/ node.multiLine, - /*trailingComma*/ elements.hasTrailingComma, /*useConcat*/ true); + return ts.createVoidZero(); } } - function emitObjectLiteralBody(node, numElements) { - if (numElements === 0) { - write("{}"); - return; + } + /** + * Determines whether to elide a module declaration. + * + * @param node The module declaration node. + */ + function shouldEmitModuleDeclaration(node) { + return ts.isInstantiatedModule(node, compilerOptions.preserveConstEnums || compilerOptions.isolatedModules); + } + function isES6ExportedDeclaration(node) { + return isExternalModuleExport(node) + && moduleKind === ts.ModuleKind.ES6; + } + /** + * Records that a declaration was emitted in the current scope, if it was the first + * declaration for the provided symbol. + * + * NOTE: if there is ever a transformation above this one, we may not be able to rely + * on symbol names. + */ + function recordEmittedDeclarationInScope(node) { + var name = node.symbol && node.symbol.name; + if (name) { + if (!currentScopeFirstDeclarationsOfName) { + currentScopeFirstDeclarationsOfName = ts.createMap(); } - write("{"); - if (numElements > 0) { - var properties = node.properties; - // If we are not doing a downlevel transformation for object literals, - // then try to preserve the original shape of the object literal. - // Otherwise just try to preserve the formatting. - if (numElements === properties.length) { - emitLinePreservingList(node, properties, /*allowTrailingComma*/ languageVersion >= 1 /* ES5 */, /*spacesBetweenBraces*/ true); - } - else { - var multiLine = node.multiLine; - if (!multiLine) { - write(" "); - } - else { - increaseIndent(); - } - emitList(properties, 0, numElements, /*multiLine*/ multiLine, /*trailingComma*/ false); - if (!multiLine) { - write(" "); - } - else { - decreaseIndent(); - } - } + if (!(name in currentScopeFirstDeclarationsOfName)) { + currentScopeFirstDeclarationsOfName[name] = node; } - write("}"); } - function emitDownlevelObjectLiteralWithComputedProperties(node, firstComputedPropertyIndex) { - var multiLine = node.multiLine; - var properties = node.properties; - write("("); - if (multiLine) { - increaseIndent(); - } - // For computed properties, we need to create a unique handle to the object - // literal so we can modify it without risking internal assignments tainting the object. - var tempVar = createAndRecordTempVariable(0 /* Auto */); - // Write out the first non-computed properties - // (or all properties if none of them are computed), - // then emit the rest through indexing on the temp variable. - emit(tempVar); - write(" = "); - emitObjectLiteralBody(node, firstComputedPropertyIndex); - for (var i = firstComputedPropertyIndex, n = properties.length; i < n; i++) { - writeComma(); - var property = properties[i]; - emitStart(property); - if (property.kind === 149 /* GetAccessor */ || property.kind === 150 /* SetAccessor */) { - // TODO (drosen): Reconcile with 'emitMemberFunctions'. - var accessors = ts.getAllAccessorDeclarations(node.properties, property); - if (property !== accessors.firstAccessor) { - continue; - } - write("Object.defineProperty("); - emit(tempVar); - write(", "); - emitStart(property.name); - emitExpressionForPropertyName(property.name); - emitEnd(property.name); - write(", {"); - increaseIndent(); - if (accessors.getAccessor) { - writeLine(); - emitLeadingComments(accessors.getAccessor); - write("get: "); - emitStart(accessors.getAccessor); - write("function "); - emitSignatureAndBody(accessors.getAccessor); - emitEnd(accessors.getAccessor); - emitTrailingComments(accessors.getAccessor); - write(","); - } - if (accessors.setAccessor) { - writeLine(); - emitLeadingComments(accessors.setAccessor); - write("set: "); - emitStart(accessors.setAccessor); - write("function "); - emitSignatureAndBody(accessors.setAccessor); - emitEnd(accessors.setAccessor); - emitTrailingComments(accessors.setAccessor); - write(","); - } - writeLine(); - write("enumerable: true,"); - writeLine(); - write("configurable: true"); - decreaseIndent(); - writeLine(); - write("})"); - emitEnd(property); - } - else { - emitLeadingComments(property); - emitStart(property.name); - emit(tempVar); - emitMemberAccessForPropertyName(property.name); - emitEnd(property.name); - write(" = "); - if (property.kind === 253 /* PropertyAssignment */) { - emit(property.initializer); - } - else if (property.kind === 254 /* ShorthandPropertyAssignment */) { - emitExpressionIdentifier(property.name); - } - else if (property.kind === 147 /* MethodDeclaration */) { - emitFunctionDeclaration(property); - } - else { - ts.Debug.fail("ObjectLiteralElement type not accounted for: " + property.kind); - } - } - emitEnd(property); - } - writeComma(); - emit(tempVar); - if (multiLine) { - decreaseIndent(); - writeLine(); - } - write(")"); - function writeComma() { - if (multiLine) { - write(","); - writeLine(); - } - else { - write(", "); - } + } + /** + * Determines whether a declaration is the first declaration with the same name emitted + * in the current scope. + */ + function isFirstEmittedDeclarationInScope(node) { + if (currentScopeFirstDeclarationsOfName) { + var name_31 = node.symbol && node.symbol.name; + if (name_31) { + return currentScopeFirstDeclarationsOfName[name_31] === node; } } - function emitObjectLiteral(node) { - var properties = node.properties; - if (languageVersion < 2 /* ES6 */) { - var numProperties = properties.length; - // Find the first computed property. - // Everything until that point can be emitted as part of the initial object literal. - var numInitialNonComputedProperties = numProperties; - for (var i = 0, n = properties.length; i < n; i++) { - if (properties[i].name.kind === 140 /* ComputedPropertyName */) { - numInitialNonComputedProperties = i; - break; - } - } - var hasComputedProperty = numInitialNonComputedProperties !== properties.length; - if (hasComputedProperty) { - emitDownlevelObjectLiteralWithComputedProperties(node, numInitialNonComputedProperties); - return; - } - } - // Ordinary case: either the object has no computed properties - // or we're compiling with an ES6+ target. - emitObjectLiteralBody(node, properties.length); + return false; + } + function shouldEmitVarForModuleDeclaration(node) { + return isFirstEmittedDeclarationInScope(node); + } + /** + * Adds a leading VariableStatement for a enum or module declaration. + */ + function addVarForEnumOrModuleDeclaration(statements, node) { + // Emit a variable statement for the module. + var statement = ts.createVariableStatement(isES6ExportedDeclaration(node) + ? ts.visitNodes(node.modifiers, visitor, ts.isModifier) + : undefined, [ + ts.createVariableDeclaration(getDeclarationName(node, /*allowComments*/ false, /*allowSourceMaps*/ true)) + ]); + ts.setOriginalNode(statement, /*original*/ node); + // Adjust the source map emit to match the old emitter. + if (node.kind === 224 /* EnumDeclaration */) { + ts.setSourceMapRange(statement.declarationList, node); } - function createBinaryExpression(left, operator, right, startsOnNewLine) { - var result = ts.createSynthesizedNode(187 /* BinaryExpression */, startsOnNewLine); - result.operatorToken = ts.createSynthesizedNode(operator); - result.left = left; - result.right = right; - return result; + else { + ts.setSourceMapRange(statement, node); } - function createPropertyAccessExpression(expression, name) { - var result = ts.createSynthesizedNode(172 /* PropertyAccessExpression */); - result.expression = parenthesizeForAccess(expression); - result.name = name; - return result; + // Trailing comments for module declaration should be emitted after the function closure + // instead of the variable statement: + // + // /** Module comment*/ + // module m1 { + // function foo4Export() { + // } + // } // trailing comment module + // + // Should emit: + // + // /** Module comment*/ + // var m1; + // (function (m1) { + // function foo4Export() { + // } + // })(m1 || (m1 = {})); // trailing comment module + // + ts.setCommentRange(statement, node); + ts.setEmitFlags(statement, 32768 /* NoTrailingComments */); + statements.push(statement); + } + /** + * Visits a module declaration node. + * + * This function will be called any time a TypeScript namespace (ModuleDeclaration) is encountered. + * + * @param node The module declaration node. + */ + function visitModuleDeclaration(node) { + if (!shouldEmitModuleDeclaration(node)) { + return ts.createNotEmittedStatement(node); + } + ts.Debug.assert(ts.isIdentifier(node.name), "TypeScript module should have an Identifier name."); + enableSubstitutionForNamespaceExports(); + var statements = []; + // We request to be advised when the printer is about to print this node. This allows + // us to set up the correct state for later substitutions. + var emitFlags = 64 /* AdviseOnEmitNode */; + // If needed, we should emit a variable declaration for the module. If we emit + // a leading variable declaration, we should not emit leading comments for the + // module body. + recordEmittedDeclarationInScope(node); + if (shouldEmitVarForModuleDeclaration(node)) { + addVarForEnumOrModuleDeclaration(statements, node); + // We should still emit the comments if we are emitting a system module. + if (moduleKind !== ts.ModuleKind.System || currentScope !== currentSourceFile) { + emitFlags |= 16384 /* NoLeadingComments */; + } + } + // `parameterName` is the declaration name used inside of the namespace. + var parameterName = getNamespaceParameterName(node); + // `containerName` is the expression used inside of the namespace for exports. + var containerName = getNamespaceContainerName(node); + // `exportName` is the expression used within this node's container for any exported references. + var exportName = getExportName(node); + // x || (x = {}) + // exports.x || (exports.x = {}) + var moduleArg = ts.createLogicalOr(exportName, ts.createAssignment(exportName, ts.createObjectLiteral())); + if (ts.hasModifier(node, 1 /* Export */) && !isES6ExportedDeclaration(node)) { + // `localName` is the expression used within this node's containing scope for any local references. + var localName = getLocalName(node); + // x = (exports.x || (exports.x = {})) + moduleArg = ts.createAssignment(localName, moduleArg); + } + // (function (x_1) { + // x_1.y = ...; + // })(x || (x = {})); + var moduleStatement = ts.createStatement(ts.createCall(ts.createFunctionExpression( + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ts.createParameter(parameterName)], + /*type*/ undefined, transformModuleBody(node, containerName)), + /*typeArguments*/ undefined, [moduleArg]), + /*location*/ node); + ts.setOriginalNode(moduleStatement, node); + ts.setEmitFlags(moduleStatement, emitFlags); + statements.push(moduleStatement); + return statements; + } + /** + * Transforms the body of a module declaration. + * + * @param node The module declaration node. + */ + function transformModuleBody(node, namespaceLocalName) { + var savedCurrentNamespaceContainerName = currentNamespaceContainerName; + var savedCurrentNamespace = currentNamespace; + var savedCurrentScopeFirstDeclarationsOfName = currentScopeFirstDeclarationsOfName; + currentNamespaceContainerName = namespaceLocalName; + currentNamespace = node; + currentScopeFirstDeclarationsOfName = undefined; + var statements = []; + startLexicalEnvironment(); + var statementsLocation; + var blockLocation; + var body = node.body; + if (body.kind === 226 /* ModuleBlock */) { + ts.addRange(statements, ts.visitNodes(body.statements, namespaceElementVisitor, ts.isStatement)); + statementsLocation = body.statements; + blockLocation = body; } - function createElementAccessExpression(expression, argumentExpression) { - var result = ts.createSynthesizedNode(173 /* ElementAccessExpression */); - result.expression = parenthesizeForAccess(expression); - result.argumentExpression = argumentExpression; - return result; + else { + var result = visitModuleDeclaration(body); + if (result) { + if (ts.isArray(result)) { + ts.addRange(statements, result); + } + else { + statements.push(result); + } + } + var moduleBlock = getInnerMostModuleDeclarationFromDottedModule(node).body; + statementsLocation = ts.moveRangePos(moduleBlock.statements, -1); + } + ts.addRange(statements, endLexicalEnvironment()); + currentNamespaceContainerName = savedCurrentNamespaceContainerName; + currentNamespace = savedCurrentNamespace; + currentScopeFirstDeclarationsOfName = savedCurrentScopeFirstDeclarationsOfName; + var block = ts.createBlock(ts.createNodeArray(statements, + /*location*/ statementsLocation), + /*location*/ blockLocation, + /*multiLine*/ true); + // namespace hello.hi.world { + // function foo() {} + // + // // TODO, blah + // } + // + // should be emitted as + // + // var hello; + // (function (hello) { + // var hi; + // (function (hi) { + // var world; + // (function (world) { + // function foo() { } + // // TODO, blah + // })(world = hi.world || (hi.world = {})); + // })(hi = hello.hi || (hello.hi = {})); + // })(hello || (hello = {})); + // We only want to emit comment on the namespace which contains block body itself, not the containing namespaces. + if (body.kind !== 226 /* ModuleBlock */) { + ts.setEmitFlags(block, ts.getEmitFlags(block) | 49152 /* NoComments */); } - function parenthesizeForAccess(expr) { - // When diagnosing whether the expression needs parentheses, the decision should be based - // on the innermost expression in a chain of nested type assertions. - while (expr.kind === 177 /* TypeAssertionExpression */ || - expr.kind === 195 /* AsExpression */ || - expr.kind === 196 /* NonNullExpression */) { - expr = expr.expression; - } - // isLeftHandSideExpression is almost the correct criterion for when it is not necessary - // to parenthesize the expression before a dot. The known exceptions are: - // - // NewExpression: - // new C.x -> not the same as (new C).x - // NumberLiteral - // 1.x -> not the same as (1).x - // - if (ts.isLeftHandSideExpression(expr) && - expr.kind !== 175 /* NewExpression */ && - expr.kind !== 8 /* NumericLiteral */) { - return expr; - } - var node = ts.createSynthesizedNode(178 /* ParenthesizedExpression */); - node.expression = expr; - return node; + return block; + } + function getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration) { + if (moduleDeclaration.body.kind === 225 /* ModuleDeclaration */) { + var recursiveInnerModule = getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration.body); + return recursiveInnerModule || moduleDeclaration.body; } - function emitComputedPropertyName(node) { - write("["); - emitExpressionForPropertyName(node); - write("]"); + } + /** + * Determines whether to emit an import equals declaration. + * + * @param node The import equals declaration node. + */ + function shouldEmitImportEqualsDeclaration(node) { + // preserve old compiler's behavior: emit 'var' for import declaration (even if we do not consider them referenced) when + // - current file is not external module + // - import declaration is top level and target is value imported by entity name + return resolver.isReferencedAliasDeclaration(node) + || (!ts.isExternalModule(currentSourceFile) + && resolver.isTopLevelValueImportEqualsWithEntityName(node)); + } + /** + * Visits an import equals declaration. + * + * @param node The import equals declaration node. + */ + function visitImportEqualsDeclaration(node) { + if (ts.isExternalModuleImportEqualsDeclaration(node)) { + return ts.visitEachChild(node, visitor, context); } - function emitMethod(node) { - if (languageVersion >= 2 /* ES6 */ && node.asteriskToken) { - write("*"); - } - emit(node.name); - if (languageVersion < 2 /* ES6 */) { - write(": function "); - } - emitSignatureAndBody(node); + if (!shouldEmitImportEqualsDeclaration(node)) { + return undefined; } - function emitPropertyAssignment(node) { - emit(node.name); - write(": "); - // This is to ensure that we emit comment in the following case: - // For example: - // obj = { - // id: /*comment1*/ ()=>void - // } - // "comment1" is not considered to be leading comment for node.initializer - // but rather a trailing comment on the previous node. - emitTrailingCommentsOfPosition(node.initializer.pos); - emit(node.initializer); - } - // Return true if identifier resolves to an exported member of a namespace - function isExportReference(node) { - var container = resolver.getReferencedExportContainer(node); - return !!container; - } - // Return true if identifier resolves to an imported identifier - function isImportedReference(node) { - var declaration = resolver.getReferencedImportDeclaration(node); - return declaration && (declaration.kind === 231 /* ImportClause */ || declaration.kind === 234 /* ImportSpecifier */); + var moduleReference = ts.createExpressionFromEntityName(node.moduleReference); + ts.setEmitFlags(moduleReference, 49152 /* NoComments */ | 65536 /* NoNestedComments */); + if (isNamedExternalModuleExport(node) || !isNamespaceExport(node)) { + // export var ${name} = ${moduleReference}; + // var ${name} = ${moduleReference}; + return ts.setOriginalNode(ts.createVariableStatement(ts.visitNodes(node.modifiers, visitor, ts.isModifier), ts.createVariableDeclarationList([ + ts.createVariableDeclaration(node.name, + /*type*/ undefined, moduleReference) + ]), node), node); } - function emitShorthandPropertyAssignment(node) { - // The name property of a short-hand property assignment is considered an expression position, so here - // we manually emit the identifier to avoid rewriting. - writeTextOfNode(currentText, node.name); - // If emitting pre-ES6 code, or if the name requires rewriting when resolved as an expression identifier, - // we emit a normal property assignment. For example: - // module m { - // export let y; - // } - // module m { - // let obj = { y }; - // } - // Here we need to emit obj = { y : m.y } regardless of the output target. - // The same rules apply for imported identifiers when targeting module formats with indirect access to - // the imported identifiers. For example, when targeting CommonJS: - // - // import {foo} from './foo'; - // export const baz = { foo }; - // - // Must be transformed into: - // - // const foo_1 = require('./foo'); - // exports.baz = { foo: foo_1.foo }; - // - if (languageVersion < 2 /* ES6 */ || (modulekind !== ts.ModuleKind.ES6 && isImportedReference(node.name)) || isExportReference(node.name)) { - // Emit identifier as an identifier - write(": "); - emitExpressionIdentifier(node.name); - } - if (languageVersion >= 2 /* ES6 */ && node.objectAssignmentInitializer) { - write(" = "); - emit(node.objectAssignmentInitializer); - } + else { + // exports.${name} = ${moduleReference}; + return ts.setOriginalNode(createNamespaceExport(node.name, moduleReference, node), node); } - function tryEmitConstantValue(node) { - var constantValue = tryGetConstEnumValue(node); - if (constantValue !== undefined) { - write(constantValue.toString()); - if (!compilerOptions.removeComments) { - var propertyName = node.kind === 172 /* PropertyAccessExpression */ ? ts.declarationNameToString(node.name) : ts.getTextOfNode(node.argumentExpression); - write(" /* " + propertyName + " */"); - } - return true; - } - return false; + } + /** + * Gets a value indicating whether the node is exported from a namespace. + * + * @param node The node to test. + */ + function isNamespaceExport(node) { + return currentNamespace !== undefined && ts.hasModifier(node, 1 /* Export */); + } + /** + * Gets a value indicating whether the node is exported from an external module. + * + * @param node The node to test. + */ + function isExternalModuleExport(node) { + return currentNamespace === undefined && ts.hasModifier(node, 1 /* Export */); + } + /** + * Gets a value indicating whether the node is a named export from an external module. + * + * @param node The node to test. + */ + function isNamedExternalModuleExport(node) { + return isExternalModuleExport(node) + && !ts.hasModifier(node, 512 /* Default */); + } + /** + * Gets a value indicating whether the node is the default export of an external module. + * + * @param node The node to test. + */ + function isDefaultExternalModuleExport(node) { + return isExternalModuleExport(node) + && ts.hasModifier(node, 512 /* Default */); + } + /** + * Creates a statement for the provided expression. This is used in calls to `map`. + */ + function expressionToStatement(expression) { + return ts.createStatement(expression, /*location*/ undefined); + } + function addExportMemberAssignment(statements, node) { + var expression = ts.createAssignment(getExportName(node), getLocalName(node, /*noSourceMaps*/ true)); + ts.setSourceMapRange(expression, ts.createRange(node.name.pos, node.end)); + var statement = ts.createStatement(expression); + ts.setSourceMapRange(statement, ts.createRange(-1, node.end)); + statements.push(statement); + } + function createNamespaceExport(exportName, exportValue, location) { + return ts.createStatement(ts.createAssignment(getNamespaceMemberName(exportName, /*allowComments*/ false, /*allowSourceMaps*/ true), exportValue), location); + } + function createExternalModuleExport(exportName) { + return ts.createExportDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, ts.createNamedExports([ + ts.createExportSpecifier(exportName) + ])); + } + function getNamespaceMemberName(name, allowComments, allowSourceMaps) { + var qualifiedName = ts.createPropertyAccess(currentNamespaceContainerName, ts.getSynthesizedClone(name), /*location*/ name); + var emitFlags; + if (!allowComments) { + emitFlags |= 49152 /* NoComments */; } - function tryGetConstEnumValue(node) { - if (compilerOptions.isolatedModules) { - return undefined; - } - return node.kind === 172 /* PropertyAccessExpression */ || node.kind === 173 /* ElementAccessExpression */ - ? resolver.getConstantValue(node) - : undefined; + if (!allowSourceMaps) { + emitFlags |= 1536 /* NoSourceMap */; } - // Returns 'true' if the code was actually indented, false otherwise. - // If the code is not indented, an optional valueToWriteWhenNotIndenting will be - // emitted instead. - function indentIfOnDifferentLines(parent, node1, node2, valueToWriteWhenNotIndenting) { - var realNodesAreOnDifferentLines = !ts.nodeIsSynthesized(parent) && !nodeEndIsOnSameLineAsNodeStart(node1, node2); - // Always use a newline for synthesized code if the synthesizer desires it. - var synthesizedNodeIsOnDifferentLine = synthesizedNodeStartsOnNewLine(node2); - if (realNodesAreOnDifferentLines || synthesizedNodeIsOnDifferentLine) { - increaseIndent(); - writeLine(); - return true; - } - else { - if (valueToWriteWhenNotIndenting) { - write(valueToWriteWhenNotIndenting); - } - return false; - } + if (emitFlags) { + ts.setEmitFlags(qualifiedName, emitFlags); } - function emitPropertyAccess(node) { - if (tryEmitConstantValue(node)) { - return; - } - if (languageVersion === 2 /* ES6 */ && - node.expression.kind === 95 /* SuperKeyword */ && - isInAsyncMethodWithSuperInES6(node)) { - var name_30 = ts.createSynthesizedNode(9 /* StringLiteral */); - name_30.text = node.name.text; - emitSuperAccessInAsyncMethod(node.expression, name_30); - return; - } - emit(node.expression); - var dotRangeStart = ts.nodeIsSynthesized(node.expression) ? -1 : node.expression.end; - var dotRangeEnd = ts.nodeIsSynthesized(node.expression) ? -1 : ts.skipTrivia(currentText, node.expression.end) + 1; - var dotToken = { pos: dotRangeStart, end: dotRangeEnd }; - var indentedBeforeDot = indentIfOnDifferentLines(node, node.expression, dotToken); - // 1 .toString is a valid property access, emit a space after the literal - // Also emit a space if expression is a integer const enum value - it will appear in generated code as numeric literal - var shouldEmitSpace = false; - if (!indentedBeforeDot) { - if (node.expression.kind === 8 /* NumericLiteral */) { - // check if numeric literal was originally written with a dot - var text = ts.getTextOfNodeFromSourceText(currentText, node.expression); - shouldEmitSpace = text.indexOf(ts.tokenToString(21 /* DotToken */)) < 0; - } - else { - // check if constant enum value is integer - var constantValue = tryGetConstEnumValue(node.expression); - // isFinite handles cases when constantValue is undefined - shouldEmitSpace = isFinite(constantValue) && Math.floor(constantValue) === constantValue; - } + return qualifiedName; + } + function getNamespaceMemberNameWithSourceMapsAndWithoutComments(name) { + return getNamespaceMemberName(name, /*allowComments*/ false, /*allowSourceMaps*/ true); + } + /** + * Gets the declaration name used inside of a namespace or enum. + */ + function getNamespaceParameterName(node) { + var name = ts.getGeneratedNameForNode(node); + ts.setSourceMapRange(name, node.name); + return name; + } + /** + * Gets the expression used to refer to a namespace or enum within the body + * of its declaration. + */ + function getNamespaceContainerName(node) { + return ts.getGeneratedNameForNode(node); + } + /** + * Gets the local name for a declaration for use in expressions. + * + * A local name will *never* be prefixed with an module or namespace export modifier like + * "exports.". + * + * @param node The declaration. + * @param noSourceMaps A value indicating whether source maps may not be emitted for the name. + * @param allowComments A value indicating whether comments may be emitted for the name. + */ + function getLocalName(node, noSourceMaps, allowComments) { + return getDeclarationName(node, allowComments, !noSourceMaps, 262144 /* LocalName */); + } + /** + * Gets the export name for a declaration for use in expressions. + * + * An export name will *always* be prefixed with an module or namespace export modifier + * like "exports." if one is required. + * + * @param node The declaration. + * @param noSourceMaps A value indicating whether source maps may not be emitted for the name. + * @param allowComments A value indicating whether comments may be emitted for the name. + */ + function getExportName(node, noSourceMaps, allowComments) { + if (isNamespaceExport(node)) { + return getNamespaceMemberName(getDeclarationName(node), allowComments, !noSourceMaps); + } + return getDeclarationName(node, allowComments, !noSourceMaps, 131072 /* ExportName */); + } + /** + * Gets the name for a declaration for use in declarations. + * + * @param node The declaration. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + * @param emitFlags Additional NodeEmitFlags to specify for the name. + */ + function getDeclarationName(node, allowComments, allowSourceMaps, emitFlags) { + if (node.name) { + var name_32 = ts.getMutableClone(node.name); + emitFlags |= ts.getEmitFlags(node.name); + if (!allowSourceMaps) { + emitFlags |= 1536 /* NoSourceMap */; } - if (shouldEmitSpace) { - write(" ."); + if (!allowComments) { + emitFlags |= 49152 /* NoComments */; } - else { - write("."); + if (emitFlags) { + ts.setEmitFlags(name_32, emitFlags); } - var indentedAfterDot = indentIfOnDifferentLines(node, dotToken, node.name); - emit(node.name); - decreaseIndentIf(indentedBeforeDot, indentedAfterDot); + return name_32; } - function emitQualifiedName(node) { - emit(node.left); - write("."); - emit(node.right); + else { + return ts.getGeneratedNameForNode(node); + } + } + function getClassPrototype(node) { + return ts.createPropertyAccess(getDeclarationName(node), "prototype"); + } + function getClassMemberPrefix(node, member) { + return ts.hasModifier(member, 32 /* Static */) + ? getDeclarationName(node) + : getClassPrototype(node); + } + function enableSubstitutionForNonQualifiedEnumMembers() { + if ((enabledSubstitutions & 8 /* NonQualifiedEnumMembers */) === 0) { + enabledSubstitutions |= 8 /* NonQualifiedEnumMembers */; + context.enableSubstitution(69 /* Identifier */); + } + } + function enableSubstitutionForAsyncMethodsWithSuper() { + if ((enabledSubstitutions & 4 /* AsyncMethodsWithSuper */) === 0) { + enabledSubstitutions |= 4 /* AsyncMethodsWithSuper */; + // We need to enable substitutions for call, property access, and element access + // if we need to rewrite super calls. + context.enableSubstitution(174 /* CallExpression */); + context.enableSubstitution(172 /* PropertyAccessExpression */); + context.enableSubstitution(173 /* ElementAccessExpression */); + // We need to be notified when entering and exiting declarations that bind super. + context.enableEmitNotification(221 /* ClassDeclaration */); + context.enableEmitNotification(147 /* MethodDeclaration */); + context.enableEmitNotification(149 /* GetAccessor */); + context.enableEmitNotification(150 /* SetAccessor */); + context.enableEmitNotification(148 /* Constructor */); + } + } + function enableSubstitutionForClassAliases() { + if ((enabledSubstitutions & 1 /* ClassAliases */) === 0) { + enabledSubstitutions |= 1 /* ClassAliases */; + // We need to enable substitutions for identifiers. This allows us to + // substitute class names inside of a class declaration. + context.enableSubstitution(69 /* Identifier */); + // Keep track of class aliases. + classAliases = ts.createMap(); + } + } + function enableSubstitutionForNamespaceExports() { + if ((enabledSubstitutions & 2 /* NamespaceExports */) === 0) { + enabledSubstitutions |= 2 /* NamespaceExports */; + // We need to enable substitutions for identifiers and shorthand property assignments. This allows us to + // substitute the names of exported members of a namespace. + context.enableSubstitution(69 /* Identifier */); + context.enableSubstitution(254 /* ShorthandPropertyAssignment */); + // We need to be notified when entering and exiting namespaces. + context.enableEmitNotification(225 /* ModuleDeclaration */); + } + } + function isSuperContainer(node) { + var kind = node.kind; + return kind === 221 /* ClassDeclaration */ + || kind === 148 /* Constructor */ + || kind === 147 /* MethodDeclaration */ + || kind === 149 /* GetAccessor */ + || kind === 150 /* SetAccessor */; + } + function isTransformedModuleDeclaration(node) { + return ts.getOriginalNode(node).kind === 225 /* ModuleDeclaration */; + } + function isTransformedEnumDeclaration(node) { + return ts.getOriginalNode(node).kind === 224 /* EnumDeclaration */; + } + /** + * Hook for node emit. + * + * @param node The node to emit. + * @param emit A callback used to emit the node in the printer. + */ + function onEmitNode(emitContext, node, emitCallback) { + var savedApplicableSubstitutions = applicableSubstitutions; + var savedCurrentSuperContainer = currentSuperContainer; + // If we need to support substitutions for `super` in an async method, + // we should track it here. + if (enabledSubstitutions & 4 /* AsyncMethodsWithSuper */ && isSuperContainer(node)) { + currentSuperContainer = node; } - function emitQualifiedNameAsExpression(node, useFallback) { - if (node.left.kind === 69 /* Identifier */) { - emitEntityNameAsExpression(node.left, useFallback); - } - else if (useFallback) { - var temp = createAndRecordTempVariable(0 /* Auto */); - write("("); - emitNodeWithoutSourceMap(temp); - write(" = "); - emitEntityNameAsExpression(node.left, /*useFallback*/ true); - write(") && "); - emitNodeWithoutSourceMap(temp); - } - else { - emitEntityNameAsExpression(node.left, /*useFallback*/ false); - } - write("."); - emit(node.right); + if (enabledSubstitutions & 2 /* NamespaceExports */ && isTransformedModuleDeclaration(node)) { + applicableSubstitutions |= 2 /* NamespaceExports */; } - function emitEntityNameAsExpression(node, useFallback) { - switch (node.kind) { - case 69 /* Identifier */: - if (useFallback) { - write("typeof "); - emitExpressionIdentifier(node); - write(" !== 'undefined' && "); - } - emitExpressionIdentifier(node); - break; - case 139 /* QualifiedName */: - emitQualifiedNameAsExpression(node, useFallback); - break; - default: - emitNodeWithoutSourceMap(node); - break; - } + if (enabledSubstitutions & 8 /* NonQualifiedEnumMembers */ && isTransformedEnumDeclaration(node)) { + applicableSubstitutions |= 8 /* NonQualifiedEnumMembers */; } - function emitIndexedAccess(node) { - if (tryEmitConstantValue(node)) { - return; - } - if (languageVersion === 2 /* ES6 */ && - node.expression.kind === 95 /* SuperKeyword */ && - isInAsyncMethodWithSuperInES6(node)) { - emitSuperAccessInAsyncMethod(node.expression, node.argumentExpression); - return; - } - emit(node.expression); - write("["); - emit(node.argumentExpression); - write("]"); + previousOnEmitNode(emitContext, node, emitCallback); + applicableSubstitutions = savedApplicableSubstitutions; + currentSuperContainer = savedCurrentSuperContainer; + } + /** + * Hooks node substitutions. + * + * @param node The node to substitute. + * @param isExpression A value indicating whether the node is to be used in an expression + * position. + */ + function onSubstituteNode(emitContext, node) { + node = previousOnSubstituteNode(emitContext, node); + if (emitContext === 1 /* Expression */) { + return substituteExpression(node); } - function hasSpreadElement(elements) { - return ts.forEach(elements, function (e) { return e.kind === 191 /* SpreadElementExpression */; }); + else if (ts.isShorthandPropertyAssignment(node)) { + return substituteShorthandPropertyAssignment(node); } - function skipParentheses(node) { - while (node.kind === 178 /* ParenthesizedExpression */ || - node.kind === 177 /* TypeAssertionExpression */ || - node.kind === 195 /* AsExpression */ || - node.kind === 196 /* NonNullExpression */) { - node = node.expression; + return node; + } + function substituteShorthandPropertyAssignment(node) { + if (enabledSubstitutions & 2 /* NamespaceExports */) { + var name_33 = node.name; + var exportedName = trySubstituteNamespaceExportedName(name_33); + if (exportedName) { + // A shorthand property with an assignment initializer is probably part of a + // destructuring assignment + if (node.objectAssignmentInitializer) { + var initializer = ts.createAssignment(exportedName, node.objectAssignmentInitializer); + return ts.createPropertyAssignment(name_33, initializer, /*location*/ node); + } + return ts.createPropertyAssignment(name_33, exportedName, /*location*/ node); } - return node; } - function emitCallTarget(node) { - if (node.kind === 69 /* Identifier */ || node.kind === 97 /* ThisKeyword */ || node.kind === 95 /* SuperKeyword */) { - emit(node); - return node; - } - var temp = createAndRecordTempVariable(0 /* Auto */); - write("("); - emit(temp); - write(" = "); - emit(node); - write(")"); - return temp; - } - function emitCallWithSpread(node) { - var target; - var expr = skipParentheses(node.expression); - if (expr.kind === 172 /* PropertyAccessExpression */) { - // Target will be emitted as "this" argument - target = emitCallTarget(expr.expression); - write("."); - emit(expr.name); - } - else if (expr.kind === 173 /* ElementAccessExpression */) { - // Target will be emitted as "this" argument - target = emitCallTarget(expr.expression); - write("["); - emit(expr.argumentExpression); - write("]"); - } - else if (expr.kind === 95 /* SuperKeyword */) { - target = expr; - write("_super"); - } - else { - emit(node.expression); - } - write(".apply("); - if (target) { - if (target.kind === 95 /* SuperKeyword */) { - // Calls of form super(...) and super.foo(...) - emitThis(target); - } - else { - // Calls of form obj.foo(...) - emit(target); + return node; + } + function substituteExpression(node) { + switch (node.kind) { + case 69 /* Identifier */: + return substituteExpressionIdentifier(node); + case 172 /* PropertyAccessExpression */: + return substitutePropertyAccessExpression(node); + case 173 /* ElementAccessExpression */: + return substituteElementAccessExpression(node); + case 174 /* CallExpression */: + if (enabledSubstitutions & 4 /* AsyncMethodsWithSuper */) { + return substituteCallExpression(node); } - } - else { - // Calls of form foo(...) - write("void 0"); - } - write(", "); - emitListWithSpread(node.arguments, /*needsUniqueCopy*/ false, /*multiLine*/ false, /*trailingComma*/ false, /*useConcat*/ true); - write(")"); + break; } - function isInAsyncMethodWithSuperInES6(node) { - if (languageVersion === 2 /* ES6 */) { - var container = ts.getSuperContainer(node, /*includeFunctions*/ false); - if (container && resolver.getNodeCheckFlags(container) & (2048 /* AsyncMethodWithSuper */ | 4096 /* AsyncMethodWithSuperBinding */)) { - return true; + return node; + } + function substituteExpressionIdentifier(node) { + return trySubstituteClassAlias(node) + || trySubstituteNamespaceExportedName(node) + || node; + } + function trySubstituteClassAlias(node) { + if (enabledSubstitutions & 1 /* ClassAliases */) { + if (resolver.getNodeCheckFlags(node) & 16777216 /* ConstructorReferenceInClass */) { + // Due to the emit for class decorators, any reference to the class from inside of the class body + // must instead be rewritten to point to a temporary variable to avoid issues with the double-bind + // behavior of class names in ES6. + // Also, when emitting statics for class expressions, we must substitute a class alias for + // constructor references in static property initializers. + var declaration = resolver.getReferencedValueDeclaration(node); + if (declaration) { + var classAlias = classAliases[declaration.id]; + if (classAlias) { + var clone_4 = ts.getSynthesizedClone(classAlias); + ts.setSourceMapRange(clone_4, node); + ts.setCommentRange(clone_4, node); + return clone_4; + } } } - return false; } - function emitSuperAccessInAsyncMethod(superNode, argumentExpression) { - var container = ts.getSuperContainer(superNode, /*includeFunctions*/ false); - var isSuperBinding = resolver.getNodeCheckFlags(container) & 4096 /* AsyncMethodWithSuperBinding */; - write("_super("); - emit(argumentExpression); - write(isSuperBinding ? ").value" : ")"); - } - function emitCallExpression(node) { - if (languageVersion < 2 /* ES6 */ && hasSpreadElement(node.arguments)) { - emitCallWithSpread(node); - return; - } - var expression = node.expression; - var superCall = false; - var isAsyncMethodWithSuper = false; - if (expression.kind === 95 /* SuperKeyword */) { - emitSuper(expression); - superCall = true; - } - else { - superCall = ts.isSuperPropertyOrElementAccess(expression); - isAsyncMethodWithSuper = superCall && isInAsyncMethodWithSuperInES6(node); - emit(expression); - } - if (superCall && (languageVersion < 2 /* ES6 */ || isAsyncMethodWithSuper)) { - write(".call("); - emitThis(expression); - if (node.arguments.length) { - write(", "); - emitCommaList(node.arguments); + return undefined; + } + function trySubstituteNamespaceExportedName(node) { + // If this is explicitly a local name, do not substitute. + if (enabledSubstitutions & applicableSubstitutions && (ts.getEmitFlags(node) & 262144 /* LocalName */) === 0) { + // If we are nested within a namespace declaration, we may need to qualifiy + // an identifier that is exported from a merged namespace. + var container = resolver.getReferencedExportContainer(node, /*prefixLocals*/ false); + if (container) { + var substitute = (applicableSubstitutions & 2 /* NamespaceExports */ && container.kind === 225 /* ModuleDeclaration */) || + (applicableSubstitutions & 8 /* NonQualifiedEnumMembers */ && container.kind === 224 /* EnumDeclaration */); + if (substitute) { + return ts.createPropertyAccess(ts.getGeneratedNameForNode(container), node, /*location*/ node); } - write(")"); - } - else { - write("("); - emitCommaList(node.arguments); - write(")"); } } - function emitNewExpression(node) { - write("new "); - // Spread operator logic is supported in new expressions in ES5 using a combination - // of Function.prototype.bind() and Function.prototype.apply(). - // - // Example: - // - // var args = [1, 2, 3, 4, 5]; - // new Array(...args); - // - // is compiled into the following ES5: - // - // var args = [1, 2, 3, 4, 5]; - // new (Array.bind.apply(Array, [void 0].concat(args))); - // - // The 'thisArg' to 'bind' is ignored when invoking the result of 'bind' with 'new', - // Thus, we set it to undefined ('void 0'). - if (languageVersion === 1 /* ES5 */ && - node.arguments && - hasSpreadElement(node.arguments)) { - write("("); - var target = emitCallTarget(node.expression); - write(".bind.apply("); - emit(target); - write(", [void 0].concat("); - emitListWithSpread(node.arguments, /*needsUniqueCopy*/ false, /*multiLine*/ false, /*trailingComma*/ false, /*useConcat*/ false); - write(")))"); - write("()"); + return undefined; + } + function substituteCallExpression(node) { + var expression = node.expression; + if (ts.isSuperProperty(expression)) { + var flags = getSuperContainerAsyncMethodFlags(); + if (flags) { + var argumentExpression = ts.isPropertyAccessExpression(expression) + ? substitutePropertyAccessExpression(expression) + : substituteElementAccessExpression(expression); + return ts.createCall(ts.createPropertyAccess(argumentExpression, "call"), + /*typeArguments*/ undefined, [ + ts.createThis() + ].concat(node.arguments)); } - else { - emit(node.expression); - if (node.arguments) { - write("("); - emitCommaList(node.arguments); - write(")"); - } + } + return node; + } + function substitutePropertyAccessExpression(node) { + if (enabledSubstitutions & 4 /* AsyncMethodsWithSuper */ && node.expression.kind === 95 /* SuperKeyword */) { + var flags = getSuperContainerAsyncMethodFlags(); + if (flags) { + return createSuperAccessInAsyncMethod(ts.createLiteral(node.name.text), flags, node); } } - function emitTaggedTemplateExpression(node) { - if (languageVersion >= 2 /* ES6 */) { - emit(node.tag); - write(" "); - emit(node.template); + return substituteConstantValue(node); + } + function substituteElementAccessExpression(node) { + if (enabledSubstitutions & 4 /* AsyncMethodsWithSuper */ && node.expression.kind === 95 /* SuperKeyword */) { + var flags = getSuperContainerAsyncMethodFlags(); + if (flags) { + return createSuperAccessInAsyncMethod(node.argumentExpression, flags, node); } - else { - emitDownlevelTaggedTemplate(node); - } - } - function emitParenExpression(node) { - // If the node is synthesized, it means the emitter put the parentheses there, - // not the user. If we didn't want them, the emitter would not have put them - // there. - if (!ts.nodeIsSynthesized(node) && node.parent.kind !== 180 /* ArrowFunction */) { - if (node.expression.kind === 177 /* TypeAssertionExpression */ || - node.expression.kind === 195 /* AsExpression */ || - node.expression.kind === 196 /* NonNullExpression */) { - var operand = node.expression.expression; - // Make sure we consider all nested cast expressions, e.g.: - // (-A).x; - while (operand.kind === 177 /* TypeAssertionExpression */ || - operand.kind === 195 /* AsExpression */ || - operand.kind === 196 /* NonNullExpression */) { - operand = operand.expression; - } - // We have an expression of the form: (SubExpr) or (SubExpr as Type) - // Emitting this as (SubExpr) is really not desirable. We would like to emit the subexpr as is. - // Omitting the parentheses, however, could cause change in the semantics of the generated - // code if the casted expression has a lower precedence than the rest of the expression, e.g.: - // (new A).foo should be emitted as (new A).foo and not new A.foo - // (typeof A).toString() should be emitted as (typeof A).toString() and not typeof A.toString() - // new (A()) should be emitted as new (A()) and not new A() - // (function foo() { })() should be emitted as an IIF (function foo(){})() and not declaration function foo(){} () - if (operand.kind !== 185 /* PrefixUnaryExpression */ && - operand.kind !== 183 /* VoidExpression */ && - operand.kind !== 182 /* TypeOfExpression */ && - operand.kind !== 181 /* DeleteExpression */ && - operand.kind !== 186 /* PostfixUnaryExpression */ && - operand.kind !== 175 /* NewExpression */ && - !(operand.kind === 187 /* BinaryExpression */ && node.expression.kind === 195 /* AsExpression */) && - !(operand.kind === 174 /* CallExpression */ && node.parent.kind === 175 /* NewExpression */) && - !(operand.kind === 179 /* FunctionExpression */ && node.parent.kind === 174 /* CallExpression */) && - !(operand.kind === 8 /* NumericLiteral */ && node.parent.kind === 172 /* PropertyAccessExpression */)) { - emit(operand); - return; - } - } + } + return substituteConstantValue(node); + } + function substituteConstantValue(node) { + var constantValue = tryGetConstEnumValue(node); + if (constantValue !== undefined) { + var substitute = ts.createLiteral(constantValue); + ts.setSourceMapRange(substitute, node); + ts.setCommentRange(substitute, node); + if (!compilerOptions.removeComments) { + var propertyName = ts.isPropertyAccessExpression(node) + ? ts.declarationNameToString(node.name) + : ts.getTextOfNode(node.argumentExpression); + substitute.trailingComment = " " + propertyName + " "; } - write("("); - emit(node.expression); - write(")"); + ts.setConstantValue(node, constantValue); + return substitute; } - function emitDeleteExpression(node) { - write(ts.tokenToString(78 /* DeleteKeyword */)); - write(" "); - emit(node.expression); + return node; + } + function tryGetConstEnumValue(node) { + if (compilerOptions.isolatedModules) { + return undefined; } - function emitVoidExpression(node) { - write(ts.tokenToString(103 /* VoidKeyword */)); - write(" "); - emit(node.expression); + return ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node) + ? resolver.getConstantValue(node) + : undefined; + } + function createSuperAccessInAsyncMethod(argumentExpression, flags, location) { + if (flags & 4096 /* AsyncMethodWithSuperBinding */) { + return ts.createPropertyAccess(ts.createCall(ts.createIdentifier("_super"), + /*typeArguments*/ undefined, [argumentExpression]), "value", location); } - function emitTypeOfExpression(node) { - write(ts.tokenToString(101 /* TypeOfKeyword */)); - write(" "); - emit(node.expression); + else { + return ts.createCall(ts.createIdentifier("_super"), + /*typeArguments*/ undefined, [argumentExpression], location); } - function isNameOfExportedSourceLevelDeclarationInSystemExternalModule(node) { - if (!isCurrentFileSystemExternalModule() || node.kind !== 69 /* Identifier */ || ts.nodeIsSynthesized(node)) { - return false; - } - var isVariableDeclarationOrBindingElement = node.parent && (node.parent.kind === 218 /* VariableDeclaration */ || node.parent.kind === 169 /* BindingElement */); - var targetDeclaration = isVariableDeclarationOrBindingElement - ? node.parent - : resolver.getReferencedValueDeclaration(node); - return isSourceFileLevelDeclarationInSystemJsModule(targetDeclaration, /*isExported*/ true); + } + function getSuperContainerAsyncMethodFlags() { + return currentSuperContainer !== undefined + && resolver.getNodeCheckFlags(currentSuperContainer) & (2048 /* AsyncMethodWithSuper */ | 4096 /* AsyncMethodWithSuperBinding */); + } + } + ts.transformTypeScript = transformTypeScript; +})(ts || (ts = {})); +/// +/// +/*@internal*/ +var ts; +(function (ts) { + var entities = createEntitiesMap(); + function transformJsx(context) { + var compilerOptions = context.getCompilerOptions(); + var currentSourceFile; + return transformSourceFile; + /** + * Transform JSX-specific syntax in a SourceFile. + * + * @param node A SourceFile node. + */ + function transformSourceFile(node) { + if (ts.isDeclarationFile(node)) { + return node; } - function isNameOfExportedDeclarationInNonES6Module(node) { - if (modulekind === ts.ModuleKind.System || node.kind !== 69 /* Identifier */ || ts.nodeIsSynthesized(node)) { - return false; - } - return !exportEquals && exportSpecifiers && node.text in exportSpecifiers; - } - function emitPrefixUnaryExpression(node) { - var isPlusPlusOrMinusMinus = (node.operator === 41 /* PlusPlusToken */ - || node.operator === 42 /* MinusMinusToken */); - var externalExportChanged = isPlusPlusOrMinusMinus && - isNameOfExportedSourceLevelDeclarationInSystemExternalModule(node.operand); - if (externalExportChanged) { - // emit - // ++x - // as - // exports('x', ++x) - write(exportFunctionForFile + "(\""); - emitNodeWithoutSourceMap(node.operand); - write("\", "); - } - var internalExportChanged = isPlusPlusOrMinusMinus && - isNameOfExportedDeclarationInNonES6Module(node.operand); - if (internalExportChanged) { - emitAliasEqual(node.operand); - } - write(ts.tokenToString(node.operator)); - // In some cases, we need to emit a space between the operator and the operand. One obvious case - // is when the operator is an identifier, like delete or typeof. We also need to do this for plus - // and minus expressions in certain cases. Specifically, consider the following two cases (parens - // are just for clarity of exposition, and not part of the source code): - // - // (+(+1)) - // (+(++1)) - // - // We need to emit a space in both cases. In the first case, the absence of a space will make - // the resulting expression a prefix increment operation. And in the second, it will make the resulting - // expression a prefix increment whose operand is a plus expression - (++(+x)) - // The same is true of minus of course. - if (node.operand.kind === 185 /* PrefixUnaryExpression */) { - var operand = node.operand; - if (node.operator === 35 /* PlusToken */ && (operand.operator === 35 /* PlusToken */ || operand.operator === 41 /* PlusPlusToken */)) { - write(" "); - } - else if (node.operator === 36 /* MinusToken */ && (operand.operator === 36 /* MinusToken */ || operand.operator === 42 /* MinusMinusToken */)) { - write(" "); - } - } - emit(node.operand); - if (externalExportChanged) { - write(")"); - } - } - function emitPostfixUnaryExpression(node) { - var externalExportChanged = isNameOfExportedSourceLevelDeclarationInSystemExternalModule(node.operand); - var internalExportChanged = isNameOfExportedDeclarationInNonES6Module(node.operand); - if (externalExportChanged) { - // export function returns the value that was passes as the second argument - // however for postfix unary expressions result value should be the value before modification. - // emit 'x++' as '(export('x', ++x) - 1)' and 'x--' as '(export('x', --x) + 1)' - write("(" + exportFunctionForFile + "(\""); - emitNodeWithoutSourceMap(node.operand); - write("\", "); - write(ts.tokenToString(node.operator)); - emit(node.operand); - if (node.operator === 41 /* PlusPlusToken */) { - write(") - 1)"); - } - else { - write(") + 1)"); - } - } - else if (internalExportChanged) { - emitAliasEqual(node.operand); - emit(node.operand); - if (node.operator === 41 /* PlusPlusToken */) { - write(" += 1"); - } - else { - write(" -= 1"); - } - } - else { - emit(node.operand); - write(ts.tokenToString(node.operator)); - } + currentSourceFile = node; + node = ts.visitEachChild(node, visitor, context); + currentSourceFile = undefined; + return node; + } + function visitor(node) { + if (node.transformFlags & 4 /* Jsx */) { + return visitorWorker(node); } - function shouldHoistDeclarationInSystemJsModule(node) { - return isSourceFileLevelDeclarationInSystemJsModule(node, /*isExported*/ false); + else if (node.transformFlags & 8 /* ContainsJsx */) { + return ts.visitEachChild(node, visitor, context); } - /* - * Checks if given node is a source file level declaration (not nested in module/function). - * If 'isExported' is true - then declaration must also be exported. - * This function is used in two cases: - * - check if node is a exported source file level value to determine - * if we should also export the value after its it changed - * - check if node is a source level declaration to emit it differently, - * i.e non-exported variable statement 'var x = 1' is hoisted so - * when we emit variable statement 'var' should be dropped. - */ - function isSourceFileLevelDeclarationInSystemJsModule(node, isExported) { - if (!node || !isCurrentFileSystemExternalModule()) { - return false; - } - var current = ts.getRootDeclaration(node).parent; - while (current) { - if (current.kind === 256 /* SourceFile */) { - return !isExported || ((ts.getCombinedNodeFlags(node) & 1 /* Export */) !== 0); - } - else if (ts.isDeclaration(current)) { - return false; - } - else { - current = current.parent; - } - } + else { + return node; + } + } + function visitorWorker(node) { + switch (node.kind) { + case 241 /* JsxElement */: + return visitJsxElement(node, /*isChild*/ false); + case 242 /* JsxSelfClosingElement */: + return visitJsxSelfClosingElement(node, /*isChild*/ false); + case 248 /* JsxExpression */: + return visitJsxExpression(node); + default: + ts.Debug.failBadSyntaxKind(node); + return undefined; + } + } + function transformJsxChildToExpression(node) { + switch (node.kind) { + case 244 /* JsxText */: + return visitJsxText(node); + case 248 /* JsxExpression */: + return visitJsxExpression(node); + case 241 /* JsxElement */: + return visitJsxElement(node, /*isChild*/ true); + case 242 /* JsxSelfClosingElement */: + return visitJsxSelfClosingElement(node, /*isChild*/ true); + default: + ts.Debug.failBadSyntaxKind(node); + return undefined; } - /** - * Emit ES7 exponentiation operator downlevel using Math.pow - * @param node a binary expression node containing exponentiationOperator (**, **=) - */ - function emitExponentiationOperator(node) { - var leftHandSideExpression = node.left; - if (node.operatorToken.kind === 60 /* AsteriskAsteriskEqualsToken */) { - var synthesizedLHS = void 0; - var shouldEmitParentheses = false; - if (ts.isElementAccessExpression(leftHandSideExpression)) { - shouldEmitParentheses = true; - write("("); - synthesizedLHS = ts.createSynthesizedNode(173 /* ElementAccessExpression */, /*startsOnNewLine*/ false); - var identifier = emitTempVariableAssignment(leftHandSideExpression.expression, /*canDefineTempVariablesInPlace*/ false, /*shouldEmitCommaBeforeAssignment*/ false); - synthesizedLHS.expression = identifier; - if (leftHandSideExpression.argumentExpression.kind !== 8 /* NumericLiteral */ && - leftHandSideExpression.argumentExpression.kind !== 9 /* StringLiteral */) { - var tempArgumentExpression = createAndRecordTempVariable(268435456 /* _i */); - synthesizedLHS.argumentExpression = tempArgumentExpression; - emitAssignment(tempArgumentExpression, leftHandSideExpression.argumentExpression, /*shouldEmitCommaBeforeAssignment*/ true, leftHandSideExpression.expression); - } - else { - synthesizedLHS.argumentExpression = leftHandSideExpression.argumentExpression; - } - write(", "); - } - else if (ts.isPropertyAccessExpression(leftHandSideExpression)) { - shouldEmitParentheses = true; - write("("); - synthesizedLHS = ts.createSynthesizedNode(172 /* PropertyAccessExpression */, /*startsOnNewLine*/ false); - var identifier = emitTempVariableAssignment(leftHandSideExpression.expression, /*canDefineTempVariablesInPlace*/ false, /*shouldEmitCommaBeforeAssignment*/ false); - synthesizedLHS.expression = identifier; - synthesizedLHS.name = leftHandSideExpression.name; - write(", "); - } - emit(synthesizedLHS || leftHandSideExpression); - write(" = "); - write("Math.pow("); - emit(synthesizedLHS || leftHandSideExpression); - write(", "); - emit(node.right); - write(")"); - if (shouldEmitParentheses) { - write(")"); - } - } - else { - write("Math.pow("); - emit(leftHandSideExpression); - write(", "); - emit(node.right); - write(")"); - } + } + function visitJsxElement(node, isChild) { + return visitJsxOpeningLikeElement(node.openingElement, node.children, isChild, /*location*/ node); + } + function visitJsxSelfClosingElement(node, isChild) { + return visitJsxOpeningLikeElement(node, /*children*/ undefined, isChild, /*location*/ node); + } + function visitJsxOpeningLikeElement(node, children, isChild, location) { + var tagName = getTagName(node); + var objectProperties; + var attrs = node.attributes; + if (attrs.length === 0) { + // When there are no attributes, React wants "null" + objectProperties = ts.createNull(); } - function emitAliasEqual(name) { - for (var _a = 0, _b = exportSpecifiers[name.text]; _a < _b.length; _a++) { - var specifier = _b[_a]; - emitStart(specifier.name); - emitContainingModuleName(specifier); - if (languageVersion === 0 /* ES3 */ && name.text === "default") { - write('["default"]'); - } - else { - write("."); - emitNodeWithCommentsAndWithoutSourcemap(specifier.name); - } - emitEnd(specifier.name); - write(" = "); - } - return true; + else { + // Map spans of JsxAttribute nodes into object literals and spans + // of JsxSpreadAttribute nodes into expressions. + var segments = ts.flatten(ts.spanMap(attrs, ts.isJsxSpreadAttribute, function (attrs, isSpread) { return isSpread + ? ts.map(attrs, transformJsxSpreadAttributeToExpression) + : ts.createObjectLiteral(ts.map(attrs, transformJsxAttributeToObjectLiteralElement)); })); + if (ts.isJsxSpreadAttribute(attrs[0])) { + // We must always emit at least one object literal before a spread + // argument. + segments.unshift(ts.createObjectLiteral()); + } + // Either emit one big object literal (no spread attribs), or + // a call to the __assign helper. + objectProperties = ts.singleOrUndefined(segments) + || ts.createAssignHelper(currentSourceFile.externalHelpersModuleName, segments); + } + var element = ts.createReactCreateElement(compilerOptions.reactNamespace, tagName, objectProperties, ts.filter(ts.map(children, transformJsxChildToExpression), ts.isDefined), node, location); + if (isChild) { + ts.startOnNewLine(element); + } + return element; + } + function transformJsxSpreadAttributeToExpression(node) { + return ts.visitNode(node.expression, visitor, ts.isExpression); + } + function transformJsxAttributeToObjectLiteralElement(node) { + var name = getAttributeName(node); + var expression = transformJsxAttributeInitializer(node.initializer); + return ts.createPropertyAssignment(name, expression); + } + function transformJsxAttributeInitializer(node) { + if (node === undefined) { + return ts.createLiteral(true); + } + else if (node.kind === 9 /* StringLiteral */) { + var decoded = tryDecodeEntities(node.text); + return decoded ? ts.createLiteral(decoded, /*location*/ node) : node; + } + else if (node.kind === 248 /* JsxExpression */) { + return visitJsxExpression(node); } - function emitBinaryExpression(node) { - if (languageVersion < 2 /* ES6 */ && node.operatorToken.kind === 56 /* EqualsToken */ && - (node.left.kind === 171 /* ObjectLiteralExpression */ || node.left.kind === 170 /* ArrayLiteralExpression */)) { - emitDestructuring(node, node.parent.kind === 202 /* ExpressionStatement */); - } - else { - var isAssignment = ts.isAssignmentOperator(node.operatorToken.kind); - var externalExportChanged = isAssignment && - isNameOfExportedSourceLevelDeclarationInSystemExternalModule(node.left); - if (externalExportChanged) { - // emit assignment 'x y' as 'exports("x", x y)' - write(exportFunctionForFile + "(\""); - emitNodeWithoutSourceMap(node.left); - write("\", "); - } - var internalExportChanged = isAssignment && - isNameOfExportedDeclarationInNonES6Module(node.left); - if (internalExportChanged) { - // export { foo } - // emit foo = 2 as exports.foo = foo = 2 - emitAliasEqual(node.left); - } - if (node.operatorToken.kind === 38 /* AsteriskAsteriskToken */ || node.operatorToken.kind === 60 /* AsteriskAsteriskEqualsToken */) { - // Downleveled emit exponentiation operator using Math.pow - emitExponentiationOperator(node); - } - else { - emit(node.left); - // Add indentation before emit the operator if the operator is on different line - // For example: - // 3 - // + 2; - // emitted as - // 3 - // + 2; - var indentedBeforeOperator = indentIfOnDifferentLines(node, node.left, node.operatorToken, node.operatorToken.kind !== 24 /* CommaToken */ ? " " : undefined); - write(ts.tokenToString(node.operatorToken.kind)); - var indentedAfterOperator = indentIfOnDifferentLines(node, node.operatorToken, node.right, " "); - emit(node.right); - decreaseIndentIf(indentedBeforeOperator, indentedAfterOperator); + else { + ts.Debug.failBadSyntaxKind(node); + } + } + function visitJsxText(node) { + var text = ts.getTextOfNode(node, /*includeTrivia*/ true); + var parts; + var firstNonWhitespace = 0; + var lastNonWhitespace = -1; + // JSX trims whitespace at the end and beginning of lines, except that the + // start/end of a tag is considered a start/end of a line only if that line is + // on the same line as the closing tag. See examples in + // tests/cases/conformance/jsx/tsxReactEmitWhitespace.tsx + for (var i = 0; i < text.length; i++) { + var c = text.charCodeAt(i); + if (ts.isLineBreak(c)) { + if (firstNonWhitespace !== -1 && (lastNonWhitespace - firstNonWhitespace + 1 > 0)) { + var part = text.substr(firstNonWhitespace, lastNonWhitespace - firstNonWhitespace + 1); + if (!parts) { + parts = []; + } + // We do not escape the string here as that is handled by the printer + // when it emits the literal. We do, however, need to decode JSX entities. + parts.push(ts.createLiteral(decodeEntities(part))); } - if (externalExportChanged) { - write(")"); + firstNonWhitespace = -1; + } + else if (!ts.isWhiteSpace(c)) { + lastNonWhitespace = i; + if (firstNonWhitespace === -1) { + firstNonWhitespace = i; } } } - function synthesizedNodeStartsOnNewLine(node) { - return ts.nodeIsSynthesized(node) && node.startsOnNewLine; - } - function emitConditionalExpression(node) { - emit(node.condition); - var indentedBeforeQuestion = indentIfOnDifferentLines(node, node.condition, node.questionToken, " "); - write("?"); - var indentedAfterQuestion = indentIfOnDifferentLines(node, node.questionToken, node.whenTrue, " "); - emit(node.whenTrue); - decreaseIndentIf(indentedBeforeQuestion, indentedAfterQuestion); - var indentedBeforeColon = indentIfOnDifferentLines(node, node.whenTrue, node.colonToken, " "); - write(":"); - var indentedAfterColon = indentIfOnDifferentLines(node, node.colonToken, node.whenFalse, " "); - emit(node.whenFalse); - decreaseIndentIf(indentedBeforeColon, indentedAfterColon); - } - // Helper function to decrease the indent if we previously indented. Allows multiple - // previous indent values to be considered at a time. This also allows caller to just - // call this once, passing in all their appropriate indent values, instead of needing - // to call this helper function multiple times. - function decreaseIndentIf(value1, value2) { - if (value1) { - decreaseIndent(); - } - if (value2) { - decreaseIndent(); + if (firstNonWhitespace !== -1) { + var part = text.substr(firstNonWhitespace); + if (!parts) { + parts = []; } + // We do not escape the string here as that is handled by the printer + // when it emits the literal. We do, however, need to decode JSX entities. + parts.push(ts.createLiteral(decodeEntities(part))); } - function isSingleLineEmptyBlock(node) { - if (node && node.kind === 199 /* Block */) { - var block = node; - return block.statements.length === 0 && nodeEndIsOnSameLineAsNodeStart(block, block); - } + if (parts) { + return ts.reduceLeft(parts, aggregateJsxTextParts); } - function emitBlock(node) { - if (isSingleLineEmptyBlock(node)) { - emitToken(15 /* OpenBraceToken */, node.pos); - write(" "); - emitToken(16 /* CloseBraceToken */, node.statements.end); - return; + return undefined; + } + /** + * Aggregates two expressions by interpolating them with a whitespace literal. + */ + function aggregateJsxTextParts(left, right) { + return ts.createAdd(ts.createAdd(left, ts.createLiteral(" ")), right); + } + /** + * Replace entities like " ", "{", and "�" with the characters they encode. + * See https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references + */ + function decodeEntities(text) { + return text.replace(/&((#((\d+)|x([\da-fA-F]+)))|(\w+));/g, function (match, _all, _number, _digits, decimal, hex, word) { + if (decimal) { + return String.fromCharCode(parseInt(decimal, 10)); } - emitToken(15 /* OpenBraceToken */, node.pos); - increaseIndent(); - if (node.kind === 226 /* ModuleBlock */) { - ts.Debug.assert(node.parent.kind === 225 /* ModuleDeclaration */); - emitCaptureThisForNodeIfNecessary(node.parent); + else if (hex) { + return String.fromCharCode(parseInt(hex, 16)); } - emitLines(node.statements); - if (node.kind === 226 /* ModuleBlock */) { - emitTempDeclarations(/*newLine*/ true); + else { + var ch = entities[word]; + // If this is not a valid entity, then just use `match` (replace it with itself, i.e. don't replace) + return ch ? String.fromCharCode(ch) : match; } - decreaseIndent(); - writeLine(); - emitToken(16 /* CloseBraceToken */, node.statements.end); + }); + } + /** Like `decodeEntities` but returns `undefined` if there were no entities to decode. */ + function tryDecodeEntities(text) { + var decoded = decodeEntities(text); + return decoded === text ? undefined : decoded; + } + function getTagName(node) { + if (node.kind === 241 /* JsxElement */) { + return getTagName(node.openingElement); } - function emitEmbeddedStatement(node) { - if (node.kind === 199 /* Block */) { - write(" "); - emit(node); + else { + var name_34 = node.tagName; + if (ts.isIdentifier(name_34) && ts.isIntrinsicJsxName(name_34.text)) { + return ts.createLiteral(name_34.text); } else { - increaseIndent(); - writeLine(); - emit(node); - decreaseIndent(); + return ts.createExpressionFromEntityName(name_34); } } - function emitExpressionStatement(node) { - emitParenthesizedIf(node.expression, /*parenthesized*/ node.expression.kind === 180 /* ArrowFunction */); - write(";"); + } + /** + * Emit an attribute name, which is quoted if it needs to be quoted. Because + * these emit into an object literal property name, we don't need to be worried + * about keywords, just non-identifier characters + */ + function getAttributeName(node) { + var name = node.name; + if (/^[A-Za-z_]\w*$/.test(name.text)) { + return name; } - function emitIfStatement(node) { - var endPos = emitToken(88 /* IfKeyword */, node.pos); - write(" "); - endPos = emitToken(17 /* OpenParenToken */, endPos); - emit(node.expression); - emitToken(18 /* CloseParenToken */, node.expression.end); - emitEmbeddedStatement(node.thenStatement); - if (node.elseStatement) { - writeLine(); - emitToken(80 /* ElseKeyword */, node.thenStatement.end); - if (node.elseStatement.kind === 203 /* IfStatement */) { - write(" "); - emit(node.elseStatement); - } - else { - emitEmbeddedStatement(node.elseStatement); - } - } + else { + return ts.createLiteral(name.text); + } + } + function visitJsxExpression(node) { + return ts.visitNode(node.expression, visitor, ts.isExpression); + } + } + ts.transformJsx = transformJsx; + function createEntitiesMap() { + return ts.createMap({ + "quot": 0x0022, + "amp": 0x0026, + "apos": 0x0027, + "lt": 0x003C, + "gt": 0x003E, + "nbsp": 0x00A0, + "iexcl": 0x00A1, + "cent": 0x00A2, + "pound": 0x00A3, + "curren": 0x00A4, + "yen": 0x00A5, + "brvbar": 0x00A6, + "sect": 0x00A7, + "uml": 0x00A8, + "copy": 0x00A9, + "ordf": 0x00AA, + "laquo": 0x00AB, + "not": 0x00AC, + "shy": 0x00AD, + "reg": 0x00AE, + "macr": 0x00AF, + "deg": 0x00B0, + "plusmn": 0x00B1, + "sup2": 0x00B2, + "sup3": 0x00B3, + "acute": 0x00B4, + "micro": 0x00B5, + "para": 0x00B6, + "middot": 0x00B7, + "cedil": 0x00B8, + "sup1": 0x00B9, + "ordm": 0x00BA, + "raquo": 0x00BB, + "frac14": 0x00BC, + "frac12": 0x00BD, + "frac34": 0x00BE, + "iquest": 0x00BF, + "Agrave": 0x00C0, + "Aacute": 0x00C1, + "Acirc": 0x00C2, + "Atilde": 0x00C3, + "Auml": 0x00C4, + "Aring": 0x00C5, + "AElig": 0x00C6, + "Ccedil": 0x00C7, + "Egrave": 0x00C8, + "Eacute": 0x00C9, + "Ecirc": 0x00CA, + "Euml": 0x00CB, + "Igrave": 0x00CC, + "Iacute": 0x00CD, + "Icirc": 0x00CE, + "Iuml": 0x00CF, + "ETH": 0x00D0, + "Ntilde": 0x00D1, + "Ograve": 0x00D2, + "Oacute": 0x00D3, + "Ocirc": 0x00D4, + "Otilde": 0x00D5, + "Ouml": 0x00D6, + "times": 0x00D7, + "Oslash": 0x00D8, + "Ugrave": 0x00D9, + "Uacute": 0x00DA, + "Ucirc": 0x00DB, + "Uuml": 0x00DC, + "Yacute": 0x00DD, + "THORN": 0x00DE, + "szlig": 0x00DF, + "agrave": 0x00E0, + "aacute": 0x00E1, + "acirc": 0x00E2, + "atilde": 0x00E3, + "auml": 0x00E4, + "aring": 0x00E5, + "aelig": 0x00E6, + "ccedil": 0x00E7, + "egrave": 0x00E8, + "eacute": 0x00E9, + "ecirc": 0x00EA, + "euml": 0x00EB, + "igrave": 0x00EC, + "iacute": 0x00ED, + "icirc": 0x00EE, + "iuml": 0x00EF, + "eth": 0x00F0, + "ntilde": 0x00F1, + "ograve": 0x00F2, + "oacute": 0x00F3, + "ocirc": 0x00F4, + "otilde": 0x00F5, + "ouml": 0x00F6, + "divide": 0x00F7, + "oslash": 0x00F8, + "ugrave": 0x00F9, + "uacute": 0x00FA, + "ucirc": 0x00FB, + "uuml": 0x00FC, + "yacute": 0x00FD, + "thorn": 0x00FE, + "yuml": 0x00FF, + "OElig": 0x0152, + "oelig": 0x0153, + "Scaron": 0x0160, + "scaron": 0x0161, + "Yuml": 0x0178, + "fnof": 0x0192, + "circ": 0x02C6, + "tilde": 0x02DC, + "Alpha": 0x0391, + "Beta": 0x0392, + "Gamma": 0x0393, + "Delta": 0x0394, + "Epsilon": 0x0395, + "Zeta": 0x0396, + "Eta": 0x0397, + "Theta": 0x0398, + "Iota": 0x0399, + "Kappa": 0x039A, + "Lambda": 0x039B, + "Mu": 0x039C, + "Nu": 0x039D, + "Xi": 0x039E, + "Omicron": 0x039F, + "Pi": 0x03A0, + "Rho": 0x03A1, + "Sigma": 0x03A3, + "Tau": 0x03A4, + "Upsilon": 0x03A5, + "Phi": 0x03A6, + "Chi": 0x03A7, + "Psi": 0x03A8, + "Omega": 0x03A9, + "alpha": 0x03B1, + "beta": 0x03B2, + "gamma": 0x03B3, + "delta": 0x03B4, + "epsilon": 0x03B5, + "zeta": 0x03B6, + "eta": 0x03B7, + "theta": 0x03B8, + "iota": 0x03B9, + "kappa": 0x03BA, + "lambda": 0x03BB, + "mu": 0x03BC, + "nu": 0x03BD, + "xi": 0x03BE, + "omicron": 0x03BF, + "pi": 0x03C0, + "rho": 0x03C1, + "sigmaf": 0x03C2, + "sigma": 0x03C3, + "tau": 0x03C4, + "upsilon": 0x03C5, + "phi": 0x03C6, + "chi": 0x03C7, + "psi": 0x03C8, + "omega": 0x03C9, + "thetasym": 0x03D1, + "upsih": 0x03D2, + "piv": 0x03D6, + "ensp": 0x2002, + "emsp": 0x2003, + "thinsp": 0x2009, + "zwnj": 0x200C, + "zwj": 0x200D, + "lrm": 0x200E, + "rlm": 0x200F, + "ndash": 0x2013, + "mdash": 0x2014, + "lsquo": 0x2018, + "rsquo": 0x2019, + "sbquo": 0x201A, + "ldquo": 0x201C, + "rdquo": 0x201D, + "bdquo": 0x201E, + "dagger": 0x2020, + "Dagger": 0x2021, + "bull": 0x2022, + "hellip": 0x2026, + "permil": 0x2030, + "prime": 0x2032, + "Prime": 0x2033, + "lsaquo": 0x2039, + "rsaquo": 0x203A, + "oline": 0x203E, + "frasl": 0x2044, + "euro": 0x20AC, + "image": 0x2111, + "weierp": 0x2118, + "real": 0x211C, + "trade": 0x2122, + "alefsym": 0x2135, + "larr": 0x2190, + "uarr": 0x2191, + "rarr": 0x2192, + "darr": 0x2193, + "harr": 0x2194, + "crarr": 0x21B5, + "lArr": 0x21D0, + "uArr": 0x21D1, + "rArr": 0x21D2, + "dArr": 0x21D3, + "hArr": 0x21D4, + "forall": 0x2200, + "part": 0x2202, + "exist": 0x2203, + "empty": 0x2205, + "nabla": 0x2207, + "isin": 0x2208, + "notin": 0x2209, + "ni": 0x220B, + "prod": 0x220F, + "sum": 0x2211, + "minus": 0x2212, + "lowast": 0x2217, + "radic": 0x221A, + "prop": 0x221D, + "infin": 0x221E, + "ang": 0x2220, + "and": 0x2227, + "or": 0x2228, + "cap": 0x2229, + "cup": 0x222A, + "int": 0x222B, + "there4": 0x2234, + "sim": 0x223C, + "cong": 0x2245, + "asymp": 0x2248, + "ne": 0x2260, + "equiv": 0x2261, + "le": 0x2264, + "ge": 0x2265, + "sub": 0x2282, + "sup": 0x2283, + "nsub": 0x2284, + "sube": 0x2286, + "supe": 0x2287, + "oplus": 0x2295, + "otimes": 0x2297, + "perp": 0x22A5, + "sdot": 0x22C5, + "lceil": 0x2308, + "rceil": 0x2309, + "lfloor": 0x230A, + "rfloor": 0x230B, + "lang": 0x2329, + "rang": 0x232A, + "loz": 0x25CA, + "spades": 0x2660, + "clubs": 0x2663, + "hearts": 0x2665, + "diams": 0x2666 + }); + } +})(ts || (ts = {})); +/// +/// +/*@internal*/ +var ts; +(function (ts) { + function transformES7(context) { + var hoistVariableDeclaration = context.hoistVariableDeclaration; + return transformSourceFile; + function transformSourceFile(node) { + if (ts.isDeclarationFile(node)) { + return node; } - function emitDoStatement(node) { - emitLoop(node, emitDoStatementWorker); + return ts.visitEachChild(node, visitor, context); + } + function visitor(node) { + if (node.transformFlags & 16 /* ES7 */) { + return visitorWorker(node); } - function emitDoStatementWorker(node, loop) { - write("do"); - if (loop) { - emitConvertedLoopCall(loop, /*emitAsBlock*/ true); - } - else { - emitNormalLoopBody(node, /*emitAsEmbeddedStatement*/ true); - } - if (node.statement.kind === 199 /* Block */) { - write(" "); - } - else { - writeLine(); - } - write("while ("); - emit(node.expression); - write(");"); + else if (node.transformFlags & 32 /* ContainsES7 */) { + return ts.visitEachChild(node, visitor, context); } - function emitWhileStatement(node) { - emitLoop(node, emitWhileStatementWorker); + else { + return node; } - function emitWhileStatementWorker(node, loop) { - write("while ("); - emit(node.expression); - write(")"); - if (loop) { - emitConvertedLoopCall(loop, /*emitAsBlock*/ true); + } + function visitorWorker(node) { + switch (node.kind) { + case 187 /* BinaryExpression */: + return visitBinaryExpression(node); + default: + ts.Debug.failBadSyntaxKind(node); + return ts.visitEachChild(node, visitor, context); + } + } + function visitBinaryExpression(node) { + // We are here because ES7 adds support for the exponentiation operator. + var left = ts.visitNode(node.left, visitor, ts.isExpression); + var right = ts.visitNode(node.right, visitor, ts.isExpression); + if (node.operatorToken.kind === 60 /* AsteriskAsteriskEqualsToken */) { + var target = void 0; + var value = void 0; + if (ts.isElementAccessExpression(left)) { + // Transforms `a[x] **= b` into `(_a = a)[_x = x] = Math.pow(_a[_x], b)` + var expressionTemp = ts.createTempVariable(hoistVariableDeclaration); + var argumentExpressionTemp = ts.createTempVariable(hoistVariableDeclaration); + target = ts.createElementAccess(ts.createAssignment(expressionTemp, left.expression, /*location*/ left.expression), ts.createAssignment(argumentExpressionTemp, left.argumentExpression, /*location*/ left.argumentExpression), + /*location*/ left); + value = ts.createElementAccess(expressionTemp, argumentExpressionTemp, + /*location*/ left); + } + else if (ts.isPropertyAccessExpression(left)) { + // Transforms `a.x **= b` into `(_a = a).x = Math.pow(_a.x, b)` + var expressionTemp = ts.createTempVariable(hoistVariableDeclaration); + target = ts.createPropertyAccess(ts.createAssignment(expressionTemp, left.expression, /*location*/ left.expression), left.name, + /*location*/ left); + value = ts.createPropertyAccess(expressionTemp, left.name, + /*location*/ left); } else { - emitNormalLoopBody(node, /*emitAsEmbeddedStatement*/ true); + // Transforms `a **= b` into `a = Math.pow(a, b)` + target = left; + value = left; } + return ts.createAssignment(target, ts.createMathPow(value, right, /*location*/ node), /*location*/ node); } - /** - * Returns true if start of variable declaration list was emitted. - * Returns false if nothing was written - this can happen for source file level variable declarations - * in system modules where such variable declarations are hoisted. - */ - function tryEmitStartOfVariableDeclarationList(decl) { - if (shouldHoistVariable(decl, /*checkIfSourceFileLevelDecl*/ true)) { - // variables in variable declaration list were already hoisted - return false; - } - if (convertedLoopState && (ts.getCombinedNodeFlags(decl) & 3072 /* BlockScoped */) === 0) { - // we are inside a converted loop - this can only happen in downlevel scenarios - // record names for all variable declarations - for (var _a = 0, _b = decl.declarations; _a < _b.length; _a++) { - var varDecl = _b[_a]; - hoistVariableDeclarationFromLoop(convertedLoopState, varDecl); - } - return false; + else if (node.operatorToken.kind === 38 /* AsteriskAsteriskToken */) { + // Transforms `a ** b` into `Math.pow(a, b)` + return ts.createMathPow(left, right, /*location*/ node); + } + else { + ts.Debug.failBadSyntaxKind(node); + return ts.visitEachChild(node, visitor, context); + } + } + } + ts.transformES7 = transformES7; +})(ts || (ts = {})); +/// +/// +/*@internal*/ +var ts; +(function (ts) { + var ES6SubstitutionFlags; + (function (ES6SubstitutionFlags) { + /** Enables substitutions for captured `this` */ + ES6SubstitutionFlags[ES6SubstitutionFlags["CapturedThis"] = 1] = "CapturedThis"; + /** Enables substitutions for block-scoped bindings. */ + ES6SubstitutionFlags[ES6SubstitutionFlags["BlockScopedBindings"] = 2] = "BlockScopedBindings"; + })(ES6SubstitutionFlags || (ES6SubstitutionFlags = {})); + var CopyDirection; + (function (CopyDirection) { + CopyDirection[CopyDirection["ToOriginal"] = 0] = "ToOriginal"; + CopyDirection[CopyDirection["ToOutParameter"] = 1] = "ToOutParameter"; + })(CopyDirection || (CopyDirection = {})); + var Jump; + (function (Jump) { + Jump[Jump["Break"] = 2] = "Break"; + Jump[Jump["Continue"] = 4] = "Continue"; + Jump[Jump["Return"] = 8] = "Return"; + })(Jump || (Jump = {})); + var SuperCaptureResult; + (function (SuperCaptureResult) { + /** + * A capture may have been added for calls to 'super', but + * the caller should emit subsequent statements normally. + */ + SuperCaptureResult[SuperCaptureResult["NoReplacement"] = 0] = "NoReplacement"; + /** + * A call to 'super()' got replaced with a capturing statement like: + * + * var _this = _super.call(...) || this; + * + * Callers should skip the current statement. + */ + SuperCaptureResult[SuperCaptureResult["ReplaceSuperCapture"] = 1] = "ReplaceSuperCapture"; + /** + * A call to 'super()' got replaced with a capturing statement like: + * + * return _super.call(...) || this; + * + * Callers should skip the current statement and avoid any returns of '_this'. + */ + SuperCaptureResult[SuperCaptureResult["ReplaceWithReturn"] = 2] = "ReplaceWithReturn"; + })(SuperCaptureResult || (SuperCaptureResult = {})); + function transformES6(context) { + var startLexicalEnvironment = context.startLexicalEnvironment, endLexicalEnvironment = context.endLexicalEnvironment, hoistVariableDeclaration = context.hoistVariableDeclaration; + var resolver = context.getEmitResolver(); + var previousOnSubstituteNode = context.onSubstituteNode; + var previousOnEmitNode = context.onEmitNode; + context.onEmitNode = onEmitNode; + context.onSubstituteNode = onSubstituteNode; + var currentSourceFile; + var currentText; + var currentParent; + var currentNode; + var enclosingVariableStatement; + var enclosingBlockScopeContainer; + var enclosingBlockScopeContainerParent; + var enclosingFunction; + var enclosingNonArrowFunction; + var enclosingNonAsyncFunctionBody; + /** + * Used to track if we are emitting body of the converted loop + */ + var convertedLoopState; + /** + * Keeps track of whether substitutions have been enabled for specific cases. + * They are persisted between each SourceFile transformation and should not + * be reset. + */ + var enabledSubstitutions; + return transformSourceFile; + function transformSourceFile(node) { + if (ts.isDeclarationFile(node)) { + return node; + } + currentSourceFile = node; + currentText = node.text; + return ts.visitNode(node, visitor, ts.isSourceFile); + } + function visitor(node) { + return saveStateAndInvoke(node, dispatcher); + } + function dispatcher(node) { + return convertedLoopState + ? visitorForConvertedLoopWorker(node) + : visitorWorker(node); + } + function saveStateAndInvoke(node, f) { + var savedEnclosingFunction = enclosingFunction; + var savedEnclosingNonArrowFunction = enclosingNonArrowFunction; + var savedEnclosingNonAsyncFunctionBody = enclosingNonAsyncFunctionBody; + var savedEnclosingBlockScopeContainer = enclosingBlockScopeContainer; + var savedEnclosingBlockScopeContainerParent = enclosingBlockScopeContainerParent; + var savedEnclosingVariableStatement = enclosingVariableStatement; + var savedCurrentParent = currentParent; + var savedCurrentNode = currentNode; + var savedConvertedLoopState = convertedLoopState; + if (ts.nodeStartsNewLexicalEnvironment(node)) { + // don't treat content of nodes that start new lexical environment as part of converted loop copy + convertedLoopState = undefined; + } + onBeforeVisitNode(node); + var visited = f(node); + convertedLoopState = savedConvertedLoopState; + enclosingFunction = savedEnclosingFunction; + enclosingNonArrowFunction = savedEnclosingNonArrowFunction; + enclosingNonAsyncFunctionBody = savedEnclosingNonAsyncFunctionBody; + enclosingBlockScopeContainer = savedEnclosingBlockScopeContainer; + enclosingBlockScopeContainerParent = savedEnclosingBlockScopeContainerParent; + enclosingVariableStatement = savedEnclosingVariableStatement; + currentParent = savedCurrentParent; + currentNode = savedCurrentNode; + return visited; + } + function shouldCheckNode(node) { + return (node.transformFlags & 64 /* ES6 */) !== 0 || + node.kind === 214 /* LabeledStatement */ || + (ts.isIterationStatement(node, /*lookInLabeledStatements*/ false) && shouldConvertIterationStatementBody(node)); + } + function visitorWorker(node) { + if (shouldCheckNode(node)) { + return visitJavaScript(node); + } + else if (node.transformFlags & 128 /* ContainsES6 */) { + return ts.visitEachChild(node, visitor, context); + } + else { + return node; + } + } + function visitorForConvertedLoopWorker(node) { + var result; + if (shouldCheckNode(node)) { + result = visitJavaScript(node); + } + else { + result = visitNodesInConvertedLoop(node); + } + return result; + } + function visitNodesInConvertedLoop(node) { + switch (node.kind) { + case 211 /* ReturnStatement */: + return visitReturnStatement(node); + case 200 /* VariableStatement */: + return visitVariableStatement(node); + case 213 /* SwitchStatement */: + return visitSwitchStatement(node); + case 210 /* BreakStatement */: + case 209 /* ContinueStatement */: + return visitBreakOrContinueStatement(node); + case 97 /* ThisKeyword */: + return visitThisKeyword(node); + case 69 /* Identifier */: + return visitIdentifier(node); + default: + return ts.visitEachChild(node, visitor, context); + } + } + function visitJavaScript(node) { + switch (node.kind) { + case 82 /* ExportKeyword */: + return node; + case 221 /* ClassDeclaration */: + return visitClassDeclaration(node); + case 192 /* ClassExpression */: + return visitClassExpression(node); + case 142 /* Parameter */: + return visitParameter(node); + case 220 /* FunctionDeclaration */: + return visitFunctionDeclaration(node); + case 180 /* ArrowFunction */: + return visitArrowFunction(node); + case 179 /* FunctionExpression */: + return visitFunctionExpression(node); + case 218 /* VariableDeclaration */: + return visitVariableDeclaration(node); + case 69 /* Identifier */: + return visitIdentifier(node); + case 219 /* VariableDeclarationList */: + return visitVariableDeclarationList(node); + case 214 /* LabeledStatement */: + return visitLabeledStatement(node); + case 204 /* DoStatement */: + return visitDoStatement(node); + case 205 /* WhileStatement */: + return visitWhileStatement(node); + case 206 /* ForStatement */: + return visitForStatement(node); + case 207 /* ForInStatement */: + return visitForInStatement(node); + case 208 /* ForOfStatement */: + return visitForOfStatement(node); + case 202 /* ExpressionStatement */: + return visitExpressionStatement(node); + case 171 /* ObjectLiteralExpression */: + return visitObjectLiteralExpression(node); + case 254 /* ShorthandPropertyAssignment */: + return visitShorthandPropertyAssignment(node); + case 170 /* ArrayLiteralExpression */: + return visitArrayLiteralExpression(node); + case 174 /* CallExpression */: + return visitCallExpression(node); + case 175 /* NewExpression */: + return visitNewExpression(node); + case 178 /* ParenthesizedExpression */: + return visitParenthesizedExpression(node, /*needsDestructuringValue*/ true); + case 187 /* BinaryExpression */: + return visitBinaryExpression(node, /*needsDestructuringValue*/ true); + case 11 /* NoSubstitutionTemplateLiteral */: + case 12 /* TemplateHead */: + case 13 /* TemplateMiddle */: + case 14 /* TemplateTail */: + return visitTemplateLiteral(node); + case 176 /* TaggedTemplateExpression */: + return visitTaggedTemplateExpression(node); + case 189 /* TemplateExpression */: + return visitTemplateExpression(node); + case 190 /* YieldExpression */: + return visitYieldExpression(node); + case 95 /* SuperKeyword */: + return visitSuperKeyword(node); + case 190 /* YieldExpression */: + // `yield` will be handled by a generators transform. + return ts.visitEachChild(node, visitor, context); + case 147 /* MethodDeclaration */: + return visitMethodDeclaration(node); + case 256 /* SourceFile */: + return visitSourceFileNode(node); + case 200 /* VariableStatement */: + return visitVariableStatement(node); + default: + ts.Debug.failBadSyntaxKind(node); + return ts.visitEachChild(node, visitor, context); + } + } + function onBeforeVisitNode(node) { + if (currentNode) { + if (ts.isBlockScope(currentNode, currentParent)) { + enclosingBlockScopeContainer = currentNode; + enclosingBlockScopeContainerParent = currentParent; } - emitStart(decl); - if (decl && languageVersion >= 2 /* ES6 */) { - if (ts.isLet(decl)) { - write("let "); - } - else if (ts.isConst(decl)) { - write("const "); - } - else { - write("var "); + if (ts.isFunctionLike(currentNode)) { + enclosingFunction = currentNode; + if (currentNode.kind !== 180 /* ArrowFunction */) { + enclosingNonArrowFunction = currentNode; + if (!(ts.getEmitFlags(currentNode) & 2097152 /* AsyncFunctionBody */)) { + enclosingNonAsyncFunctionBody = currentNode; + } } } - else { - write("var "); + // keep track of the enclosing variable statement when in the context of + // variable statements, variable declarations, binding elements, and binding + // patterns. + switch (currentNode.kind) { + case 200 /* VariableStatement */: + enclosingVariableStatement = currentNode; + break; + case 219 /* VariableDeclarationList */: + case 218 /* VariableDeclaration */: + case 169 /* BindingElement */: + case 167 /* ObjectBindingPattern */: + case 168 /* ArrayBindingPattern */: + break; + default: + enclosingVariableStatement = undefined; } - // Note here we specifically dont emit end so that if we are going to emit binding pattern - // we can alter the source map correctly - return true; } - function emitVariableDeclarationListSkippingUninitializedEntries(list) { - var started = false; - for (var _a = 0, _b = list.declarations; _a < _b.length; _a++) { - var decl = _b[_a]; - if (!decl.initializer) { - continue; - } - if (!started) { - started = true; - } - else { - write(", "); - } - emit(decl); - } - return started; + currentParent = currentNode; + currentNode = node; + } + function visitSwitchStatement(node) { + ts.Debug.assert(convertedLoopState !== undefined); + var savedAllowedNonLabeledJumps = convertedLoopState.allowedNonLabeledJumps; + // for switch statement allow only non-labeled break + convertedLoopState.allowedNonLabeledJumps |= 2 /* Break */; + var result = ts.visitEachChild(node, visitor, context); + convertedLoopState.allowedNonLabeledJumps = savedAllowedNonLabeledJumps; + return result; + } + function visitReturnStatement(node) { + ts.Debug.assert(convertedLoopState !== undefined); + convertedLoopState.nonLocalJumps |= 8 /* Return */; + return ts.createReturn(ts.createObjectLiteral([ + ts.createPropertyAssignment(ts.createIdentifier("value"), node.expression + ? ts.visitNode(node.expression, visitor, ts.isExpression) + : ts.createVoidZero()) + ])); + } + function visitThisKeyword(node) { + ts.Debug.assert(convertedLoopState !== undefined); + if (enclosingFunction && enclosingFunction.kind === 180 /* ArrowFunction */) { + // if the enclosing function is an ArrowFunction is then we use the captured 'this' keyword. + convertedLoopState.containsLexicalThis = true; + return node; + } + return convertedLoopState.thisName || (convertedLoopState.thisName = ts.createUniqueName("this")); + } + function visitIdentifier(node) { + if (!convertedLoopState) { + return node; } - function shouldConvertLoopBody(node) { - return languageVersion < 2 /* ES6 */ && - (resolver.getNodeCheckFlags(node) & 65536 /* LoopWithCapturedBlockScopedBinding */) !== 0; + if (ts.isGeneratedIdentifier(node)) { + return node; } - function emitLoop(node, loopEmitter) { - var shouldConvert = shouldConvertLoopBody(node); - if (!shouldConvert) { - loopEmitter(node, /* convertedLoop*/ undefined); - } - else { - var loop = convertLoopBody(node); - if (node.parent.kind === 214 /* LabeledStatement */) { - // if parent of the loop was labeled statement - attach the label to loop skipping converted loop body - emitLabelAndColon(node.parent); - } - loopEmitter(node, loop); - } + if (node.text !== "arguments" && !resolver.isArgumentsLocalBinding(node)) { + return node; } - function convertLoopBody(node) { - var functionName = makeUniqueName("_loop"); - var loopInitializer; - switch (node.kind) { - case 206 /* ForStatement */: - case 207 /* ForInStatement */: - case 208 /* ForOfStatement */: - var initializer = node.initializer; - if (initializer && initializer.kind === 219 /* VariableDeclarationList */) { - loopInitializer = node.initializer; + return convertedLoopState.argumentsName || (convertedLoopState.argumentsName = ts.createUniqueName("arguments")); + } + function visitBreakOrContinueStatement(node) { + if (convertedLoopState) { + // check if we can emit break/continue as is + // it is possible if either + // - break/continue is labeled and label is located inside the converted loop + // - break/continue is non-labeled and located in non-converted loop/switch statement + var jump = node.kind === 210 /* BreakStatement */ ? 2 /* Break */ : 4 /* Continue */; + var canUseBreakOrContinue = (node.label && convertedLoopState.labels && convertedLoopState.labels[node.label.text]) || + (!node.label && (convertedLoopState.allowedNonLabeledJumps & jump)); + if (!canUseBreakOrContinue) { + var labelMarker = void 0; + if (!node.label) { + if (node.kind === 210 /* BreakStatement */) { + convertedLoopState.nonLocalJumps |= 2 /* Break */; + labelMarker = "break"; } - break; - } - var loopParameters; - var loopOutParameters; - if (loopInitializer && (ts.getCombinedNodeFlags(loopInitializer) & 3072 /* BlockScoped */)) { - // if loop initializer contains block scoped variables - they should be passed to converted loop body as parameters - loopParameters = []; - for (var _a = 0, _b = loopInitializer.declarations; _a < _b.length; _a++) { - var varDeclaration = _b[_a]; - processVariableDeclaration(varDeclaration.name); - } - } - var bodyIsBlock = node.statement.kind === 199 /* Block */; - var paramList = loopParameters ? loopParameters.join(", ") : ""; - writeLine(); - write("var " + functionName + " = function(" + paramList + ")"); - var convertedOuterLoopState = convertedLoopState; - convertedLoopState = { loopOutParameters: loopOutParameters }; - if (convertedOuterLoopState) { - // convertedOuterLoopState !== undefined means that this converted loop is nested in another converted loop. - // if outer converted loop has already accumulated some state - pass it through - if (convertedOuterLoopState.argumentsName) { - // outer loop has already used 'arguments' so we've already have some name to alias it - // use the same name in all nested loops - convertedLoopState.argumentsName = convertedOuterLoopState.argumentsName; - } - if (convertedOuterLoopState.thisName) { - // outer loop has already used 'this' so we've already have some name to alias it - // use the same name in all nested loops - convertedLoopState.thisName = convertedOuterLoopState.thisName; - } - if (convertedOuterLoopState.hoistedLocalVariables) { - // we've already collected some non-block scoped variable declarations in enclosing loop - // use the same storage in nested loop - convertedLoopState.hoistedLocalVariables = convertedOuterLoopState.hoistedLocalVariables; - } - } - write(" {"); - writeLine(); - increaseIndent(); - if (bodyIsBlock) { - emitLines(node.statement.statements); - } - else { - emit(node.statement); - } - writeLine(); - // end of loop body -> copy out parameter - copyLoopOutParameters(convertedLoopState, 1 /* ToOutParameter */, /*emitAsStatements*/ true); - decreaseIndent(); - writeLine(); - write("};"); - writeLine(); - if (loopOutParameters) { - // declare variables to hold out params for loop body - write("var "); - for (var i = 0; i < loopOutParameters.length; i++) { - if (i !== 0) { - write(", "); + else { + convertedLoopState.nonLocalJumps |= 4 /* Continue */; + // note: return value is emitted only to simplify debugging, call to converted loop body does not do any dispatching on it. + labelMarker = "continue"; } - write(loopOutParameters[i].outParamName); - } - write(";"); - writeLine(); - } - if (convertedLoopState.argumentsName) { - // if alias for arguments is set - if (convertedOuterLoopState) { - // pass it to outer converted loop - convertedOuterLoopState.argumentsName = convertedLoopState.argumentsName; - } - else { - // this is top level converted loop and we need to create an alias for 'arguments' object - write("var " + convertedLoopState.argumentsName + " = arguments;"); - writeLine(); - } - } - if (convertedLoopState.thisName) { - // if alias for this is set - if (convertedOuterLoopState) { - // pass it to outer converted loop - convertedOuterLoopState.thisName = convertedLoopState.thisName; - } - else { - // this is top level converted loop so we need to create an alias for 'this' here - // NOTE: - // if converted loops were all nested in arrow function then we'll always emit '_this' so convertedLoopState.thisName will not be set. - // If it is set this means that all nested loops are not nested in arrow function and it is safe to capture 'this'. - write("var " + convertedLoopState.thisName + " = this;"); - writeLine(); - } - } - if (convertedLoopState.hoistedLocalVariables) { - // if hoistedLocalVariables !== undefined this means that we've possibly collected some variable declarations to be hoisted later - if (convertedOuterLoopState) { - // pass them to outer converted loop - convertedOuterLoopState.hoistedLocalVariables = convertedLoopState.hoistedLocalVariables; } else { - // deduplicate and hoist collected variable declarations - write("var "); - var seen = void 0; - for (var _c = 0, _d = convertedLoopState.hoistedLocalVariables; _c < _d.length; _c++) { - var id = _d[_c]; - // Don't initialize seen unless we have at least one element. - // Emit a comma to separate for all but the first element. - if (!seen) { - seen = ts.createMap(); + if (node.kind === 210 /* BreakStatement */) { + labelMarker = "break-" + node.label.text; + setLabeledJump(convertedLoopState, /*isBreak*/ true, node.label.text, labelMarker); + } + else { + labelMarker = "continue-" + node.label.text; + setLabeledJump(convertedLoopState, /*isBreak*/ false, node.label.text, labelMarker); + } + } + var returnExpression = ts.createLiteral(labelMarker); + if (convertedLoopState.loopOutParameters.length) { + var outParams = convertedLoopState.loopOutParameters; + var expr = void 0; + for (var i = 0; i < outParams.length; i++) { + var copyExpr = copyOutParameter(outParams[i], 1 /* ToOutParameter */); + if (i === 0) { + expr = copyExpr; } else { - write(", "); - } - if (!(id.text in seen)) { - emit(id); - seen[id.text] = id.text; + expr = ts.createBinary(expr, 24 /* CommaToken */, copyExpr); } } - write(";"); - writeLine(); - } - } - var currentLoopState = convertedLoopState; - convertedLoopState = convertedOuterLoopState; - return { functionName: functionName, paramList: paramList, state: currentLoopState }; - function processVariableDeclaration(name) { - if (name.kind === 69 /* Identifier */) { - var nameText = isNameOfNestedBlockScopedRedeclarationOrCapturedBinding(name) - ? getGeneratedNameForNode(name) - : name.text; - loopParameters.push(nameText); - if (resolver.getNodeCheckFlags(name.parent) & 2097152 /* NeedsLoopOutParameter */) { - var reassignedVariable = { originalName: name, outParamName: makeUniqueName("out_" + nameText) }; - (loopOutParameters || (loopOutParameters = [])).push(reassignedVariable); - } - } - else { - for (var _a = 0, _b = name.elements; _a < _b.length; _a++) { - var element = _b[_a]; - processVariableDeclaration(element.name); - } + returnExpression = ts.createBinary(expr, 24 /* CommaToken */, returnExpression); } + return ts.createReturn(returnExpression); } } - function emitNormalLoopBody(node, emitAsEmbeddedStatement) { - var saveAllowedNonLabeledJumps; - if (convertedLoopState) { - // we get here if we are trying to emit normal loop loop inside converted loop - // set allowedNonLabeledJumps to Break | Continue to mark that break\continue inside the loop should be emitted as is - saveAllowedNonLabeledJumps = convertedLoopState.allowedNonLabeledJumps; - convertedLoopState.allowedNonLabeledJumps = 2 /* Break */ | 4 /* Continue */; + return ts.visitEachChild(node, visitor, context); + } + /** + * Visits a ClassDeclaration and transforms it into a variable statement. + * + * @param node A ClassDeclaration node. + */ + function visitClassDeclaration(node) { + // [source] + // class C { } + // + // [output] + // var C = (function () { + // function C() { + // } + // return C; + // }()); + var modifierFlags = ts.getModifierFlags(node); + var isExported = modifierFlags & 1 /* Export */; + var isDefault = modifierFlags & 512 /* Default */; + // Add an `export` modifier to the statement if needed (for `--target es5 --module es6`) + var modifiers = isExported && !isDefault + ? ts.filter(node.modifiers, isExportModifier) + : undefined; + var statement = ts.createVariableStatement(modifiers, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(getDeclarationName(node, /*allowComments*/ true), + /*type*/ undefined, transformClassLikeDeclarationToExpression(node)) + ]), + /*location*/ node); + ts.setOriginalNode(statement, node); + ts.startOnNewLine(statement); + // Add an `export default` statement for default exports (for `--target es5 --module es6`) + if (isExported && isDefault) { + var statements = [statement]; + statements.push(ts.createExportAssignment( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*isExportEquals*/ false, getDeclarationName(node, /*allowComments*/ false))); + return statements; + } + return statement; + } + function isExportModifier(node) { + return node.kind === 82 /* ExportKeyword */; + } + /** + * Visits a ClassExpression and transforms it into an expression. + * + * @param node A ClassExpression node. + */ + function visitClassExpression(node) { + // [source] + // C = class { } + // + // [output] + // C = (function () { + // function class_1() { + // } + // return class_1; + // }()) + return transformClassLikeDeclarationToExpression(node); + } + /** + * Transforms a ClassExpression or ClassDeclaration into an expression. + * + * @param node A ClassExpression or ClassDeclaration node. + */ + function transformClassLikeDeclarationToExpression(node) { + // [source] + // class C extends D { + // constructor() {} + // method() {} + // get prop() {} + // set prop(v) {} + // } + // + // [output] + // (function (_super) { + // __extends(C, _super); + // function C() { + // } + // C.prototype.method = function () {} + // Object.defineProperty(C.prototype, "prop", { + // get: function() {}, + // set: function() {}, + // enumerable: true, + // configurable: true + // }); + // return C; + // }(D)) + if (node.name) { + enableSubstitutionsForBlockScopedBindings(); + } + var extendsClauseElement = ts.getClassExtendsHeritageClauseElement(node); + var classFunction = ts.createFunctionExpression( + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, extendsClauseElement ? [ts.createParameter("_super")] : [], + /*type*/ undefined, transformClassBody(node, extendsClauseElement)); + // To preserve the behavior of the old emitter, we explicitly indent + // the body of the function here if it was requested in an earlier + // transformation. + if (ts.getEmitFlags(node) & 524288 /* Indented */) { + ts.setEmitFlags(classFunction, 524288 /* Indented */); + } + // "inner" and "outer" below are added purely to preserve source map locations from + // the old emitter + var inner = ts.createPartiallyEmittedExpression(classFunction); + inner.end = node.end; + ts.setEmitFlags(inner, 49152 /* NoComments */); + var outer = ts.createPartiallyEmittedExpression(inner); + outer.end = ts.skipTrivia(currentText, node.pos); + ts.setEmitFlags(outer, 49152 /* NoComments */); + return ts.createParen(ts.createCall(outer, + /*typeArguments*/ undefined, extendsClauseElement + ? [ts.visitNode(extendsClauseElement.expression, visitor, ts.isExpression)] + : [])); + } + /** + * Transforms a ClassExpression or ClassDeclaration into a function body. + * + * @param node A ClassExpression or ClassDeclaration node. + * @param extendsClauseElement The expression for the class `extends` clause. + */ + function transformClassBody(node, extendsClauseElement) { + var statements = []; + startLexicalEnvironment(); + addExtendsHelperIfNeeded(statements, node, extendsClauseElement); + addConstructor(statements, node, extendsClauseElement); + addClassMembers(statements, node); + // Create a synthetic text range for the return statement. + var closingBraceLocation = ts.createTokenRange(ts.skipTrivia(currentText, node.members.end), 16 /* CloseBraceToken */); + var localName = getLocalName(node); + // The following partially-emitted expression exists purely to align our sourcemap + // emit with the original emitter. + var outer = ts.createPartiallyEmittedExpression(localName); + outer.end = closingBraceLocation.end; + ts.setEmitFlags(outer, 49152 /* NoComments */); + var statement = ts.createReturn(outer); + statement.pos = closingBraceLocation.pos; + ts.setEmitFlags(statement, 49152 /* NoComments */ | 12288 /* NoTokenSourceMaps */); + statements.push(statement); + ts.addRange(statements, endLexicalEnvironment()); + var block = ts.createBlock(ts.createNodeArray(statements, /*location*/ node.members), /*location*/ undefined, /*multiLine*/ true); + ts.setEmitFlags(block, 49152 /* NoComments */); + return block; + } + /** + * Adds a call to the `__extends` helper if needed for a class. + * + * @param statements The statements of the class body function. + * @param node The ClassExpression or ClassDeclaration node. + * @param extendsClauseElement The expression for the class `extends` clause. + */ + function addExtendsHelperIfNeeded(statements, node, extendsClauseElement) { + if (extendsClauseElement) { + statements.push(ts.createStatement(ts.createExtendsHelper(currentSourceFile.externalHelpersModuleName, getDeclarationName(node)), + /*location*/ extendsClauseElement)); + } + } + /** + * Adds the constructor of the class to a class body function. + * + * @param statements The statements of the class body function. + * @param node The ClassExpression or ClassDeclaration node. + * @param extendsClauseElement The expression for the class `extends` clause. + */ + function addConstructor(statements, node, extendsClauseElement) { + var constructor = ts.getFirstConstructorWithBody(node); + var hasSynthesizedSuper = hasSynthesizedDefaultSuperCall(constructor, extendsClauseElement !== undefined); + var constructorFunction = ts.createFunctionDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, getDeclarationName(node), + /*typeParameters*/ undefined, transformConstructorParameters(constructor, hasSynthesizedSuper), + /*type*/ undefined, transformConstructorBody(constructor, node, extendsClauseElement, hasSynthesizedSuper), + /*location*/ constructor || node); + if (extendsClauseElement) { + ts.setEmitFlags(constructorFunction, 256 /* CapturesThis */); + } + statements.push(constructorFunction); + } + /** + * Transforms the parameters of the constructor declaration of a class. + * + * @param constructor The constructor for the class. + * @param hasSynthesizedSuper A value indicating whether the constructor starts with a + * synthesized `super` call. + */ + function transformConstructorParameters(constructor, hasSynthesizedSuper) { + // If the TypeScript transformer needed to synthesize a constructor for property + // initializers, it would have also added a synthetic `...args` parameter and + // `super` call. + // If this is the case, we do not include the synthetic `...args` parameter and + // will instead use the `arguments` object in ES5/3. + if (constructor && !hasSynthesizedSuper) { + return ts.visitNodes(constructor.parameters, visitor, ts.isParameter); + } + return []; + } + /** + * Transforms the body of a constructor declaration of a class. + * + * @param constructor The constructor for the class. + * @param node The node which contains the constructor. + * @param extendsClauseElement The expression for the class `extends` clause. + * @param hasSynthesizedSuper A value indicating whether the constructor starts with a + * synthesized `super` call. + */ + function transformConstructorBody(constructor, node, extendsClauseElement, hasSynthesizedSuper) { + var statements = []; + startLexicalEnvironment(); + var statementOffset = -1; + if (hasSynthesizedSuper) { + // If a super call has already been synthesized, + // we're going to assume that we should just transform everything after that. + // The assumption is that no prior step in the pipeline has added any prologue directives. + statementOffset = 1; + } + else if (constructor) { + // Otherwise, try to emit all potential prologue directives first. + statementOffset = ts.addPrologueDirectives(statements, constructor.body.statements, /*ensureUseStrict*/ false, visitor); + } + if (constructor) { + addDefaultValueAssignmentsIfNeeded(statements, constructor); + addRestParameterIfNeeded(statements, constructor, hasSynthesizedSuper); + ts.Debug.assert(statementOffset >= 0, "statementOffset not initialized correctly!"); + } + var superCaptureStatus = declareOrCaptureOrReturnThisForConstructorIfNeeded(statements, constructor, !!extendsClauseElement, hasSynthesizedSuper, statementOffset); + // The last statement expression was replaced. Skip it. + if (superCaptureStatus === 1 /* ReplaceSuperCapture */ || superCaptureStatus === 2 /* ReplaceWithReturn */) { + statementOffset++; + } + if (constructor) { + var body = saveStateAndInvoke(constructor, function (constructor) { return ts.visitNodes(constructor.body.statements, visitor, ts.isStatement, /*start*/ statementOffset); }); + ts.addRange(statements, body); + } + // Return `_this` unless we're sure enough that it would be pointless to add a return statement. + // If there's a constructor that we can tell returns in enough places, then we *do not* want to add a return. + if (extendsClauseElement + && superCaptureStatus !== 2 /* ReplaceWithReturn */ + && !(constructor && isSufficientlyCoveredByReturnStatements(constructor.body))) { + statements.push(ts.createReturn(ts.createIdentifier("_this"))); + } + ts.addRange(statements, endLexicalEnvironment()); + var block = ts.createBlock(ts.createNodeArray(statements, + /*location*/ constructor ? constructor.body.statements : node.members), + /*location*/ constructor ? constructor.body : node, + /*multiLine*/ true); + if (!constructor) { + ts.setEmitFlags(block, 49152 /* NoComments */); + } + return block; + } + /** + * We want to try to avoid emitting a return statement in certain cases if a user already returned something. + * It would generate obviously dead code, so we'll try to make things a little bit prettier + * by doing a minimal check on whether some common patterns always explicitly return. + */ + function isSufficientlyCoveredByReturnStatements(statement) { + // A return statement is considered covered. + if (statement.kind === 211 /* ReturnStatement */) { + return true; + } + else if (statement.kind === 203 /* IfStatement */) { + var ifStatement = statement; + if (ifStatement.elseStatement) { + return isSufficientlyCoveredByReturnStatements(ifStatement.thenStatement) && + isSufficientlyCoveredByReturnStatements(ifStatement.elseStatement); } - if (emitAsEmbeddedStatement) { - emitEmbeddedStatement(node.statement); + } + else if (statement.kind === 199 /* Block */) { + var lastStatement = ts.lastOrUndefined(statement.statements); + if (lastStatement && isSufficientlyCoveredByReturnStatements(lastStatement)) { + return true; } - else if (node.statement.kind === 199 /* Block */) { - emitLines(node.statement.statements); + } + return false; + } + /** + * Declares a `_this` variable for derived classes and for when arrow functions capture `this`. + * + * @returns The new statement offset into the `statements` array. + */ + function declareOrCaptureOrReturnThisForConstructorIfNeeded(statements, ctor, hasExtendsClause, hasSynthesizedSuper, statementOffset) { + // If this isn't a derived class, just capture 'this' for arrow functions if necessary. + if (!hasExtendsClause) { + if (ctor) { + addCaptureThisForNodeIfNeeded(statements, ctor); + } + return 0 /* NoReplacement */; + } + // We must be here because the user didn't write a constructor + // but we needed to call 'super(...args)' anyway as per 14.5.14 of the ES2016 spec. + // If that's the case we can just immediately return the result of a 'super()' call. + if (!ctor) { + statements.push(ts.createReturn(createDefaultSuperCallOrThis())); + return 2 /* ReplaceWithReturn */; + } + // The constructor exists, but it and the 'super()' call it contains were generated + // for something like property initializers. + // Create a captured '_this' variable and assume it will subsequently be used. + if (hasSynthesizedSuper) { + captureThisForNode(statements, ctor, createDefaultSuperCallOrThis()); + enableSubstitutionsForCapturedThis(); + return 1 /* ReplaceSuperCapture */; + } + // Most of the time, a 'super' call will be the first real statement in a constructor body. + // In these cases, we'd like to transform these into a *single* statement instead of a declaration + // followed by an assignment statement for '_this'. For instance, if we emitted without an initializer, + // we'd get: + // + // var _this; + // _this = _super.call(...) || this; + // + // instead of + // + // var _this = _super.call(...) || this; + // + // Additionally, if the 'super()' call is the last statement, we should just avoid capturing + // entirely and immediately return the result like so: + // + // return _super.call(...) || this; + // + var firstStatement; + var superCallExpression; + var ctorStatements = ctor.body.statements; + if (statementOffset < ctorStatements.length) { + firstStatement = ctorStatements[statementOffset]; + if (firstStatement.kind === 202 /* ExpressionStatement */ && ts.isSuperCallExpression(firstStatement.expression)) { + var superCall = firstStatement.expression; + superCallExpression = ts.setOriginalNode(saveStateAndInvoke(superCall, visitImmediateSuperCallInBody), superCall); + } + } + // Return the result if we have an immediate super() call on the last statement. + if (superCallExpression && statementOffset === ctorStatements.length - 1) { + statements.push(ts.createReturn(superCallExpression)); + return 2 /* ReplaceWithReturn */; + } + // Perform the capture. + captureThisForNode(statements, ctor, superCallExpression, firstStatement); + // If we're actually replacing the original statement, we need to signal this to the caller. + if (superCallExpression) { + return 1 /* ReplaceSuperCapture */; + } + return 0 /* NoReplacement */; + } + function createDefaultSuperCallOrThis() { + var actualThis = ts.createThis(); + ts.setEmitFlags(actualThis, 128 /* NoSubstitution */); + var superCall = ts.createFunctionApply(ts.createIdentifier("_super"), actualThis, ts.createIdentifier("arguments")); + return ts.createLogicalOr(superCall, actualThis); + } + /** + * Visits a parameter declaration. + * + * @param node A ParameterDeclaration node. + */ + function visitParameter(node) { + if (node.dotDotDotToken) { + // rest parameters are elided + return undefined; + } + else if (ts.isBindingPattern(node.name)) { + // Binding patterns are converted into a generated name and are + // evaluated inside the function body. + return ts.setOriginalNode(ts.createParameter(ts.getGeneratedNameForNode(node), + /*initializer*/ undefined, + /*location*/ node), + /*original*/ node); + } + else if (node.initializer) { + // Initializers are elided + return ts.setOriginalNode(ts.createParameter(node.name, + /*initializer*/ undefined, + /*location*/ node), + /*original*/ node); + } + else { + return node; + } + } + /** + * Gets a value indicating whether we need to add default value assignments for a + * function-like node. + * + * @param node A function-like node. + */ + function shouldAddDefaultValueAssignments(node) { + return (node.transformFlags & 65536 /* ContainsDefaultValueAssignments */) !== 0; + } + /** + * Adds statements to the body of a function-like node if it contains parameters with + * binding patterns or initializers. + * + * @param statements The statements for the new function body. + * @param node A function-like node. + */ + function addDefaultValueAssignmentsIfNeeded(statements, node) { + if (!shouldAddDefaultValueAssignments(node)) { + return; + } + for (var _i = 0, _a = node.parameters; _i < _a.length; _i++) { + var parameter = _a[_i]; + var name_35 = parameter.name, initializer = parameter.initializer, dotDotDotToken = parameter.dotDotDotToken; + // A rest parameter cannot have a binding pattern or an initializer, + // so let's just ignore it. + if (dotDotDotToken) { + continue; } - else { - writeLine(); - emit(node.statement); + if (ts.isBindingPattern(name_35)) { + addDefaultValueAssignmentForBindingPattern(statements, parameter, name_35, initializer); } - if (convertedLoopState) { - convertedLoopState.allowedNonLabeledJumps = saveAllowedNonLabeledJumps; + else if (initializer) { + addDefaultValueAssignmentForInitializer(statements, parameter, name_35, initializer); } } - function copyLoopOutParameters(state, copyDirection, emitAsStatements) { - if (state.loopOutParameters) { - for (var _a = 0, _b = state.loopOutParameters; _a < _b.length; _a++) { - var outParam = _b[_a]; - if (copyDirection === 0 /* ToOriginal */) { - emitIdentifier(outParam.originalName); - write(" = " + outParam.outParamName); - } - else { - write(outParam.outParamName + " = "); - emitIdentifier(outParam.originalName); - } - if (emitAsStatements) { - write(";"); - writeLine(); - } - else { - write(", "); - } - } - } + } + /** + * Adds statements to the body of a function-like node for parameters with binding patterns + * + * @param statements The statements for the new function body. + * @param parameter The parameter for the function. + * @param name The name of the parameter. + * @param initializer The initializer for the parameter. + */ + function addDefaultValueAssignmentForBindingPattern(statements, parameter, name, initializer) { + var temp = ts.getGeneratedNameForNode(parameter); + // In cases where a binding pattern is simply '[]' or '{}', + // we usually don't want to emit a var declaration; however, in the presence + // of an initializer, we must emit that expression to preserve side effects. + if (name.elements.length > 0) { + statements.push(ts.setEmitFlags(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList(ts.flattenParameterDestructuring(context, parameter, temp, visitor))), 8388608 /* CustomPrologue */)); } - function emitConvertedLoopCall(loop, emitAsBlock) { - if (emitAsBlock) { - write(" {"); - writeLine(); - increaseIndent(); - } - // loop is considered simple if it does not have any return statements or break\continue that transfer control outside of the loop - // simple loops are emitted as just 'loop()'; - // NOTE: if loop uses only 'continue' it still will be emitted as simple loop - var isSimpleLoop = !(loop.state.nonLocalJumps & ~4 /* Continue */) && - !loop.state.labeledNonLocalBreaks && - !loop.state.labeledNonLocalContinues; - var loopResult = makeUniqueName("state"); - if (!isSimpleLoop) { - write("var " + loopResult + " = "); - } - write(loop.functionName + "(" + loop.paramList + ");"); - writeLine(); - copyLoopOutParameters(loop.state, 0 /* ToOriginal */, /*emitAsStatements*/ true); - if (!isSimpleLoop) { - // for non simple loops we need to store result returned from converted loop function and use it to do dispatching - // converted loop function can return: - // - object - used when body of the converted loop contains return statement. Property "value" of this object stores retuned value - // - string - used to dispatch jumps. "break" and "continue" are used to non-labeled jumps, other values are used to transfer control to - // different labels - writeLine(); - if (loop.state.nonLocalJumps & 8 /* Return */) { - write("if (typeof " + loopResult + " === \"object\") "); - if (convertedLoopState) { - // we are currently nested in another converted loop - return unwrapped result - write("return " + loopResult + ";"); - // propagate 'hasReturn' flag to outer loop - convertedLoopState.nonLocalJumps |= 8 /* Return */; - } - else { - // top level converted loop - return unwrapped value - write("return " + loopResult + ".value;"); + else if (initializer) { + statements.push(ts.setEmitFlags(ts.createStatement(ts.createAssignment(temp, ts.visitNode(initializer, visitor, ts.isExpression))), 8388608 /* CustomPrologue */)); + } + } + /** + * Adds statements to the body of a function-like node for parameters with initializers. + * + * @param statements The statements for the new function body. + * @param parameter The parameter for the function. + * @param name The name of the parameter. + * @param initializer The initializer for the parameter. + */ + function addDefaultValueAssignmentForInitializer(statements, parameter, name, initializer) { + initializer = ts.visitNode(initializer, visitor, ts.isExpression); + var statement = ts.createIf(ts.createStrictEquality(ts.getSynthesizedClone(name), ts.createVoidZero()), ts.setEmitFlags(ts.createBlock([ + ts.createStatement(ts.createAssignment(ts.setEmitFlags(ts.getMutableClone(name), 1536 /* NoSourceMap */), ts.setEmitFlags(initializer, 1536 /* NoSourceMap */ | ts.getEmitFlags(initializer)), + /*location*/ parameter)) + ], /*location*/ parameter), 32 /* SingleLine */ | 1024 /* NoTrailingSourceMap */ | 12288 /* NoTokenSourceMaps */), + /*elseStatement*/ undefined, + /*location*/ parameter); + statement.startsOnNewLine = true; + ts.setEmitFlags(statement, 12288 /* NoTokenSourceMaps */ | 1024 /* NoTrailingSourceMap */ | 8388608 /* CustomPrologue */); + statements.push(statement); + } + /** + * Gets a value indicating whether we need to add statements to handle a rest parameter. + * + * @param node A ParameterDeclaration node. + * @param inConstructorWithSynthesizedSuper A value indicating whether the parameter is + * part of a constructor declaration with a + * synthesized call to `super` + */ + function shouldAddRestParameter(node, inConstructorWithSynthesizedSuper) { + return node && node.dotDotDotToken && node.name.kind === 69 /* Identifier */ && !inConstructorWithSynthesizedSuper; + } + /** + * Adds statements to the body of a function-like node if it contains a rest parameter. + * + * @param statements The statements for the new function body. + * @param node A function-like node. + * @param inConstructorWithSynthesizedSuper A value indicating whether the parameter is + * part of a constructor declaration with a + * synthesized call to `super` + */ + function addRestParameterIfNeeded(statements, node, inConstructorWithSynthesizedSuper) { + var parameter = ts.lastOrUndefined(node.parameters); + if (!shouldAddRestParameter(parameter, inConstructorWithSynthesizedSuper)) { + return; + } + // `declarationName` is the name of the local declaration for the parameter. + var declarationName = ts.getMutableClone(parameter.name); + ts.setEmitFlags(declarationName, 1536 /* NoSourceMap */); + // `expressionName` is the name of the parameter used in expressions. + var expressionName = ts.getSynthesizedClone(parameter.name); + var restIndex = node.parameters.length - 1; + var temp = ts.createLoopVariable(); + // var param = []; + statements.push(ts.setEmitFlags(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(declarationName, + /*type*/ undefined, ts.createArrayLiteral([])) + ]), + /*location*/ parameter), 8388608 /* CustomPrologue */)); + // for (var _i = restIndex; _i < arguments.length; _i++) { + // param[_i - restIndex] = arguments[_i]; + // } + var forStatement = ts.createFor(ts.createVariableDeclarationList([ + ts.createVariableDeclaration(temp, /*type*/ undefined, ts.createLiteral(restIndex)) + ], /*location*/ parameter), ts.createLessThan(temp, ts.createPropertyAccess(ts.createIdentifier("arguments"), "length"), + /*location*/ parameter), ts.createPostfixIncrement(temp, /*location*/ parameter), ts.createBlock([ + ts.startOnNewLine(ts.createStatement(ts.createAssignment(ts.createElementAccess(expressionName, ts.createSubtract(temp, ts.createLiteral(restIndex))), ts.createElementAccess(ts.createIdentifier("arguments"), temp)), + /*location*/ parameter)) + ])); + ts.setEmitFlags(forStatement, 8388608 /* CustomPrologue */); + ts.startOnNewLine(forStatement); + statements.push(forStatement); + } + /** + * Adds a statement to capture the `this` of a function declaration if it is needed. + * + * @param statements The statements for the new function body. + * @param node A node. + */ + function addCaptureThisForNodeIfNeeded(statements, node) { + if (node.transformFlags & 16384 /* ContainsCapturedLexicalThis */ && node.kind !== 180 /* ArrowFunction */) { + captureThisForNode(statements, node, ts.createThis()); + } + } + function captureThisForNode(statements, node, initializer, originalStatement) { + enableSubstitutionsForCapturedThis(); + var captureThisStatement = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration("_this", + /*type*/ undefined, initializer) + ]), originalStatement); + ts.setEmitFlags(captureThisStatement, 49152 /* NoComments */ | 8388608 /* CustomPrologue */); + ts.setSourceMapRange(captureThisStatement, node); + statements.push(captureThisStatement); + } + /** + * Adds statements to the class body function for a class to define the members of the + * class. + * + * @param statements The statements for the class body function. + * @param node The ClassExpression or ClassDeclaration node. + */ + function addClassMembers(statements, node) { + for (var _i = 0, _a = node.members; _i < _a.length; _i++) { + var member = _a[_i]; + switch (member.kind) { + case 198 /* SemicolonClassElement */: + statements.push(transformSemicolonClassElementToStatement(member)); + break; + case 147 /* MethodDeclaration */: + statements.push(transformClassMethodDeclarationToStatement(getClassMemberPrefix(node, member), member)); + break; + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + var accessors = ts.getAllAccessorDeclarations(node.members, member); + if (member === accessors.firstAccessor) { + statements.push(transformAccessorsToStatement(getClassMemberPrefix(node, member), accessors)); } - writeLine(); - } - if (loop.state.nonLocalJumps & 2 /* Break */) { - write("if (" + loopResult + " === \"break\") break;"); - writeLine(); - } - // in case of labeled breaks emit code that either breaks to some known label inside outer loop or delegates jump decision to outer loop - emitDispatchTableForLabeledJumps(loopResult, loop.state, convertedLoopState); - } - if (emitAsBlock) { - writeLine(); - decreaseIndent(); - write("}"); - } - function emitDispatchTableForLabeledJumps(loopResultVariable, currentLoop, outerLoop) { - if (!currentLoop.labeledNonLocalBreaks && !currentLoop.labeledNonLocalContinues) { - return; - } - write("switch(" + loopResultVariable + ") {"); - increaseIndent(); - emitDispatchEntriesForLabeledJumps(currentLoop.labeledNonLocalBreaks, /*isBreak*/ true, loopResultVariable, outerLoop); - emitDispatchEntriesForLabeledJumps(currentLoop.labeledNonLocalContinues, /*isBreak*/ false, loopResultVariable, outerLoop); - decreaseIndent(); - writeLine(); - write("}"); + break; + case 148 /* Constructor */: + // Constructors are handled in visitClassExpression/visitClassDeclaration + break; + default: + ts.Debug.failBadSyntaxKind(node); + break; } - function emitDispatchEntriesForLabeledJumps(table, isBreak, loopResultVariable, outerLoop) { - if (!table) { - return; - } - for (var labelText in table) { - var labelMarker = table[labelText]; - writeLine(); - write("case \"" + labelMarker + "\": "); - // if there are no outer converted loop or outer label in question is located inside outer converted loop - // then emit labeled break\continue - // otherwise propagate pair 'label -> marker' to outer converted loop and emit 'return labelMarker' so outer loop can later decide what to do - if (!outerLoop || (outerLoop.labels && outerLoop.labels[labelText])) { - if (isBreak) { - write("break "); - } - else { - write("continue "); - } - write(labelText + ";"); - } - else { - setLabeledJump(outerLoop, isBreak, labelText, labelMarker); - write("return " + loopResultVariable + ";"); - } - } + } + } + /** + * Transforms a SemicolonClassElement into a statement for a class body function. + * + * @param member The SemicolonClassElement node. + */ + function transformSemicolonClassElementToStatement(member) { + return ts.createEmptyStatement(/*location*/ member); + } + /** + * Transforms a MethodDeclaration into a statement for a class body function. + * + * @param receiver The receiver for the member. + * @param member The MethodDeclaration node. + */ + function transformClassMethodDeclarationToStatement(receiver, member) { + var commentRange = ts.getCommentRange(member); + var sourceMapRange = ts.getSourceMapRange(member); + var func = transformFunctionLikeToExpression(member, /*location*/ member, /*name*/ undefined); + ts.setEmitFlags(func, 49152 /* NoComments */); + ts.setSourceMapRange(func, sourceMapRange); + var statement = ts.createStatement(ts.createAssignment(ts.createMemberAccessForPropertyName(receiver, ts.visitNode(member.name, visitor, ts.isPropertyName), + /*location*/ member.name), func), + /*location*/ member); + ts.setOriginalNode(statement, member); + ts.setCommentRange(statement, commentRange); + // The location for the statement is used to emit comments only. + // No source map should be emitted for this statement to align with the + // old emitter. + ts.setEmitFlags(statement, 1536 /* NoSourceMap */); + return statement; + } + /** + * Transforms a set of related of get/set accessors into a statement for a class body function. + * + * @param receiver The receiver for the member. + * @param accessors The set of related get/set accessors. + */ + function transformAccessorsToStatement(receiver, accessors) { + var statement = ts.createStatement(transformAccessorsToExpression(receiver, accessors, /*startsOnNewLine*/ false), + /*location*/ ts.getSourceMapRange(accessors.firstAccessor)); + // The location for the statement is used to emit source maps only. + // No comments should be emitted for this statement to align with the + // old emitter. + ts.setEmitFlags(statement, 49152 /* NoComments */); + return statement; + } + /** + * Transforms a set of related get/set accessors into an expression for either a class + * body function or an ObjectLiteralExpression with computed properties. + * + * @param receiver The receiver for the member. + */ + function transformAccessorsToExpression(receiver, _a, startsOnNewLine) { + var firstAccessor = _a.firstAccessor, getAccessor = _a.getAccessor, setAccessor = _a.setAccessor; + // To align with source maps in the old emitter, the receiver and property name + // arguments are both mapped contiguously to the accessor name. + var target = ts.getMutableClone(receiver); + ts.setEmitFlags(target, 49152 /* NoComments */ | 1024 /* NoTrailingSourceMap */); + ts.setSourceMapRange(target, firstAccessor.name); + var propertyName = ts.createExpressionForPropertyName(ts.visitNode(firstAccessor.name, visitor, ts.isPropertyName)); + ts.setEmitFlags(propertyName, 49152 /* NoComments */ | 512 /* NoLeadingSourceMap */); + ts.setSourceMapRange(propertyName, firstAccessor.name); + var properties = []; + if (getAccessor) { + var getterFunction = transformFunctionLikeToExpression(getAccessor, /*location*/ undefined, /*name*/ undefined); + ts.setSourceMapRange(getterFunction, ts.getSourceMapRange(getAccessor)); + var getter = ts.createPropertyAssignment("get", getterFunction); + ts.setCommentRange(getter, ts.getCommentRange(getAccessor)); + properties.push(getter); + } + if (setAccessor) { + var setterFunction = transformFunctionLikeToExpression(setAccessor, /*location*/ undefined, /*name*/ undefined); + ts.setSourceMapRange(setterFunction, ts.getSourceMapRange(setAccessor)); + var setter = ts.createPropertyAssignment("set", setterFunction); + ts.setCommentRange(setter, ts.getCommentRange(setAccessor)); + properties.push(setter); + } + properties.push(ts.createPropertyAssignment("enumerable", ts.createLiteral(true)), ts.createPropertyAssignment("configurable", ts.createLiteral(true))); + var call = ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Object"), "defineProperty"), + /*typeArguments*/ undefined, [ + target, + propertyName, + ts.createObjectLiteral(properties, /*location*/ undefined, /*multiLine*/ true) + ]); + if (startsOnNewLine) { + call.startsOnNewLine = true; + } + return call; + } + /** + * Visits an ArrowFunction and transforms it into a FunctionExpression. + * + * @param node An ArrowFunction node. + */ + function visitArrowFunction(node) { + if (node.transformFlags & 8192 /* ContainsLexicalThis */) { + enableSubstitutionsForCapturedThis(); + } + var func = transformFunctionLikeToExpression(node, /*location*/ node, /*name*/ undefined); + ts.setEmitFlags(func, 256 /* CapturesThis */); + return func; + } + /** + * Visits a FunctionExpression node. + * + * @param node a FunctionExpression node. + */ + function visitFunctionExpression(node) { + return transformFunctionLikeToExpression(node, /*location*/ node, node.name); + } + /** + * Visits a FunctionDeclaration node. + * + * @param node a FunctionDeclaration node. + */ + function visitFunctionDeclaration(node) { + return ts.setOriginalNode(ts.createFunctionDeclaration( + /*decorators*/ undefined, node.modifiers, node.asteriskToken, node.name, + /*typeParameters*/ undefined, ts.visitNodes(node.parameters, visitor, ts.isParameter), + /*type*/ undefined, transformFunctionBody(node), + /*location*/ node), + /*original*/ node); + } + /** + * Transforms a function-like node into a FunctionExpression. + * + * @param node The function-like node to transform. + * @param location The source-map location for the new FunctionExpression. + * @param name The name of the new FunctionExpression. + */ + function transformFunctionLikeToExpression(node, location, name) { + var savedContainingNonArrowFunction = enclosingNonArrowFunction; + if (node.kind !== 180 /* ArrowFunction */) { + enclosingNonArrowFunction = node; + } + var expression = ts.setOriginalNode(ts.createFunctionExpression(node.asteriskToken, name, + /*typeParameters*/ undefined, ts.visitNodes(node.parameters, visitor, ts.isParameter), + /*type*/ undefined, saveStateAndInvoke(node, transformFunctionBody), location), + /*original*/ node); + enclosingNonArrowFunction = savedContainingNonArrowFunction; + return expression; + } + /** + * Transforms the body of a function-like node. + * + * @param node A function-like node. + */ + function transformFunctionBody(node) { + var multiLine = false; // indicates whether the block *must* be emitted as multiple lines + var singleLine = false; // indicates whether the block *may* be emitted as a single line + var statementsLocation; + var closeBraceLocation; + var statements = []; + var body = node.body; + var statementOffset; + startLexicalEnvironment(); + if (ts.isBlock(body)) { + // ensureUseStrict is false because no new prologue-directive should be added. + // addPrologueDirectives will simply put already-existing directives at the beginning of the target statement-array + statementOffset = ts.addPrologueDirectives(statements, body.statements, /*ensureUseStrict*/ false, visitor); + } + addCaptureThisForNodeIfNeeded(statements, node); + addDefaultValueAssignmentsIfNeeded(statements, node); + addRestParameterIfNeeded(statements, node, /*inConstructorWithSynthesizedSuper*/ false); + // If we added any generated statements, this must be a multi-line block. + if (!multiLine && statements.length > 0) { + multiLine = true; + } + if (ts.isBlock(body)) { + statementsLocation = body.statements; + ts.addRange(statements, ts.visitNodes(body.statements, visitor, ts.isStatement, statementOffset)); + // If the original body was a multi-line block, this must be a multi-line block. + if (!multiLine && body.multiLine) { + multiLine = true; } } - function emitForStatement(node) { - emitLoop(node, emitForStatementWorker); - } - function emitForStatementWorker(node, loop) { - var endPos = emitToken(86 /* ForKeyword */, node.pos); - write(" "); - endPos = emitToken(17 /* OpenParenToken */, endPos); - if (node.initializer && node.initializer.kind === 219 /* VariableDeclarationList */) { - var variableDeclarationList = node.initializer; - var startIsEmitted = tryEmitStartOfVariableDeclarationList(variableDeclarationList); - if (startIsEmitted) { - emitCommaList(variableDeclarationList.declarations); + else { + ts.Debug.assert(node.kind === 180 /* ArrowFunction */); + // To align with the old emitter, we use a synthetic end position on the location + // for the statement list we synthesize when we down-level an arrow function with + // an expression function body. This prevents both comments and source maps from + // being emitted for the end position only. + statementsLocation = ts.moveRangeEnd(body, -1); + var equalsGreaterThanToken = node.equalsGreaterThanToken; + if (!ts.nodeIsSynthesized(equalsGreaterThanToken) && !ts.nodeIsSynthesized(body)) { + if (ts.rangeEndIsOnSameLineAsRangeStart(equalsGreaterThanToken, body, currentSourceFile)) { + singleLine = true; } else { - emitVariableDeclarationListSkippingUninitializedEntries(variableDeclarationList); + multiLine = true; } } - else if (node.initializer) { - emit(node.initializer); - } - write(";"); - emitOptional(" ", node.condition); - write(";"); - emitOptional(" ", node.incrementor); - write(")"); - if (loop) { - emitConvertedLoopCall(loop, /*emitAsBlock*/ true); - } - else { - emitNormalLoopBody(node, /*emitAsEmbeddedStatement*/ true); - } + var expression = ts.visitNode(body, visitor, ts.isExpression); + var returnStatement = ts.createReturn(expression, /*location*/ body); + ts.setEmitFlags(returnStatement, 12288 /* NoTokenSourceMaps */ | 1024 /* NoTrailingSourceMap */ | 32768 /* NoTrailingComments */); + statements.push(returnStatement); + // To align with the source map emit for the old emitter, we set a custom + // source map location for the close brace. + closeBraceLocation = body; } - function emitForInOrForOfStatement(node) { - if (languageVersion < 2 /* ES6 */ && node.kind === 208 /* ForOfStatement */) { - emitLoop(node, emitDownLevelForOfStatementWorker); - } - else { - emitLoop(node, emitForInOrForOfStatementWorker); - } + var lexicalEnvironment = endLexicalEnvironment(); + ts.addRange(statements, lexicalEnvironment); + // If we added any final generated statements, this must be a multi-line block + if (!multiLine && lexicalEnvironment && lexicalEnvironment.length) { + multiLine = true; } - function emitForInOrForOfStatementWorker(node, loop) { - var endPos = emitToken(86 /* ForKeyword */, node.pos); - write(" "); - endPos = emitToken(17 /* OpenParenToken */, endPos); - if (node.initializer.kind === 219 /* VariableDeclarationList */) { - var variableDeclarationList = node.initializer; - if (variableDeclarationList.declarations.length >= 1) { - tryEmitStartOfVariableDeclarationList(variableDeclarationList); - emit(variableDeclarationList.declarations[0]); - } - } - else { - emit(node.initializer); - } - if (node.kind === 207 /* ForInStatement */) { - write(" in "); - } - else { - write(" of "); - } - emit(node.expression); - emitToken(18 /* CloseParenToken */, node.expression.end); - if (loop) { - emitConvertedLoopCall(loop, /*emitAsBlock*/ true); - } - else { - emitNormalLoopBody(node, /*emitAsEmbeddedStatement*/ true); + var block = ts.createBlock(ts.createNodeArray(statements, statementsLocation), node.body, multiLine); + if (!multiLine && singleLine) { + ts.setEmitFlags(block, 32 /* SingleLine */); + } + if (closeBraceLocation) { + ts.setTokenSourceMapRange(block, 16 /* CloseBraceToken */, closeBraceLocation); + } + ts.setOriginalNode(block, node.body); + return block; + } + /** + * Visits an ExpressionStatement that contains a destructuring assignment. + * + * @param node An ExpressionStatement node. + */ + function visitExpressionStatement(node) { + // If we are here it is most likely because our expression is a destructuring assignment. + switch (node.expression.kind) { + case 178 /* ParenthesizedExpression */: + return ts.updateStatement(node, visitParenthesizedExpression(node.expression, /*needsDestructuringValue*/ false)); + case 187 /* BinaryExpression */: + return ts.updateStatement(node, visitBinaryExpression(node.expression, /*needsDestructuringValue*/ false)); + } + return ts.visitEachChild(node, visitor, context); + } + /** + * Visits a ParenthesizedExpression that may contain a destructuring assignment. + * + * @param node A ParenthesizedExpression node. + * @param needsDestructuringValue A value indicating whether we need to hold onto the rhs + * of a destructuring assignment. + */ + function visitParenthesizedExpression(node, needsDestructuringValue) { + // If we are here it is most likely because our expression is a destructuring assignment. + if (needsDestructuringValue) { + switch (node.expression.kind) { + case 178 /* ParenthesizedExpression */: + return ts.createParen(visitParenthesizedExpression(node.expression, /*needsDestructuringValue*/ true), + /*location*/ node); + case 187 /* BinaryExpression */: + return ts.createParen(visitBinaryExpression(node.expression, /*needsDestructuringValue*/ true), + /*location*/ node); } } - function emitDownLevelForOfStatementWorker(node, loop) { - // The following ES6 code: - // - // for (let v of expr) { } - // - // should be emitted as - // - // for (let _i = 0, _a = expr; _i < _a.length; _i++) { - // let v = _a[_i]; - // } - // - // where _a and _i are temps emitted to capture the RHS and the counter, - // respectively. - // When the left hand side is an expression instead of a let declaration, - // the "let v" is not emitted. - // When the left hand side is a let/const, the v is renamed if there is - // another v in scope. - // Note that all assignments to the LHS are emitted in the body, including - // all destructuring. - // Note also that because an extra statement is needed to assign to the LHS, - // for-of bodies are always emitted as blocks. - var endPos = emitToken(86 /* ForKeyword */, node.pos); - write(" "); - endPos = emitToken(17 /* OpenParenToken */, endPos); - // Do not emit the LHS let declaration yet, because it might contain destructuring. - // Do not call recordTempDeclaration because we are declaring the temps - // right here. Recording means they will be declared later. - // In the case where the user wrote an identifier as the RHS, like this: - // - // for (let v of arr) { } - // - // we can't reuse 'arr' because it might be modified within the body of the loop. - var counter = createTempVariable(268435456 /* _i */); - var rhsReference = ts.createSynthesizedNode(69 /* Identifier */); - rhsReference.text = node.expression.kind === 69 /* Identifier */ ? - makeUniqueName(node.expression.text) : - makeTempVariableName(0 /* Auto */); - // This is the let keyword for the counter and rhsReference. The let keyword for - // the LHS will be emitted inside the body. - emitStart(node.expression); - write("var "); - // _i = 0 - emitNodeWithoutSourceMap(counter); - write(" = 0"); - emitEnd(node.expression); - // , _a = expr - write(", "); - emitStart(node.expression); - emitNodeWithoutSourceMap(rhsReference); - write(" = "); - emitNodeWithoutSourceMap(node.expression); - emitEnd(node.expression); - write("; "); - // _i < _a.length; - emitStart(node.expression); - emitNodeWithoutSourceMap(counter); - write(" < "); - emitNodeWithCommentsAndWithoutSourcemap(rhsReference); - write(".length"); - emitEnd(node.expression); - write("; "); - // _i++) - emitStart(node.expression); - emitNodeWithoutSourceMap(counter); - write("++"); - emitEnd(node.expression); - emitToken(18 /* CloseParenToken */, node.expression.end); - // Body - write(" {"); - writeLine(); - increaseIndent(); - // Initialize LHS - // let v = _a[_i]; - var rhsIterationValue = createElementAccessExpression(rhsReference, counter); - emitStart(node.initializer); - if (node.initializer.kind === 219 /* VariableDeclarationList */) { - write("var "); - var variableDeclarationList = node.initializer; - if (variableDeclarationList.declarations.length > 0) { - var declaration = variableDeclarationList.declarations[0]; - if (ts.isBindingPattern(declaration.name)) { - // This works whether the declaration is a var, let, or const. - // It will use rhsIterationValue _a[_i] as the initializer. - emitDestructuring(declaration, /*isAssignmentExpressionStatement*/ false, rhsIterationValue); + return ts.visitEachChild(node, visitor, context); + } + /** + * Visits a BinaryExpression that contains a destructuring assignment. + * + * @param node A BinaryExpression node. + * @param needsDestructuringValue A value indicating whether we need to hold onto the rhs + * of a destructuring assignment. + */ + function visitBinaryExpression(node, needsDestructuringValue) { + // If we are here it is because this is a destructuring assignment. + ts.Debug.assert(ts.isDestructuringAssignment(node)); + return ts.flattenDestructuringAssignment(context, node, needsDestructuringValue, hoistVariableDeclaration, visitor); + } + function visitVariableStatement(node) { + if (convertedLoopState && (ts.getCombinedNodeFlags(node.declarationList) & 3 /* BlockScoped */) == 0) { + // we are inside a converted loop - hoist variable declarations + var assignments = void 0; + for (var _i = 0, _a = node.declarationList.declarations; _i < _a.length; _i++) { + var decl = _a[_i]; + hoistVariableDeclarationDeclaredInConvertedLoop(convertedLoopState, decl); + if (decl.initializer) { + var assignment = void 0; + if (ts.isBindingPattern(decl.name)) { + assignment = ts.flattenVariableDestructuringToExpression(context, decl, hoistVariableDeclaration, /*nameSubstitution*/ undefined, visitor); } else { - // The following call does not include the initializer, so we have - // to emit it separately. - emitNodeWithCommentsAndWithoutSourcemap(declaration); - write(" = "); - emitNodeWithoutSourceMap(rhsIterationValue); + assignment = ts.createBinary(decl.name, 56 /* EqualsToken */, decl.initializer); } - } - else { - // It's an empty declaration list. This can only happen in an error case, if the user wrote - // for (let of []) {} - emitNodeWithoutSourceMap(createTempVariable(0 /* Auto */)); - write(" = "); - emitNodeWithoutSourceMap(rhsIterationValue); - } - } - else { - // Initializer is an expression. Emit the expression in the body, so that it's - // evaluated on every iteration. - var assignmentExpression = createBinaryExpression(node.initializer, 56 /* EqualsToken */, rhsIterationValue, /*startsOnNewLine*/ false); - if (node.initializer.kind === 170 /* ArrayLiteralExpression */ || node.initializer.kind === 171 /* ObjectLiteralExpression */) { - // This is a destructuring pattern, so call emitDestructuring instead of emit. Calling emit will not work, because it will cause - // the BinaryExpression to be passed in instead of the expression statement, which will cause emitDestructuring to crash. - emitDestructuring(assignmentExpression, /*isAssignmentExpressionStatement*/ true, /*value*/ undefined); - } - else { - emitNodeWithCommentsAndWithoutSourcemap(assignmentExpression); + (assignments || (assignments = [])).push(assignment); } } - emitEnd(node.initializer); - write(";"); - if (loop) { - writeLine(); - emitConvertedLoopCall(loop, /*emitAsBlock*/ false); + if (assignments) { + return ts.createStatement(ts.reduceLeft(assignments, function (acc, v) { return ts.createBinary(v, 24 /* CommaToken */, acc); }), node); } else { - emitNormalLoopBody(node, /*emitAsEmbeddedStatement*/ false); + // none of declarations has initializer - the entire variable statement can be deleted + return undefined; } - writeLine(); - decreaseIndent(); - write("}"); } - function emitBreakOrContinueStatement(node) { - if (convertedLoopState) { - // check if we can emit break\continue as is - // it is possible if either - // - break\continue is statement labeled and label is located inside the converted loop - // - break\continue is non-labeled and located in non-converted loop\switch statement - var jump = node.kind === 210 /* BreakStatement */ ? 2 /* Break */ : 4 /* Continue */; - var canUseBreakOrContinue = (node.label && convertedLoopState.labels && convertedLoopState.labels[node.label.text]) || - (!node.label && (convertedLoopState.allowedNonLabeledJumps & jump)); - if (!canUseBreakOrContinue) { - write("return "); - // explicit exit from loop -> copy out parameters - copyLoopOutParameters(convertedLoopState, 1 /* ToOutParameter */, /*emitAsStatements*/ false); - if (!node.label) { - if (node.kind === 210 /* BreakStatement */) { - convertedLoopState.nonLocalJumps |= 2 /* Break */; - write("\"break\";"); - } - else { - convertedLoopState.nonLocalJumps |= 4 /* Continue */; - // note: return value is emitted only to simplify debugging, call to converted loop body does not do any dispatching on it. - write("\"continue\";"); - } - } - else { - var labelMarker = void 0; - if (node.kind === 210 /* BreakStatement */) { - labelMarker = "break-" + node.label.text; - setLabeledJump(convertedLoopState, /*isBreak*/ true, node.label.text, labelMarker); - } - else { - labelMarker = "continue-" + node.label.text; - setLabeledJump(convertedLoopState, /*isBreak*/ false, node.label.text, labelMarker); - } - write("\"" + labelMarker + "\";"); - } - return; - } - } - emitToken(node.kind === 210 /* BreakStatement */ ? 70 /* BreakKeyword */ : 75 /* ContinueKeyword */, node.pos); - emitOptional(" ", node.label); - write(";"); + return ts.visitEachChild(node, visitor, context); + } + /** + * Visits a VariableDeclarationList that is block scoped (e.g. `let` or `const`). + * + * @param node A VariableDeclarationList node. + */ + function visitVariableDeclarationList(node) { + if (node.flags & 3 /* BlockScoped */) { + enableSubstitutionsForBlockScopedBindings(); + } + var declarations = ts.flatten(ts.map(node.declarations, node.flags & 1 /* Let */ + ? visitVariableDeclarationInLetDeclarationList + : visitVariableDeclaration)); + var declarationList = ts.createVariableDeclarationList(declarations, /*location*/ node); + ts.setOriginalNode(declarationList, node); + ts.setCommentRange(declarationList, node); + if (node.transformFlags & 2097152 /* ContainsBindingPattern */ + && (ts.isBindingPattern(node.declarations[0].name) + || ts.isBindingPattern(ts.lastOrUndefined(node.declarations).name))) { + // If the first or last declaration is a binding pattern, we need to modify + // the source map range for the declaration list. + var firstDeclaration = ts.firstOrUndefined(declarations); + var lastDeclaration = ts.lastOrUndefined(declarations); + ts.setSourceMapRange(declarationList, ts.createRange(firstDeclaration.pos, lastDeclaration.end)); + } + return declarationList; + } + /** + * Gets a value indicating whether we should emit an explicit initializer for a variable + * declaration in a `let` declaration list. + * + * @param node A VariableDeclaration node. + */ + function shouldEmitExplicitInitializerForLetDeclaration(node) { + // Nested let bindings might need to be initialized explicitly to preserve + // ES6 semantic: + // + // { let x = 1; } + // { let x; } // x here should be undefined. not 1 + // + // Top level bindings never collide with anything and thus don't require + // explicit initialization. As for nested let bindings there are two cases: + // + // - Nested let bindings that were not renamed definitely should be + // initialized explicitly: + // + // { let x = 1; } + // { let x; if (some-condition) { x = 1}; if (x) { /*1*/ } } + // + // Without explicit initialization code in /*1*/ can be executed even if + // some-condition is evaluated to false. + // + // - Renaming introduces fresh name that should not collide with any + // existing names, however renamed bindings sometimes also should be + // explicitly initialized. One particular case: non-captured binding + // declared inside loop body (but not in loop initializer): + // + // let x; + // for (;;) { + // let x; + // } + // + // In downlevel codegen inner 'x' will be renamed so it won't collide + // with outer 'x' however it will should be reset on every iteration as + // if it was declared anew. + // + // * Why non-captured binding? + // - Because if loop contains block scoped binding captured in some + // function then loop body will be rewritten to have a fresh scope + // on every iteration so everything will just work. + // + // * Why loop initializer is excluded? + // - Since we've introduced a fresh name it already will be undefined. + var flags = resolver.getNodeCheckFlags(node); + var isCapturedInFunction = flags & 131072 /* CapturedBlockScopedBinding */; + var isDeclaredInLoop = flags & 262144 /* BlockScopedBindingInLoop */; + var emittedAsTopLevel = ts.isBlockScopedContainerTopLevel(enclosingBlockScopeContainer) + || (isCapturedInFunction + && isDeclaredInLoop + && ts.isBlock(enclosingBlockScopeContainer) + && ts.isIterationStatement(enclosingBlockScopeContainerParent, /*lookInLabeledStatements*/ false)); + var emitExplicitInitializer = !emittedAsTopLevel + && enclosingBlockScopeContainer.kind !== 207 /* ForInStatement */ + && enclosingBlockScopeContainer.kind !== 208 /* ForOfStatement */ + && (!resolver.isDeclarationWithCollidingName(node) + || (isDeclaredInLoop + && !isCapturedInFunction + && !ts.isIterationStatement(enclosingBlockScopeContainer, /*lookInLabeledStatements*/ false))); + return emitExplicitInitializer; + } + /** + * Visits a VariableDeclaration in a `let` declaration list. + * + * @param node A VariableDeclaration node. + */ + function visitVariableDeclarationInLetDeclarationList(node) { + // For binding pattern names that lack initializers there is no point to emit + // explicit initializer since downlevel codegen for destructuring will fail + // in the absence of initializer so all binding elements will say uninitialized + var name = node.name; + if (ts.isBindingPattern(name)) { + return visitVariableDeclaration(node); } - function emitReturnStatement(node) { - if (convertedLoopState) { - convertedLoopState.nonLocalJumps |= 8 /* Return */; - write("return { value: "); - if (node.expression) { - emit(node.expression); - } - else { - write("void 0"); - } - write(" };"); - return; - } - emitToken(94 /* ReturnKeyword */, node.pos); - emitOptional(" ", node.expression); - write(";"); + if (!node.initializer && shouldEmitExplicitInitializerForLetDeclaration(node)) { + var clone_5 = ts.getMutableClone(node); + clone_5.initializer = ts.createVoidZero(); + return clone_5; } - function emitWithStatement(node) { - write("with ("); - emit(node.expression); - write(")"); - emitEmbeddedStatement(node.statement); + return ts.visitEachChild(node, visitor, context); + } + /** + * Visits a VariableDeclaration node with a binding pattern. + * + * @param node A VariableDeclaration node. + */ + function visitVariableDeclaration(node) { + // If we are here it is because the name contains a binding pattern. + if (ts.isBindingPattern(node.name)) { + var recordTempVariablesInLine = !enclosingVariableStatement + || !ts.hasModifier(enclosingVariableStatement, 1 /* Export */); + return ts.flattenVariableDestructuring(context, node, /*value*/ undefined, visitor, recordTempVariablesInLine ? undefined : hoistVariableDeclaration); } - function emitSwitchStatement(node) { - var endPos = emitToken(96 /* SwitchKeyword */, node.pos); - write(" "); - emitToken(17 /* OpenParenToken */, endPos); - emit(node.expression); - endPos = emitToken(18 /* CloseParenToken */, node.expression.end); - write(" "); - var saveAllowedNonLabeledJumps; - if (convertedLoopState) { - saveAllowedNonLabeledJumps = convertedLoopState.allowedNonLabeledJumps; - // for switch statement allow only non-labeled break - convertedLoopState.allowedNonLabeledJumps |= 2 /* Break */; - } - emitCaseBlock(node.caseBlock, endPos); - if (convertedLoopState) { - convertedLoopState.allowedNonLabeledJumps = saveAllowedNonLabeledJumps; + return ts.visitEachChild(node, visitor, context); + } + function visitLabeledStatement(node) { + if (convertedLoopState) { + if (!convertedLoopState.labels) { + convertedLoopState.labels = ts.createMap(); } + convertedLoopState.labels[node.label.text] = node.label.text; } - function emitCaseBlock(node, startPos) { - emitToken(15 /* OpenBraceToken */, startPos); - increaseIndent(); - emitLines(node.clauses); - decreaseIndent(); - writeLine(); - emitToken(16 /* CloseBraceToken */, node.clauses.end); - } - function nodeStartPositionsAreOnSameLine(node1, node2) { - return ts.getLineOfLocalPositionFromLineMap(currentLineMap, ts.skipTrivia(currentText, node1.pos)) === - ts.getLineOfLocalPositionFromLineMap(currentLineMap, ts.skipTrivia(currentText, node2.pos)); + var result; + if (ts.isIterationStatement(node.statement, /*lookInLabeledStatements*/ false) && shouldConvertIterationStatementBody(node.statement)) { + result = ts.visitNodes(ts.createNodeArray([node.statement]), visitor, ts.isStatement); } - function nodeEndPositionsAreOnSameLine(node1, node2) { - return ts.getLineOfLocalPositionFromLineMap(currentLineMap, node1.end) === - ts.getLineOfLocalPositionFromLineMap(currentLineMap, node2.end); + else { + result = ts.visitEachChild(node, visitor, context); } - function nodeEndIsOnSameLineAsNodeStart(node1, node2) { - return ts.getLineOfLocalPositionFromLineMap(currentLineMap, node1.end) === - ts.getLineOfLocalPositionFromLineMap(currentLineMap, ts.skipTrivia(currentText, node2.pos)); + if (convertedLoopState) { + convertedLoopState.labels[node.label.text] = undefined; } - function emitCaseOrDefaultClause(node) { - if (node.kind === 249 /* CaseClause */) { - write("case "); - emit(node.expression); - write(":"); + return result; + } + function visitDoStatement(node) { + return convertIterationStatementBodyIfNecessary(node); + } + function visitWhileStatement(node) { + return convertIterationStatementBodyIfNecessary(node); + } + function visitForStatement(node) { + return convertIterationStatementBodyIfNecessary(node); + } + function visitForInStatement(node) { + return convertIterationStatementBodyIfNecessary(node); + } + /** + * Visits a ForOfStatement and converts it into a compatible ForStatement. + * + * @param node A ForOfStatement. + */ + function visitForOfStatement(node) { + return convertIterationStatementBodyIfNecessary(node, convertForOfToFor); + } + function convertForOfToFor(node, convertedLoopBodyStatements) { + // The following ES6 code: + // + // for (let v of expr) { } + // + // should be emitted as + // + // for (var _i = 0, _a = expr; _i < _a.length; _i++) { + // var v = _a[_i]; + // } + // + // where _a and _i are temps emitted to capture the RHS and the counter, + // respectively. + // When the left hand side is an expression instead of a let declaration, + // the "let v" is not emitted. + // When the left hand side is a let/const, the v is renamed if there is + // another v in scope. + // Note that all assignments to the LHS are emitted in the body, including + // all destructuring. + // Note also that because an extra statement is needed to assign to the LHS, + // for-of bodies are always emitted as blocks. + var expression = ts.visitNode(node.expression, visitor, ts.isExpression); + var initializer = node.initializer; + var statements = []; + // In the case where the user wrote an identifier as the RHS, like this: + // + // for (let v of arr) { } + // + // we don't want to emit a temporary variable for the RHS, just use it directly. + var counter = ts.createLoopVariable(); + var rhsReference = expression.kind === 69 /* Identifier */ + ? ts.createUniqueName(expression.text) + : ts.createTempVariable(/*recordTempVariable*/ undefined); + // Initialize LHS + // var v = _a[_i]; + if (ts.isVariableDeclarationList(initializer)) { + if (initializer.flags & 3 /* BlockScoped */) { + enableSubstitutionsForBlockScopedBindings(); + } + var firstOriginalDeclaration = ts.firstOrUndefined(initializer.declarations); + if (firstOriginalDeclaration && ts.isBindingPattern(firstOriginalDeclaration.name)) { + // This works whether the declaration is a var, let, or const. + // It will use rhsIterationValue _a[_i] as the initializer. + var declarations = ts.flattenVariableDestructuring(context, firstOriginalDeclaration, ts.createElementAccess(rhsReference, counter), visitor); + var declarationList = ts.createVariableDeclarationList(declarations, /*location*/ initializer); + ts.setOriginalNode(declarationList, initializer); + // Adjust the source map range for the first declaration to align with the old + // emitter. + var firstDeclaration = declarations[0]; + var lastDeclaration = ts.lastOrUndefined(declarations); + ts.setSourceMapRange(declarationList, ts.createRange(firstDeclaration.pos, lastDeclaration.end)); + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, declarationList)); } else { - write("default:"); + // The following call does not include the initializer, so we have + // to emit it separately. + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(firstOriginalDeclaration ? firstOriginalDeclaration.name : ts.createTempVariable(/*recordTempVariable*/ undefined), + /*type*/ undefined, ts.createElementAccess(rhsReference, counter)) + ], /*location*/ ts.moveRangePos(initializer, -1)), + /*location*/ ts.moveRangeEnd(initializer, -1))); } - if (node.statements.length === 1 && nodeStartPositionsAreOnSameLine(node, node.statements[0])) { - write(" "); - emit(node.statements[0]); + } + else { + // Initializer is an expression. Emit the expression in the body, so that it's + // evaluated on every iteration. + var assignment = ts.createAssignment(initializer, ts.createElementAccess(rhsReference, counter)); + if (ts.isDestructuringAssignment(assignment)) { + // This is a destructuring pattern, so we flatten the destructuring instead. + statements.push(ts.createStatement(ts.flattenDestructuringAssignment(context, assignment, + /*needsValue*/ false, hoistVariableDeclaration, visitor))); } else { - increaseIndent(); - emitLines(node.statements); - decreaseIndent(); + // Currently there is not way to check that assignment is binary expression of destructing assignment + // so we have to cast never type to binaryExpression + assignment.end = initializer.end; + statements.push(ts.createStatement(assignment, /*location*/ ts.moveRangeEnd(initializer, -1))); } } - function emitThrowStatement(node) { - write("throw "); - emit(node.expression); - write(";"); + var bodyLocation; + var statementsLocation; + if (convertedLoopBodyStatements) { + ts.addRange(statements, convertedLoopBodyStatements); } - function emitTryStatement(node) { - write("try "); - emit(node.tryBlock); - emit(node.catchClause); - if (node.finallyBlock) { - writeLine(); - write("finally "); - emit(node.finallyBlock); + else { + var statement = ts.visitNode(node.statement, visitor, ts.isStatement); + if (ts.isBlock(statement)) { + ts.addRange(statements, statement.statements); + bodyLocation = statement; + statementsLocation = statement.statements; + } + else { + statements.push(statement); + } + } + // The old emitter does not emit source maps for the expression + ts.setEmitFlags(expression, 1536 /* NoSourceMap */ | ts.getEmitFlags(expression)); + // The old emitter does not emit source maps for the block. + // We add the location to preserve comments. + var body = ts.createBlock(ts.createNodeArray(statements, /*location*/ statementsLocation), + /*location*/ bodyLocation); + ts.setEmitFlags(body, 1536 /* NoSourceMap */ | 12288 /* NoTokenSourceMaps */); + var forStatement = ts.createFor(ts.createVariableDeclarationList([ + ts.createVariableDeclaration(counter, /*type*/ undefined, ts.createLiteral(0), /*location*/ ts.moveRangePos(node.expression, -1)), + ts.createVariableDeclaration(rhsReference, /*type*/ undefined, expression, /*location*/ node.expression) + ], /*location*/ node.expression), ts.createLessThan(counter, ts.createPropertyAccess(rhsReference, "length"), + /*location*/ node.expression), ts.createPostfixIncrement(counter, /*location*/ node.expression), body, + /*location*/ node); + // Disable trailing source maps for the OpenParenToken to align source map emit with the old emitter. + ts.setEmitFlags(forStatement, 8192 /* NoTokenTrailingSourceMaps */); + return forStatement; + } + /** + * Visits an ObjectLiteralExpression with computed propety names. + * + * @param node An ObjectLiteralExpression node. + */ + function visitObjectLiteralExpression(node) { + // We are here because a ComputedPropertyName was used somewhere in the expression. + var properties = node.properties; + var numProperties = properties.length; + // Find the first computed property. + // Everything until that point can be emitted as part of the initial object literal. + var numInitialProperties = numProperties; + for (var i = 0; i < numProperties; i++) { + var property = properties[i]; + if (property.transformFlags & 4194304 /* ContainsYield */ + || property.name.kind === 140 /* ComputedPropertyName */) { + numInitialProperties = i; + break; } } - function emitCatchClause(node) { - writeLine(); - var endPos = emitToken(72 /* CatchKeyword */, node.pos); - write(" "); - emitToken(17 /* OpenParenToken */, endPos); - emit(node.variableDeclaration); - emitToken(18 /* CloseParenToken */, node.variableDeclaration ? node.variableDeclaration.end : endPos); - write(" "); - emitBlock(node.block); - } - function emitDebuggerStatement(node) { - emitToken(76 /* DebuggerKeyword */, node.pos); - write(";"); + ts.Debug.assert(numInitialProperties !== numProperties); + // For computed properties, we need to create a unique handle to the object + // literal so we can modify it without risking internal assignments tainting the object. + var temp = ts.createTempVariable(hoistVariableDeclaration); + // Write out the first non-computed properties, then emit the rest through indexing on the temp variable. + var expressions = []; + var assignment = ts.createAssignment(temp, ts.setEmitFlags(ts.createObjectLiteral(ts.visitNodes(properties, visitor, ts.isObjectLiteralElementLike, 0, numInitialProperties), + /*location*/ undefined, node.multiLine), 524288 /* Indented */)); + if (node.multiLine) { + assignment.startsOnNewLine = true; } - function emitLabelAndColon(node) { - emit(node.label); - write(": "); + expressions.push(assignment); + addObjectLiteralMembers(expressions, node, temp, numInitialProperties); + // We need to clone the temporary identifier so that we can write it on a + // new line + expressions.push(node.multiLine ? ts.startOnNewLine(ts.getMutableClone(temp)) : temp); + return ts.inlineExpressions(expressions); + } + function shouldConvertIterationStatementBody(node) { + return (resolver.getNodeCheckFlags(node) & 65536 /* LoopWithCapturedBlockScopedBinding */) !== 0; + } + /** + * Records constituents of name for the given variable to be hoisted in the outer scope. + */ + function hoistVariableDeclarationDeclaredInConvertedLoop(state, node) { + if (!state.hoistedLocalVariables) { + state.hoistedLocalVariables = []; } - function emitLabeledStatement(node) { - if (!ts.isIterationStatement(node.statement, /* lookInLabeledStatements */ false) || !shouldConvertLoopBody(node.statement)) { - emitLabelAndColon(node); + visit(node.name); + function visit(node) { + if (node.kind === 69 /* Identifier */) { + state.hoistedLocalVariables.push(node); } - if (convertedLoopState) { - if (!convertedLoopState.labels) { - convertedLoopState.labels = ts.createMap(); + else { + for (var _i = 0, _a = node.elements; _i < _a.length; _i++) { + var element = _a[_i]; + if (!ts.isOmittedExpression(element)) { + visit(element.name); + } } - convertedLoopState.labels[node.label.text] = node.label.text; } - emit(node.statement); + } + } + function convertIterationStatementBodyIfNecessary(node, convert) { + if (!shouldConvertIterationStatementBody(node)) { + var saveAllowedNonLabeledJumps = void 0; if (convertedLoopState) { - convertedLoopState.labels[node.label.text] = undefined; + // we get here if we are trying to emit normal loop loop inside converted loop + // set allowedNonLabeledJumps to Break | Continue to mark that break\continue inside the loop should be emitted as is + saveAllowedNonLabeledJumps = convertedLoopState.allowedNonLabeledJumps; + convertedLoopState.allowedNonLabeledJumps = 2 /* Break */ | 4 /* Continue */; } - } - function getContainingModule(node) { - do { - node = node.parent; - } while (node && node.kind !== 225 /* ModuleDeclaration */); - return node; - } - function emitContainingModuleName(node) { - var container = getContainingModule(node); - write(container ? getGeneratedNameForNode(container) : "exports"); - } - function emitModuleMemberName(node) { - emitStart(node.name); - if (ts.getCombinedNodeFlags(node) & 1 /* Export */) { - var container = getContainingModule(node); - if (container) { - write(getGeneratedNameForNode(container)); - write("."); - } - else if (modulekind !== ts.ModuleKind.ES6 && modulekind !== ts.ModuleKind.System) { - write("exports."); - } + var result = convert ? convert(node, /*convertedLoopBodyStatements*/ undefined) : ts.visitEachChild(node, visitor, context); + if (convertedLoopState) { + convertedLoopState.allowedNonLabeledJumps = saveAllowedNonLabeledJumps; } - emitNodeWithCommentsAndWithoutSourcemap(node.name); - emitEnd(node.name); - } - function createVoidZero() { - var zero = ts.createSynthesizedNode(8 /* NumericLiteral */); - zero.text = "0"; - var result = ts.createSynthesizedNode(183 /* VoidExpression */); - result.expression = zero; return result; } - function emitEs6ExportDefaultCompat(node) { - if (node.parent.kind === 256 /* SourceFile */) { - ts.Debug.assert(!!(node.flags & 512 /* Default */) || node.kind === 235 /* ExportAssignment */); - // only allow export default at a source file level - if (modulekind === ts.ModuleKind.CommonJS || modulekind === ts.ModuleKind.AMD || modulekind === ts.ModuleKind.UMD) { - if (!isEs6Module) { - if (languageVersion !== 0 /* ES3 */) { - // default value of configurable, enumerable, writable are `false`. - write('Object.defineProperty(exports, "__esModule", { value: true });'); - writeLine(); - } - else { - write("exports.__esModule = true;"); - writeLine(); - } - } - } - } - } - function emitExportMemberAssignment(node) { - if (node.flags & 1 /* Export */) { - writeLine(); - emitStart(node); - // emit call to exporter only for top level nodes - if (modulekind === ts.ModuleKind.System && node.parent === currentSourceFile) { - // emit export default as - // export("default", ) - write(exportFunctionForFile + "(\""); - if (node.flags & 512 /* Default */) { - write("default"); - } - else { - emitNodeWithCommentsAndWithoutSourcemap(node.name); - } - write("\", "); - emitDeclarationName(node); - write(")"); - } - else { - if (node.flags & 512 /* Default */) { - emitEs6ExportDefaultCompat(node); - if (languageVersion === 0 /* ES3 */) { - write('exports["default"]'); - } - else { - write("exports.default"); - } - } - else { - emitModuleMemberName(node); - } - write(" = "); - emitDeclarationName(node); + var functionName = ts.createUniqueName("_loop"); + var loopInitializer; + switch (node.kind) { + case 206 /* ForStatement */: + case 207 /* ForInStatement */: + case 208 /* ForOfStatement */: + var initializer = node.initializer; + if (initializer && initializer.kind === 219 /* VariableDeclarationList */) { + loopInitializer = initializer; } - emitEnd(node); - write(";"); - } + break; } - function emitExportMemberAssignments(name) { - if (modulekind === ts.ModuleKind.System) { - return; + // variables that will be passed to the loop as parameters + var loopParameters = []; + // variables declared in the loop initializer that will be changed inside the loop + var loopOutParameters = []; + if (loopInitializer && (ts.getCombinedNodeFlags(loopInitializer) & 3 /* BlockScoped */)) { + for (var _i = 0, _a = loopInitializer.declarations; _i < _a.length; _i++) { + var decl = _a[_i]; + processLoopVariableDeclaration(decl, loopParameters, loopOutParameters); + } + } + var outerConvertedLoopState = convertedLoopState; + convertedLoopState = { loopOutParameters: loopOutParameters }; + if (outerConvertedLoopState) { + // convertedOuterLoopState !== undefined means that this converted loop is nested in another converted loop. + // if outer converted loop has already accumulated some state - pass it through + if (outerConvertedLoopState.argumentsName) { + // outer loop has already used 'arguments' so we've already have some name to alias it + // use the same name in all nested loops + convertedLoopState.argumentsName = outerConvertedLoopState.argumentsName; + } + if (outerConvertedLoopState.thisName) { + // outer loop has already used 'this' so we've already have some name to alias it + // use the same name in all nested loops + convertedLoopState.thisName = outerConvertedLoopState.thisName; + } + if (outerConvertedLoopState.hoistedLocalVariables) { + // we've already collected some non-block scoped variable declarations in enclosing loop + // use the same storage in nested loop + convertedLoopState.hoistedLocalVariables = outerConvertedLoopState.hoistedLocalVariables; + } + } + var loopBody = ts.visitNode(node.statement, visitor, ts.isStatement); + var currentState = convertedLoopState; + convertedLoopState = outerConvertedLoopState; + if (loopOutParameters.length) { + var statements_3 = ts.isBlock(loopBody) ? loopBody.statements.slice() : [loopBody]; + copyOutParameters(loopOutParameters, 1 /* ToOutParameter */, statements_3); + loopBody = ts.createBlock(statements_3, /*location*/ undefined, /*multiline*/ true); + } + if (!ts.isBlock(loopBody)) { + loopBody = ts.createBlock([loopBody], /*location*/ undefined, /*multiline*/ true); + } + var isAsyncBlockContainingAwait = enclosingNonArrowFunction + && (ts.getEmitFlags(enclosingNonArrowFunction) & 2097152 /* AsyncFunctionBody */) !== 0 + && (node.statement.transformFlags & 4194304 /* ContainsYield */) !== 0; + var loopBodyFlags = 0; + if (currentState.containsLexicalThis) { + loopBodyFlags |= 256 /* CapturesThis */; + } + if (isAsyncBlockContainingAwait) { + loopBodyFlags |= 2097152 /* AsyncFunctionBody */; + } + var convertedLoopVariable = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(functionName, + /*type*/ undefined, ts.setEmitFlags(ts.createFunctionExpression(isAsyncBlockContainingAwait ? ts.createToken(37 /* AsteriskToken */) : undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, loopParameters, + /*type*/ undefined, loopBody), loopBodyFlags)) + ])); + var statements = [convertedLoopVariable]; + var extraVariableDeclarations; + // propagate state from the inner loop to the outer loop if necessary + if (currentState.argumentsName) { + // if alias for arguments is set + if (outerConvertedLoopState) { + // pass it to outer converted loop + outerConvertedLoopState.argumentsName = currentState.argumentsName; } - if (!exportEquals && exportSpecifiers && name.text in exportSpecifiers) { - for (var _a = 0, _b = exportSpecifiers[name.text]; _a < _b.length; _a++) { - var specifier = _b[_a]; - writeLine(); - emitStart(specifier.name); - emitContainingModuleName(specifier); - write("."); - emitNodeWithCommentsAndWithoutSourcemap(specifier.name); - emitEnd(specifier.name); - write(" = "); - emitExpressionIdentifier(name); - write(";"); - } + else { + // this is top level converted loop and we need to create an alias for 'arguments' object + (extraVariableDeclarations || (extraVariableDeclarations = [])).push(ts.createVariableDeclaration(currentState.argumentsName, + /*type*/ undefined, ts.createIdentifier("arguments"))); } } - function emitExportSpecifierInSystemModule(specifier) { - ts.Debug.assert(modulekind === ts.ModuleKind.System); - if (!resolver.getReferencedValueDeclaration(specifier.propertyName || specifier.name) && !resolver.isValueAliasDeclaration(specifier)) { - return; + if (currentState.thisName) { + // if alias for this is set + if (outerConvertedLoopState) { + // pass it to outer converted loop + outerConvertedLoopState.thisName = currentState.thisName; } - writeLine(); - emitStart(specifier.name); - write(exportFunctionForFile + "(\""); - emitNodeWithCommentsAndWithoutSourcemap(specifier.name); - write("\", "); - emitExpressionIdentifier(specifier.propertyName || specifier.name); - write(")"); - emitEnd(specifier.name); - write(";"); - } - /** - * Emit an assignment to a given identifier, 'name', with a given expression, 'value'. - * @param name an identifier as a left-hand-side operand of the assignment - * @param value an expression as a right-hand-side operand of the assignment - * @param shouldEmitCommaBeforeAssignment a boolean indicating whether to prefix an assignment with comma - */ - function emitAssignment(name, value, shouldEmitCommaBeforeAssignment, nodeForSourceMap) { - if (shouldEmitCommaBeforeAssignment) { - write(", "); - } - var exportChanged = isNameOfExportedSourceLevelDeclarationInSystemExternalModule(name); - if (exportChanged) { - write(exportFunctionForFile + "(\""); - emitNodeWithCommentsAndWithoutSourcemap(name); - write("\", "); - } - var isVariableDeclarationOrBindingElement = name.parent && (name.parent.kind === 218 /* VariableDeclaration */ || name.parent.kind === 169 /* BindingElement */); - // If this is first var declaration, we need to start at var/let/const keyword instead - // otherwise use nodeForSourceMap as the start position - emitStart(isFirstVariableDeclaration(nodeForSourceMap) ? nodeForSourceMap.parent : nodeForSourceMap); - withTemporaryNoSourceMap(function () { - if (isVariableDeclarationOrBindingElement) { - emitModuleMemberName(name.parent); - } - else { - emit(name); - } - write(" = "); - emit(value); - }); - emitEnd(nodeForSourceMap, /*stopOverridingSpan*/ true); - if (exportChanged) { - write(")"); + else { + // this is top level converted loop so we need to create an alias for 'this' here + // NOTE: + // if converted loops were all nested in arrow function then we'll always emit '_this' so convertedLoopState.thisName will not be set. + // If it is set this means that all nested loops are not nested in arrow function and it is safe to capture 'this'. + (extraVariableDeclarations || (extraVariableDeclarations = [])).push(ts.createVariableDeclaration(currentState.thisName, + /*type*/ undefined, ts.createIdentifier("this"))); } } - /** - * Create temporary variable, emit an assignment of the variable the given expression - * @param expression an expression to assign to the newly created temporary variable - * @param canDefineTempVariablesInPlace a boolean indicating whether you can define the temporary variable at an assignment location - * @param shouldEmitCommaBeforeAssignment a boolean indicating whether an assignment should prefix with comma - */ - function emitTempVariableAssignment(expression, canDefineTempVariablesInPlace, shouldEmitCommaBeforeAssignment, sourceMapNode) { - var identifier = createTempVariable(0 /* Auto */); - if (!canDefineTempVariablesInPlace) { - recordTempDeclaration(identifier); - } - emitAssignment(identifier, expression, shouldEmitCommaBeforeAssignment, sourceMapNode || expression.parent); - return identifier; - } - function isFirstVariableDeclaration(root) { - return root.kind === 218 /* VariableDeclaration */ && - root.parent.kind === 219 /* VariableDeclarationList */ && - root.parent.declarations[0] === root; - } - function emitDestructuring(root, isAssignmentExpressionStatement, value) { - var emitCount = 0; - // An exported declaration is actually emitted as an assignment (to a property on the module object), so - // temporary variables in an exported declaration need to have real declarations elsewhere - // Also temporary variables should be explicitly allocated for source level declarations when module target is system - // because actual variable declarations are hoisted - var canDefineTempVariablesInPlace = false; - if (root.kind === 218 /* VariableDeclaration */) { - var isExported = ts.getCombinedNodeFlags(root) & 1 /* Export */; - var isSourceLevelForSystemModuleKind = shouldHoistDeclarationInSystemJsModule(root); - canDefineTempVariablesInPlace = !isExported && !isSourceLevelForSystemModuleKind; - } - else if (root.kind === 142 /* Parameter */) { - canDefineTempVariablesInPlace = true; - } - if (root.kind === 187 /* BinaryExpression */) { - emitAssignmentExpression(root); + if (currentState.hoistedLocalVariables) { + // if hoistedLocalVariables !== undefined this means that we've possibly collected some variable declarations to be hoisted later + if (outerConvertedLoopState) { + // pass them to outer converted loop + outerConvertedLoopState.hoistedLocalVariables = currentState.hoistedLocalVariables; } else { - ts.Debug.assert(!isAssignmentExpressionStatement); - // If first variable declaration of variable statement correct the start location - if (isFirstVariableDeclaration(root)) { - // Use emit location of "var " as next emit start entry - sourceMap.changeEmitSourcePos(); + if (!extraVariableDeclarations) { + extraVariableDeclarations = []; } - emitBindingElement(root, value); - } - /** - * Ensures that there exists a declared identifier whose value holds the given expression. - * This function is useful to ensure that the expression's value can be read from in subsequent expressions. - * Unless 'reuseIdentifierExpressions' is false, 'expr' will be returned if it is just an identifier. - * - * @param expr the expression whose value needs to be bound. - * @param reuseIdentifierExpressions true if identifier expressions can simply be returned; - * false if it is necessary to always emit an identifier. - */ - function ensureIdentifier(expr, reuseIdentifierExpressions, sourceMapNode) { - if (expr.kind === 69 /* Identifier */ && reuseIdentifierExpressions) { - return expr; + // hoist collected variable declarations + for (var name_36 in currentState.hoistedLocalVariables) { + var identifier = currentState.hoistedLocalVariables[name_36]; + extraVariableDeclarations.push(ts.createVariableDeclaration(identifier)); } - var identifier = emitTempVariableAssignment(expr, canDefineTempVariablesInPlace, emitCount > 0, sourceMapNode); - emitCount++; - return identifier; - } - function createDefaultValueCheck(value, defaultValue, sourceMapNode) { - // The value expression will be evaluated twice, so for anything but a simple identifier - // we need to generate a temporary variable - // If the temporary variable needs to be emitted use the source Map node for assignment of that statement - value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, sourceMapNode); - // Return the expression 'value === void 0 ? defaultValue : value' - var equals = ts.createSynthesizedNode(187 /* BinaryExpression */); - equals.left = value; - equals.operatorToken = ts.createSynthesizedNode(32 /* EqualsEqualsEqualsToken */); - equals.right = createVoidZero(); - return createConditionalExpression(equals, defaultValue, value); - } - function createConditionalExpression(condition, whenTrue, whenFalse) { - var cond = ts.createSynthesizedNode(188 /* ConditionalExpression */); - cond.condition = condition; - cond.questionToken = ts.createSynthesizedNode(53 /* QuestionToken */); - cond.whenTrue = whenTrue; - cond.colonToken = ts.createSynthesizedNode(54 /* ColonToken */); - cond.whenFalse = whenFalse; - return cond; - } - function createNumericLiteral(value) { - var node = ts.createSynthesizedNode(8 /* NumericLiteral */); - node.text = "" + value; - return node; } - function createPropertyAccessForDestructuringProperty(object, propName) { - var index; - var nameIsComputed = propName.kind === 140 /* ComputedPropertyName */; - if (nameIsComputed) { - // TODO to handle when we look into sourcemaps for computed properties, for now use propName - index = ensureIdentifier(propName.expression, /*reuseIdentifierExpressions*/ false, propName); - } - else { - // We create a synthetic copy of the identifier in order to avoid the rewriting that might - // otherwise occur when the identifier is emitted. - index = ts.createSynthesizedNode(propName.kind); - // We need to unescape identifier here because when parsing an identifier prefixing with "__" - // the parser need to append "_" in order to escape colliding with magic identifiers such as "__proto__" - // Therefore, in order to correctly emit identifiers that are written in original TypeScript file, - // we will unescapeIdentifier to remove additional underscore (if no underscore is added, the function will return original input string) - index.text = ts.unescapeIdentifier(propName.text); - } - return !nameIsComputed && index.kind === 69 /* Identifier */ - ? createPropertyAccessExpression(object, index) - : createElementAccessExpression(object, index); - } - function createSliceCall(value, sliceIndex) { - var call = ts.createSynthesizedNode(174 /* CallExpression */); - var sliceIdentifier = ts.createSynthesizedNode(69 /* Identifier */); - sliceIdentifier.text = "slice"; - call.expression = createPropertyAccessExpression(value, sliceIdentifier); - call.arguments = ts.createSynthesizedNodeArray(); - call.arguments[0] = createNumericLiteral(sliceIndex); - return call; - } - function emitObjectLiteralAssignment(target, value, sourceMapNode) { - var properties = target.properties; - if (properties.length !== 1) { - // For anything but a single element destructuring we need to generate a temporary - // to ensure value is evaluated exactly once. - // When doing so we want to highlight the passed in source map node since thats the one needing this temp assignment - value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, sourceMapNode); - } - for (var _a = 0, properties_5 = properties; _a < properties_5.length; _a++) { - var p = properties_5[_a]; - if (p.kind === 253 /* PropertyAssignment */ || p.kind === 254 /* ShorthandPropertyAssignment */) { - var propName = p.name; - var target_1 = p.kind === 254 /* ShorthandPropertyAssignment */ ? p : p.initializer || propName; - // Assignment for target = value.propName should highlight whole property, hence use p as source map node - emitDestructuringAssignment(target_1, createPropertyAccessForDestructuringProperty(value, propName), p); - } - } - } - function emitArrayLiteralAssignment(target, value, sourceMapNode) { - var elements = target.elements; - if (elements.length !== 1) { - // For anything but a single element destructuring we need to generate a temporary - // to ensure value is evaluated exactly once. - // When doing so we want to highlight the passed in source map node since thats the one needing this temp assignment - value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, sourceMapNode); - } - for (var i = 0; i < elements.length; i++) { - var e = elements[i]; - if (e.kind !== 193 /* OmittedExpression */) { - // Assignment for target = value.propName should highlight whole property, hence use e as source map node - if (e.kind !== 191 /* SpreadElementExpression */) { - emitDestructuringAssignment(e, createElementAccessExpression(value, createNumericLiteral(i)), e); - } - else if (i === elements.length - 1) { - emitDestructuringAssignment(e.expression, createSliceCall(value, i), e); - } - } - } - } - function emitDestructuringAssignment(target, value, sourceMapNode) { - // When emitting target = value use source map node to highlight, including any temporary assignments needed for this - if (target.kind === 254 /* ShorthandPropertyAssignment */) { - if (target.objectAssignmentInitializer) { - value = createDefaultValueCheck(value, target.objectAssignmentInitializer, sourceMapNode); - } - target = target.name; - } - else if (target.kind === 187 /* BinaryExpression */ && target.operatorToken.kind === 56 /* EqualsToken */) { - value = createDefaultValueCheck(value, target.right, sourceMapNode); - target = target.left; - } - if (target.kind === 171 /* ObjectLiteralExpression */) { - emitObjectLiteralAssignment(target, value, sourceMapNode); - } - else if (target.kind === 170 /* ArrayLiteralExpression */) { - emitArrayLiteralAssignment(target, value, sourceMapNode); - } - else { - emitAssignment(target, value, /*shouldEmitCommaBeforeAssignment*/ emitCount > 0, sourceMapNode); - emitCount++; - } + } + // add extra variables to hold out parameters if necessary + if (loopOutParameters.length) { + if (!extraVariableDeclarations) { + extraVariableDeclarations = []; } - function emitAssignmentExpression(root) { - var target = root.left; - var value = root.right; - if (ts.isEmptyObjectLiteralOrArrayLiteral(target)) { - emit(value); - } - else if (isAssignmentExpressionStatement) { - // Source map node for root.left = root.right is root - // but if root is synthetic, which could be in below case, use the target which is { a } - // for ({a} of {a: string}) { - // } - emitDestructuringAssignment(target, value, ts.nodeIsSynthesized(root) ? target : root); - } - else { - if (root.parent.kind !== 178 /* ParenthesizedExpression */) { - write("("); - } - // Temporary assignment needed to emit root should highlight whole binary expression - value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, root); - // Source map node for root.left = root.right is root - emitDestructuringAssignment(target, value, root); - write(", "); - emit(value); - if (root.parent.kind !== 178 /* ParenthesizedExpression */) { - write(")"); - } - } - } - function emitBindingElement(target, value) { - // Any temporary assignments needed to emit target = value should point to target - if (target.initializer) { - // Combine value and initializer - value = value ? createDefaultValueCheck(value, target.initializer, target) : target.initializer; - } - else if (!value) { - // Use 'void 0' in absence of value and initializer - value = createVoidZero(); - } - if (ts.isBindingPattern(target.name)) { - var pattern = target.name; - var elements = pattern.elements; - var numElements = elements.length; - if (numElements !== 1) { - // For anything other than a single-element destructuring we need to generate a temporary - // to ensure value is evaluated exactly once. Additionally, if we have zero elements - // we need to emit *something* to ensure that in case a 'var' keyword was already emitted, - // so in that case, we'll intentionally create that temporary. - value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ numElements !== 0, target); - } - for (var i = 0; i < numElements; i++) { - var element = elements[i]; - if (pattern.kind === 167 /* ObjectBindingPattern */) { - // Rewrite element to a declaration with an initializer that fetches property - var propName = element.propertyName || element.name; - emitBindingElement(element, createPropertyAccessForDestructuringProperty(value, propName)); - } - else if (element.kind !== 193 /* OmittedExpression */) { - if (!element.dotDotDotToken) { - // Rewrite element to a declaration that accesses array element at index i - emitBindingElement(element, createElementAccessExpression(value, createNumericLiteral(i))); - } - else if (i === numElements - 1) { - emitBindingElement(element, createSliceCall(value, i)); - } - } - } - } - else { - emitAssignment(target.name, value, /*shouldEmitCommaBeforeAssignment*/ emitCount > 0, target); - emitCount++; - } + for (var _b = 0, loopOutParameters_1 = loopOutParameters; _b < loopOutParameters_1.length; _b++) { + var outParam = loopOutParameters_1[_b]; + extraVariableDeclarations.push(ts.createVariableDeclaration(outParam.outParamName)); } } - function emitVariableDeclaration(node) { - if (ts.isBindingPattern(node.name)) { - var isExported = ts.getCombinedNodeFlags(node) & 1 /* Export */; - if (languageVersion >= 2 /* ES6 */ && (!isExported || modulekind === ts.ModuleKind.ES6)) { - // emit ES6 destructuring only if target module is ES6 or variable is not exported - // exported variables in CJS/AMD are prefixed with 'exports.' so result javascript { exports.toString } = 1; is illegal - var isTopLevelDeclarationInSystemModule = modulekind === ts.ModuleKind.System && - shouldHoistVariable(node, /*checkIfSourceFileLevelDecl*/ true); - if (isTopLevelDeclarationInSystemModule) { - // In System modules top level variables are hoisted - // so variable declarations with destructuring are turned into destructuring assignments. - // As a result, they will need parentheses to disambiguate object binding assignments from blocks. - write("("); - } - emit(node.name); - emitOptional(" = ", node.initializer); - if (isTopLevelDeclarationInSystemModule) { - write(")"); - } + // create variable statement to hold all introduced variable declarations + if (extraVariableDeclarations) { + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList(extraVariableDeclarations))); + } + var convertedLoopBodyStatements = generateCallToConvertedLoop(functionName, loopParameters, currentState, isAsyncBlockContainingAwait); + var loop; + if (convert) { + loop = convert(node, convertedLoopBodyStatements); + } + else { + loop = ts.getMutableClone(node); + // clean statement part + loop.statement = undefined; + // visit childnodes to transform initializer/condition/incrementor parts + loop = ts.visitEachChild(loop, visitor, context); + // set loop statement + loop.statement = ts.createBlock(convertedLoopBodyStatements, + /*location*/ undefined, + /*multiline*/ true); + // reset and re-aggregate the transform flags + loop.transformFlags = 0; + ts.aggregateTransformFlags(loop); + } + statements.push(currentParent.kind === 214 /* LabeledStatement */ + ? ts.createLabel(currentParent.label, loop) + : loop); + return statements; + } + function copyOutParameter(outParam, copyDirection) { + var source = copyDirection === 0 /* ToOriginal */ ? outParam.outParamName : outParam.originalName; + var target = copyDirection === 0 /* ToOriginal */ ? outParam.originalName : outParam.outParamName; + return ts.createBinary(target, 56 /* EqualsToken */, source); + } + function copyOutParameters(outParams, copyDirection, statements) { + for (var _i = 0, outParams_1 = outParams; _i < outParams_1.length; _i++) { + var outParam = outParams_1[_i]; + statements.push(ts.createStatement(copyOutParameter(outParam, copyDirection))); + } + } + function generateCallToConvertedLoop(loopFunctionExpressionName, parameters, state, isAsyncBlockContainingAwait) { + var outerConvertedLoopState = convertedLoopState; + var statements = []; + // loop is considered simple if it does not have any return statements or break\continue that transfer control outside of the loop + // simple loops are emitted as just 'loop()'; + // NOTE: if loop uses only 'continue' it still will be emitted as simple loop + var isSimpleLoop = !(state.nonLocalJumps & ~4 /* Continue */) && + !state.labeledNonLocalBreaks && + !state.labeledNonLocalContinues; + var call = ts.createCall(loopFunctionExpressionName, /*typeArguments*/ undefined, ts.map(parameters, function (p) { return p.name; })); + var callResult = isAsyncBlockContainingAwait ? ts.createYield(ts.createToken(37 /* AsteriskToken */), call) : call; + if (isSimpleLoop) { + statements.push(ts.createStatement(callResult)); + copyOutParameters(state.loopOutParameters, 0 /* ToOriginal */, statements); + } + else { + var loopResultName = ts.createUniqueName("state"); + var stateVariable = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(loopResultName, /*type*/ undefined, callResult)])); + statements.push(stateVariable); + copyOutParameters(state.loopOutParameters, 0 /* ToOriginal */, statements); + if (state.nonLocalJumps & 8 /* Return */) { + var returnStatement = void 0; + if (outerConvertedLoopState) { + outerConvertedLoopState.nonLocalJumps |= 8 /* Return */; + returnStatement = ts.createReturn(loopResultName); } else { - emitDestructuring(node, /*isAssignmentExpressionStatement*/ false); + returnStatement = ts.createReturn(ts.createPropertyAccess(loopResultName, "value")); } + statements.push(ts.createIf(ts.createBinary(ts.createTypeOf(loopResultName), 32 /* EqualsEqualsEqualsToken */, ts.createLiteral("object")), returnStatement)); } - else { - var initializer = node.initializer; - if (!initializer && - languageVersion < 2 /* ES6 */ && - // for names - binding patterns that lack initializer there is no point to emit explicit initializer - // since downlevel codegen for destructuring will fail in the absence of initializer so all binding elements will say uninitialized - node.name.kind === 69 /* Identifier */) { - var container = ts.getEnclosingBlockScopeContainer(node); - var flags = resolver.getNodeCheckFlags(node); - // nested let bindings might need to be initialized explicitly to preserve ES6 semantic - // { let x = 1; } - // { let x; } // x here should be undefined. not 1 - // NOTES: - // Top level bindings never collide with anything and thus don't require explicit initialization. - // As for nested let bindings there are two cases: - // - nested let bindings that were not renamed definitely should be initialized explicitly - // { let x = 1; } - // { let x; if (some-condition) { x = 1}; if (x) { /*1*/ } } - // Without explicit initialization code in /*1*/ can be executed even if some-condition is evaluated to false - // - renaming introduces fresh name that should not collide with any existing names, however renamed bindings sometimes also should be - // explicitly initialized. One particular case: non-captured binding declared inside loop body (but not in loop initializer) - // let x; - // for (;;) { - // let x; - // } - // in downlevel codegen inner 'x' will be renamed so it won't collide with outer 'x' however it will should be reset on every iteration - // as if it was declared anew. - // * Why non-captured binding - because if loop contains block scoped binding captured in some function then loop body will be rewritten - // to have a fresh scope on every iteration so everything will just work. - // * Why loop initializer is excluded - since we've introduced a fresh name it already will be undefined. - var isCapturedInFunction = flags & 131072 /* CapturedBlockScopedBinding */; - var isDeclaredInLoop = flags & 262144 /* BlockScopedBindingInLoop */; - var emittedAsTopLevel = ts.isBlockScopedContainerTopLevel(container) || - (isCapturedInFunction && isDeclaredInLoop && container.kind === 199 /* Block */ && ts.isIterationStatement(container.parent, /*lookInLabeledStatements*/ false)); - var emittedAsNestedLetDeclaration = ts.getCombinedNodeFlags(node) & 1024 /* Let */ && - !emittedAsTopLevel; - var emitExplicitInitializer = emittedAsNestedLetDeclaration && - container.kind !== 207 /* ForInStatement */ && - container.kind !== 208 /* ForOfStatement */ && - (!resolver.isDeclarationWithCollidingName(node) || - (isDeclaredInLoop && !isCapturedInFunction && !ts.isIterationStatement(container, /*lookInLabeledStatements*/ false))); - if (emitExplicitInitializer) { - initializer = createVoidZero(); - } - } - var exportChanged = isNameOfExportedSourceLevelDeclarationInSystemExternalModule(node.name); - if (exportChanged) { - write(exportFunctionForFile + "(\""); - emitNodeWithCommentsAndWithoutSourcemap(node.name); - write("\", "); - } - emitModuleMemberName(node); - emitOptional(" = ", initializer); - if (exportChanged) { - write(")"); - } - } - } - function emitExportVariableAssignments(node) { - if (node.kind === 193 /* OmittedExpression */) { - return; + if (state.nonLocalJumps & 2 /* Break */) { + statements.push(ts.createIf(ts.createBinary(loopResultName, 32 /* EqualsEqualsEqualsToken */, ts.createLiteral("break")), ts.createBreak())); } - var name = node.name; - if (name.kind === 69 /* Identifier */) { - emitExportMemberAssignments(name); + if (state.labeledNonLocalBreaks || state.labeledNonLocalContinues) { + var caseClauses = []; + processLabeledJumps(state.labeledNonLocalBreaks, /*isBreak*/ true, loopResultName, outerConvertedLoopState, caseClauses); + processLabeledJumps(state.labeledNonLocalContinues, /*isBreak*/ false, loopResultName, outerConvertedLoopState, caseClauses); + statements.push(ts.createSwitch(loopResultName, ts.createCaseBlock(caseClauses))); } - else if (ts.isBindingPattern(name)) { - ts.forEach(name.elements, emitExportVariableAssignments); + } + return statements; + } + function setLabeledJump(state, isBreak, labelText, labelMarker) { + if (isBreak) { + if (!state.labeledNonLocalBreaks) { + state.labeledNonLocalBreaks = ts.createMap(); + } + state.labeledNonLocalBreaks[labelText] = labelMarker; + } + else { + if (!state.labeledNonLocalContinues) { + state.labeledNonLocalContinues = ts.createMap(); } + state.labeledNonLocalContinues[labelText] = labelMarker; } - function isES6ExportedDeclaration(node) { - return !!(node.flags & 1 /* Export */) && - modulekind === ts.ModuleKind.ES6 && - node.parent.kind === 256 /* SourceFile */; + } + function processLabeledJumps(table, isBreak, loopResultName, outerLoop, caseClauses) { + if (!table) { + return; } - function emitVariableStatement(node) { - var startIsEmitted = false; - if (node.flags & 1 /* Export */) { - if (isES6ExportedDeclaration(node)) { - // Exported ES6 module member - write("export "); - startIsEmitted = tryEmitStartOfVariableDeclarationList(node.declarationList); - } + for (var labelText in table) { + var labelMarker = table[labelText]; + var statements = []; + // if there are no outer converted loop or outer label in question is located inside outer converted loop + // then emit labeled break\continue + // otherwise propagate pair 'label -> marker' to outer converted loop and emit 'return labelMarker' so outer loop can later decide what to do + if (!outerLoop || (outerLoop.labels && outerLoop.labels[labelText])) { + var label = ts.createIdentifier(labelText); + statements.push(isBreak ? ts.createBreak(label) : ts.createContinue(label)); } else { - startIsEmitted = tryEmitStartOfVariableDeclarationList(node.declarationList); + setLabeledJump(outerLoop, isBreak, labelText, labelMarker); + statements.push(ts.createReturn(loopResultName)); } - if (startIsEmitted) { - emitCommaList(node.declarationList.declarations); - write(";"); - } - else { - var atLeastOneItem = emitVariableDeclarationListSkippingUninitializedEntries(node.declarationList); - if (atLeastOneItem) { - write(";"); + caseClauses.push(ts.createCaseClause(ts.createLiteral(labelMarker), statements)); + } + } + function processLoopVariableDeclaration(decl, loopParameters, loopOutParameters) { + var name = decl.name; + if (ts.isBindingPattern(name)) { + for (var _i = 0, _a = name.elements; _i < _a.length; _i++) { + var element = _a[_i]; + if (!ts.isOmittedExpression(element)) { + processLoopVariableDeclaration(element, loopParameters, loopOutParameters); } } - if (modulekind !== ts.ModuleKind.ES6 && node.parent === currentSourceFile) { - ts.forEach(node.declarationList.declarations, emitExportVariableAssignments); + } + else { + loopParameters.push(ts.createParameter(name)); + if (resolver.getNodeCheckFlags(decl) & 2097152 /* NeedsLoopOutParameter */) { + var outParamName = ts.createUniqueName("out_" + name.text); + loopOutParameters.push({ originalName: name, outParamName: outParamName }); + } + } + } + /** + * Adds the members of an object literal to an array of expressions. + * + * @param expressions An array of expressions. + * @param node An ObjectLiteralExpression node. + * @param receiver The receiver for members of the ObjectLiteralExpression. + * @param numInitialNonComputedProperties The number of initial properties without + * computed property names. + */ + function addObjectLiteralMembers(expressions, node, receiver, start) { + var properties = node.properties; + var numProperties = properties.length; + for (var i = start; i < numProperties; i++) { + var property = properties[i]; + switch (property.kind) { + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + var accessors = ts.getAllAccessorDeclarations(node.properties, property); + if (property === accessors.firstAccessor) { + expressions.push(transformAccessorsToExpression(receiver, accessors, node.multiLine)); + } + break; + case 253 /* PropertyAssignment */: + expressions.push(transformPropertyAssignmentToExpression(node, property, receiver, node.multiLine)); + break; + case 254 /* ShorthandPropertyAssignment */: + expressions.push(transformShorthandPropertyAssignmentToExpression(node, property, receiver, node.multiLine)); + break; + case 147 /* MethodDeclaration */: + expressions.push(transformObjectLiteralMethodDeclarationToExpression(node, property, receiver, node.multiLine)); + break; + default: + ts.Debug.failBadSyntaxKind(node); + break; } } - function shouldEmitLeadingAndTrailingCommentsForVariableStatement(node) { - // If we're not exporting the variables, there's nothing special here. - // Always emit comments for these nodes. - if (!(node.flags & 1 /* Export */)) { - return true; + } + /** + * Transforms a PropertyAssignment node into an expression. + * + * @param node The ObjectLiteralExpression that contains the PropertyAssignment. + * @param property The PropertyAssignment node. + * @param receiver The receiver for the assignment. + */ + function transformPropertyAssignmentToExpression(node, property, receiver, startsOnNewLine) { + var expression = ts.createAssignment(ts.createMemberAccessForPropertyName(receiver, ts.visitNode(property.name, visitor, ts.isPropertyName)), ts.visitNode(property.initializer, visitor, ts.isExpression), + /*location*/ property); + if (startsOnNewLine) { + expression.startsOnNewLine = true; + } + return expression; + } + /** + * Transforms a ShorthandPropertyAssignment node into an expression. + * + * @param node The ObjectLiteralExpression that contains the ShorthandPropertyAssignment. + * @param property The ShorthandPropertyAssignment node. + * @param receiver The receiver for the assignment. + */ + function transformShorthandPropertyAssignmentToExpression(node, property, receiver, startsOnNewLine) { + var expression = ts.createAssignment(ts.createMemberAccessForPropertyName(receiver, ts.visitNode(property.name, visitor, ts.isPropertyName)), ts.getSynthesizedClone(property.name), + /*location*/ property); + if (startsOnNewLine) { + expression.startsOnNewLine = true; + } + return expression; + } + /** + * Transforms a MethodDeclaration of an ObjectLiteralExpression into an expression. + * + * @param node The ObjectLiteralExpression that contains the MethodDeclaration. + * @param method The MethodDeclaration node. + * @param receiver The receiver for the assignment. + */ + function transformObjectLiteralMethodDeclarationToExpression(node, method, receiver, startsOnNewLine) { + var expression = ts.createAssignment(ts.createMemberAccessForPropertyName(receiver, ts.visitNode(method.name, visitor, ts.isPropertyName)), transformFunctionLikeToExpression(method, /*location*/ method, /*name*/ undefined), + /*location*/ method); + if (startsOnNewLine) { + expression.startsOnNewLine = true; + } + return expression; + } + /** + * Visits a MethodDeclaration of an ObjectLiteralExpression and transforms it into a + * PropertyAssignment. + * + * @param node A MethodDeclaration node. + */ + function visitMethodDeclaration(node) { + // We should only get here for methods on an object literal with regular identifier names. + // Methods on classes are handled in visitClassDeclaration/visitClassExpression. + // Methods with computed property names are handled in visitObjectLiteralExpression. + ts.Debug.assert(!ts.isComputedPropertyName(node.name)); + var functionExpression = transformFunctionLikeToExpression(node, /*location*/ ts.moveRangePos(node, -1), /*name*/ undefined); + ts.setEmitFlags(functionExpression, 16384 /* NoLeadingComments */ | ts.getEmitFlags(functionExpression)); + return ts.createPropertyAssignment(node.name, functionExpression, + /*location*/ node); + } + /** + * Visits a ShorthandPropertyAssignment and transforms it into a PropertyAssignment. + * + * @param node A ShorthandPropertyAssignment node. + */ + function visitShorthandPropertyAssignment(node) { + return ts.createPropertyAssignment(node.name, ts.getSynthesizedClone(node.name), + /*location*/ node); + } + /** + * Visits a YieldExpression node. + * + * @param node A YieldExpression node. + */ + function visitYieldExpression(node) { + // `yield` expressions are transformed using the generators transformer. + return ts.visitEachChild(node, visitor, context); + } + /** + * Visits an ArrayLiteralExpression that contains a spread element. + * + * @param node An ArrayLiteralExpression node. + */ + function visitArrayLiteralExpression(node) { + // We are here because we contain a SpreadElementExpression. + return transformAndSpreadElements(node.elements, /*needsUniqueCopy*/ true, node.multiLine, /*hasTrailingComma*/ node.elements.hasTrailingComma); + } + /** + * Visits a CallExpression that contains either a spread element or `super`. + * + * @param node a CallExpression. + */ + function visitCallExpression(node) { + return visitCallExpressionWithPotentialCapturedThisAssignment(node, /*assignToCapturedThis*/ true); + } + function visitImmediateSuperCallInBody(node) { + return visitCallExpressionWithPotentialCapturedThisAssignment(node, /*assignToCapturedThis*/ false); + } + function visitCallExpressionWithPotentialCapturedThisAssignment(node, assignToCapturedThis) { + // We are here either because SuperKeyword was used somewhere in the expression, or + // because we contain a SpreadElementExpression. + var _a = ts.createCallBinding(node.expression, hoistVariableDeclaration), target = _a.target, thisArg = _a.thisArg; + if (node.expression.kind === 95 /* SuperKeyword */) { + ts.setEmitFlags(thisArg, 128 /* NoSubstitution */); + } + var resultingCall; + if (node.transformFlags & 262144 /* ContainsSpreadElementExpression */) { + // [source] + // f(...a, b) + // x.m(...a, b) + // super(...a, b) + // super.m(...a, b) // in static + // super.m(...a, b) // in instance + // + // [output] + // f.apply(void 0, a.concat([b])) + // (_a = x).m.apply(_a, a.concat([b])) + // _super.apply(this, a.concat([b])) + // _super.m.apply(this, a.concat([b])) + // _super.prototype.m.apply(this, a.concat([b])) + resultingCall = ts.createFunctionApply(ts.visitNode(target, visitor, ts.isExpression), ts.visitNode(thisArg, visitor, ts.isExpression), transformAndSpreadElements(node.arguments, /*needsUniqueCopy*/ false, /*multiLine*/ false, /*hasTrailingComma*/ false)); + } + else { + // [source] + // super(a) + // super.m(a) // in static + // super.m(a) // in instance + // + // [output] + // _super.call(this, a) + // _super.m.call(this, a) + // _super.prototype.m.call(this, a) + resultingCall = ts.createFunctionCall(ts.visitNode(target, visitor, ts.isExpression), ts.visitNode(thisArg, visitor, ts.isExpression), ts.visitNodes(node.arguments, visitor, ts.isExpression), + /*location*/ node); + } + if (node.expression.kind === 95 /* SuperKeyword */) { + var actualThis = ts.createThis(); + ts.setEmitFlags(actualThis, 128 /* NoSubstitution */); + var initializer = ts.createLogicalOr(resultingCall, actualThis); + return assignToCapturedThis + ? ts.createAssignment(ts.createIdentifier("_this"), initializer) + : initializer; + } + return resultingCall; + } + /** + * Visits a NewExpression that contains a spread element. + * + * @param node A NewExpression node. + */ + function visitNewExpression(node) { + // We are here because we contain a SpreadElementExpression. + ts.Debug.assert((node.transformFlags & 262144 /* ContainsSpreadElementExpression */) !== 0); + // [source] + // new C(...a) + // + // [output] + // new ((_a = C).bind.apply(_a, [void 0].concat(a)))() + var _a = ts.createCallBinding(ts.createPropertyAccess(node.expression, "bind"), hoistVariableDeclaration), target = _a.target, thisArg = _a.thisArg; + return ts.createNew(ts.createFunctionApply(ts.visitNode(target, visitor, ts.isExpression), thisArg, transformAndSpreadElements(ts.createNodeArray([ts.createVoidZero()].concat(node.arguments)), /*needsUniqueCopy*/ false, /*multiLine*/ false, /*hasTrailingComma*/ false)), + /*typeArguments*/ undefined, []); + } + /** + * Transforms an array of Expression nodes that contains a SpreadElementExpression. + * + * @param elements The array of Expression nodes. + * @param needsUniqueCopy A value indicating whether to ensure that the result is a fresh array. + * @param multiLine A value indicating whether the result should be emitted on multiple lines. + */ + function transformAndSpreadElements(elements, needsUniqueCopy, multiLine, hasTrailingComma) { + // [source] + // [a, ...b, c] + // + // [output] + // [a].concat(b, [c]) + // Map spans of spread expressions into their expressions and spans of other + // expressions into an array literal. + var numElements = elements.length; + var segments = ts.flatten(ts.spanMap(elements, partitionSpreadElement, function (partition, visitPartition, start, end) { + return visitPartition(partition, multiLine, hasTrailingComma && end === numElements); + })); + if (segments.length === 1) { + var firstElement = elements[0]; + return needsUniqueCopy && ts.isSpreadElementExpression(firstElement) && firstElement.expression.kind !== 170 /* ArrayLiteralExpression */ + ? ts.createArraySlice(segments[0]) + : segments[0]; + } + // Rewrite using the pattern .concat(, , ...) + return ts.createArrayConcat(segments.shift(), segments); + } + function partitionSpreadElement(node) { + return ts.isSpreadElementExpression(node) + ? visitSpanOfSpreadElements + : visitSpanOfNonSpreadElements; + } + function visitSpanOfSpreadElements(chunk, multiLine, hasTrailingComma) { + return ts.map(chunk, visitExpressionOfSpreadElement); + } + function visitSpanOfNonSpreadElements(chunk, multiLine, hasTrailingComma) { + return ts.createArrayLiteral(ts.visitNodes(ts.createNodeArray(chunk, /*location*/ undefined, hasTrailingComma), visitor, ts.isExpression), + /*location*/ undefined, multiLine); + } + /** + * Transforms the expression of a SpreadElementExpression node. + * + * @param node A SpreadElementExpression node. + */ + function visitExpressionOfSpreadElement(node) { + return ts.visitNode(node.expression, visitor, ts.isExpression); + } + /** + * Visits a template literal. + * + * @param node A template literal. + */ + function visitTemplateLiteral(node) { + return ts.createLiteral(node.text, /*location*/ node); + } + /** + * Visits a TaggedTemplateExpression node. + * + * @param node A TaggedTemplateExpression node. + */ + function visitTaggedTemplateExpression(node) { + // Visit the tag expression + var tag = ts.visitNode(node.tag, visitor, ts.isExpression); + // Allocate storage for the template site object + var temp = ts.createTempVariable(hoistVariableDeclaration); + // Build up the template arguments and the raw and cooked strings for the template. + var templateArguments = [temp]; + var cookedStrings = []; + var rawStrings = []; + var template = node.template; + if (ts.isNoSubstitutionTemplateLiteral(template)) { + cookedStrings.push(ts.createLiteral(template.text)); + rawStrings.push(getRawLiteral(template)); + } + else { + cookedStrings.push(ts.createLiteral(template.head.text)); + rawStrings.push(getRawLiteral(template.head)); + for (var _i = 0, _a = template.templateSpans; _i < _a.length; _i++) { + var templateSpan = _a[_i]; + cookedStrings.push(ts.createLiteral(templateSpan.literal.text)); + rawStrings.push(getRawLiteral(templateSpan.literal)); + templateArguments.push(ts.visitNode(templateSpan.expression, visitor, ts.isExpression)); + } + } + // NOTE: The parentheses here is entirely optional as we are now able to auto- + // parenthesize when rebuilding the tree. This should be removed in a + // future version. It is here for now to match our existing emit. + return ts.createParen(ts.inlineExpressions([ + ts.createAssignment(temp, ts.createArrayLiteral(cookedStrings)), + ts.createAssignment(ts.createPropertyAccess(temp, "raw"), ts.createArrayLiteral(rawStrings)), + ts.createCall(tag, /*typeArguments*/ undefined, templateArguments) + ])); + } + /** + * Creates an ES5 compatible literal from an ES6 template literal. + * + * @param node The ES6 template literal. + */ + function getRawLiteral(node) { + // Find original source text, since we need to emit the raw strings of the tagged template. + // The raw strings contain the (escaped) strings of what the user wrote. + // Examples: `\n` is converted to "\\n", a template string with a newline to "\n". + var text = ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node); + // text contains the original source, it will also contain quotes ("`"), dolar signs and braces ("${" and "}"), + // thus we need to remove those characters. + // First template piece starts with "`", others with "}" + // Last template piece ends with "`", others with "${" + var isLast = node.kind === 11 /* NoSubstitutionTemplateLiteral */ || node.kind === 14 /* TemplateTail */; + text = text.substring(1, text.length - (isLast ? 1 : 2)); + // Newline normalization: + // ES6 Spec 11.8.6.1 - Static Semantics of TV's and TRV's + // and LineTerminatorSequences are normalized to for both TV and TRV. + text = text.replace(/\r\n?/g, "\n"); + return ts.createLiteral(text, /*location*/ node); + } + /** + * Visits a TemplateExpression node. + * + * @param node A TemplateExpression node. + */ + function visitTemplateExpression(node) { + var expressions = []; + addTemplateHead(expressions, node); + addTemplateSpans(expressions, node); + // createAdd will check if each expression binds less closely than binary '+'. + // If it does, it wraps the expression in parentheses. Otherwise, something like + // `abc${ 1 << 2 }` + // becomes + // "abc" + 1 << 2 + "" + // which is really + // ("abc" + 1) << (2 + "") + // rather than + // "abc" + (1 << 2) + "" + var expression = ts.reduceLeft(expressions, ts.createAdd); + if (ts.nodeIsSynthesized(expression)) { + ts.setTextRange(expression, node); + } + return expression; + } + /** + * Gets a value indicating whether we need to include the head of a TemplateExpression. + * + * @param node A TemplateExpression node. + */ + function shouldAddTemplateHead(node) { + // If this expression has an empty head literal and the first template span has a non-empty + // literal, then emitting the empty head literal is not necessary. + // `${ foo } and ${ bar }` + // can be emitted as + // foo + " and " + bar + // This is because it is only required that one of the first two operands in the emit + // output must be a string literal, so that the other operand and all following operands + // are forced into strings. + // + // If the first template span has an empty literal, then the head must still be emitted. + // `${ foo }${ bar }` + // must still be emitted as + // "" + foo + bar + // There is always atleast one templateSpan in this code path, since + // NoSubstitutionTemplateLiterals are directly emitted via emitLiteral() + ts.Debug.assert(node.templateSpans.length !== 0); + return node.head.text.length !== 0 || node.templateSpans[0].literal.text.length === 0; + } + /** + * Adds the head of a TemplateExpression to an array of expressions. + * + * @param expressions An array of expressions. + * @param node A TemplateExpression node. + */ + function addTemplateHead(expressions, node) { + if (!shouldAddTemplateHead(node)) { + return; + } + expressions.push(ts.createLiteral(node.head.text)); + } + /** + * Visits and adds the template spans of a TemplateExpression to an array of expressions. + * + * @param expressions An array of expressions. + * @param node A TemplateExpression node. + */ + function addTemplateSpans(expressions, node) { + for (var _i = 0, _a = node.templateSpans; _i < _a.length; _i++) { + var span_6 = _a[_i]; + expressions.push(ts.visitNode(span_6.expression, visitor, ts.isExpression)); + // Only emit if the literal is non-empty. + // The binary '+' operator is left-associative, so the first string concatenation + // with the head will force the result up to this point to be a string. + // Emitting a '+ ""' has no semantic effect for middles and tails. + if (span_6.literal.text.length !== 0) { + expressions.push(ts.createLiteral(span_6.literal.text)); + } + } + } + /** + * Visits the `super` keyword + */ + function visitSuperKeyword(node) { + return enclosingNonAsyncFunctionBody + && ts.isClassElement(enclosingNonAsyncFunctionBody) + && !ts.hasModifier(enclosingNonAsyncFunctionBody, 32 /* Static */) + && currentParent.kind !== 174 /* CallExpression */ + ? ts.createPropertyAccess(ts.createIdentifier("_super"), "prototype") + : ts.createIdentifier("_super"); + } + function visitSourceFileNode(node) { + var _a = ts.span(node.statements, ts.isPrologueDirective), prologue = _a[0], remaining = _a[1]; + var statements = []; + startLexicalEnvironment(); + ts.addRange(statements, prologue); + addCaptureThisForNodeIfNeeded(statements, node); + ts.addRange(statements, ts.visitNodes(ts.createNodeArray(remaining), visitor, ts.isStatement)); + ts.addRange(statements, endLexicalEnvironment()); + var clone = ts.getMutableClone(node); + clone.statements = ts.createNodeArray(statements, /*location*/ node.statements); + return clone; + } + /** + * Called by the printer just before a node is printed. + * + * @param node The node to be printed. + */ + function onEmitNode(emitContext, node, emitCallback) { + var savedEnclosingFunction = enclosingFunction; + if (enabledSubstitutions & 1 /* CapturedThis */ && ts.isFunctionLike(node)) { + // If we are tracking a captured `this`, keep track of the enclosing function. + enclosingFunction = node; + } + previousOnEmitNode(emitContext, node, emitCallback); + enclosingFunction = savedEnclosingFunction; + } + /** + * Enables a more costly code path for substitutions when we determine a source file + * contains block-scoped bindings (e.g. `let` or `const`). + */ + function enableSubstitutionsForBlockScopedBindings() { + if ((enabledSubstitutions & 2 /* BlockScopedBindings */) === 0) { + enabledSubstitutions |= 2 /* BlockScopedBindings */; + context.enableSubstitution(69 /* Identifier */); + } + } + /** + * Enables a more costly code path for substitutions when we determine a source file + * contains a captured `this`. + */ + function enableSubstitutionsForCapturedThis() { + if ((enabledSubstitutions & 1 /* CapturedThis */) === 0) { + enabledSubstitutions |= 1 /* CapturedThis */; + context.enableSubstitution(97 /* ThisKeyword */); + context.enableEmitNotification(148 /* Constructor */); + context.enableEmitNotification(147 /* MethodDeclaration */); + context.enableEmitNotification(149 /* GetAccessor */); + context.enableEmitNotification(150 /* SetAccessor */); + context.enableEmitNotification(180 /* ArrowFunction */); + context.enableEmitNotification(179 /* FunctionExpression */); + context.enableEmitNotification(220 /* FunctionDeclaration */); + } + } + /** + * Hooks node substitutions. + * + * @param node The node to substitute. + * @param isExpression A value indicating whether the node is to be used in an expression + * position. + */ + function onSubstituteNode(emitContext, node) { + node = previousOnSubstituteNode(emitContext, node); + if (emitContext === 1 /* Expression */) { + return substituteExpression(node); + } + if (ts.isIdentifier(node)) { + return substituteIdentifier(node); + } + return node; + } + /** + * Hooks substitutions for non-expression identifiers. + */ + function substituteIdentifier(node) { + // Only substitute the identifier if we have enabled substitutions for block-scoped + // bindings. + if (enabledSubstitutions & 2 /* BlockScopedBindings */) { + var original = ts.getParseTreeNode(node, ts.isIdentifier); + if (original && isNameOfDeclarationWithCollidingName(original)) { + return ts.getGeneratedNameForNode(original); + } + } + return node; + } + /** + * Determines whether a name is the name of a declaration with a colliding name. + * NOTE: This function expects to be called with an original source tree node. + * + * @param node An original source tree node. + */ + function isNameOfDeclarationWithCollidingName(node) { + var parent = node.parent; + switch (parent.kind) { + case 169 /* BindingElement */: + case 221 /* ClassDeclaration */: + case 224 /* EnumDeclaration */: + case 218 /* VariableDeclaration */: + return parent.name === node + && resolver.isDeclarationWithCollidingName(parent); + } + return false; + } + /** + * Substitutes an expression. + * + * @param node An Expression node. + */ + function substituteExpression(node) { + switch (node.kind) { + case 69 /* Identifier */: + return substituteExpressionIdentifier(node); + case 97 /* ThisKeyword */: + return substituteThisKeyword(node); + } + return node; + } + /** + * Substitutes an expression identifier. + * + * @param node An Identifier node. + */ + function substituteExpressionIdentifier(node) { + if (enabledSubstitutions & 2 /* BlockScopedBindings */) { + var declaration = resolver.getReferencedDeclarationWithCollidingName(node); + if (declaration) { + return ts.getGeneratedNameForNode(declaration.name); + } + } + return node; + } + /** + * Substitutes `this` when contained within an arrow function. + * + * @param node The ThisKeyword node. + */ + function substituteThisKeyword(node) { + if (enabledSubstitutions & 1 /* CapturedThis */ + && enclosingFunction + && ts.getEmitFlags(enclosingFunction) & 256 /* CapturesThis */) { + return ts.createIdentifier("_this", /*location*/ node); + } + return node; + } + /** + * Gets the local name for a declaration for use in expressions. + * + * A local name will *never* be prefixed with an module or namespace export modifier like + * "exports.". + * + * @param node The declaration. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ + function getLocalName(node, allowComments, allowSourceMaps) { + return getDeclarationName(node, allowComments, allowSourceMaps, 262144 /* LocalName */); + } + /** + * Gets the name of a declaration, without source map or comments. + * + * @param node The declaration. + * @param allowComments Allow comments for the name. + */ + function getDeclarationName(node, allowComments, allowSourceMaps, emitFlags) { + if (node.name && !ts.isGeneratedIdentifier(node.name)) { + var name_37 = ts.getMutableClone(node.name); + emitFlags |= ts.getEmitFlags(node.name); + if (!allowSourceMaps) { + emitFlags |= 1536 /* NoSourceMap */; } - // If we are exporting, but it's a top-level ES6 module exports, - // we'll emit the declaration list verbatim, so emit comments too. - if (isES6ExportedDeclaration(node)) { - return true; + if (!allowComments) { + emitFlags |= 49152 /* NoComments */; } - // Otherwise, only emit if we have at least one initializer present. - for (var _a = 0, _b = node.declarationList.declarations; _a < _b.length; _a++) { - var declaration = _b[_a]; - if (declaration.initializer) { - return true; - } + if (emitFlags) { + ts.setEmitFlags(name_37, emitFlags); } + return name_37; + } + return ts.getGeneratedNameForNode(node); + } + function getClassMemberPrefix(node, member) { + var expression = getLocalName(node); + return ts.hasModifier(member, 32 /* Static */) ? expression : ts.createPropertyAccess(expression, "prototype"); + } + function hasSynthesizedDefaultSuperCall(constructor, hasExtendsClause) { + if (!constructor || !hasExtendsClause) { return false; } - function emitParameter(node) { - if (languageVersion < 2 /* ES6 */) { - if (ts.isBindingPattern(node.name)) { - var name_31 = createTempVariable(0 /* Auto */); - if (!tempParameters) { - tempParameters = []; - } - tempParameters.push(name_31); - emit(name_31); - } - else { - emit(node.name); - } - } - else { - if (node.dotDotDotToken) { - write("..."); - } - emit(node.name); - emitOptional(" = ", node.initializer); - } + var parameter = ts.singleOrUndefined(constructor.parameters); + if (!parameter || !ts.nodeIsSynthesized(parameter) || !parameter.dotDotDotToken) { + return false; } - function emitDefaultValueAssignments(node) { - if (languageVersion < 2 /* ES6 */) { - var tempIndex_1 = 0; - ts.forEach(node.parameters, function (parameter) { - // A rest parameter cannot have a binding pattern or an initializer, - // so let's just ignore it. - if (parameter.dotDotDotToken) { - return; - } - var paramName = parameter.name, initializer = parameter.initializer; - if (ts.isBindingPattern(paramName)) { - // In cases where a binding pattern is simply '[]' or '{}', - // we usually don't want to emit a var declaration; however, in the presence - // of an initializer, we must emit that expression to preserve side effects. - var hasBindingElements = paramName.elements.length > 0; - if (hasBindingElements || initializer) { - writeLine(); - write("var "); - if (hasBindingElements) { - emitDestructuring(parameter, /*isAssignmentExpressionStatement*/ false, tempParameters[tempIndex_1]); - } - else { - emit(tempParameters[tempIndex_1]); - write(" = "); - emit(initializer); - } - write(";"); - } - // Regardless of whether we will emit a var declaration for the binding pattern, we generate the temporary - // variable for the parameter (see: emitParameter) - tempIndex_1++; - } - else if (initializer) { - writeLine(); - emitStart(parameter); - write("if ("); - emitNodeWithoutSourceMap(paramName); - write(" === void 0)"); - emitEnd(parameter); - write(" { "); - emitStart(parameter); - emitNodeWithCommentsAndWithoutSourcemap(paramName); - write(" = "); - emitNodeWithCommentsAndWithoutSourcemap(initializer); - emitEnd(parameter); - write("; }"); - } - }); - } + var statement = ts.firstOrUndefined(constructor.body.statements); + if (!statement || !ts.nodeIsSynthesized(statement) || statement.kind !== 202 /* ExpressionStatement */) { + return false; } - function emitRestParameter(node) { - if (languageVersion < 2 /* ES6 */ && ts.hasDeclaredRestParameter(node)) { - var restParam = node.parameters[node.parameters.length - 1]; - // A rest parameter cannot have a binding pattern, so let's just ignore it if it does. - if (ts.isBindingPattern(restParam.name)) { - return; - } - var skipThisCount = node.parameters.length && node.parameters[0].name.originalKeywordKind === 97 /* ThisKeyword */ ? 1 : 0; - var restIndex = node.parameters.length - 1 - skipThisCount; - var tempName = createTempVariable(268435456 /* _i */).text; - writeLine(); - emitLeadingComments(restParam); - emitStart(restParam); - write("var "); - emitNodeWithCommentsAndWithoutSourcemap(restParam.name); - write(" = [];"); - emitEnd(restParam); - emitTrailingComments(restParam); - writeLine(); - write("for ("); - emitStart(restParam); - write("var " + tempName + " = " + restIndex + ";"); - emitEnd(restParam); - write(" "); - emitStart(restParam); - write(tempName + " < arguments.length;"); - emitEnd(restParam); - write(" "); - emitStart(restParam); - write(tempName + "++"); - emitEnd(restParam); - write(") {"); - increaseIndent(); - writeLine(); - emitStart(restParam); - emitNodeWithCommentsAndWithoutSourcemap(restParam.name); - write("[" + tempName + " - " + restIndex + "] = arguments[" + tempName + "];"); - emitEnd(restParam); - decreaseIndent(); - writeLine(); - write("}"); - } + var statementExpression = statement.expression; + if (!ts.nodeIsSynthesized(statementExpression) || statementExpression.kind !== 174 /* CallExpression */) { + return false; } - function emitAccessor(node) { - write(node.kind === 149 /* GetAccessor */ ? "get " : "set "); - emit(node.name); - emitSignatureAndBody(node); + var callTarget = statementExpression.expression; + if (!ts.nodeIsSynthesized(callTarget) || callTarget.kind !== 95 /* SuperKeyword */) { + return false; } - function shouldEmitAsArrowFunction(node) { - return node.kind === 180 /* ArrowFunction */ && languageVersion >= 2 /* ES6 */; + var callArgument = ts.singleOrUndefined(statementExpression.arguments); + if (!callArgument || !ts.nodeIsSynthesized(callArgument) || callArgument.kind !== 191 /* SpreadElementExpression */) { + return false; } - function emitDeclarationName(node) { - if (node.name) { - emitNodeWithCommentsAndWithoutSourcemap(node.name); - } - else { - write(getGeneratedNameForNode(node)); - } + var expression = callArgument.expression; + return ts.isIdentifier(expression) && expression === parameter.name; + } + } + ts.transformES6 = transformES6; +})(ts || (ts = {})); +/// +/// +// Transforms generator functions into a compatible ES5 representation with similar runtime +// semantics. This is accomplished by first transforming the body of each generator +// function into an intermediate representation that is the compiled into a JavaScript +// switch statement. +// +// Many functions in this transformer will contain comments indicating the expected +// intermediate representation. For illustrative purposes, the following intermediate +// language is used to define this intermediate representation: +// +// .nop - Performs no operation. +// .local NAME, ... - Define local variable declarations. +// .mark LABEL - Mark the location of a label. +// .br LABEL - Jump to a label. If jumping out of a protected +// region, all .finally blocks are executed. +// .brtrue LABEL, (x) - Jump to a label IIF the expression `x` is truthy. +// If jumping out of a protected region, all .finally +// blocks are executed. +// .brfalse LABEL, (x) - Jump to a label IIF the expression `x` is falsey. +// If jumping out of a protected region, all .finally +// blocks are executed. +// .yield (x) - Yield the value of the optional expression `x`. +// Resume at the next label. +// .yieldstar (x) - Delegate yield to the value of the optional +// expression `x`. Resume at the next label. +// NOTE: `x` must be an Iterator, not an Iterable. +// .loop CONTINUE, BREAK - Marks the beginning of a loop. Any "continue" or +// "break" abrupt completions jump to the CONTINUE or +// BREAK labels, respectively. +// .endloop - Marks the end of a loop. +// .with (x) - Marks the beginning of a WithStatement block, using +// the supplied expression. +// .endwith - Marks the end of a WithStatement. +// .switch - Marks the beginning of a SwitchStatement. +// .endswitch - Marks the end of a SwitchStatement. +// .labeled NAME - Marks the beginning of a LabeledStatement with the +// supplied name. +// .endlabeled - Marks the end of a LabeledStatement. +// .try TRY, CATCH, FINALLY, END - Marks the beginning of a protected region, and the +// labels for each block. +// .catch (x) - Marks the beginning of a catch block. +// .finally - Marks the beginning of a finally block. +// .endfinally - Marks the end of a finally block. +// .endtry - Marks the end of a protected region. +// .throw (x) - Throws the value of the expression `x`. +// .return (x) - Returns the value of the expression `x`. +// +// In addition, the illustrative intermediate representation introduces some special +// variables: +// +// %sent% - Either returns the next value sent to the generator, +// returns the result of a delegated yield, or throws +// the exception sent to the generator. +// %error% - Returns the value of the current exception in a +// catch block. +// +// This intermediate representation is then compiled into JavaScript syntax. The resulting +// compilation output looks something like the following: +// +// function f() { +// var /*locals*/; +// /*functions*/ +// return __generator(function (state) { +// switch (state.label) { +// /*cases per label*/ +// } +// }); +// } +// +// Each of the above instructions corresponds to JavaScript emit similar to the following: +// +// .local NAME | var NAME; +// -------------------------------|---------------------------------------------- +// .mark LABEL | case LABEL: +// -------------------------------|---------------------------------------------- +// .br LABEL | return [3 /*break*/, LABEL]; +// -------------------------------|---------------------------------------------- +// .brtrue LABEL, (x) | if (x) return [3 /*break*/, LABEL]; +// -------------------------------|---------------------------------------------- +// .brfalse LABEL, (x) | if (!(x)) return [3, /*break*/, LABEL]; +// -------------------------------|---------------------------------------------- +// .yield (x) | return [4 /*yield*/, x]; +// .mark RESUME | case RESUME: +// a = %sent%; | a = state.sent(); +// -------------------------------|---------------------------------------------- +// .yieldstar (x) | return [5 /*yield**/, x]; +// .mark RESUME | case RESUME: +// a = %sent%; | a = state.sent(); +// -------------------------------|---------------------------------------------- +// .with (_a) | with (_a) { +// a(); | a(); +// | } +// | state.label = LABEL; +// .mark LABEL | case LABEL: +// | with (_a) { +// b(); | b(); +// | } +// .endwith | +// -------------------------------|---------------------------------------------- +// | case 0: +// | state.trys = []; +// | ... +// .try TRY, CATCH, FINALLY, END | +// .mark TRY | case TRY: +// | state.trys.push([TRY, CATCH, FINALLY, END]); +// .nop | +// a(); | a(); +// .br END | return [3 /*break*/, END]; +// .catch (e) | +// .mark CATCH | case CATCH: +// | e = state.sent(); +// b(); | b(); +// .br END | return [3 /*break*/, END]; +// .finally | +// .mark FINALLY | case FINALLY: +// c(); | c(); +// .endfinally | return [7 /*endfinally*/]; +// .endtry | +// .mark END | case END: +/*@internal*/ +var ts; +(function (ts) { + var OpCode; + (function (OpCode) { + OpCode[OpCode["Nop"] = 0] = "Nop"; + OpCode[OpCode["Statement"] = 1] = "Statement"; + OpCode[OpCode["Assign"] = 2] = "Assign"; + OpCode[OpCode["Break"] = 3] = "Break"; + OpCode[OpCode["BreakWhenTrue"] = 4] = "BreakWhenTrue"; + OpCode[OpCode["BreakWhenFalse"] = 5] = "BreakWhenFalse"; + OpCode[OpCode["Yield"] = 6] = "Yield"; + OpCode[OpCode["YieldStar"] = 7] = "YieldStar"; + OpCode[OpCode["Return"] = 8] = "Return"; + OpCode[OpCode["Throw"] = 9] = "Throw"; + OpCode[OpCode["Endfinally"] = 10] = "Endfinally"; // Marks the end of a `finally` block + })(OpCode || (OpCode = {})); + // whether a generated code block is opening or closing at the current operation for a FunctionBuilder + var BlockAction; + (function (BlockAction) { + BlockAction[BlockAction["Open"] = 0] = "Open"; + BlockAction[BlockAction["Close"] = 1] = "Close"; + })(BlockAction || (BlockAction = {})); + // the kind for a generated code block in a FunctionBuilder + var CodeBlockKind; + (function (CodeBlockKind) { + CodeBlockKind[CodeBlockKind["Exception"] = 0] = "Exception"; + CodeBlockKind[CodeBlockKind["With"] = 1] = "With"; + CodeBlockKind[CodeBlockKind["Switch"] = 2] = "Switch"; + CodeBlockKind[CodeBlockKind["Loop"] = 3] = "Loop"; + CodeBlockKind[CodeBlockKind["Labeled"] = 4] = "Labeled"; + })(CodeBlockKind || (CodeBlockKind = {})); + // the state for a generated code exception block + var ExceptionBlockState; + (function (ExceptionBlockState) { + ExceptionBlockState[ExceptionBlockState["Try"] = 0] = "Try"; + ExceptionBlockState[ExceptionBlockState["Catch"] = 1] = "Catch"; + ExceptionBlockState[ExceptionBlockState["Finally"] = 2] = "Finally"; + ExceptionBlockState[ExceptionBlockState["Done"] = 3] = "Done"; + })(ExceptionBlockState || (ExceptionBlockState = {})); + // NOTE: changes to this enum should be reflected in the __generator helper. + var Instruction; + (function (Instruction) { + Instruction[Instruction["Next"] = 0] = "Next"; + Instruction[Instruction["Throw"] = 1] = "Throw"; + Instruction[Instruction["Return"] = 2] = "Return"; + Instruction[Instruction["Break"] = 3] = "Break"; + Instruction[Instruction["Yield"] = 4] = "Yield"; + Instruction[Instruction["YieldStar"] = 5] = "YieldStar"; + Instruction[Instruction["Catch"] = 6] = "Catch"; + Instruction[Instruction["Endfinally"] = 7] = "Endfinally"; + })(Instruction || (Instruction = {})); + var instructionNames = ts.createMap((_a = {}, + _a[2 /* Return */] = "return", + _a[3 /* Break */] = "break", + _a[4 /* Yield */] = "yield", + _a[5 /* YieldStar */] = "yield*", + _a[7 /* Endfinally */] = "endfinally", + _a)); + function transformGenerators(context) { + var startLexicalEnvironment = context.startLexicalEnvironment, endLexicalEnvironment = context.endLexicalEnvironment, hoistFunctionDeclaration = context.hoistFunctionDeclaration, hoistVariableDeclaration = context.hoistVariableDeclaration; + var compilerOptions = context.getCompilerOptions(); + var languageVersion = ts.getEmitScriptTarget(compilerOptions); + var resolver = context.getEmitResolver(); + var previousOnSubstituteNode = context.onSubstituteNode; + context.onSubstituteNode = onSubstituteNode; + var currentSourceFile; + var renamedCatchVariables; + var renamedCatchVariableDeclarations; + var inGeneratorFunctionBody; + var inStatementContainingYield; + // The following three arrays store information about generated code blocks. + // All three arrays are correlated by their index. This approach is used over allocating + // objects to store the same information to avoid GC overhead. + // + var blocks; // Information about the code block + var blockOffsets; // The operation offset at which a code block begins or ends + var blockActions; // Whether the code block is opened or closed + var blockStack; // A stack of currently open code blocks + // Labels are used to mark locations in the code that can be the target of a Break (jump) + // operation. These are translated into case clauses in a switch statement. + // The following two arrays are correlated by their index. This approach is used over + // allocating objects to store the same information to avoid GC overhead. + // + var labelOffsets; // The operation offset at which the label is defined. + var labelExpressions; // The NumericLiteral nodes bound to each label. + var nextLabelId = 1; // The next label id to use. + // Operations store information about generated code for the function body. This + // Includes things like statements, assignments, breaks (jumps), and yields. + // The following three arrays are correlated by their index. This approach is used over + // allocating objects to store the same information to avoid GC overhead. + // + var operations; // The operation to perform. + var operationArguments; // The arguments to the operation. + var operationLocations; // The source map location for the operation. + var state; // The name of the state object used by the generator at runtime. + // The following variables store information used by the `build` function: + // + var blockIndex = 0; // The index of the current block. + var labelNumber = 0; // The current label number. + var labelNumbers; + var lastOperationWasAbrupt; // Indicates whether the last operation was abrupt (break/continue). + var lastOperationWasCompletion; // Indicates whether the last operation was a completion (return/throw). + var clauses; // The case clauses generated for labels. + var statements; // The statements for the current label. + var exceptionBlockStack; // A stack of containing exception blocks. + var currentExceptionBlock; // The current exception block. + var withBlockStack; // A stack containing `with` blocks. + return transformSourceFile; + function transformSourceFile(node) { + if (ts.isDeclarationFile(node)) { + return node; } - function shouldEmitFunctionName(node) { - if (node.kind === 179 /* FunctionExpression */) { - // Emit name if one is present - return !!node.name; - } - if (node.kind === 220 /* FunctionDeclaration */) { - // Emit name if one is present, or emit generated name in down-level case (for export default case) - return !!node.name || modulekind !== ts.ModuleKind.ES6; - } - } - function emitFunctionDeclaration(node) { - if (ts.nodeIsMissing(node.body)) { - return emitCommentsOnNotEmittedNode(node); - } - // TODO (yuisu) : we should not have special cases to condition emitting comments - // but have one place to fix check for these conditions. - var kind = node.kind, parent = node.parent; - if (kind !== 147 /* MethodDeclaration */ && - kind !== 146 /* MethodSignature */ && - parent && - parent.kind !== 253 /* PropertyAssignment */ && - parent.kind !== 174 /* CallExpression */ && - parent.kind !== 170 /* ArrayLiteralExpression */) { - // 1. Methods will emit comments at their assignment declaration sites. - // - // 2. If the function is a property of object literal, emitting leading-comments - // is done by emitNodeWithoutSourceMap which then call this function. - // In particular, we would like to avoid emit comments twice in following case: - // - // var obj = { - // id: - // /*comment*/ () => void - // } - // - // 3. If the function is an argument in call expression, emitting of comments will be - // taken care of in emit list of arguments inside of 'emitCallExpression'. - // - // 4. If the function is in an array literal, 'emitLinePreservingList' will take care - // of leading comments. - emitLeadingComments(node); - } - emitStart(node); - // For targeting below es6, emit functions-like declaration including arrow function using function keyword. - // When targeting ES6, emit arrow function natively in ES6 by omitting function keyword and using fat arrow instead - if (!shouldEmitAsArrowFunction(node)) { - if (isES6ExportedDeclaration(node)) { - write("export "); - if (node.flags & 512 /* Default */) { - write("default "); - } - } - write("function"); - if (languageVersion >= 2 /* ES6 */ && node.asteriskToken) { - write("*"); - } - write(" "); - } - if (shouldEmitFunctionName(node)) { - emitDeclarationName(node); - } - emitSignatureAndBody(node); - if (modulekind !== ts.ModuleKind.ES6 && kind === 220 /* FunctionDeclaration */ && parent === currentSourceFile && node.name) { - emitExportMemberAssignments(node.name); - } - emitEnd(node); - if (kind !== 147 /* MethodDeclaration */ && - kind !== 146 /* MethodSignature */ && - kind !== 180 /* ArrowFunction */) { - emitTrailingComments(node); - } + if (node.transformFlags & 1024 /* ContainsGenerator */) { + currentSourceFile = node; + node = ts.visitEachChild(node, visitor, context); + currentSourceFile = undefined; } - function emitCaptureThisForNodeIfNecessary(node) { - if (resolver.getNodeCheckFlags(node) & 4 /* CaptureThis */) { - writeLine(); - emitStart(node); - write("var _this = this;"); - emitEnd(node); - } + return node; + } + /** + * Visits a node. + * + * @param node The node to visit. + */ + function visitor(node) { + var transformFlags = node.transformFlags; + if (inStatementContainingYield) { + return visitJavaScriptInStatementContainingYield(node); } - function emitSignatureParameters(node) { - increaseIndent(); - write("("); - if (node) { - var parameters = node.parameters; - var skipCount = node.parameters.length && node.parameters[0].name.originalKeywordKind === 97 /* ThisKeyword */ ? 1 : 0; - var omitCount = languageVersion < 2 /* ES6 */ && ts.hasDeclaredRestParameter(node) ? 1 : 0; - emitList(parameters, skipCount, parameters.length - omitCount - skipCount, /*multiLine*/ false, /*trailingComma*/ false); - } - write(")"); - decreaseIndent(); + else if (inGeneratorFunctionBody) { + return visitJavaScriptInGeneratorFunctionBody(node); } - function emitSignatureParametersForArrow(node) { - // Check whether the parameter list needs parentheses and preserve no-parenthesis - if (node.parameters.length === 1 && node.pos === node.parameters[0].pos) { - emit(node.parameters[0]); - return; - } - emitSignatureParameters(node); - } - function emitAsyncFunctionBodyForES6(node) { - var promiseConstructor = ts.getEntityNameFromTypeNode(node.type); - var isArrowFunction = node.kind === 180 /* ArrowFunction */; - var hasLexicalArguments = (resolver.getNodeCheckFlags(node) & 8192 /* CaptureArguments */) !== 0; - // An async function is emit as an outer function that calls an inner - // generator function. To preserve lexical bindings, we pass the current - // `this` and `arguments` objects to `__awaiter`. The generator function - // passed to `__awaiter` is executed inside of the callback to the - // promise constructor. - // - // The emit for an async arrow without a lexical `arguments` binding might be: - // - // // input - // let a = async (b) => { await b; } - // - // // output - // let a = (b) => __awaiter(this, void 0, void 0, function* () { - // yield b; - // }); - // - // The emit for an async arrow with a lexical `arguments` binding might be: - // - // // input - // let a = async (b) => { await arguments[0]; } - // - // // output - // let a = (b) => __awaiter(this, arguments, void 0, function* (arguments) { - // yield arguments[0]; - // }); - // - // The emit for an async function expression without a lexical `arguments` binding - // might be: - // - // // input - // let a = async function (b) { - // await b; - // } - // - // // output - // let a = function (b) { - // return __awaiter(this, void 0, void 0, function* () { - // yield b; - // }); - // } - // - // The emit for an async function expression with a lexical `arguments` binding - // might be: - // - // // input - // let a = async function (b) { - // await arguments[0]; - // } - // - // // output - // let a = function (b) { - // return __awaiter(this, arguments, void 0, function* (_arguments) { - // yield _arguments[0]; - // }); - // } - // - // The emit for an async function expression with a lexical `arguments` binding - // and a return type annotation might be: - // - // // input - // let a = async function (b): MyPromise { - // await arguments[0]; - // } - // - // // output - // let a = function (b) { - // return __awaiter(this, arguments, MyPromise, function* (_arguments) { - // yield _arguments[0]; - // }); - // } - // - // If this is not an async arrow, emit the opening brace of the function body - // and the start of the return statement. - if (!isArrowFunction) { - write(" {"); - increaseIndent(); - writeLine(); - if (resolver.getNodeCheckFlags(node) & 4096 /* AsyncMethodWithSuperBinding */) { - writeLines("\nconst _super = (function (geti, seti) {\n const cache = Object.create(null);\n return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });\n})(name => super[name], (name, value) => super[name] = value);"); - writeLine(); - } - else if (resolver.getNodeCheckFlags(node) & 2048 /* AsyncMethodWithSuper */) { - write("const _super = name => super[name];"); - writeLine(); - } - write("return"); - } - write(" __awaiter(this"); - if (hasLexicalArguments) { - write(", arguments, "); - } - else { - write(", void 0, "); - } - if (languageVersion >= 2 /* ES6 */ || !promiseConstructor) { - write("void 0"); - } - else { - emitEntityNameAsExpression(promiseConstructor, /*useFallback*/ false); - } - // Emit the call to __awaiter. - write(", function* ()"); - // Emit the signature and body for the inner generator function. - emitFunctionBody(node); - write(")"); - // If this is not an async arrow, emit the closing brace of the outer function body. - if (!isArrowFunction) { - write(";"); - decreaseIndent(); - writeLine(); - write("}"); - } + else if (transformFlags & 512 /* Generator */) { + return visitGenerator(node); } - function emitFunctionBody(node) { - if (!node.body) { - // There can be no body when there are parse errors. Just emit an empty block - // in that case. - write(" { }"); - } - else { - if (node.body.kind === 199 /* Block */) { - emitBlockFunctionBody(node, node.body); + else if (transformFlags & 1024 /* ContainsGenerator */) { + return ts.visitEachChild(node, visitor, context); + } + else { + return node; + } + } + /** + * Visits a node that is contained within a statement that contains yield. + * + * @param node The node to visit. + */ + function visitJavaScriptInStatementContainingYield(node) { + switch (node.kind) { + case 204 /* DoStatement */: + return visitDoStatement(node); + case 205 /* WhileStatement */: + return visitWhileStatement(node); + case 213 /* SwitchStatement */: + return visitSwitchStatement(node); + case 214 /* LabeledStatement */: + return visitLabeledStatement(node); + default: + return visitJavaScriptInGeneratorFunctionBody(node); + } + } + /** + * Visits a node that is contained within a generator function. + * + * @param node The node to visit. + */ + function visitJavaScriptInGeneratorFunctionBody(node) { + switch (node.kind) { + case 220 /* FunctionDeclaration */: + return visitFunctionDeclaration(node); + case 179 /* FunctionExpression */: + return visitFunctionExpression(node); + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + return visitAccessorDeclaration(node); + case 200 /* VariableStatement */: + return visitVariableStatement(node); + case 206 /* ForStatement */: + return visitForStatement(node); + case 207 /* ForInStatement */: + return visitForInStatement(node); + case 210 /* BreakStatement */: + return visitBreakStatement(node); + case 209 /* ContinueStatement */: + return visitContinueStatement(node); + case 211 /* ReturnStatement */: + return visitReturnStatement(node); + default: + if (node.transformFlags & 4194304 /* ContainsYield */) { + return visitJavaScriptContainingYield(node); + } + else if (node.transformFlags & (1024 /* ContainsGenerator */ | 8388608 /* ContainsHoistedDeclarationOrCompletion */)) { + return ts.visitEachChild(node, visitor, context); } else { - emitExpressionFunctionBody(node, node.body); + return node; } - } } - function emitSignatureAndBody(node) { - var saveConvertedLoopState = convertedLoopState; - var saveTempFlags = tempFlags; - var saveTempVariables = tempVariables; - var saveTempParameters = tempParameters; - convertedLoopState = undefined; - tempFlags = 0; - tempVariables = undefined; - tempParameters = undefined; - // When targeting ES6, emit arrow function natively in ES6 - if (shouldEmitAsArrowFunction(node)) { - emitSignatureParametersForArrow(node); - write(" =>"); - } - else { - emitSignatureParameters(node); - } - var isAsync = ts.isAsyncFunctionLike(node); - if (isAsync) { - emitAsyncFunctionBodyForES6(node); - } - else { - emitFunctionBody(node); - } - if (!isES6ExportedDeclaration(node)) { - emitExportMemberAssignment(node); - } - ts.Debug.assert(convertedLoopState === undefined); - convertedLoopState = saveConvertedLoopState; - tempFlags = saveTempFlags; - tempVariables = saveTempVariables; - tempParameters = saveTempParameters; - } - // Returns true if any preamble code was emitted. - function emitFunctionBodyPreamble(node) { - emitCaptureThisForNodeIfNecessary(node); - emitDefaultValueAssignments(node); - emitRestParameter(node); - } - function emitExpressionFunctionBody(node, body) { - if (languageVersion < 2 /* ES6 */ || node.flags & 256 /* Async */) { - emitDownLevelExpressionFunctionBody(node, body); - return; - } - // For es6 and higher we can emit the expression as is. However, in the case - // where the expression might end up looking like a block when emitted, we'll - // also wrap it in parentheses first. For example if you have: a => {} - // then we need to generate: a => ({}) - write(" "); - // Unwrap all type assertions. - var current = body; - while (current.kind === 177 /* TypeAssertionExpression */) { - current = current.expression; - } - emitParenthesizedIf(body, current.kind === 171 /* ObjectLiteralExpression */); + } + /** + * Visits a node that contains a YieldExpression. + * + * @param node The node to visit. + */ + function visitJavaScriptContainingYield(node) { + switch (node.kind) { + case 187 /* BinaryExpression */: + return visitBinaryExpression(node); + case 188 /* ConditionalExpression */: + return visitConditionalExpression(node); + case 190 /* YieldExpression */: + return visitYieldExpression(node); + case 170 /* ArrayLiteralExpression */: + return visitArrayLiteralExpression(node); + case 171 /* ObjectLiteralExpression */: + return visitObjectLiteralExpression(node); + case 173 /* ElementAccessExpression */: + return visitElementAccessExpression(node); + case 174 /* CallExpression */: + return visitCallExpression(node); + case 175 /* NewExpression */: + return visitNewExpression(node); + default: + return ts.visitEachChild(node, visitor, context); } - function emitDownLevelExpressionFunctionBody(node, body) { - write(" {"); - increaseIndent(); - var outPos = writer.getTextPos(); - emitDetachedCommentsAndUpdateCommentsInfo(node.body); - emitFunctionBodyPreamble(node); - var preambleEmitted = writer.getTextPos() !== outPos; - decreaseIndent(); - // If we didn't have to emit any preamble code, then attempt to keep the arrow - // function on one line. - if (!preambleEmitted && nodeStartPositionsAreOnSameLine(node, body)) { - write(" "); - emitStart(body); - write("return "); - emit(body); - emitEnd(body); - write(";"); - emitTempDeclarations(/*newLine*/ false); - write(" "); - } - else { - increaseIndent(); - writeLine(); - emitLeadingComments(node.body); - emitStart(body); - write("return "); - emit(body); - emitEnd(body); - write(";"); - emitTrailingComments(node.body); - emitTempDeclarations(/*newLine*/ true); - decreaseIndent(); - writeLine(); - } - emitStart(node.body); - write("}"); - emitEnd(node.body); + } + /** + * Visits a generator function. + * + * @param node The node to visit. + */ + function visitGenerator(node) { + switch (node.kind) { + case 220 /* FunctionDeclaration */: + return visitFunctionDeclaration(node); + case 179 /* FunctionExpression */: + return visitFunctionExpression(node); + default: + ts.Debug.failBadSyntaxKind(node); + return ts.visitEachChild(node, visitor, context); } - function emitBlockFunctionBody(node, body) { - write(" {"); - var initialTextPos = writer.getTextPos(); - increaseIndent(); - emitDetachedCommentsAndUpdateCommentsInfo(body.statements); - // Emit all the directive prologues (like "use strict"). These have to come before - // any other preamble code we write (like parameter initializers). - var startIndex = emitDirectivePrologues(body.statements, /*startWithNewLine*/ true); - emitFunctionBodyPreamble(node); - decreaseIndent(); - var preambleEmitted = writer.getTextPos() !== initialTextPos; - if (!preambleEmitted && nodeEndIsOnSameLineAsNodeStart(body, body)) { - for (var _a = 0, _b = body.statements; _a < _b.length; _a++) { - var statement = _b[_a]; - write(" "); - emit(statement); - } - emitTempDeclarations(/*newLine*/ false); - write(" "); - emitLeadingCommentsOfPosition(body.statements.end); - } - else { - increaseIndent(); - emitLinesStartingAt(body.statements, startIndex); - emitTempDeclarations(/*newLine*/ true); - writeLine(); - emitLeadingCommentsOfPosition(body.statements.end); - decreaseIndent(); - } - emitToken(16 /* CloseBraceToken */, body.statements.end); + } + /** + * Visits a function declaration. + * + * This will be called when one of the following conditions are met: + * - The function declaration is a generator function. + * - The function declaration is contained within the body of a generator function. + * + * @param node The node to visit. + */ + function visitFunctionDeclaration(node) { + // Currently, we only support generators that were originally async functions. + if (node.asteriskToken && ts.getEmitFlags(node) & 2097152 /* AsyncFunctionBody */) { + node = ts.setOriginalNode(ts.createFunctionDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, node.name, + /*typeParameters*/ undefined, node.parameters, + /*type*/ undefined, transformGeneratorFunctionBody(node.body), + /*location*/ node), node); } - /** - * Return the statement at a given index if it is a super-call statement - * @param ctor a constructor declaration - * @param index an index to constructor's body to check - */ - function getSuperCallAtGivenIndex(ctor, index) { - if (!ctor.body) { - return undefined; - } - var statements = ctor.body.statements; - if (!statements || index >= statements.length) { - return undefined; - } - var statement = statements[index]; - if (statement.kind === 202 /* ExpressionStatement */) { - return ts.isSuperCallExpression(statement.expression) ? statement : undefined; - } + else { + var savedInGeneratorFunctionBody = inGeneratorFunctionBody; + var savedInStatementContainingYield = inStatementContainingYield; + inGeneratorFunctionBody = false; + inStatementContainingYield = false; + node = ts.visitEachChild(node, visitor, context); + inGeneratorFunctionBody = savedInGeneratorFunctionBody; + inStatementContainingYield = savedInStatementContainingYield; + } + if (inGeneratorFunctionBody) { + // Function declarations in a generator function body are hoisted + // to the top of the lexical scope and elided from the current statement. + hoistFunctionDeclaration(node); + return undefined; } - function emitParameterPropertyAssignments(node) { - ts.forEach(node.parameters, function (param) { - if (param.flags & 92 /* ParameterPropertyModifier */) { - writeLine(); - emitStart(param); - emitStart(param.name); - write("this."); - emitNodeWithoutSourceMap(param.name); - emitEnd(param.name); - write(" = "); - emit(param.name); - write(";"); - emitEnd(param); - } - }); + else { + return node; } - function emitMemberAccessForPropertyName(memberName) { - // This does not emit source map because it is emitted by caller as caller - // is aware how the property name changes to the property access - // eg. public x = 10; becomes this.x and static x = 10 becomes className.x - if (memberName.kind === 9 /* StringLiteral */ || memberName.kind === 8 /* NumericLiteral */) { - write("["); - emitNodeWithCommentsAndWithoutSourcemap(memberName); - write("]"); - } - else if (memberName.kind === 140 /* ComputedPropertyName */) { - emitComputedPropertyName(memberName); - } - else { - write("."); - emitNodeWithCommentsAndWithoutSourcemap(memberName); - } + } + /** + * Visits a function expression. + * + * This will be called when one of the following conditions are met: + * - The function expression is a generator function. + * - The function expression is contained within the body of a generator function. + * + * @param node The node to visit. + */ + function visitFunctionExpression(node) { + // Currently, we only support generators that were originally async functions. + if (node.asteriskToken && ts.getEmitFlags(node) & 2097152 /* AsyncFunctionBody */) { + node = ts.setOriginalNode(ts.createFunctionExpression( + /*asteriskToken*/ undefined, node.name, + /*typeParameters*/ undefined, node.parameters, + /*type*/ undefined, transformGeneratorFunctionBody(node.body), + /*location*/ node), node); } - function getInitializedProperties(node, isStatic) { - var properties = []; - for (var _a = 0, _b = node.members; _a < _b.length; _a++) { - var member = _b[_a]; - if (member.kind === 145 /* PropertyDeclaration */ && isStatic === ((member.flags & 32 /* Static */) !== 0) && member.initializer) { - properties.push(member); - } - } - return properties; + else { + var savedInGeneratorFunctionBody = inGeneratorFunctionBody; + var savedInStatementContainingYield = inStatementContainingYield; + inGeneratorFunctionBody = false; + inStatementContainingYield = false; + node = ts.visitEachChild(node, visitor, context); + inGeneratorFunctionBody = savedInGeneratorFunctionBody; + inStatementContainingYield = savedInStatementContainingYield; } - function emitPropertyDeclarations(node, properties) { - for (var _a = 0, properties_6 = properties; _a < properties_6.length; _a++) { - var property = properties_6[_a]; - emitPropertyDeclaration(node, property); - } + return node; + } + /** + * Visits a get or set accessor declaration. + * + * This will be called when one of the following conditions are met: + * - The accessor is contained within the body of a generator function. + * + * @param node The node to visit. + */ + function visitAccessorDeclaration(node) { + var savedInGeneratorFunctionBody = inGeneratorFunctionBody; + var savedInStatementContainingYield = inStatementContainingYield; + inGeneratorFunctionBody = false; + inStatementContainingYield = false; + node = ts.visitEachChild(node, visitor, context); + inGeneratorFunctionBody = savedInGeneratorFunctionBody; + inStatementContainingYield = savedInStatementContainingYield; + return node; + } + /** + * Transforms the body of a generator function declaration. + * + * @param node The function body to transform. + */ + function transformGeneratorFunctionBody(body) { + // Save existing generator state + var statements = []; + var savedInGeneratorFunctionBody = inGeneratorFunctionBody; + var savedInStatementContainingYield = inStatementContainingYield; + var savedBlocks = blocks; + var savedBlockOffsets = blockOffsets; + var savedBlockActions = blockActions; + var savedLabelOffsets = labelOffsets; + var savedLabelExpressions = labelExpressions; + var savedNextLabelId = nextLabelId; + var savedOperations = operations; + var savedOperationArguments = operationArguments; + var savedOperationLocations = operationLocations; + var savedState = state; + // Initialize generator state + inGeneratorFunctionBody = true; + inStatementContainingYield = false; + blocks = undefined; + blockOffsets = undefined; + blockActions = undefined; + labelOffsets = undefined; + labelExpressions = undefined; + nextLabelId = 1; + operations = undefined; + operationArguments = undefined; + operationLocations = undefined; + state = ts.createTempVariable(/*recordTempVariable*/ undefined); + // Build the generator + startLexicalEnvironment(); + var statementOffset = ts.addPrologueDirectives(statements, body.statements, /*ensureUseStrict*/ false, visitor); + transformAndEmitStatements(body.statements, statementOffset); + var buildResult = build(); + ts.addRange(statements, endLexicalEnvironment()); + statements.push(ts.createReturn(buildResult)); + // Restore previous generator state + inGeneratorFunctionBody = savedInGeneratorFunctionBody; + inStatementContainingYield = savedInStatementContainingYield; + blocks = savedBlocks; + blockOffsets = savedBlockOffsets; + blockActions = savedBlockActions; + labelOffsets = savedLabelOffsets; + labelExpressions = savedLabelExpressions; + nextLabelId = savedNextLabelId; + operations = savedOperations; + operationArguments = savedOperationArguments; + operationLocations = savedOperationLocations; + state = savedState; + return ts.createBlock(statements, /*location*/ body, body.multiLine); + } + /** + * Visits a variable statement. + * + * This will be called when one of the following conditions are met: + * - The variable statement is contained within the body of a generator function. + * + * @param node The node to visit. + */ + function visitVariableStatement(node) { + if (node.transformFlags & 4194304 /* ContainsYield */) { + transformAndEmitVariableDeclarationList(node.declarationList); + return undefined; } - function emitPropertyDeclaration(node, property, receiver, isExpression) { - writeLine(); - emitLeadingComments(property); - emitStart(property); - emitStart(property.name); - if (receiver) { - write(receiver); + else { + // Do not hoist custom prologues. + if (ts.getEmitFlags(node) & 8388608 /* CustomPrologue */) { + return node; } - else { - if (property.flags & 32 /* Static */) { - emitDeclarationName(node); - } - else { - write("this"); - } + for (var _i = 0, _a = node.declarationList.declarations; _i < _a.length; _i++) { + var variable = _a[_i]; + hoistVariableDeclaration(variable.name); } - emitMemberAccessForPropertyName(property.name); - emitEnd(property.name); - write(" = "); - emit(property.initializer); - if (!isExpression) { - write(";"); + var variables = ts.getInitializedVariables(node.declarationList); + if (variables.length === 0) { + return undefined; } - emitEnd(property); - emitTrailingComments(property); + return ts.createStatement(ts.inlineExpressions(ts.map(variables, transformInitializedVariable))); } - function emitMemberFunctionsForES5AndLower(node) { - ts.forEach(node.members, function (member) { - if (member.kind === 198 /* SemicolonClassElement */) { - writeLine(); - write(";"); - } - else if (member.kind === 147 /* MethodDeclaration */ || node.kind === 146 /* MethodSignature */) { - if (!member.body) { - return emitCommentsOnNotEmittedNode(member); - } - writeLine(); - emitLeadingComments(member); - emitStart(member); - emitStart(member.name); - emitClassMemberPrefix(node, member); - emitMemberAccessForPropertyName(member.name); - emitEnd(member.name); - write(" = "); - emitFunctionDeclaration(member); - emitEnd(member); - write(";"); - emitTrailingComments(member); - } - else if (member.kind === 149 /* GetAccessor */ || member.kind === 150 /* SetAccessor */) { - var accessors = ts.getAllAccessorDeclarations(node.members, member); - if (member === accessors.firstAccessor) { - writeLine(); - emitStart(member); - write("Object.defineProperty("); - emitStart(member.name); - emitClassMemberPrefix(node, member); - write(", "); - emitExpressionForPropertyName(member.name); - emitEnd(member.name); - write(", {"); - increaseIndent(); - if (accessors.getAccessor) { - writeLine(); - emitLeadingComments(accessors.getAccessor); - write("get: "); - emitStart(accessors.getAccessor); - write("function "); - emitSignatureAndBody(accessors.getAccessor); - emitEnd(accessors.getAccessor); - emitTrailingComments(accessors.getAccessor); - write(","); - } - if (accessors.setAccessor) { - writeLine(); - emitLeadingComments(accessors.setAccessor); - write("set: "); - emitStart(accessors.setAccessor); - write("function "); - emitSignatureAndBody(accessors.setAccessor); - emitEnd(accessors.setAccessor); - emitTrailingComments(accessors.setAccessor); - write(","); - } - writeLine(); - write("enumerable: true,"); - writeLine(); - write("configurable: true"); - decreaseIndent(); - writeLine(); - write("});"); - emitEnd(member); - } - } - }); + } + /** + * Visits a binary expression. + * + * This will be called when one of the following conditions are met: + * - The node contains a YieldExpression. + * + * @param node The node to visit. + */ + function visitBinaryExpression(node) { + switch (ts.getExpressionAssociativity(node)) { + case 0 /* Left */: + return visitLeftAssociativeBinaryExpression(node); + case 1 /* Right */: + return visitRightAssociativeBinaryExpression(node); + default: + ts.Debug.fail("Unknown associativity."); } - function emitMemberFunctionsForES6AndHigher(node) { - for (var _a = 0, _b = node.members; _a < _b.length; _a++) { - var member = _b[_a]; - if ((member.kind === 147 /* MethodDeclaration */ || node.kind === 146 /* MethodSignature */) && !member.body) { - emitCommentsOnNotEmittedNode(member); - } - else if (member.kind === 147 /* MethodDeclaration */ || - member.kind === 149 /* GetAccessor */ || - member.kind === 150 /* SetAccessor */) { - writeLine(); - emitLeadingComments(member); - emitStart(member); - if (member.flags & 32 /* Static */) { - write("static "); - } - if (member.kind === 149 /* GetAccessor */) { - write("get "); - } - else if (member.kind === 150 /* SetAccessor */) { - write("set "); - } - if (member.asteriskToken) { - write("*"); - } - emit(member.name); - emitSignatureAndBody(member); - emitEnd(member); - emitTrailingComments(member); - } - else if (member.kind === 198 /* SemicolonClassElement */) { - writeLine(); - write(";"); - } - } + } + function isCompoundAssignment(kind) { + return kind >= 57 /* FirstCompoundAssignment */ + && kind <= 68 /* LastCompoundAssignment */; + } + function getOperatorForCompoundAssignment(kind) { + switch (kind) { + case 57 /* PlusEqualsToken */: return 35 /* PlusToken */; + case 58 /* MinusEqualsToken */: return 36 /* MinusToken */; + case 59 /* AsteriskEqualsToken */: return 37 /* AsteriskToken */; + case 60 /* AsteriskAsteriskEqualsToken */: return 38 /* AsteriskAsteriskToken */; + case 61 /* SlashEqualsToken */: return 39 /* SlashToken */; + case 62 /* PercentEqualsToken */: return 40 /* PercentToken */; + case 63 /* LessThanLessThanEqualsToken */: return 43 /* LessThanLessThanToken */; + case 64 /* GreaterThanGreaterThanEqualsToken */: return 44 /* GreaterThanGreaterThanToken */; + case 65 /* GreaterThanGreaterThanGreaterThanEqualsToken */: return 45 /* GreaterThanGreaterThanGreaterThanToken */; + case 66 /* AmpersandEqualsToken */: return 46 /* AmpersandToken */; + case 67 /* BarEqualsToken */: return 47 /* BarToken */; + case 68 /* CaretEqualsToken */: return 48 /* CaretToken */; } - function emitConstructor(node, baseTypeElement) { - var saveConvertedLoopState = convertedLoopState; - var saveTempFlags = tempFlags; - var saveTempVariables = tempVariables; - var saveTempParameters = tempParameters; - convertedLoopState = undefined; - tempFlags = 0; - tempVariables = undefined; - tempParameters = undefined; - emitConstructorWorker(node, baseTypeElement); - ts.Debug.assert(convertedLoopState === undefined); - convertedLoopState = saveConvertedLoopState; - tempFlags = saveTempFlags; - tempVariables = saveTempVariables; - tempParameters = saveTempParameters; - } - function emitConstructorWorker(node, baseTypeElement) { - // Check if we have property assignment inside class declaration. - // If there is property assignment, we need to emit constructor whether users define it or not - // If there is no property assignment, we can omit constructor if users do not define it - var hasInstancePropertyWithInitializer = false; - // Emit the constructor overload pinned comments - ts.forEach(node.members, function (member) { - if (member.kind === 148 /* Constructor */ && !member.body) { - emitCommentsOnNotEmittedNode(member); - } - // Check if there is any non-static property assignment - if (member.kind === 145 /* PropertyDeclaration */ && member.initializer && (member.flags & 32 /* Static */) === 0) { - hasInstancePropertyWithInitializer = true; - } - }); - var ctor = ts.getFirstConstructorWithBody(node); - // For target ES6 and above, if there is no user-defined constructor and there is no property assignment - // do not emit constructor in class declaration. - if (languageVersion >= 2 /* ES6 */ && !ctor && !hasInstancePropertyWithInitializer) { - return; - } - if (ctor) { - emitLeadingComments(ctor); - } - emitStart(ctor || node); - if (languageVersion < 2 /* ES6 */) { - write("function "); - emitDeclarationName(node); - emitSignatureParameters(ctor); - } - else { - write("constructor"); - if (ctor) { - emitSignatureParameters(ctor); - } - else { - // The ES2015 spec specifies in 14.5.14. Runtime Semantics: ClassDefinitionEvaluation: - // If constructor is empty, then - // If ClassHeritag_eopt is present and protoParent is not null, then - // Let constructor be the result of parsing the source text - // constructor(...args) { super (...args);} - // using the syntactic grammar with the goal symbol MethodDefinition[~Yield]. - // Else, - // Let constructor be the result of parsing the source text - // constructor( ){ } - // using the syntactic grammar with the goal symbol MethodDefinition[~Yield]. + } + /** + * Visits a right-associative binary expression containing `yield`. + * + * @param node The node to visit. + */ + function visitRightAssociativeBinaryExpression(node) { + var left = node.left, right = node.right; + if (containsYield(right)) { + var target = void 0; + switch (left.kind) { + case 172 /* PropertyAccessExpression */: + // [source] + // a.b = yield; // - // While we could emit the '...args' rest parameter, certain later tools in the pipeline might - // downlevel the '...args' portion less efficiently by naively copying the contents of 'arguments' to an array. - // Instead, we'll avoid using a rest parameter and spread into the super call as - // 'super(...arguments)' instead of 'super(...args)', as you can see below. - write("()"); - } - } - var startIndex = 0; - write(" {"); - increaseIndent(); - if (ctor) { - // Emit all the directive prologues (like "use strict"). These have to come before - // any other preamble code we write (like parameter initializers). - startIndex = emitDirectivePrologues(ctor.body.statements, /*startWithNewLine*/ true); - emitDetachedCommentsAndUpdateCommentsInfo(ctor.body.statements); + // [intermediate] + // .local _a + // _a = a; + // .yield resumeLabel + // .mark resumeLabel + // _a.b = %sent%; + target = ts.updatePropertyAccess(left, cacheExpression(ts.visitNode(left.expression, visitor, ts.isLeftHandSideExpression)), left.name); + break; + case 173 /* ElementAccessExpression */: + // [source] + // a[b] = yield; + // + // [intermediate] + // .local _a, _b + // _a = a; + // _b = b; + // .yield resumeLabel + // .mark resumeLabel + // _a[_b] = %sent%; + target = ts.updateElementAccess(left, cacheExpression(ts.visitNode(left.expression, visitor, ts.isLeftHandSideExpression)), cacheExpression(ts.visitNode(left.argumentExpression, visitor, ts.isExpression))); + break; + default: + target = ts.visitNode(left, visitor, ts.isExpression); + break; } - emitCaptureThisForNodeIfNecessary(node); - var superCall; - if (ctor) { - emitDefaultValueAssignments(ctor); - emitRestParameter(ctor); - if (baseTypeElement) { - superCall = getSuperCallAtGivenIndex(ctor, startIndex); - if (superCall) { - writeLine(); - emit(superCall); - } - } - emitParameterPropertyAssignments(ctor); + var operator = node.operatorToken.kind; + if (isCompoundAssignment(operator)) { + return ts.createBinary(target, 56 /* EqualsToken */, ts.createBinary(cacheExpression(target), getOperatorForCompoundAssignment(operator), ts.visitNode(right, visitor, ts.isExpression), node), node); } else { - if (baseTypeElement) { - writeLine(); - emitStart(baseTypeElement); - if (languageVersion < 2 /* ES6 */) { - write("_super.apply(this, arguments);"); - } - else { - // See comment above on using '...arguments' instead of '...args'. - write("super(...arguments);"); - } - emitEnd(baseTypeElement); - } - } - emitPropertyDeclarations(node, getInitializedProperties(node, /*isStatic*/ false)); - if (ctor) { - var statements = ctor.body.statements; - if (superCall) { - statements = statements.slice(1); - } - emitLinesStartingAt(statements, startIndex); + return ts.updateBinary(node, target, ts.visitNode(right, visitor, ts.isExpression)); } - emitTempDeclarations(/*newLine*/ true); - writeLine(); - if (ctor) { - emitLeadingCommentsOfPosition(ctor.body.statements.end); + } + return ts.visitEachChild(node, visitor, context); + } + function visitLeftAssociativeBinaryExpression(node) { + if (containsYield(node.right)) { + if (ts.isLogicalOperator(node.operatorToken.kind)) { + return visitLogicalBinaryExpression(node); } - decreaseIndent(); - emitToken(16 /* CloseBraceToken */, ctor ? ctor.body.statements.end : node.members.end); - emitEnd(ctor || node); - if (ctor) { - emitTrailingComments(ctor); + else if (node.operatorToken.kind === 24 /* CommaToken */) { + return visitCommaExpression(node); } + // [source] + // a() + (yield) + c() + // + // [intermediate] + // .local _a + // _a = a(); + // .yield resumeLabel + // _a + %sent% + c() + var clone_6 = ts.getMutableClone(node); + clone_6.left = cacheExpression(ts.visitNode(node.left, visitor, ts.isExpression)); + clone_6.right = ts.visitNode(node.right, visitor, ts.isExpression); + return clone_6; + } + return ts.visitEachChild(node, visitor, context); + } + /** + * Visits a logical binary expression containing `yield`. + * + * @param node A node to visit. + */ + function visitLogicalBinaryExpression(node) { + // Logical binary expressions (`&&` and `||`) are shortcutting expressions and need + // to be transformed as such: + // + // [source] + // x = a() && yield; + // + // [intermediate] + // .local _a + // _a = a(); + // .brfalse resultLabel, (_a) + // .yield resumeLabel + // .mark resumeLabel + // _a = %sent%; + // .mark resultLabel + // x = _a; + // + // [source] + // x = a() || yield; + // + // [intermediate] + // .local _a + // _a = a(); + // .brtrue resultLabel, (_a) + // .yield resumeLabel + // .mark resumeLabel + // _a = %sent%; + // .mark resultLabel + // x = _a; + var resultLabel = defineLabel(); + var resultLocal = declareLocal(); + emitAssignment(resultLocal, ts.visitNode(node.left, visitor, ts.isExpression), /*location*/ node.left); + if (node.operatorToken.kind === 51 /* AmpersandAmpersandToken */) { + // Logical `&&` shortcuts when the left-hand operand is falsey. + emitBreakWhenFalse(resultLabel, resultLocal, /*location*/ node.left); } - function emitClassExpression(node) { - return emitClassLikeDeclaration(node); - } - function emitClassDeclaration(node) { - return emitClassLikeDeclaration(node); + else { + // Logical `||` shortcuts when the left-hand operand is truthy. + emitBreakWhenTrue(resultLabel, resultLocal, /*location*/ node.left); } - function emitClassLikeDeclaration(node) { - if (languageVersion < 2 /* ES6 */) { - emitClassLikeDeclarationBelowES6(node); + emitAssignment(resultLocal, ts.visitNode(node.right, visitor, ts.isExpression), /*location*/ node.right); + markLabel(resultLabel); + return resultLocal; + } + /** + * Visits a comma expression containing `yield`. + * + * @param node The node to visit. + */ + function visitCommaExpression(node) { + // [source] + // x = a(), yield, b(); + // + // [intermediate] + // a(); + // .yield resumeLabel + // .mark resumeLabel + // x = %sent%, b(); + var pendingExpressions = []; + visit(node.left); + visit(node.right); + return ts.inlineExpressions(pendingExpressions); + function visit(node) { + if (ts.isBinaryExpression(node) && node.operatorToken.kind === 24 /* CommaToken */) { + visit(node.left); + visit(node.right); } else { - emitClassLikeDeclarationForES6AndHigher(node); - } - if (modulekind !== ts.ModuleKind.ES6 && node.parent === currentSourceFile && node.name) { - emitExportMemberAssignments(node.name); + if (containsYield(node) && pendingExpressions.length > 0) { + emitWorker(1 /* Statement */, [ts.createStatement(ts.inlineExpressions(pendingExpressions))]); + pendingExpressions = []; + } + pendingExpressions.push(ts.visitNode(node, visitor, ts.isExpression)); } } - function emitClassLikeDeclarationForES6AndHigher(node) { - var decoratedClassAlias; - var isHoistedDeclarationInSystemModule = shouldHoistDeclarationInSystemJsModule(node); - var isDecorated = ts.nodeIsDecorated(node); - var rewriteAsClassExpression = isDecorated || isHoistedDeclarationInSystemModule; - if (node.kind === 221 /* ClassDeclaration */) { - if (rewriteAsClassExpression) { - // When we emit an ES6 class that has a class decorator, we must tailor the - // emit to certain specific cases. - // - // In the simplest case, we emit the class declaration as a let declaration, and - // evaluate decorators after the close of the class body: - // - // TypeScript | Javascript - // --------------------------------|------------------------------------ - // @dec | let C = class C { - // class C { | } - // } | C = __decorate([dec], C); - // --------------------------------|------------------------------------ - // @dec | export let C = class C { - // export class C { | } - // } | C = __decorate([dec], C); - // --------------------------------------------------------------------- - // [Example 1] - // - // If a class declaration contains a reference to itself *inside* of the class body, - // this introduces two bindings to the class: One outside of the class body, and one - // inside of the class body. If we apply decorators as in [Example 1] above, there - // is the possibility that the decorator `dec` will return a new value for the - // constructor, which would result in the binding inside of the class no longer - // pointing to the same reference as the binding outside of the class. - // - // As a result, we must instead rewrite all references to the class *inside* of the - // class body to instead point to a local temporary alias for the class: - // - // TypeScript | Javascript - // --------------------------------|------------------------------------ - // @dec | let C_1 = class C { - // class C { | static x() { return C_1.y; } - // static x() { return C.y; } | } - // static y = 1; | let C = C_1; - // } | C.y = 1; - // | C = C_1 = __decorate([dec], C); - // --------------------------------|------------------------------------ - // @dec | let C_1 = class C { - // export class C { | static x() { return C_1.y; } - // static x() { return C.y; } | } - // static y = 1; | export let C = C_1; - // } | C.y = 1; - // | C = C_1 = __decorate([dec], C); - // --------------------------------------------------------------------- - // [Example 2] - // - // If a class declaration is the default export of a module, we instead emit - // the export after the decorated declaration: - // - // TypeScript | Javascript - // --------------------------------|------------------------------------ - // @dec | let default_1 = class { - // export default class { | } - // } | default_1 = __decorate([dec], default_1); - // | export default default_1; - // --------------------------------|------------------------------------ - // @dec | let C = class C { - // export default class { | } - // } | C = __decorate([dec], C); - // | export default C; - // --------------------------------------------------------------------- - // [Example 3] - // - // If the class declaration is the default export and a reference to itself - // inside of the class body, we must emit both an alias for the class *and* - // move the export after the declaration: - // - // TypeScript | Javascript - // --------------------------------|------------------------------------ - // @dec | let C_1 = class C { - // export default class C { | static x() { return C_1.y; } - // static x() { return C.y; } | }; - // static y = 1; | let C = C_1; - // } | C.y = 1; - // | C = C_1 = __decorate([dec], C); - // | export default C; - // --------------------------------------------------------------------- - // [Example 4] - // - // NOTE: we reuse the same rewriting logic for cases when targeting ES6 and module kind is System. - // Because of hoisting top level class declaration need to be emitted as class expressions. - // Double bind case is only required if node is decorated. - if (isDecorated && resolver.getNodeCheckFlags(node) & 524288 /* ClassWithBodyScopedClassBinding */) { - decoratedClassAlias = ts.unescapeIdentifier(makeUniqueName(node.name ? node.name.text : "default")); - decoratedClassAliases[ts.getNodeId(node)] = decoratedClassAlias; - } - if (isES6ExportedDeclaration(node) && !(node.flags & 512 /* Default */) && decoratedClassAlias === undefined) { - write("export "); - } - if (decoratedClassAlias !== undefined) { - write("let " + decoratedClassAlias); - } - else { - if (!isHoistedDeclarationInSystemModule) { - write("let "); - } - emitDeclarationName(node); - } - write(" = "); - } - else if (isES6ExportedDeclaration(node)) { - write("export "); - if (node.flags & 512 /* Default */) { - write("default "); - } + } + /** + * Visits a conditional expression containing `yield`. + * + * @param node The node to visit. + */ + function visitConditionalExpression(node) { + // [source] + // x = a() ? yield : b(); + // + // [intermediate] + // .local _a + // .brfalse whenFalseLabel, (a()) + // .yield resumeLabel + // .mark resumeLabel + // _a = %sent%; + // .br resultLabel + // .mark whenFalseLabel + // _a = b(); + // .mark resultLabel + // x = _a; + // We only need to perform a specific transformation if a `yield` expression exists + // in either the `whenTrue` or `whenFalse` branches. + // A `yield` in the condition will be handled by the normal visitor. + if (containsYield(node.whenTrue) || containsYield(node.whenFalse)) { + var whenFalseLabel = defineLabel(); + var resultLabel = defineLabel(); + var resultLocal = declareLocal(); + emitBreakWhenFalse(whenFalseLabel, ts.visitNode(node.condition, visitor, ts.isExpression), /*location*/ node.condition); + emitAssignment(resultLocal, ts.visitNode(node.whenTrue, visitor, ts.isExpression), /*location*/ node.whenTrue); + emitBreak(resultLabel); + markLabel(whenFalseLabel); + emitAssignment(resultLocal, ts.visitNode(node.whenFalse, visitor, ts.isExpression), /*location*/ node.whenFalse); + markLabel(resultLabel); + return resultLocal; + } + return ts.visitEachChild(node, visitor, context); + } + /** + * Visits a `yield` expression. + * + * @param node The node to visit. + */ + function visitYieldExpression(node) { + // [source] + // x = yield a(); + // + // [intermediate] + // .yield resumeLabel, (a()) + // .mark resumeLabel + // x = %sent%; + // NOTE: we are explicitly not handling YieldStar at this time. + var resumeLabel = defineLabel(); + var expression = ts.visitNode(node.expression, visitor, ts.isExpression); + if (node.asteriskToken) { + emitYieldStar(expression, /*location*/ node); + } + else { + emitYield(expression, /*location*/ node); + } + markLabel(resumeLabel); + return createGeneratorResume(); + } + /** + * Visits an ArrayLiteralExpression that contains a YieldExpression. + * + * @param node The node to visit. + */ + function visitArrayLiteralExpression(node) { + return visitElements(node.elements, node.multiLine); + } + /** + * Visits an array of expressions containing one or more YieldExpression nodes + * and returns an expression for the resulting value. + * + * @param elements The elements to visit. + * @param multiLine Whether array literals created should be emitted on multiple lines. + */ + function visitElements(elements, multiLine) { + // [source] + // ar = [1, yield, 2]; + // + // [intermediate] + // .local _a + // _a = [1]; + // .yield resumeLabel + // .mark resumeLabel + // ar = _a.concat([%sent%, 2]); + var numInitialElements = countInitialNodesWithoutYield(elements); + var temp = declareLocal(); + var hasAssignedTemp = false; + if (numInitialElements > 0) { + emitAssignment(temp, ts.createArrayLiteral(ts.visitNodes(elements, visitor, ts.isExpression, 0, numInitialElements))); + hasAssignedTemp = true; + } + var expressions = ts.reduceLeft(elements, reduceElement, [], numInitialElements); + return hasAssignedTemp + ? ts.createArrayConcat(temp, [ts.createArrayLiteral(expressions)]) + : ts.createArrayLiteral(expressions); + function reduceElement(expressions, element) { + if (containsYield(element) && expressions.length > 0) { + emitAssignment(temp, hasAssignedTemp + ? ts.createArrayConcat(temp, [ts.createArrayLiteral(expressions)]) + : ts.createArrayLiteral(expressions)); + hasAssignedTemp = true; + expressions = []; + } + expressions.push(ts.visitNode(element, visitor, ts.isExpression)); + return expressions; + } + } + function visitObjectLiteralExpression(node) { + // [source] + // o = { + // a: 1, + // b: yield, + // c: 2 + // }; + // + // [intermediate] + // .local _a + // _a = { + // a: 1 + // }; + // .yield resumeLabel + // .mark resumeLabel + // o = (_a.b = %sent%, + // _a.c = 2, + // _a); + var properties = node.properties; + var multiLine = node.multiLine; + var numInitialProperties = countInitialNodesWithoutYield(properties); + var temp = declareLocal(); + emitAssignment(temp, ts.createObjectLiteral(ts.visitNodes(properties, visitor, ts.isObjectLiteralElementLike, 0, numInitialProperties), + /*location*/ undefined, multiLine)); + var expressions = ts.reduceLeft(properties, reduceProperty, [], numInitialProperties); + expressions.push(multiLine ? ts.startOnNewLine(ts.getMutableClone(temp)) : temp); + return ts.inlineExpressions(expressions); + function reduceProperty(expressions, property) { + if (containsYield(property) && expressions.length > 0) { + emitStatement(ts.createStatement(ts.inlineExpressions(expressions))); + expressions = []; + } + var expression = ts.createExpressionForObjectLiteralElementLike(node, property, temp); + var visited = ts.visitNode(expression, visitor, ts.isExpression); + if (visited) { + if (multiLine) { + visited.startsOnNewLine = true; } + expressions.push(visited); } - // If the class has static properties, and it's a class expression, then we'll need - // to specialize the emit a bit. for a class expression of the form: - // - // (class C { static a = 1; static b = 2; ... }) + return expressions; + } + } + /** + * Visits an ElementAccessExpression that contains a YieldExpression. + * + * @param node The node to visit. + */ + function visitElementAccessExpression(node) { + if (containsYield(node.argumentExpression)) { + // [source] + // a = x[yield]; // - // We'll emit: + // [intermediate] + // .local _a + // _a = x; + // .yield resumeLabel + // .mark resumeLabel + // a = _a[%sent%] + var clone_7 = ts.getMutableClone(node); + clone_7.expression = cacheExpression(ts.visitNode(node.expression, visitor, ts.isLeftHandSideExpression)); + clone_7.argumentExpression = ts.visitNode(node.argumentExpression, visitor, ts.isExpression); + return clone_7; + } + return ts.visitEachChild(node, visitor, context); + } + function visitCallExpression(node) { + if (ts.forEach(node.arguments, containsYield)) { + // [source] + // a.b(1, yield, 2); // - // ((C_1 = class C { - // // Normal class body - // }, - // C_1.a = 1, - // C_1.b = 2, - // C_1)); - // var C_1; + // [intermediate] + // .local _a, _b, _c + // _b = (_a = a).b; + // _c = [1]; + // .yield resumeLabel + // .mark resumeLabel + // _b.apply(_a, _c.concat([%sent%, 2])); + var _a = ts.createCallBinding(node.expression, hoistVariableDeclaration, languageVersion, /*cacheIdentifiers*/ true), target = _a.target, thisArg = _a.thisArg; + return ts.setOriginalNode(ts.createFunctionApply(cacheExpression(ts.visitNode(target, visitor, ts.isLeftHandSideExpression)), thisArg, visitElements(node.arguments, /*multiLine*/ false), + /*location*/ node), node); + } + return ts.visitEachChild(node, visitor, context); + } + function visitNewExpression(node) { + if (ts.forEach(node.arguments, containsYield)) { + // [source] + // new a.b(1, yield, 2); // - // This keeps the expression as an expression, while ensuring that the static parts - // of it have been initialized by the time it is used. - var staticProperties = getInitializedProperties(node, /*isStatic*/ true); - var isClassExpressionWithStaticProperties = staticProperties.length > 0 && node.kind === 192 /* ClassExpression */; - var generatedName; - if (isClassExpressionWithStaticProperties) { - generatedName = node.name ? getGeneratedNameForNode(node.name) : makeUniqueName("classExpression"); - var synthesizedNode = ts.createSynthesizedNode(69 /* Identifier */); - synthesizedNode.text = generatedName; - recordTempDeclaration(synthesizedNode); - write("("); - increaseIndent(); - emit(synthesizedNode); - write(" = "); - } - write("class"); - // emit name if - // - node has a name - // - this is default export with static initializers - if (node.name || (node.flags & 512 /* Default */ && (staticProperties.length > 0 || modulekind !== ts.ModuleKind.ES6) && !rewriteAsClassExpression)) { - write(" "); - emitDeclarationName(node); - } - var baseTypeNode = ts.getClassExtendsHeritageClauseElement(node); - if (baseTypeNode) { - write(" extends "); - emit(baseTypeNode.expression); - } - write(" {"); - increaseIndent(); - writeLine(); - emitConstructor(node, baseTypeNode); - emitMemberFunctionsForES6AndHigher(node); - decreaseIndent(); - writeLine(); - emitToken(16 /* CloseBraceToken */, node.members.end); - if (rewriteAsClassExpression) { - if (decoratedClassAlias !== undefined) { - write(";"); - writeLine(); - if (isES6ExportedDeclaration(node) && !(node.flags & 512 /* Default */)) { - write("export "); - } - write("let "); - emitDeclarationName(node); - write(" = " + decoratedClassAlias); - } - decoratedClassAliases[ts.getNodeId(node)] = undefined; - write(";"); - } - // Emit static property assignment. Because classDeclaration is lexically evaluated, - // it is safe to emit static property assignment after classDeclaration - // From ES6 specification: - // HasLexicalDeclaration (N) : Determines if the argument identifier has a binding in this environment record that was created using - // a lexical declaration such as a LexicalDeclaration or a ClassDeclaration. - if (isClassExpressionWithStaticProperties) { - for (var _a = 0, staticProperties_1 = staticProperties; _a < staticProperties_1.length; _a++) { - var property = staticProperties_1[_a]; - write(","); - writeLine(); - emitPropertyDeclaration(node, property, /*receiver*/ generatedName, /*isExpression*/ true); - } - write(","); - writeLine(); - write(generatedName); - decreaseIndent(); - write(")"); - } - else { - writeLine(); - emitPropertyDeclarations(node, staticProperties); - emitDecoratorsOfClass(node, decoratedClassAlias); + // [intermediate] + // .local _a, _b, _c + // _b = (_a = a.b).bind; + // _c = [1]; + // .yield resumeLabel + // .mark resumeLabel + // new (_b.apply(_a, _c.concat([%sent%, 2]))); + var _a = ts.createCallBinding(ts.createPropertyAccess(node.expression, "bind"), hoistVariableDeclaration), target = _a.target, thisArg = _a.thisArg; + return ts.setOriginalNode(ts.createNew(ts.createFunctionApply(cacheExpression(ts.visitNode(target, visitor, ts.isExpression)), thisArg, visitElements(node.arguments, /*multiLine*/ false)), + /*typeArguments*/ undefined, [], + /*location*/ node), node); + } + return ts.visitEachChild(node, visitor, context); + } + function transformAndEmitStatements(statements, start) { + if (start === void 0) { start = 0; } + var numStatements = statements.length; + for (var i = start; i < numStatements; i++) { + transformAndEmitStatement(statements[i]); + } + } + function transformAndEmitEmbeddedStatement(node) { + if (ts.isBlock(node)) { + transformAndEmitStatements(node.statements); + } + else { + transformAndEmitStatement(node); + } + } + function transformAndEmitStatement(node) { + var savedInStatementContainingYield = inStatementContainingYield; + if (!inStatementContainingYield) { + inStatementContainingYield = containsYield(node); + } + transformAndEmitStatementWorker(node); + inStatementContainingYield = savedInStatementContainingYield; + } + function transformAndEmitStatementWorker(node) { + switch (node.kind) { + case 199 /* Block */: + return transformAndEmitBlock(node); + case 202 /* ExpressionStatement */: + return transformAndEmitExpressionStatement(node); + case 203 /* IfStatement */: + return transformAndEmitIfStatement(node); + case 204 /* DoStatement */: + return transformAndEmitDoStatement(node); + case 205 /* WhileStatement */: + return transformAndEmitWhileStatement(node); + case 206 /* ForStatement */: + return transformAndEmitForStatement(node); + case 207 /* ForInStatement */: + return transformAndEmitForInStatement(node); + case 209 /* ContinueStatement */: + return transformAndEmitContinueStatement(node); + case 210 /* BreakStatement */: + return transformAndEmitBreakStatement(node); + case 211 /* ReturnStatement */: + return transformAndEmitReturnStatement(node); + case 212 /* WithStatement */: + return transformAndEmitWithStatement(node); + case 213 /* SwitchStatement */: + return transformAndEmitSwitchStatement(node); + case 214 /* LabeledStatement */: + return transformAndEmitLabeledStatement(node); + case 215 /* ThrowStatement */: + return transformAndEmitThrowStatement(node); + case 216 /* TryStatement */: + return transformAndEmitTryStatement(node); + default: + return emitStatement(ts.visitNode(node, visitor, ts.isStatement, /*optional*/ true)); + } + } + function transformAndEmitBlock(node) { + if (containsYield(node)) { + transformAndEmitStatements(node.statements); + } + else { + emitStatement(ts.visitNode(node, visitor, ts.isStatement)); + } + } + function transformAndEmitExpressionStatement(node) { + emitStatement(ts.visitNode(node, visitor, ts.isStatement)); + } + function transformAndEmitVariableDeclarationList(node) { + for (var _i = 0, _a = node.declarations; _i < _a.length; _i++) { + var variable = _a[_i]; + hoistVariableDeclaration(variable.name); + } + var variables = ts.getInitializedVariables(node); + var numVariables = variables.length; + var variablesWritten = 0; + var pendingExpressions = []; + while (variablesWritten < numVariables) { + for (var i = variablesWritten; i < numVariables; i++) { + var variable = variables[i]; + if (containsYield(variable.initializer) && pendingExpressions.length > 0) { + break; + } + pendingExpressions.push(transformInitializedVariable(variable)); } - if (!(node.flags & 1 /* Export */)) { - return; + if (pendingExpressions.length) { + emitStatement(ts.createStatement(ts.inlineExpressions(pendingExpressions))); + variablesWritten += pendingExpressions.length; + pendingExpressions = []; } - if (modulekind !== ts.ModuleKind.ES6) { - emitExportMemberAssignment(node); + } + return undefined; + } + function transformInitializedVariable(node) { + return ts.createAssignment(ts.getSynthesizedClone(node.name), ts.visitNode(node.initializer, visitor, ts.isExpression)); + } + function transformAndEmitIfStatement(node) { + if (containsYield(node)) { + // [source] + // if (x) + // /*thenStatement*/ + // else + // /*elseStatement*/ + // + // [intermediate] + // .brfalse elseLabel, (x) + // /*thenStatement*/ + // .br endLabel + // .mark elseLabel + // /*elseStatement*/ + // .mark endLabel + if (containsYield(node.thenStatement) || containsYield(node.elseStatement)) { + var endLabel = defineLabel(); + var elseLabel = node.elseStatement ? defineLabel() : undefined; + emitBreakWhenFalse(node.elseStatement ? elseLabel : endLabel, ts.visitNode(node.expression, visitor, ts.isExpression)); + transformAndEmitEmbeddedStatement(node.thenStatement); + if (node.elseStatement) { + emitBreak(endLabel); + markLabel(elseLabel); + transformAndEmitEmbeddedStatement(node.elseStatement); + } + markLabel(endLabel); } else { - // If this is an exported class, but not on the top level (i.e. on an internal - // module), export it - if (node.flags & 512 /* Default */) { - // if this is a top level default export of decorated class, write the export after the declaration. - if (isDecorated) { - writeLine(); - write("export default "); - emitDeclarationName(node); - write(";"); - } - } - else if (node.parent.kind !== 256 /* SourceFile */) { - writeLine(); - emitStart(node); - emitModuleMemberName(node); - write(" = "); - emitDeclarationName(node); - emitEnd(node); - write(";"); - } + emitStatement(ts.visitNode(node, visitor, ts.isStatement)); } } - function emitClassLikeDeclarationBelowES6(node) { - var isES6ExportedClass = isES6ExportedDeclaration(node); - if (node.kind === 221 /* ClassDeclaration */) { - if (isES6ExportedClass && !(node.flags & 512 /* Default */)) { - write("export "); + else { + emitStatement(ts.visitNode(node, visitor, ts.isStatement)); + } + } + function transformAndEmitDoStatement(node) { + if (containsYield(node)) { + // [source] + // do { + // /*body*/ + // } + // while (i < 10); + // + // [intermediate] + // .loop conditionLabel, endLabel + // .mark loopLabel + // /*body*/ + // .mark conditionLabel + // .brtrue loopLabel, (i < 10) + // .endloop + // .mark endLabel + var conditionLabel = defineLabel(); + var loopLabel = defineLabel(); + beginLoopBlock(/*continueLabel*/ conditionLabel); + markLabel(loopLabel); + transformAndEmitEmbeddedStatement(node.statement); + markLabel(conditionLabel); + emitBreakWhenTrue(loopLabel, ts.visitNode(node.expression, visitor, ts.isExpression)); + endLoopBlock(); + } + else { + emitStatement(ts.visitNode(node, visitor, ts.isStatement)); + } + } + function visitDoStatement(node) { + if (inStatementContainingYield) { + beginScriptLoopBlock(); + node = ts.visitEachChild(node, visitor, context); + endLoopBlock(); + return node; + } + else { + return ts.visitEachChild(node, visitor, context); + } + } + function transformAndEmitWhileStatement(node) { + if (containsYield(node)) { + // [source] + // while (i < 10) { + // /*body*/ + // } + // + // [intermediate] + // .loop loopLabel, endLabel + // .mark loopLabel + // .brfalse endLabel, (i < 10) + // /*body*/ + // .br loopLabel + // .endloop + // .mark endLabel + var loopLabel = defineLabel(); + var endLabel = beginLoopBlock(loopLabel); + markLabel(loopLabel); + emitBreakWhenFalse(endLabel, ts.visitNode(node.expression, visitor, ts.isExpression)); + transformAndEmitEmbeddedStatement(node.statement); + emitBreak(loopLabel); + endLoopBlock(); + } + else { + emitStatement(ts.visitNode(node, visitor, ts.isStatement)); + } + } + function visitWhileStatement(node) { + if (inStatementContainingYield) { + beginScriptLoopBlock(); + node = ts.visitEachChild(node, visitor, context); + endLoopBlock(); + return node; + } + else { + return ts.visitEachChild(node, visitor, context); + } + } + function transformAndEmitForStatement(node) { + if (containsYield(node)) { + // [source] + // for (var i = 0; i < 10; i++) { + // /*body*/ + // } + // + // [intermediate] + // .local i + // i = 0; + // .loop incrementLabel, endLoopLabel + // .mark conditionLabel + // .brfalse endLoopLabel, (i < 10) + // /*body*/ + // .mark incrementLabel + // i++; + // .br conditionLabel + // .endloop + // .mark endLoopLabel + var conditionLabel = defineLabel(); + var incrementLabel = defineLabel(); + var endLabel = beginLoopBlock(incrementLabel); + if (node.initializer) { + var initializer = node.initializer; + if (ts.isVariableDeclarationList(initializer)) { + transformAndEmitVariableDeclarationList(initializer); } - // source file level classes in system modules are hoisted so 'var's for them are already defined - if (!shouldHoistDeclarationInSystemJsModule(node)) { - write("var "); + else { + emitStatement(ts.createStatement(ts.visitNode(initializer, visitor, ts.isExpression), + /*location*/ initializer)); } - emitDeclarationName(node); - write(" = "); } - write("(function ("); - var baseTypeNode = ts.getClassExtendsHeritageClauseElement(node); - if (baseTypeNode) { - write("_super"); - } - write(") {"); - var saveTempFlags = tempFlags; - var saveTempVariables = tempVariables; - var saveTempParameters = tempParameters; - var saveComputedPropertyNamesToGeneratedNames = computedPropertyNamesToGeneratedNames; - var saveConvertedLoopState = convertedLoopState; - convertedLoopState = undefined; - tempFlags = 0; - tempVariables = undefined; - tempParameters = undefined; - computedPropertyNamesToGeneratedNames = undefined; - increaseIndent(); - if (baseTypeNode) { - writeLine(); - emitStart(baseTypeNode); - write("__extends("); - emitDeclarationName(node); - write(", _super);"); - emitEnd(baseTypeNode); + markLabel(conditionLabel); + if (node.condition) { + emitBreakWhenFalse(endLabel, ts.visitNode(node.condition, visitor, ts.isExpression)); } - writeLine(); - emitConstructor(node, baseTypeNode); - emitMemberFunctionsForES5AndLower(node); - emitPropertyDeclarations(node, getInitializedProperties(node, /*isStatic*/ true)); - writeLine(); - emitDecoratorsOfClass(node, /*decoratedClassAlias*/ undefined); - writeLine(); - emitToken(16 /* CloseBraceToken */, node.members.end, function () { - write("return "); - emitDeclarationName(node); - }); - write(";"); - emitTempDeclarations(/*newLine*/ true); - ts.Debug.assert(convertedLoopState === undefined); - convertedLoopState = saveConvertedLoopState; - tempFlags = saveTempFlags; - tempVariables = saveTempVariables; - tempParameters = saveTempParameters; - computedPropertyNamesToGeneratedNames = saveComputedPropertyNamesToGeneratedNames; - decreaseIndent(); - writeLine(); - emitToken(16 /* CloseBraceToken */, node.members.end); - emitStart(node); - write("("); - if (baseTypeNode) { - emit(baseTypeNode.expression); + transformAndEmitEmbeddedStatement(node.statement); + markLabel(incrementLabel); + if (node.incrementor) { + emitStatement(ts.createStatement(ts.visitNode(node.incrementor, visitor, ts.isExpression), + /*location*/ node.incrementor)); } - write("))"); - if (node.kind === 221 /* ClassDeclaration */) { - write(";"); + emitBreak(conditionLabel); + endLoopBlock(); + } + else { + emitStatement(ts.visitNode(node, visitor, ts.isStatement)); + } + } + function visitForStatement(node) { + if (inStatementContainingYield) { + beginScriptLoopBlock(); + } + var initializer = node.initializer; + if (ts.isVariableDeclarationList(initializer)) { + for (var _i = 0, _a = initializer.declarations; _i < _a.length; _i++) { + var variable = _a[_i]; + hoistVariableDeclaration(variable.name); } - emitEnd(node); - if (node.kind === 221 /* ClassDeclaration */ && !isES6ExportedClass) { - emitExportMemberAssignment(node); + var variables = ts.getInitializedVariables(initializer); + node = ts.updateFor(node, variables.length > 0 + ? ts.inlineExpressions(ts.map(variables, transformInitializedVariable)) + : undefined, ts.visitNode(node.condition, visitor, ts.isExpression, /*optional*/ true), ts.visitNode(node.incrementor, visitor, ts.isExpression, /*optional*/ true), ts.visitNode(node.statement, visitor, ts.isStatement, /*optional*/ false, ts.liftToBlock)); + } + else { + node = ts.visitEachChild(node, visitor, context); + } + if (inStatementContainingYield) { + endLoopBlock(); + } + return node; + } + function transformAndEmitForInStatement(node) { + // TODO(rbuckton): Source map locations + if (containsYield(node)) { + // [source] + // for (var p in o) { + // /*body*/ + // } + // + // [intermediate] + // .local _a, _b, _i + // _a = []; + // for (_b in o) _a.push(_b); + // _i = 0; + // .loop incrementLabel, endLoopLabel + // .mark conditionLabel + // .brfalse endLoopLabel, (_i < _a.length) + // p = _a[_i]; + // /*body*/ + // .mark incrementLabel + // _b++; + // .br conditionLabel + // .endloop + // .mark endLoopLabel + var keysArray = declareLocal(); // _a + var key = declareLocal(); // _b + var keysIndex = ts.createLoopVariable(); // _i + var initializer = node.initializer; + hoistVariableDeclaration(keysIndex); + emitAssignment(keysArray, ts.createArrayLiteral()); + emitStatement(ts.createForIn(key, ts.visitNode(node.expression, visitor, ts.isExpression), ts.createStatement(ts.createCall(ts.createPropertyAccess(keysArray, "push"), + /*typeArguments*/ undefined, [key])))); + emitAssignment(keysIndex, ts.createLiteral(0)); + var conditionLabel = defineLabel(); + var incrementLabel = defineLabel(); + var endLabel = beginLoopBlock(incrementLabel); + markLabel(conditionLabel); + emitBreakWhenFalse(endLabel, ts.createLessThan(keysIndex, ts.createPropertyAccess(keysArray, "length"))); + var variable = void 0; + if (ts.isVariableDeclarationList(initializer)) { + for (var _i = 0, _a = initializer.declarations; _i < _a.length; _i++) { + var variable_1 = _a[_i]; + hoistVariableDeclaration(variable_1.name); + } + variable = ts.getSynthesizedClone(initializer.declarations[0].name); } - else if (isES6ExportedClass && (node.flags & 512 /* Default */)) { - writeLine(); - write("export default "); - emitDeclarationName(node); - write(";"); + else { + variable = ts.visitNode(initializer, visitor, ts.isExpression); + ts.Debug.assert(ts.isLeftHandSideExpression(variable)); } + emitAssignment(variable, ts.createElementAccess(keysArray, keysIndex)); + transformAndEmitEmbeddedStatement(node.statement); + markLabel(incrementLabel); + emitStatement(ts.createStatement(ts.createPostfixIncrement(keysIndex))); + emitBreak(conditionLabel); + endLoopBlock(); } - function emitClassMemberPrefix(node, member) { - emitDeclarationName(node); - if (!(member.flags & 32 /* Static */)) { - write(".prototype"); - } + else { + emitStatement(ts.visitNode(node, visitor, ts.isStatement)); } - function emitDecoratorsOfClass(node, decoratedClassAlias) { - emitDecoratorsOfMembers(node, /*staticFlag*/ 0); - emitDecoratorsOfMembers(node, 32 /* Static */); - emitDecoratorsOfConstructor(node, decoratedClassAlias); + } + function visitForInStatement(node) { + // [source] + // for (var x in a) { + // /*body*/ + // } + // + // [intermediate] + // .local x + // .loop + // for (x in a) { + // /*body*/ + // } + // .endloop + if (inStatementContainingYield) { + beginScriptLoopBlock(); } - function emitDecoratorsOfConstructor(node, decoratedClassAlias) { - var decorators = node.decorators; - var constructor = ts.getFirstConstructorWithBody(node); - var firstParameterDecorator = constructor && ts.forEach(constructor.parameters, function (parameter) { return parameter.decorators; }); - // skip decoration of the constructor if neither it nor its parameters are decorated - if (!decorators && !firstParameterDecorator) { - return; + var initializer = node.initializer; + if (ts.isVariableDeclarationList(initializer)) { + for (var _i = 0, _a = initializer.declarations; _i < _a.length; _i++) { + var variable = _a[_i]; + hoistVariableDeclaration(variable.name); } - // Emit the call to __decorate. Given the class: - // - // @dec - // class C { - // } - // - // The emit for the class is: - // - // C = __decorate([dec], C); - // - writeLine(); - emitStart(node.decorators || firstParameterDecorator); - emitDeclarationName(node); - if (decoratedClassAlias !== undefined) { - write(" = " + decoratedClassAlias); + node = ts.updateForIn(node, initializer.declarations[0].name, ts.visitNode(node.expression, visitor, ts.isExpression), ts.visitNode(node.statement, visitor, ts.isStatement, /*optional*/ false, ts.liftToBlock)); + } + else { + node = ts.visitEachChild(node, visitor, context); + } + if (inStatementContainingYield) { + endLoopBlock(); + } + return node; + } + function transformAndEmitContinueStatement(node) { + var label = findContinueTarget(node.label ? node.label.text : undefined); + ts.Debug.assert(label > 0, "Expected continue statment to point to a valid Label."); + emitBreak(label, /*location*/ node); + } + function visitContinueStatement(node) { + if (inStatementContainingYield) { + var label = findContinueTarget(node.label && node.label.text); + if (label > 0) { + return createInlineBreak(label, /*location*/ node); } - write(" = __decorate(["); - increaseIndent(); - writeLine(); - var decoratorCount = decorators ? decorators.length : 0; - var argumentsWritten = emitList(decorators, 0, decoratorCount, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ false, /*noTrailingNewLine*/ true, function (decorator) { return emit(decorator.expression); }); - if (firstParameterDecorator) { - argumentsWritten += emitDecoratorsOfParameters(constructor, /*leadingComma*/ argumentsWritten > 0); + } + return ts.visitEachChild(node, visitor, context); + } + function transformAndEmitBreakStatement(node) { + var label = findBreakTarget(node.label ? node.label.text : undefined); + ts.Debug.assert(label > 0, "Expected break statment to point to a valid Label."); + emitBreak(label, /*location*/ node); + } + function visitBreakStatement(node) { + if (inStatementContainingYield) { + var label = findBreakTarget(node.label && node.label.text); + if (label > 0) { + return createInlineBreak(label, /*location*/ node); } - emitSerializedTypeMetadata(node, /*leadingComma*/ argumentsWritten >= 0); - decreaseIndent(); - writeLine(); - write("], "); - emitDeclarationName(node); - write(")"); - emitEnd(node.decorators || firstParameterDecorator); - write(";"); - writeLine(); } - function emitDecoratorsOfMembers(node, staticFlag) { - for (var _a = 0, _b = node.members; _a < _b.length; _a++) { - var member = _b[_a]; - // only emit members in the correct group - if ((member.flags & 32 /* Static */) !== staticFlag) { - continue; - } - // skip members that cannot be decorated (such as the constructor) - if (!ts.nodeCanBeDecorated(member)) { - continue; - } - // skip an accessor declaration if it is not the first accessor - var decorators = void 0; - var functionLikeMember = void 0; - if (ts.isAccessor(member)) { - var accessors = ts.getAllAccessorDeclarations(node.members, member); - if (member !== accessors.firstAccessor) { - continue; - } - // get the decorators from the first accessor with decorators - decorators = accessors.firstAccessor.decorators; - if (!decorators && accessors.secondAccessor) { - decorators = accessors.secondAccessor.decorators; + return ts.visitEachChild(node, visitor, context); + } + function transformAndEmitReturnStatement(node) { + emitReturn(ts.visitNode(node.expression, visitor, ts.isExpression, /*optional*/ true), + /*location*/ node); + } + function visitReturnStatement(node) { + return createInlineReturn(ts.visitNode(node.expression, visitor, ts.isExpression, /*optional*/ true), + /*location*/ node); + } + function transformAndEmitWithStatement(node) { + if (containsYield(node)) { + // [source] + // with (x) { + // /*body*/ + // } + // + // [intermediate] + // .with (x) + // /*body*/ + // .endwith + beginWithBlock(cacheExpression(ts.visitNode(node.expression, visitor, ts.isExpression))); + transformAndEmitEmbeddedStatement(node.statement); + endWithBlock(); + } + else { + emitStatement(ts.visitNode(node, visitor, ts.isStatement)); + } + } + function transformAndEmitSwitchStatement(node) { + if (containsYield(node.caseBlock)) { + // [source] + // switch (x) { + // case a: + // /*caseStatements*/ + // case b: + // /*caseStatements*/ + // default: + // /*defaultStatements*/ + // } + // + // [intermediate] + // .local _a + // .switch endLabel + // _a = x; + // switch (_a) { + // case a: + // .br clauseLabels[0] + // } + // switch (_a) { + // case b: + // .br clauseLabels[1] + // } + // .br clauseLabels[2] + // .mark clauseLabels[0] + // /*caseStatements*/ + // .mark clauseLabels[1] + // /*caseStatements*/ + // .mark clauseLabels[2] + // /*caseStatements*/ + // .endswitch + // .mark endLabel + var caseBlock = node.caseBlock; + var numClauses = caseBlock.clauses.length; + var endLabel = beginSwitchBlock(); + var expression = cacheExpression(ts.visitNode(node.expression, visitor, ts.isExpression)); + // Create labels for each clause and find the index of the first default clause. + var clauseLabels = []; + var defaultClauseIndex = -1; + for (var i = 0; i < numClauses; i++) { + var clause = caseBlock.clauses[i]; + clauseLabels.push(defineLabel()); + if (clause.kind === 250 /* DefaultClause */ && defaultClauseIndex === -1) { + defaultClauseIndex = i; + } + } + // Emit switch statements for each run of case clauses either from the first case + // clause or the next case clause with a `yield` in its expression, up to the next + // case clause with a `yield` in its expression. + var clausesWritten = 0; + var pendingClauses = []; + while (clausesWritten < numClauses) { + var defaultClausesSkipped = 0; + for (var i = clausesWritten; i < numClauses; i++) { + var clause = caseBlock.clauses[i]; + if (clause.kind === 249 /* CaseClause */) { + var caseClause = clause; + if (containsYield(caseClause.expression) && pendingClauses.length > 0) { + break; + } + pendingClauses.push(ts.createCaseClause(ts.visitNode(caseClause.expression, visitor, ts.isExpression), [ + createInlineBreak(clauseLabels[i], /*location*/ caseClause.expression) + ])); } - // we only decorate parameters of the set accessor - functionLikeMember = accessors.setAccessor; - } - else { - decorators = member.decorators; - // we only decorate the parameters here if this is a method - if (member.kind === 147 /* MethodDeclaration */) { - functionLikeMember = member; + else { + defaultClausesSkipped++; } } - var firstParameterDecorator = functionLikeMember && ts.forEach(functionLikeMember.parameters, function (parameter) { return parameter.decorators; }); - // skip a member if it or any of its parameters are not decorated - if (!decorators && !firstParameterDecorator) { - continue; - } - // Emit the call to __decorate. Given the following: - // - // class C { - // @dec method(@dec2 x) {} - // @dec get accessor() {} - // @dec prop; - // } - // - // The emit for a method is: - // - // __decorate([ - // dec, - // __param(0, dec2), - // __metadata("design:type", Function), - // __metadata("design:paramtypes", [Object]), - // __metadata("design:returntype", void 0) - // ], C.prototype, "method", undefined); - // - // The emit for an accessor is: - // - // __decorate([ - // dec - // ], C.prototype, "accessor", undefined); - // - // The emit for a property is: - // - // __decorate([ - // dec - // ], C.prototype, "prop"); - // - writeLine(); - emitStart(decorators || firstParameterDecorator); - write("__decorate(["); - increaseIndent(); - writeLine(); - var decoratorCount = decorators ? decorators.length : 0; - var argumentsWritten = emitList(decorators, 0, decoratorCount, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ false, /*noTrailingNewLine*/ true, function (decorator) { return emit(decorator.expression); }); - if (firstParameterDecorator) { - argumentsWritten += emitDecoratorsOfParameters(functionLikeMember, argumentsWritten > 0); + if (pendingClauses.length) { + emitStatement(ts.createSwitch(expression, ts.createCaseBlock(pendingClauses))); + clausesWritten += pendingClauses.length; + pendingClauses = []; } - emitSerializedTypeMetadata(member, argumentsWritten > 0); - decreaseIndent(); - writeLine(); - write("], "); - emitClassMemberPrefix(node, member); - write(", "); - emitExpressionForPropertyName(member.name); - if (languageVersion > 0 /* ES3 */) { - if (member.kind !== 145 /* PropertyDeclaration */) { - // We emit `null` here to indicate to `__decorate` that it can invoke `Object.getOwnPropertyDescriptor` directly. - // We have this extra argument here so that we can inject an explicit property descriptor at a later date. - write(", null"); - } - else { - // We emit `void 0` here to indicate to `__decorate` that it can invoke `Object.defineProperty` directly, but that it - // should not invoke `Object.getOwnPropertyDescriptor`. - write(", void 0"); - } + if (defaultClausesSkipped > 0) { + clausesWritten += defaultClausesSkipped; + defaultClausesSkipped = 0; } - write(")"); - emitEnd(decorators || firstParameterDecorator); - write(";"); - writeLine(); } - } - function emitDecoratorsOfParameters(node, leadingComma) { - var argumentsWritten = 0; - if (node) { - var parameterIndex_1 = 0; - for (var _a = 0, _b = node.parameters; _a < _b.length; _a++) { - var parameter = _b[_a]; - if (ts.nodeIsDecorated(parameter)) { - var decorators = parameter.decorators; - argumentsWritten += emitList(decorators, 0, decorators.length, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ leadingComma, /*noTrailingNewLine*/ true, function (decorator) { - write("__param(" + parameterIndex_1 + ", "); - emit(decorator.expression); - write(")"); - }); - leadingComma = true; - } - parameterIndex_1++; - } + if (defaultClauseIndex >= 0) { + emitBreak(clauseLabels[defaultClauseIndex]); } - return argumentsWritten; - } - function shouldEmitTypeMetadata(node) { - // This method determines whether to emit the "design:type" metadata based on the node's kind. - // The caller should have already tested whether the node has decorators and whether the emitDecoratorMetadata - // compiler option is set. - switch (node.kind) { - case 147 /* MethodDeclaration */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 145 /* PropertyDeclaration */: - return true; + else { + emitBreak(endLabel); } - return false; - } - function shouldEmitReturnTypeMetadata(node) { - // This method determines whether to emit the "design:returntype" metadata based on the node's kind. - // The caller should have already tested whether the node has decorators and whether the emitDecoratorMetadata - // compiler option is set. - switch (node.kind) { - case 147 /* MethodDeclaration */: - return true; + for (var i = 0; i < numClauses; i++) { + markLabel(clauseLabels[i]); + transformAndEmitStatements(caseBlock.clauses[i].statements); } - return false; + endSwitchBlock(); } - function shouldEmitParamTypesMetadata(node) { - // This method determines whether to emit the "design:paramtypes" metadata based on the node's kind. - // The caller should have already tested whether the node has decorators and whether the emitDecoratorMetadata - // compiler option is set. - switch (node.kind) { - case 221 /* ClassDeclaration */: - case 147 /* MethodDeclaration */: - case 150 /* SetAccessor */: - return true; - } - return false; + else { + emitStatement(ts.visitNode(node, visitor, ts.isStatement)); + } + } + function visitSwitchStatement(node) { + if (inStatementContainingYield) { + beginScriptSwitchBlock(); + } + node = ts.visitEachChild(node, visitor, context); + if (inStatementContainingYield) { + endSwitchBlock(); } - /** Serializes the type of a declaration to an appropriate JS constructor value. Used by the __metadata decorator for a class member. */ - function emitSerializedTypeOfNode(node) { - // serialization of the type of a declaration uses the following rules: + return node; + } + function transformAndEmitLabeledStatement(node) { + if (containsYield(node)) { + // [source] + // x: { + // /*body*/ + // } // - // * The serialized type of a ClassDeclaration is "Function" - // * The serialized type of a ParameterDeclaration is the serialized type of its type annotation. - // * The serialized type of a PropertyDeclaration is the serialized type of its type annotation. - // * The serialized type of an AccessorDeclaration is the serialized type of the return type annotation of its getter or parameter type annotation of its setter. - // * The serialized type of any other FunctionLikeDeclaration is "Function". - // * The serialized type of any other node is "void 0". + // [intermediate] + // .labeled "x", endLabel + // /*body*/ + // .endlabeled + // .mark endLabel + beginLabeledBlock(node.label.text); + transformAndEmitEmbeddedStatement(node.statement); + endLabeledBlock(); + } + else { + emitStatement(ts.visitNode(node, visitor, ts.isStatement)); + } + } + function visitLabeledStatement(node) { + if (inStatementContainingYield) { + beginScriptLabeledBlock(node.label.text); + } + node = ts.visitEachChild(node, visitor, context); + if (inStatementContainingYield) { + endLabeledBlock(); + } + return node; + } + function transformAndEmitThrowStatement(node) { + emitThrow(ts.visitNode(node.expression, visitor, ts.isExpression), + /*location*/ node); + } + function transformAndEmitTryStatement(node) { + if (containsYield(node)) { + // [source] + // try { + // /*tryBlock*/ + // } + // catch (e) { + // /*catchBlock*/ + // } + // finally { + // /*finallyBlock*/ + // } // - // For rules on serializing type annotations, see `serializeTypeNode`. - switch (node.kind) { - case 221 /* ClassDeclaration */: - write("Function"); - return; - case 145 /* PropertyDeclaration */: - emitSerializedTypeNode(node.type); - return; - case 142 /* Parameter */: - emitSerializedTypeNode(node.type); - return; - case 149 /* GetAccessor */: - emitSerializedTypeNode(node.type); - return; - case 150 /* SetAccessor */: - emitSerializedTypeNode(ts.getSetAccessorTypeAnnotationNode(node)); - return; + // [intermediate] + // .local _a + // .try tryLabel, catchLabel, finallyLabel, endLabel + // .mark tryLabel + // .nop + // /*tryBlock*/ + // .br endLabel + // .catch + // .mark catchLabel + // _a = %error%; + // /*catchBlock*/ + // .br endLabel + // .finally + // .mark finallyLabel + // /*finallyBlock*/ + // .endfinally + // .endtry + // .mark endLabel + beginExceptionBlock(); + transformAndEmitEmbeddedStatement(node.tryBlock); + if (node.catchClause) { + beginCatchBlock(node.catchClause.variableDeclaration); + transformAndEmitEmbeddedStatement(node.catchClause.block); } - if (ts.isFunctionLike(node)) { - write("Function"); - return; + if (node.finallyBlock) { + beginFinallyBlock(); + transformAndEmitEmbeddedStatement(node.finallyBlock); } - write("void 0"); + endExceptionBlock(); } - function emitSerializedTypeNode(node) { - if (node) { - switch (node.kind) { - case 103 /* VoidKeyword */: - write("void 0"); - return; - case 164 /* ParenthesizedType */: - emitSerializedTypeNode(node.type); - return; - case 156 /* FunctionType */: - case 157 /* ConstructorType */: - write("Function"); - return; - case 160 /* ArrayType */: - case 161 /* TupleType */: - write("Array"); - return; - case 154 /* TypePredicate */: - case 120 /* BooleanKeyword */: - write("Boolean"); - return; - case 132 /* StringKeyword */: - case 166 /* LiteralType */: - write("String"); - return; - case 130 /* NumberKeyword */: - write("Number"); - return; - case 133 /* SymbolKeyword */: - write("Symbol"); - return; - case 155 /* TypeReference */: - emitSerializedTypeReferenceNode(node); - return; - case 158 /* TypeQuery */: - case 159 /* TypeLiteral */: - case 162 /* UnionType */: - case 163 /* IntersectionType */: - case 117 /* AnyKeyword */: - case 165 /* ThisType */: - break; - default: - ts.Debug.fail("Cannot serialize unexpected type node."); - break; - } - } - write("Object"); + else { + emitStatement(ts.visitEachChild(node, visitor, context)); } - /** Serializes a TypeReferenceNode to an appropriate JS constructor value. Used by the __metadata decorator. */ - function emitSerializedTypeReferenceNode(node) { - var location = node.parent; - while (ts.isDeclaration(location) || ts.isTypeNode(location)) { - location = location.parent; - } - // Clone the type name and parent it to a location outside of the current declaration. - var typeName = ts.cloneEntityName(node.typeName, location); - var result = resolver.getTypeReferenceSerializationKind(typeName); - switch (result) { - case ts.TypeReferenceSerializationKind.Unknown: - var temp = createAndRecordTempVariable(0 /* Auto */); - write("(typeof ("); - emitNodeWithoutSourceMap(temp); - write(" = "); - emitEntityNameAsExpression(typeName, /*useFallback*/ true); - write(") === 'function' && "); - emitNodeWithoutSourceMap(temp); - write(") || Object"); - break; - case ts.TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue: - emitEntityNameAsExpression(typeName, /*useFallback*/ false); - break; - case ts.TypeReferenceSerializationKind.VoidType: - write("void 0"); - break; - case ts.TypeReferenceSerializationKind.BooleanType: - write("Boolean"); - break; - case ts.TypeReferenceSerializationKind.NumberLikeType: - write("Number"); - break; - case ts.TypeReferenceSerializationKind.StringLikeType: - write("String"); - break; - case ts.TypeReferenceSerializationKind.ArrayLikeType: - write("Array"); - break; - case ts.TypeReferenceSerializationKind.ESSymbolType: - if (languageVersion < 2 /* ES6 */) { - write("typeof Symbol === 'function' ? Symbol : Object"); - } - else { - write("Symbol"); - } - break; - case ts.TypeReferenceSerializationKind.TypeWithCallSignature: - write("Function"); - break; - case ts.TypeReferenceSerializationKind.ObjectType: - write("Object"); - break; + } + function containsYield(node) { + return node && (node.transformFlags & 4194304 /* ContainsYield */) !== 0; + } + function countInitialNodesWithoutYield(nodes) { + var numNodes = nodes.length; + for (var i = 0; i < numNodes; i++) { + if (containsYield(nodes[i])) { + return i; } } - /** Serializes the parameter types of a function or the constructor of a class. Used by the __metadata decorator for a method or set accessor. */ - function emitSerializedParameterTypesOfNode(node) { - // serialization of parameter types uses the following rules: - // - // * If the declaration is a class, the parameters of the first constructor with a body are used. - // * If the declaration is function-like and has a body, the parameters of the function are used. - // - // For the rules on serializing the type of each parameter declaration, see `serializeTypeOfDeclaration`. - if (node) { - var valueDeclaration = void 0; - if (node.kind === 221 /* ClassDeclaration */) { - valueDeclaration = ts.getFirstConstructorWithBody(node); - } - else if (ts.isFunctionLike(node) && ts.nodeIsPresent(node.body)) { - valueDeclaration = node; - } - if (valueDeclaration) { - var parameters = valueDeclaration.parameters; - var skipThisCount = parameters.length && parameters[0].name.originalKeywordKind === 97 /* ThisKeyword */ ? 1 : 0; - var parameterCount = parameters.length; - if (parameterCount > skipThisCount) { - for (var i = skipThisCount; i < parameterCount; i++) { - if (i > skipThisCount) { - write(", "); - } - if (parameters[i].dotDotDotToken) { - var parameterType = parameters[i].type; - if (parameterType && parameterType.kind === 160 /* ArrayType */) { - parameterType = parameterType.elementType; - } - else if (parameterType && parameterType.kind === 155 /* TypeReference */ && parameterType.typeArguments && parameterType.typeArguments.length === 1) { - parameterType = parameterType.typeArguments[0]; - } - else { - parameterType = undefined; - } - emitSerializedTypeNode(parameterType); - } - else { - emitSerializedTypeOfNode(parameters[i]); - } - } + return -1; + } + function onSubstituteNode(emitContext, node) { + node = previousOnSubstituteNode(emitContext, node); + if (emitContext === 1 /* Expression */) { + return substituteExpression(node); + } + return node; + } + function substituteExpression(node) { + if (ts.isIdentifier(node)) { + return substituteExpressionIdentifier(node); + } + return node; + } + function substituteExpressionIdentifier(node) { + if (renamedCatchVariables && ts.hasProperty(renamedCatchVariables, node.text)) { + var original = ts.getOriginalNode(node); + if (ts.isIdentifier(original) && original.parent) { + var declaration = resolver.getReferencedValueDeclaration(original); + if (declaration) { + var name_38 = ts.getProperty(renamedCatchVariableDeclarations, String(ts.getOriginalNodeId(declaration))); + if (name_38) { + var clone_8 = ts.getMutableClone(name_38); + ts.setSourceMapRange(clone_8, node); + ts.setCommentRange(clone_8, node); + return clone_8; } } } } - /** Serializes the return type of function. Used by the __metadata decorator for a method. */ - function emitSerializedReturnTypeOfNode(node) { - if (node && ts.isFunctionLike(node)) { - if (node.type) { - emitSerializedTypeNode(node.type); - return; - } - else if (ts.isAsyncFunctionLike(node)) { - write("Promise"); - return; + return node; + } + function cacheExpression(node) { + var temp; + if (ts.isGeneratedIdentifier(node)) { + return node; + } + temp = ts.createTempVariable(hoistVariableDeclaration); + emitAssignment(temp, node, /*location*/ node); + return temp; + } + function declareLocal(name) { + var temp = name + ? ts.createUniqueName(name) + : ts.createTempVariable(/*recordTempVariable*/ undefined); + hoistVariableDeclaration(temp); + return temp; + } + /** + * Defines a label, uses as the target of a Break operation. + */ + function defineLabel() { + if (!labelOffsets) { + labelOffsets = []; + } + var label = nextLabelId; + nextLabelId++; + labelOffsets[label] = -1; + return label; + } + /** + * Marks the current operation with the specified label. + */ + function markLabel(label) { + ts.Debug.assert(labelOffsets !== undefined, "No labels were defined."); + labelOffsets[label] = operations ? operations.length : 0; + } + /** + * Begins a block operation (With, Break/Continue, Try/Catch/Finally) + * + * @param block Information about the block. + */ + function beginBlock(block) { + if (!blocks) { + blocks = []; + blockActions = []; + blockOffsets = []; + blockStack = []; + } + var index = blockActions.length; + blockActions[index] = 0 /* Open */; + blockOffsets[index] = operations ? operations.length : 0; + blocks[index] = block; + blockStack.push(block); + return index; + } + /** + * Ends the current block operation. + */ + function endBlock() { + var block = peekBlock(); + ts.Debug.assert(block !== undefined, "beginBlock was never called."); + var index = blockActions.length; + blockActions[index] = 1 /* Close */; + blockOffsets[index] = operations ? operations.length : 0; + blocks[index] = block; + blockStack.pop(); + return block; + } + /** + * Gets the current open block. + */ + function peekBlock() { + return ts.lastOrUndefined(blockStack); + } + /** + * Gets the kind of the current open block. + */ + function peekBlockKind() { + var block = peekBlock(); + return block && block.kind; + } + /** + * Begins a code block for a generated `with` statement. + * + * @param expression An identifier representing expression for the `with` block. + */ + function beginWithBlock(expression) { + var startLabel = defineLabel(); + var endLabel = defineLabel(); + markLabel(startLabel); + beginBlock({ + kind: 1 /* With */, + expression: expression, + startLabel: startLabel, + endLabel: endLabel + }); + } + /** + * Ends a code block for a generated `with` statement. + */ + function endWithBlock() { + ts.Debug.assert(peekBlockKind() === 1 /* With */); + var block = endBlock(); + markLabel(block.endLabel); + } + function isWithBlock(block) { + return block.kind === 1 /* With */; + } + /** + * Begins a code block for a generated `try` statement. + */ + function beginExceptionBlock() { + var startLabel = defineLabel(); + var endLabel = defineLabel(); + markLabel(startLabel); + beginBlock({ + kind: 0 /* Exception */, + state: 0 /* Try */, + startLabel: startLabel, + endLabel: endLabel + }); + emitNop(); + return endLabel; + } + /** + * Enters the `catch` clause of a generated `try` statement. + * + * @param variable The catch variable. + */ + function beginCatchBlock(variable) { + ts.Debug.assert(peekBlockKind() === 0 /* Exception */); + var text = variable.name.text; + var name = declareLocal(text); + if (!renamedCatchVariables) { + renamedCatchVariables = ts.createMap(); + renamedCatchVariableDeclarations = ts.createMap(); + context.enableSubstitution(69 /* Identifier */); + } + renamedCatchVariables[text] = true; + renamedCatchVariableDeclarations[ts.getOriginalNodeId(variable)] = name; + var exception = peekBlock(); + ts.Debug.assert(exception.state < 1 /* Catch */); + var endLabel = exception.endLabel; + emitBreak(endLabel); + var catchLabel = defineLabel(); + markLabel(catchLabel); + exception.state = 1 /* Catch */; + exception.catchVariable = name; + exception.catchLabel = catchLabel; + emitAssignment(name, ts.createCall(ts.createPropertyAccess(state, "sent"), /*typeArguments*/ undefined, [])); + emitNop(); + } + /** + * Enters the `finally` block of a generated `try` statement. + */ + function beginFinallyBlock() { + ts.Debug.assert(peekBlockKind() === 0 /* Exception */); + var exception = peekBlock(); + ts.Debug.assert(exception.state < 2 /* Finally */); + var endLabel = exception.endLabel; + emitBreak(endLabel); + var finallyLabel = defineLabel(); + markLabel(finallyLabel); + exception.state = 2 /* Finally */; + exception.finallyLabel = finallyLabel; + } + /** + * Ends the code block for a generated `try` statement. + */ + function endExceptionBlock() { + ts.Debug.assert(peekBlockKind() === 0 /* Exception */); + var exception = endBlock(); + var state = exception.state; + if (state < 2 /* Finally */) { + emitBreak(exception.endLabel); + } + else { + emitEndfinally(); + } + markLabel(exception.endLabel); + emitNop(); + exception.state = 3 /* Done */; + } + function isExceptionBlock(block) { + return block.kind === 0 /* Exception */; + } + /** + * Begins a code block that supports `break` or `continue` statements that are defined in + * the source tree and not from generated code. + * + * @param labelText Names from containing labeled statements. + */ + function beginScriptLoopBlock() { + beginBlock({ + kind: 3 /* Loop */, + isScript: true, + breakLabel: -1, + continueLabel: -1 + }); + } + /** + * Begins a code block that supports `break` or `continue` statements that are defined in + * generated code. Returns a label used to mark the operation to which to jump when a + * `break` statement targets this block. + * + * @param continueLabel A Label used to mark the operation to which to jump when a + * `continue` statement targets this block. + */ + function beginLoopBlock(continueLabel) { + var breakLabel = defineLabel(); + beginBlock({ + kind: 3 /* Loop */, + isScript: false, + breakLabel: breakLabel, + continueLabel: continueLabel + }); + return breakLabel; + } + /** + * Ends a code block that supports `break` or `continue` statements that are defined in + * generated code or in the source tree. + */ + function endLoopBlock() { + ts.Debug.assert(peekBlockKind() === 3 /* Loop */); + var block = endBlock(); + var breakLabel = block.breakLabel; + if (!block.isScript) { + markLabel(breakLabel); + } + } + /** + * Begins a code block that supports `break` statements that are defined in the source + * tree and not from generated code. + * + */ + function beginScriptSwitchBlock() { + beginBlock({ + kind: 2 /* Switch */, + isScript: true, + breakLabel: -1 + }); + } + /** + * Begins a code block that supports `break` statements that are defined in generated code. + * Returns a label used to mark the operation to which to jump when a `break` statement + * targets this block. + */ + function beginSwitchBlock() { + var breakLabel = defineLabel(); + beginBlock({ + kind: 2 /* Switch */, + isScript: false, + breakLabel: breakLabel + }); + return breakLabel; + } + /** + * Ends a code block that supports `break` statements that are defined in generated code. + */ + function endSwitchBlock() { + ts.Debug.assert(peekBlockKind() === 2 /* Switch */); + var block = endBlock(); + var breakLabel = block.breakLabel; + if (!block.isScript) { + markLabel(breakLabel); + } + } + function beginScriptLabeledBlock(labelText) { + beginBlock({ + kind: 4 /* Labeled */, + isScript: true, + labelText: labelText, + breakLabel: -1 + }); + } + function beginLabeledBlock(labelText) { + var breakLabel = defineLabel(); + beginBlock({ + kind: 4 /* Labeled */, + isScript: false, + labelText: labelText, + breakLabel: breakLabel + }); + } + function endLabeledBlock() { + ts.Debug.assert(peekBlockKind() === 4 /* Labeled */); + var block = endBlock(); + if (!block.isScript) { + markLabel(block.breakLabel); + } + } + /** + * Indicates whether the provided block supports `break` statements. + * + * @param block A code block. + */ + function supportsUnlabeledBreak(block) { + return block.kind === 2 /* Switch */ + || block.kind === 3 /* Loop */; + } + /** + * Indicates whether the provided block supports `break` statements with labels. + * + * @param block A code block. + */ + function supportsLabeledBreakOrContinue(block) { + return block.kind === 4 /* Labeled */; + } + /** + * Indicates whether the provided block supports `continue` statements. + * + * @param block A code block. + */ + function supportsUnlabeledContinue(block) { + return block.kind === 3 /* Loop */; + } + function hasImmediateContainingLabeledBlock(labelText, start) { + for (var j = start; j >= 0; j--) { + var containingBlock = blockStack[j]; + if (supportsLabeledBreakOrContinue(containingBlock)) { + if (containingBlock.labelText === labelText) { + return true; } } - write("void 0"); + else { + break; + } } - function emitSerializedTypeMetadata(node, writeComma) { - // This method emits the serialized type metadata for a decorator target. - // The caller should have already tested whether the node has decorators. - var argumentsWritten = 0; - if (compilerOptions.emitDecoratorMetadata) { - if (shouldEmitTypeMetadata(node)) { - if (writeComma) { - write(", "); - } - writeLine(); - write("__metadata('design:type', "); - emitSerializedTypeOfNode(node); - write(")"); - argumentsWritten++; - } - if (shouldEmitParamTypesMetadata(node)) { - if (writeComma || argumentsWritten) { - write(", "); - } - writeLine(); - write("__metadata('design:paramtypes', ["); - emitSerializedParameterTypesOfNode(node); - write("])"); - argumentsWritten++; + return false; + } + /** + * Finds the label that is the target for a `break` statement. + * + * @param labelText An optional name of a containing labeled statement. + */ + function findBreakTarget(labelText) { + ts.Debug.assert(blocks !== undefined); + if (labelText) { + for (var i = blockStack.length - 1; i >= 0; i--) { + var block = blockStack[i]; + if (supportsLabeledBreakOrContinue(block) && block.labelText === labelText) { + return block.breakLabel; } - if (shouldEmitReturnTypeMetadata(node)) { - if (writeComma || argumentsWritten) { - write(", "); - } - writeLine(); - write("__metadata('design:returntype', "); - emitSerializedReturnTypeOfNode(node); - write(")"); - argumentsWritten++; + else if (supportsUnlabeledBreak(block) && hasImmediateContainingLabeledBlock(labelText, i - 1)) { + return block.breakLabel; } } - return argumentsWritten; - } - function emitInterfaceDeclaration(node) { - emitCommentsOnNotEmittedNode(node); } - function shouldEmitEnumDeclaration(node) { - var isConstEnum = ts.isConst(node); - return !isConstEnum || compilerOptions.preserveConstEnums || compilerOptions.isolatedModules; - } - function emitEnumDeclaration(node) { - // const enums are completely erased during compilation. - if (!shouldEmitEnumDeclaration(node)) { - return; - } - if (!shouldHoistDeclarationInSystemJsModule(node)) { - // do not emit var if variable was already hoisted - var isES6ExportedEnum = isES6ExportedDeclaration(node); - if (!(node.flags & 1 /* Export */) || (isES6ExportedEnum && isFirstDeclarationOfKind(node, node.symbol && node.symbol.declarations, 224 /* EnumDeclaration */))) { - emitStart(node); - if (isES6ExportedEnum) { - write("export "); - } - write("var "); - emit(node.name); - emitEnd(node); - write(";"); + else { + for (var i = blockStack.length - 1; i >= 0; i--) { + var block = blockStack[i]; + if (supportsUnlabeledBreak(block)) { + return block.breakLabel; } } - writeLine(); - emitStart(node); - write("(function ("); - emitStart(node.name); - write(getGeneratedNameForNode(node)); - emitEnd(node.name); - write(") {"); - increaseIndent(); - emitLines(node.members); - decreaseIndent(); - writeLine(); - emitToken(16 /* CloseBraceToken */, node.members.end); - write(")("); - emitModuleMemberName(node); - write(" || ("); - emitModuleMemberName(node); - write(" = {}));"); - emitEnd(node); - if (!isES6ExportedDeclaration(node) && node.flags & 1 /* Export */ && !shouldHoistDeclarationInSystemJsModule(node)) { - // do not emit var if variable was already hoisted - writeLine(); - emitStart(node); - write("var "); - emit(node.name); - write(" = "); - emitModuleMemberName(node); - emitEnd(node); - write(";"); - } - if (modulekind !== ts.ModuleKind.ES6 && node.parent === currentSourceFile) { - if (modulekind === ts.ModuleKind.System && (node.flags & 1 /* Export */)) { - // write the call to exporter for enum - writeLine(); - write(exportFunctionForFile + "(\""); - emitDeclarationName(node); - write("\", "); - emitDeclarationName(node); - write(");"); + } + return 0; + } + /** + * Finds the label that is the target for a `continue` statement. + * + * @param labelText An optional name of a containing labeled statement. + */ + function findContinueTarget(labelText) { + ts.Debug.assert(blocks !== undefined); + if (labelText) { + for (var i = blockStack.length - 1; i >= 0; i--) { + var block = blockStack[i]; + if (supportsUnlabeledContinue(block) && hasImmediateContainingLabeledBlock(labelText, i - 1)) { + return block.continueLabel; } - emitExportMemberAssignments(node.name); } } - function emitEnumMember(node) { - var enumParent = node.parent; - emitStart(node); - write(getGeneratedNameForNode(enumParent)); - write("["); - write(getGeneratedNameForNode(enumParent)); - write("["); - emitExpressionForPropertyName(node.name); - write("] = "); - writeEnumMemberDeclarationValue(node); - write("] = "); - emitExpressionForPropertyName(node.name); - emitEnd(node); - write(";"); + else { + for (var i = blockStack.length - 1; i >= 0; i--) { + var block = blockStack[i]; + if (supportsUnlabeledContinue(block)) { + return block.continueLabel; + } + } } - function writeEnumMemberDeclarationValue(member) { - var value = resolver.getConstantValue(member); - if (value !== undefined) { - write(value.toString()); - return; + return 0; + } + /** + * Creates an expression that can be used to indicate the value for a label. + * + * @param label A label. + */ + function createLabel(label) { + if (label > 0) { + if (labelExpressions === undefined) { + labelExpressions = []; } - else if (member.initializer) { - emit(member.initializer); + var expression = ts.createSynthesizedNode(8 /* NumericLiteral */); + if (labelExpressions[label] === undefined) { + labelExpressions[label] = [expression]; } else { - write("undefined"); + labelExpressions[label].push(expression); } + return expression; } - function getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration) { - if (moduleDeclaration.body && moduleDeclaration.body.kind === 225 /* ModuleDeclaration */) { - var recursiveInnerModule = getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration.body); - return recursiveInnerModule || moduleDeclaration.body; - } + return ts.createNode(193 /* OmittedExpression */); + } + /** + * Creates a numeric literal for the provided instruction. + */ + function createInstruction(instruction) { + var literal = ts.createLiteral(instruction); + literal.trailingComment = instructionNames[instruction]; + return literal; + } + /** + * Creates a statement that can be used indicate a Break operation to the provided label. + * + * @param label A label. + * @param location An optional source map location for the statement. + */ + function createInlineBreak(label, location) { + ts.Debug.assert(label > 0, "Invalid label: " + label); + return ts.createReturn(ts.createArrayLiteral([ + createInstruction(3 /* Break */), + createLabel(label) + ]), location); + } + /** + * Creates a statement that can be used indicate a Return operation. + * + * @param expression The expression for the return statement. + * @param location An optional source map location for the statement. + */ + function createInlineReturn(expression, location) { + return ts.createReturn(ts.createArrayLiteral(expression + ? [createInstruction(2 /* Return */), expression] + : [createInstruction(2 /* Return */)]), location); + } + /** + * Creates an expression that can be used to resume from a Yield operation. + */ + function createGeneratorResume(location) { + return ts.createCall(ts.createPropertyAccess(state, "sent"), /*typeArguments*/ undefined, [], location); + } + /** + * Emits an empty instruction. + */ + function emitNop() { + emitWorker(0 /* Nop */); + } + /** + * Emits a Statement. + * + * @param node A statement. + */ + function emitStatement(node) { + if (node) { + emitWorker(1 /* Statement */, [node]); } - function shouldEmitModuleDeclaration(node) { - return ts.isInstantiatedModule(node, compilerOptions.preserveConstEnums || compilerOptions.isolatedModules); + else { + emitNop(); } - function isModuleMergedWithES6Class(node) { - return languageVersion === 2 /* ES6 */ && !!(resolver.getNodeCheckFlags(node) & 32768 /* LexicalModuleMergesWithClass */); + } + /** + * Emits an Assignment operation. + * + * @param left The left-hand side of the assignment. + * @param right The right-hand side of the assignment. + * @param location An optional source map location for the assignment. + */ + function emitAssignment(left, right, location) { + emitWorker(2 /* Assign */, [left, right], location); + } + /** + * Emits a Break operation to the specified label. + * + * @param label A label. + * @param location An optional source map location for the assignment. + */ + function emitBreak(label, location) { + emitWorker(3 /* Break */, [label], location); + } + /** + * Emits a Break operation to the specified label when a condition evaluates to a truthy + * value at runtime. + * + * @param label A label. + * @param condition The condition. + * @param location An optional source map location for the assignment. + */ + function emitBreakWhenTrue(label, condition, location) { + emitWorker(4 /* BreakWhenTrue */, [label, condition], location); + } + /** + * Emits a Break to the specified label when a condition evaluates to a falsey value at + * runtime. + * + * @param label A label. + * @param condition The condition. + * @param location An optional source map location for the assignment. + */ + function emitBreakWhenFalse(label, condition, location) { + emitWorker(5 /* BreakWhenFalse */, [label, condition], location); + } + /** + * Emits a YieldStar operation for the provided expression. + * + * @param expression An optional value for the yield operation. + * @param location An optional source map location for the assignment. + */ + function emitYieldStar(expression, location) { + emitWorker(7 /* YieldStar */, [expression], location); + } + /** + * Emits a Yield operation for the provided expression. + * + * @param expression An optional value for the yield operation. + * @param location An optional source map location for the assignment. + */ + function emitYield(expression, location) { + emitWorker(6 /* Yield */, [expression], location); + } + /** + * Emits a Return operation for the provided expression. + * + * @param expression An optional value for the operation. + * @param location An optional source map location for the assignment. + */ + function emitReturn(expression, location) { + emitWorker(8 /* Return */, [expression], location); + } + /** + * Emits a Throw operation for the provided expression. + * + * @param expression A value for the operation. + * @param location An optional source map location for the assignment. + */ + function emitThrow(expression, location) { + emitWorker(9 /* Throw */, [expression], location); + } + /** + * Emits an Endfinally operation. This is used to handle `finally` block semantics. + */ + function emitEndfinally() { + emitWorker(10 /* Endfinally */); + } + /** + * Emits an operation. + * + * @param code The OpCode for the operation. + * @param args The optional arguments for the operation. + */ + function emitWorker(code, args, location) { + if (operations === undefined) { + operations = []; + operationArguments = []; + operationLocations = []; } - function isFirstDeclarationOfKind(node, declarations, kind) { - return !ts.forEach(declarations, function (declaration) { return declaration.kind === kind && declaration.pos < node.pos; }); + if (labelOffsets === undefined) { + // mark entry point + markLabel(defineLabel()); } - function emitModuleDeclaration(node) { - // Emit only if this module is non-ambient. - var shouldEmit = shouldEmitModuleDeclaration(node); - if (!shouldEmit) { - return emitCommentsOnNotEmittedNode(node); - } - var hoistedInDeclarationScope = shouldHoistDeclarationInSystemJsModule(node); - var emitVarForModule = !hoistedInDeclarationScope && !isModuleMergedWithES6Class(node); - if (emitVarForModule) { - var isES6ExportedNamespace = isES6ExportedDeclaration(node); - if (!isES6ExportedNamespace || isFirstDeclarationOfKind(node, node.symbol && node.symbol.declarations, 225 /* ModuleDeclaration */)) { - emitStart(node); - if (isES6ExportedNamespace) { - write("export "); - } - write("var "); - emit(node.name); - write(";"); - emitEnd(node); - writeLine(); - } - } - emitStart(node); - write("(function ("); - emitStart(node.name); - write(getGeneratedNameForNode(node)); - emitEnd(node.name); - write(") "); - ts.Debug.assert(node.body !== undefined); // node.body must exist, as this is a non-ambient module - if (node.body.kind === 226 /* ModuleBlock */) { - var saveConvertedLoopState = convertedLoopState; - var saveTempFlags = tempFlags; - var saveTempVariables = tempVariables; - convertedLoopState = undefined; - tempFlags = 0; - tempVariables = undefined; - emit(node.body); - ts.Debug.assert(convertedLoopState === undefined); - convertedLoopState = saveConvertedLoopState; - tempFlags = saveTempFlags; - tempVariables = saveTempVariables; - } - else { - write("{"); - increaseIndent(); - emitCaptureThisForNodeIfNecessary(node); - writeLine(); - emit(node.body); - decreaseIndent(); - writeLine(); - var moduleBlock = getInnerMostModuleDeclarationFromDottedModule(node).body; - emitToken(16 /* CloseBraceToken */, moduleBlock.statements.end); - } - write(")("); - // write moduleDecl = containingModule.m only if it is not exported es6 module member - if ((node.flags & 1 /* Export */) && !isES6ExportedDeclaration(node)) { - emit(node.name); - write(" = "); - } - emitModuleMemberName(node); - write(" || ("); - emitModuleMemberName(node); - write(" = {}));"); - emitEnd(node); - if (!isES6ExportedDeclaration(node) && node.name.kind === 69 /* Identifier */ && node.parent === currentSourceFile) { - if (modulekind === ts.ModuleKind.System && (node.flags & 1 /* Export */)) { - writeLine(); - write(exportFunctionForFile + "(\""); - emitDeclarationName(node); - write("\", "); - emitDeclarationName(node); - write(");"); - } - emitExportMemberAssignments(node.name); + var operationIndex = operations.length; + operations[operationIndex] = code; + operationArguments[operationIndex] = args; + operationLocations[operationIndex] = location; + } + /** + * Builds the generator function body. + */ + function build() { + blockIndex = 0; + labelNumber = 0; + labelNumbers = undefined; + lastOperationWasAbrupt = false; + lastOperationWasCompletion = false; + clauses = undefined; + statements = undefined; + exceptionBlockStack = undefined; + currentExceptionBlock = undefined; + withBlockStack = undefined; + var buildResult = buildStatements(); + return ts.createCall(ts.createHelperName(currentSourceFile.externalHelpersModuleName, "__generator"), + /*typeArguments*/ undefined, [ + ts.createThis(), + ts.setEmitFlags(ts.createFunctionExpression( + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ts.createParameter(state)], + /*type*/ undefined, ts.createBlock(buildResult, + /*location*/ undefined, + /*multiLine*/ buildResult.length > 0)), 4194304 /* ReuseTempVariableScope */) + ]); + } + /** + * Builds the statements for the generator function body. + */ + function buildStatements() { + if (operations) { + for (var operationIndex = 0; operationIndex < operations.length; operationIndex++) { + writeOperation(operationIndex); } + flushFinalLabel(operations.length); } - /* - * Some bundlers (SystemJS builder) sometimes want to rename dependencies. - * Here we check if alternative name was provided for a given moduleName and return it if possible. - */ - function tryRenameExternalModule(moduleName) { - if (renamedDependencies && moduleName.text in renamedDependencies) { - return "\"" + renamedDependencies[moduleName.text] + "\""; - } - return undefined; + else { + flushFinalLabel(0); + } + if (clauses) { + var labelExpression = ts.createPropertyAccess(state, "label"); + var switchStatement = ts.createSwitch(labelExpression, ts.createCaseBlock(clauses)); + switchStatement.startsOnNewLine = true; + return [switchStatement]; + } + if (statements) { + return statements; + } + return []; + } + /** + * Flush the current label and advance to a new label. + */ + function flushLabel() { + if (!statements) { + return; } - function emitRequire(moduleName) { - if (moduleName.kind === 9 /* StringLiteral */) { - write("require("); - var text = tryRenameExternalModule(moduleName); - if (text) { - write(text); - } - else { - emitStart(moduleName); - emitLiteral(moduleName); - emitEnd(moduleName); - } - emitToken(18 /* CloseParenToken */, moduleName.end); - } - else { - write("require()"); - } + appendLabel(/*markLabelEnd*/ !lastOperationWasAbrupt); + lastOperationWasAbrupt = false; + lastOperationWasCompletion = false; + labelNumber++; + } + /** + * Flush the final label of the generator function body. + */ + function flushFinalLabel(operationIndex) { + if (isFinalLabelReachable(operationIndex)) { + tryEnterLabel(operationIndex); + withBlockStack = undefined; + writeReturn(/*expression*/ undefined, /*operationLocation*/ undefined); } - function getNamespaceDeclarationNode(node) { - if (node.kind === 229 /* ImportEqualsDeclaration */) { - return node; - } - var importClause = node.importClause; - if (importClause && importClause.namedBindings && importClause.namedBindings.kind === 232 /* NamespaceImport */) { - return importClause.namedBindings; - } + if (statements && clauses) { + appendLabel(/*markLabelEnd*/ false); } - function isDefaultImport(node) { - return node.kind === 230 /* ImportDeclaration */ && node.importClause && !!node.importClause.name; + updateLabelExpressions(); + } + /** + * Tests whether the final label of the generator function body + * is reachable by user code. + */ + function isFinalLabelReachable(operationIndex) { + // if the last operation was *not* a completion (return/throw) then + // the final label is reachable. + if (!lastOperationWasCompletion) { + return true; } - function emitExportImportAssignments(node) { - if (ts.isAliasSymbolDeclaration(node) && resolver.isValueAliasDeclaration(node)) { - emitExportMemberAssignments(node.name); - } - ts.forEachChild(node, emitExportImportAssignments); + // if there are no labels defined or referenced, then the final label is + // not reachable. + if (!labelOffsets || !labelExpressions) { + return false; } - function emitImportDeclaration(node) { - if (modulekind !== ts.ModuleKind.ES6) { - return emitExternalImportDeclaration(node); + // if the label for this offset is referenced, then the final label + // is reachable. + for (var label = 0; label < labelOffsets.length; label++) { + if (labelOffsets[label] === operationIndex && labelExpressions[label]) { + return true; } - // ES6 import - if (node.importClause) { - var shouldEmitDefaultBindings = resolver.isReferencedAliasDeclaration(node.importClause); - var shouldEmitNamedBindings = node.importClause.namedBindings && resolver.isReferencedAliasDeclaration(node.importClause.namedBindings, /* checkChildren */ true); - if (shouldEmitDefaultBindings || shouldEmitNamedBindings) { - write("import "); - emitStart(node.importClause); - if (shouldEmitDefaultBindings) { - emit(node.importClause.name); - if (shouldEmitNamedBindings) { - write(", "); - } - } - if (shouldEmitNamedBindings) { - emitLeadingComments(node.importClause.namedBindings); - emitStart(node.importClause.namedBindings); - if (node.importClause.namedBindings.kind === 232 /* NamespaceImport */) { - write("* as "); - emit(node.importClause.namedBindings.name); - } - else { - write("{ "); - emitExportOrImportSpecifierList(node.importClause.namedBindings.elements, resolver.isReferencedAliasDeclaration); - write(" }"); - } - emitEnd(node.importClause.namedBindings); - emitTrailingComments(node.importClause.namedBindings); - } - emitEnd(node.importClause); - write(" from "); - emit(node.moduleSpecifier); - write(";"); + } + return false; + } + /** + * Appends a case clause for the last label and sets the new label. + * + * @param markLabelEnd Indicates that the transition between labels was a fall-through + * from a previous case clause and the change in labels should be + * reflected on the `state` object. + */ + function appendLabel(markLabelEnd) { + if (!clauses) { + clauses = []; + } + if (statements) { + if (withBlockStack) { + // The previous label was nested inside one or more `with` blocks, so we + // surround the statements in generated `with` blocks to create the same environment. + for (var i = withBlockStack.length - 1; i >= 0; i--) { + var withBlock = withBlockStack[i]; + statements = [ts.createWith(withBlock.expression, ts.createBlock(statements))]; + } + } + if (currentExceptionBlock) { + // The previous label was nested inside of an exception block, so we must + // indicate entry into a protected region by pushing the label numbers + // for each block in the protected region. + var startLabel = currentExceptionBlock.startLabel, catchLabel = currentExceptionBlock.catchLabel, finallyLabel = currentExceptionBlock.finallyLabel, endLabel = currentExceptionBlock.endLabel; + statements.unshift(ts.createStatement(ts.createCall(ts.createPropertyAccess(ts.createPropertyAccess(state, "trys"), "push"), + /*typeArguments*/ undefined, [ + ts.createArrayLiteral([ + createLabel(startLabel), + createLabel(catchLabel), + createLabel(finallyLabel), + createLabel(endLabel) + ]) + ]))); + currentExceptionBlock = undefined; + } + if (markLabelEnd) { + // The case clause for the last label falls through to this label, so we + // add an assignment statement to reflect the change in labels. + statements.push(ts.createStatement(ts.createAssignment(ts.createPropertyAccess(state, "label"), ts.createLiteral(labelNumber + 1)))); + } + } + clauses.push(ts.createCaseClause(ts.createLiteral(labelNumber), statements || [])); + statements = undefined; + } + /** + * Tries to enter into a new label at the current operation index. + */ + function tryEnterLabel(operationIndex) { + if (!labelOffsets) { + return; + } + for (var label = 0; label < labelOffsets.length; label++) { + if (labelOffsets[label] === operationIndex) { + flushLabel(); + if (labelNumbers === undefined) { + labelNumbers = []; } - } - else { - write("import "); - emit(node.moduleSpecifier); - write(";"); - } - } - function emitExternalImportDeclaration(node) { - if (ts.contains(externalImports, node)) { - var isExportedImport = node.kind === 229 /* ImportEqualsDeclaration */ && (node.flags & 1 /* Export */) !== 0; - var namespaceDeclaration = getNamespaceDeclarationNode(node); - var varOrConst = (languageVersion <= 1 /* ES5 */) ? "var " : "const "; - if (modulekind !== ts.ModuleKind.AMD) { - emitLeadingComments(node); - emitStart(node); - if (namespaceDeclaration && !isDefaultImport(node)) { - // import x = require("foo") - // import * as x from "foo" - if (!isExportedImport) { - write(varOrConst); - } - ; - emitModuleMemberName(namespaceDeclaration); - write(" = "); - } - else { - // import "foo" - // import x from "foo" - // import { x, y } from "foo" - // import d, * as x from "foo" - // import d, { x, y } from "foo" - var isNakedImport = node.kind === 230 /* ImportDeclaration */ && !node.importClause; - if (!isNakedImport) { - write(varOrConst); - write(getGeneratedNameForNode(node)); - write(" = "); - } - } - emitRequire(ts.getExternalModuleName(node)); - if (namespaceDeclaration && isDefaultImport(node)) { - // import d, * as x from "foo" - write(", "); - emitModuleMemberName(namespaceDeclaration); - write(" = "); - write(getGeneratedNameForNode(node)); - } - write(";"); - emitEnd(node); - emitExportImportAssignments(node); - emitTrailingComments(node); + if (labelNumbers[labelNumber] === undefined) { + labelNumbers[labelNumber] = [label]; } else { - if (isExportedImport) { - emitModuleMemberName(namespaceDeclaration); - write(" = "); - emit(namespaceDeclaration.name); - write(";"); - } - else if (namespaceDeclaration && isDefaultImport(node)) { - // import d, * as x from "foo" - write(varOrConst); - emitModuleMemberName(namespaceDeclaration); - write(" = "); - write(getGeneratedNameForNode(node)); - write(";"); - } - emitExportImportAssignments(node); + labelNumbers[labelNumber].push(label); } } } - function emitImportEqualsDeclaration(node) { - if (ts.isExternalModuleImportEqualsDeclaration(node)) { - emitExternalImportDeclaration(node); - return; - } - // preserve old compiler's behavior: emit 'var' for import declaration (even if we do not consider them referenced) when - // - current file is not external module - // - import declaration is top level and target is value imported by entity name - if (resolver.isReferencedAliasDeclaration(node) || - (!isCurrentFileExternalModule && resolver.isTopLevelValueImportEqualsWithEntityName(node))) { - emitLeadingComments(node); - emitStart(node); - // variable declaration for import-equals declaration can be hoisted in system modules - // in this case 'var' should be omitted and emit should contain only initialization - var variableDeclarationIsHoisted = shouldHoistVariable(node, /*checkIfSourceFileLevelDecl*/ true); - // is it top level export import v = a.b.c in system module? - // if yes - it needs to be rewritten as exporter('v', v = a.b.c) - var isExported = isSourceFileLevelDeclarationInSystemJsModule(node, /*isExported*/ true); - if (!variableDeclarationIsHoisted) { - ts.Debug.assert(!isExported); - if (isES6ExportedDeclaration(node)) { - write("export "); - write("var "); - } - else if (!(node.flags & 1 /* Export */)) { - write("var "); - } - } - if (isExported) { - write(exportFunctionForFile + "(\""); - emitNodeWithoutSourceMap(node.name); - write("\", "); - } - emitModuleMemberName(node); - write(" = "); - emit(node.moduleReference); - if (isExported) { - write(")"); - } - write(";"); - emitEnd(node); - emitExportImportAssignments(node); - emitTrailingComments(node); - } - } - function emitExportDeclaration(node) { - ts.Debug.assert(modulekind !== ts.ModuleKind.System); - if (modulekind !== ts.ModuleKind.ES6) { - if (node.moduleSpecifier && (!node.exportClause || resolver.isValueAliasDeclaration(node))) { - emitStart(node); - var generatedName = getGeneratedNameForNode(node); - if (node.exportClause) { - // export { x, y, ... } from "foo" - if (modulekind !== ts.ModuleKind.AMD) { - write("var "); - write(generatedName); - write(" = "); - emitRequire(ts.getExternalModuleName(node)); - write(";"); - } - for (var _a = 0, _b = node.exportClause.elements; _a < _b.length; _a++) { - var specifier = _b[_a]; - if (resolver.isValueAliasDeclaration(specifier)) { - writeLine(); - emitStart(specifier); - emitContainingModuleName(specifier); - write("."); - emitNodeWithCommentsAndWithoutSourcemap(specifier.name); - write(" = "); - write(generatedName); - write("."); - emitNodeWithCommentsAndWithoutSourcemap(specifier.propertyName || specifier.name); - write(";"); - emitEnd(specifier); - } - } - } - else { - // export * from "foo" - if (hasExportStarsToExportValues && resolver.moduleExportsSomeValue(node.moduleSpecifier)) { - writeLine(); - write("__export("); - if (modulekind !== ts.ModuleKind.AMD) { - emitRequire(ts.getExternalModuleName(node)); - } - else { - write(generatedName); + } + /** + * Updates literal expressions for labels with actual label numbers. + */ + function updateLabelExpressions() { + if (labelExpressions !== undefined && labelNumbers !== undefined) { + for (var labelNumber_1 = 0; labelNumber_1 < labelNumbers.length; labelNumber_1++) { + var labels = labelNumbers[labelNumber_1]; + if (labels !== undefined) { + for (var _i = 0, labels_1 = labels; _i < labels_1.length; _i++) { + var label = labels_1[_i]; + var expressions = labelExpressions[label]; + if (expressions !== undefined) { + for (var _a = 0, expressions_1 = expressions; _a < expressions_1.length; _a++) { + var expression = expressions_1[_a]; + expression.text = String(labelNumber_1); } - write(");"); } } - emitEnd(node); - } - } - else { - if (!node.exportClause || resolver.isValueAliasDeclaration(node)) { - write("export "); - if (node.exportClause) { - // export { x, y, ... } - write("{ "); - emitExportOrImportSpecifierList(node.exportClause.elements, resolver.isValueAliasDeclaration); - write(" }"); - } - else { - write("*"); - } - if (node.moduleSpecifier) { - write(" from "); - emit(node.moduleSpecifier); - } - write(";"); } } } - function emitExportOrImportSpecifierList(specifiers, shouldEmit) { - ts.Debug.assert(modulekind === ts.ModuleKind.ES6); - var needsComma = false; - for (var _a = 0, specifiers_1 = specifiers; _a < specifiers_1.length; _a++) { - var specifier = specifiers_1[_a]; - if (shouldEmit(specifier)) { - if (needsComma) { - write(", "); - } - if (specifier.propertyName) { - emit(specifier.propertyName); - write(" as "); + } + /** + * Tries to enter or leave a code block. + */ + function tryEnterOrLeaveBlock(operationIndex) { + if (blocks) { + for (; blockIndex < blockActions.length && blockOffsets[blockIndex] <= operationIndex; blockIndex++) { + var block = blocks[blockIndex]; + var blockAction = blockActions[blockIndex]; + if (isExceptionBlock(block)) { + if (blockAction === 0 /* Open */) { + if (!exceptionBlockStack) { + exceptionBlockStack = []; + } + if (!statements) { + statements = []; + } + exceptionBlockStack.push(currentExceptionBlock); + currentExceptionBlock = block; } - emit(specifier.name); - needsComma = true; - } - } - } - function emitExportAssignment(node) { - if (!node.isExportEquals && resolver.isValueAliasDeclaration(node)) { - if (modulekind === ts.ModuleKind.ES6) { - writeLine(); - emitStart(node); - write("export default "); - var expression = node.expression; - emit(expression); - if (expression.kind !== 220 /* FunctionDeclaration */ && - expression.kind !== 221 /* ClassDeclaration */) { - write(";"); + else if (blockAction === 1 /* Close */) { + currentExceptionBlock = exceptionBlockStack.pop(); } - emitEnd(node); } - else { - writeLine(); - emitStart(node); - if (modulekind === ts.ModuleKind.System) { - write(exportFunctionForFile + "(\"default\","); - emit(node.expression); - write(")"); - } - else { - emitEs6ExportDefaultCompat(node); - emitContainingModuleName(node); - if (languageVersion === 0 /* ES3 */) { - write('["default"] = '); + else if (isWithBlock(block)) { + if (blockAction === 0 /* Open */) { + if (!withBlockStack) { + withBlockStack = []; } - else { - write(".default = "); - } - emit(node.expression); + withBlockStack.push(block); + } + else if (blockAction === 1 /* Close */) { + withBlockStack.pop(); } - write(";"); - emitEnd(node); } } } - function collectExternalModuleInfo(sourceFile) { - externalImports = []; - exportSpecifiers = ts.createMap(); - exportEquals = undefined; - hasExportStarsToExportValues = false; - for (var _a = 0, _b = sourceFile.statements; _a < _b.length; _a++) { - var node = _b[_a]; - switch (node.kind) { - case 230 /* ImportDeclaration */: - if (!node.importClause || - resolver.isReferencedAliasDeclaration(node.importClause, /*checkChildren*/ true)) { - // import "mod" - // import x from "mod" where x is referenced - // import * as x from "mod" where x is referenced - // import { x, y } from "mod" where at least one import is referenced - externalImports.push(node); - } - break; - case 229 /* ImportEqualsDeclaration */: - if (node.moduleReference.kind === 240 /* ExternalModuleReference */ && resolver.isReferencedAliasDeclaration(node)) { - // import x = require("mod") where x is referenced - externalImports.push(node); - } - break; - case 236 /* ExportDeclaration */: - if (node.moduleSpecifier) { - if (!node.exportClause) { - // export * from "mod" - if (resolver.moduleExportsSomeValue(node.moduleSpecifier)) { - externalImports.push(node); - hasExportStarsToExportValues = true; - } - } - else if (resolver.isValueAliasDeclaration(node)) { - // export { x, y } from "mod" where at least one export is a value symbol - externalImports.push(node); - } - } - else { - // export { x, y } - for (var _c = 0, _d = node.exportClause.elements; _c < _d.length; _c++) { - var specifier = _d[_c]; - var name_32 = (specifier.propertyName || specifier.name).text; - ts.multiMapAdd(exportSpecifiers, name_32, specifier); - } - } - break; - case 235 /* ExportAssignment */: - if (node.isExportEquals && !exportEquals) { - // export = x - exportEquals = node; - } - break; - } - } + } + /** + * Writes an operation as a statement to the current label's statement list. + * + * @param operation The OpCode of the operation + */ + function writeOperation(operationIndex) { + tryEnterLabel(operationIndex); + tryEnterOrLeaveBlock(operationIndex); + // early termination, nothing else to process in this label + if (lastOperationWasAbrupt) { + return; } - function emitExportStarHelper() { - if (hasExportStarsToExportValues) { - writeLine(); - write("function __export(m) {"); - increaseIndent(); - writeLine(); - write("for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];"); - decreaseIndent(); - writeLine(); - write("}"); - } + lastOperationWasAbrupt = false; + lastOperationWasCompletion = false; + var opcode = operations[operationIndex]; + if (opcode === 0 /* Nop */) { + return; } - function getLocalNameForExternalImport(node) { - var namespaceDeclaration = getNamespaceDeclarationNode(node); - if (namespaceDeclaration && !isDefaultImport(node)) { - return ts.getTextOfNodeFromSourceText(currentText, namespaceDeclaration.name); - } - if (node.kind === 230 /* ImportDeclaration */ && node.importClause) { - return getGeneratedNameForNode(node); + else if (opcode === 10 /* Endfinally */) { + return writeEndfinally(); + } + var args = operationArguments[operationIndex]; + if (opcode === 1 /* Statement */) { + return writeStatement(args[0]); + } + var location = operationLocations[operationIndex]; + switch (opcode) { + case 2 /* Assign */: + return writeAssign(args[0], args[1], location); + case 3 /* Break */: + return writeBreak(args[0], location); + case 4 /* BreakWhenTrue */: + return writeBreakWhenTrue(args[0], args[1], location); + case 5 /* BreakWhenFalse */: + return writeBreakWhenFalse(args[0], args[1], location); + case 6 /* Yield */: + return writeYield(args[0], location); + case 7 /* YieldStar */: + return writeYieldStar(args[0], location); + case 8 /* Return */: + return writeReturn(args[0], location); + case 9 /* Throw */: + return writeThrow(args[0], location); + } + } + /** + * Writes a statement to the current label's statement list. + * + * @param statement A statement to write. + */ + function writeStatement(statement) { + if (statement) { + if (!statements) { + statements = [statement]; } - if (node.kind === 236 /* ExportDeclaration */ && node.moduleSpecifier) { - return getGeneratedNameForNode(node); + else { + statements.push(statement); } } - function getExternalModuleNameText(importNode, emitRelativePathAsModuleName) { - if (emitRelativePathAsModuleName) { - var name_33 = getExternalModuleNameFromDeclaration(host, resolver, importNode); - if (name_33) { - return "\"" + name_33 + "\""; - } + } + /** + * Writes an Assign operation to the current label's statement list. + * + * @param left The left-hand side of the assignment. + * @param right The right-hand side of the assignment. + * @param operationLocation The source map location for the operation. + */ + function writeAssign(left, right, operationLocation) { + writeStatement(ts.createStatement(ts.createAssignment(left, right), operationLocation)); + } + /** + * Writes a Throw operation to the current label's statement list. + * + * @param expression The value to throw. + * @param operationLocation The source map location for the operation. + */ + function writeThrow(expression, operationLocation) { + lastOperationWasAbrupt = true; + lastOperationWasCompletion = true; + writeStatement(ts.createThrow(expression, operationLocation)); + } + /** + * Writes a Return operation to the current label's statement list. + * + * @param expression The value to return. + * @param operationLocation The source map location for the operation. + */ + function writeReturn(expression, operationLocation) { + lastOperationWasAbrupt = true; + lastOperationWasCompletion = true; + writeStatement(ts.createReturn(ts.createArrayLiteral(expression + ? [createInstruction(2 /* Return */), expression] + : [createInstruction(2 /* Return */)]), operationLocation)); + } + /** + * Writes a Break operation to the current label's statement list. + * + * @param label The label for the Break. + * @param operationLocation The source map location for the operation. + */ + function writeBreak(label, operationLocation) { + lastOperationWasAbrupt = true; + writeStatement(ts.createReturn(ts.createArrayLiteral([ + createInstruction(3 /* Break */), + createLabel(label) + ]), operationLocation)); + } + /** + * Writes a BreakWhenTrue operation to the current label's statement list. + * + * @param label The label for the Break. + * @param condition The condition for the Break. + * @param operationLocation The source map location for the operation. + */ + function writeBreakWhenTrue(label, condition, operationLocation) { + writeStatement(ts.createIf(condition, ts.createReturn(ts.createArrayLiteral([ + createInstruction(3 /* Break */), + createLabel(label) + ]), operationLocation))); + } + /** + * Writes a BreakWhenFalse operation to the current label's statement list. + * + * @param label The label for the Break. + * @param condition The condition for the Break. + * @param operationLocation The source map location for the operation. + */ + function writeBreakWhenFalse(label, condition, operationLocation) { + writeStatement(ts.createIf(ts.createLogicalNot(condition), ts.createReturn(ts.createArrayLiteral([ + createInstruction(3 /* Break */), + createLabel(label) + ]), operationLocation))); + } + /** + * Writes a Yield operation to the current label's statement list. + * + * @param expression The expression to yield. + * @param operationLocation The source map location for the operation. + */ + function writeYield(expression, operationLocation) { + lastOperationWasAbrupt = true; + writeStatement(ts.createReturn(ts.createArrayLiteral(expression + ? [createInstruction(4 /* Yield */), expression] + : [createInstruction(4 /* Yield */)]), operationLocation)); + } + /** + * Writes a YieldStar instruction to the current label's statement list. + * + * @param expression The expression to yield. + * @param operationLocation The source map location for the operation. + */ + function writeYieldStar(expression, operationLocation) { + lastOperationWasAbrupt = true; + writeStatement(ts.createReturn(ts.createArrayLiteral([ + createInstruction(5 /* YieldStar */), + expression + ]), operationLocation)); + } + /** + * Writes an Endfinally instruction to the current label's statement list. + */ + function writeEndfinally() { + lastOperationWasAbrupt = true; + writeStatement(ts.createReturn(ts.createArrayLiteral([ + createInstruction(7 /* Endfinally */) + ]))); + } + } + ts.transformGenerators = transformGenerators; + var _a; +})(ts || (ts = {})); +/// +/// +/*@internal*/ +var ts; +(function (ts) { + function transformModule(context) { + var transformModuleDelegates = ts.createMap((_a = {}, + _a[ts.ModuleKind.None] = transformCommonJSModule, + _a[ts.ModuleKind.CommonJS] = transformCommonJSModule, + _a[ts.ModuleKind.AMD] = transformAMDModule, + _a[ts.ModuleKind.UMD] = transformUMDModule, + _a)); + var startLexicalEnvironment = context.startLexicalEnvironment, endLexicalEnvironment = context.endLexicalEnvironment, hoistVariableDeclaration = context.hoistVariableDeclaration; + var compilerOptions = context.getCompilerOptions(); + var resolver = context.getEmitResolver(); + var host = context.getEmitHost(); + var languageVersion = ts.getEmitScriptTarget(compilerOptions); + var moduleKind = ts.getEmitModuleKind(compilerOptions); + var previousOnSubstituteNode = context.onSubstituteNode; + var previousOnEmitNode = context.onEmitNode; + context.onSubstituteNode = onSubstituteNode; + context.onEmitNode = onEmitNode; + context.enableSubstitution(69 /* Identifier */); + context.enableSubstitution(187 /* BinaryExpression */); + context.enableSubstitution(185 /* PrefixUnaryExpression */); + context.enableSubstitution(186 /* PostfixUnaryExpression */); + context.enableSubstitution(254 /* ShorthandPropertyAssignment */); + context.enableEmitNotification(256 /* SourceFile */); + var currentSourceFile; + var externalImports; + var exportSpecifiers; + var exportEquals; + var bindingNameExportSpecifiersMap; + // Subset of exportSpecifiers that is a binding-name. + // This is to reduce amount of memory we have to keep around even after we done with module-transformer + var bindingNameExportSpecifiersForFileMap = ts.createMap(); + var hasExportStarsToExportValues; + return transformSourceFile; + /** + * Transforms the module aspects of a SourceFile. + * + * @param node The SourceFile node. + */ + function transformSourceFile(node) { + if (ts.isDeclarationFile(node)) { + return node; + } + if (ts.isExternalModule(node) || compilerOptions.isolatedModules) { + currentSourceFile = node; + // Collect information about the external module. + (_a = ts.collectExternalModuleInfo(node, resolver), externalImports = _a.externalImports, exportSpecifiers = _a.exportSpecifiers, exportEquals = _a.exportEquals, hasExportStarsToExportValues = _a.hasExportStarsToExportValues, _a); + // Perform the transformation. + var transformModule_1 = transformModuleDelegates[moduleKind] || transformModuleDelegates[ts.ModuleKind.None]; + var updated = transformModule_1(node); + ts.aggregateTransformFlags(updated); + currentSourceFile = undefined; + externalImports = undefined; + exportSpecifiers = undefined; + exportEquals = undefined; + hasExportStarsToExportValues = false; + return updated; + } + return node; + var _a; + } + /** + * Transforms a SourceFile into a CommonJS module. + * + * @param node The SourceFile node. + */ + function transformCommonJSModule(node) { + startLexicalEnvironment(); + var statements = []; + var statementOffset = ts.addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, visitor); + ts.addRange(statements, ts.visitNodes(node.statements, visitor, ts.isStatement, statementOffset)); + ts.addRange(statements, endLexicalEnvironment()); + addExportEqualsIfNeeded(statements, /*emitAsReturn*/ false); + var updated = updateSourceFile(node, statements); + if (hasExportStarsToExportValues) { + ts.setEmitFlags(updated, 2 /* EmitExportStar */ | ts.getEmitFlags(node)); + } + return updated; + } + /** + * Transforms a SourceFile into an AMD module. + * + * @param node The SourceFile node. + */ + function transformAMDModule(node) { + var define = ts.createIdentifier("define"); + var moduleName = ts.tryGetModuleNameFromFile(node, host, compilerOptions); + return transformAsynchronousModule(node, define, moduleName, /*includeNonAmdDependencies*/ true); + } + /** + * Transforms a SourceFile into a UMD module. + * + * @param node The SourceFile node. + */ + function transformUMDModule(node) { + var define = ts.createIdentifier("define"); + ts.setEmitFlags(define, 16 /* UMDDefine */); + return transformAsynchronousModule(node, define, /*moduleName*/ undefined, /*includeNonAmdDependencies*/ false); + } + /** + * Transforms a SourceFile into an AMD or UMD module. + * + * @param node The SourceFile node. + * @param define The expression used to define the module. + * @param moduleName An expression for the module name, if available. + * @param includeNonAmdDependencies A value indicating whether to incldue any non-AMD dependencies. + */ + function transformAsynchronousModule(node, define, moduleName, includeNonAmdDependencies) { + // An AMD define function has the following shape: + // + // define(id?, dependencies?, factory); + // + // This has the shape of the following: + // + // define(name, ["module1", "module2"], function (module1Alias) { ... } + // + // The location of the alias in the parameter list in the factory function needs to + // match the position of the module name in the dependency list. + // + // To ensure this is true in cases of modules with no aliases, e.g.: + // + // import "module" + // + // or + // + // /// + // + // we need to add modules without alias names to the end of the dependencies list + var _a = collectAsynchronousDependencies(node, includeNonAmdDependencies), aliasedModuleNames = _a.aliasedModuleNames, unaliasedModuleNames = _a.unaliasedModuleNames, importAliasNames = _a.importAliasNames; + // Create an updated SourceFile: + // + // define(moduleName?, ["module1", "module2"], function ... + return updateSourceFile(node, [ + ts.createStatement(ts.createCall(define, + /*typeArguments*/ undefined, (moduleName ? [moduleName] : []).concat([ + // Add the dependency array argument: + // + // ["require", "exports", module1", "module2", ...] + ts.createArrayLiteral([ + ts.createLiteral("require"), + ts.createLiteral("exports") + ].concat(aliasedModuleNames, unaliasedModuleNames)), + // Add the module body function argument: + // + // function (require, exports, module1, module2) ... + ts.createFunctionExpression( + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ + ts.createParameter("require"), + ts.createParameter("exports") + ].concat(importAliasNames), + /*type*/ undefined, transformAsynchronousModuleBody(node)) + ]))) + ]); + } + /** + * Transforms a SourceFile into an AMD or UMD module body. + * + * @param node The SourceFile node. + */ + function transformAsynchronousModuleBody(node) { + startLexicalEnvironment(); + var statements = []; + var statementOffset = ts.addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, visitor); + // Visit each statement of the module body. + ts.addRange(statements, ts.visitNodes(node.statements, visitor, ts.isStatement, statementOffset)); + // End the lexical environment for the module body + // and merge any new lexical declarations. + ts.addRange(statements, endLexicalEnvironment()); + // Append the 'export =' statement if provided. + addExportEqualsIfNeeded(statements, /*emitAsReturn*/ true); + var body = ts.createBlock(statements, /*location*/ undefined, /*multiLine*/ true); + if (hasExportStarsToExportValues) { + // If we have any `export * from ...` declarations + // we need to inform the emitter to add the __export helper. + ts.setEmitFlags(body, 2 /* EmitExportStar */); + } + return body; + } + function addExportEqualsIfNeeded(statements, emitAsReturn) { + if (exportEquals && resolver.isValueAliasDeclaration(exportEquals)) { + if (emitAsReturn) { + var statement = ts.createReturn(exportEquals.expression, + /*location*/ exportEquals); + ts.setEmitFlags(statement, 12288 /* NoTokenSourceMaps */ | 49152 /* NoComments */); + statements.push(statement); } - var moduleName = ts.getExternalModuleName(importNode); - if (moduleName.kind === 9 /* StringLiteral */) { - return tryRenameExternalModule(moduleName) || getLiteralText(moduleName); + else { + var statement = ts.createStatement(ts.createAssignment(ts.createPropertyAccess(ts.createIdentifier("module"), "exports"), exportEquals.expression), + /*location*/ exportEquals); + ts.setEmitFlags(statement, 49152 /* NoComments */); + statements.push(statement); } + } + } + /** + * Visits a node at the top level of the source file. + * + * @param node The node. + */ + function visitor(node) { + switch (node.kind) { + case 230 /* ImportDeclaration */: + return visitImportDeclaration(node); + case 229 /* ImportEqualsDeclaration */: + return visitImportEqualsDeclaration(node); + case 236 /* ExportDeclaration */: + return visitExportDeclaration(node); + case 235 /* ExportAssignment */: + return visitExportAssignment(node); + case 200 /* VariableStatement */: + return visitVariableStatement(node); + case 220 /* FunctionDeclaration */: + return visitFunctionDeclaration(node); + case 221 /* ClassDeclaration */: + return visitClassDeclaration(node); + case 202 /* ExpressionStatement */: + return visitExpressionStatement(node); + default: + // This visitor does not descend into the tree, as export/import statements + // are only transformed at the top level of a file. + return node; + } + } + /** + * Visits an ImportDeclaration node. + * + * @param node The ImportDeclaration node. + */ + function visitImportDeclaration(node) { + if (!ts.contains(externalImports, node)) { return undefined; } - function emitVariableDeclarationsForImports() { - if (externalImports.length === 0) { - return; + var statements = []; + var namespaceDeclaration = ts.getNamespaceDeclarationNode(node); + if (moduleKind !== ts.ModuleKind.AMD) { + if (!node.importClause) { + // import "mod"; + statements.push(ts.createStatement(createRequireCall(node), + /*location*/ node)); } - writeLine(); - var started = false; - for (var _a = 0, externalImports_1 = externalImports; _a < externalImports_1.length; _a++) { - var importNode = externalImports_1[_a]; - // do not create variable declaration for exports and imports that lack import clause - var skipNode = importNode.kind === 236 /* ExportDeclaration */ || - (importNode.kind === 230 /* ImportDeclaration */ && !importNode.importClause); - if (skipNode) { - continue; - } - if (!started) { - write("var "); - started = true; + else { + var variables = []; + if (namespaceDeclaration && !ts.isDefaultImport(node)) { + // import * as n from "mod"; + variables.push(ts.createVariableDeclaration(ts.getSynthesizedClone(namespaceDeclaration.name), + /*type*/ undefined, createRequireCall(node))); } else { - write(", "); - } - write(getLocalNameForExternalImport(importNode)); - } - if (started) { - write(";"); - } + // import d from "mod"; + // import { x, y } from "mod"; + // import d, { x, y } from "mod"; + // import d, * as n from "mod"; + variables.push(ts.createVariableDeclaration(ts.getGeneratedNameForNode(node), + /*type*/ undefined, createRequireCall(node))); + if (namespaceDeclaration && ts.isDefaultImport(node)) { + variables.push(ts.createVariableDeclaration(ts.getSynthesizedClone(namespaceDeclaration.name), + /*type*/ undefined, ts.getGeneratedNameForNode(node))); + } + } + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createConstDeclarationList(variables), + /*location*/ node)); + } + } + else if (namespaceDeclaration && ts.isDefaultImport(node)) { + // import d, * as n from "mod"; + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(ts.getSynthesizedClone(namespaceDeclaration.name), + /*type*/ undefined, ts.getGeneratedNameForNode(node), + /*location*/ node) + ]))); + } + addExportImportAssignments(statements, node); + return ts.singleOrMany(statements); + } + function visitImportEqualsDeclaration(node) { + if (!ts.contains(externalImports, node)) { + return undefined; } - function emitLocalStorageForExportedNamesIfNecessary(exportedDeclarations) { - // when resolving exports local exported entries/indirect exported entries in the module - // should always win over entries with similar names that were added via star exports - // to support this we store names of local/indirect exported entries in a set. - // this set is used to filter names brought by star exports. - if (!hasExportStarsToExportValues) { - // local names set is needed only in presence of star exports - return undefined; - } - // local names set should only be added if we have anything exported - if (!exportedDeclarations && !ts.someProperties(exportSpecifiers)) { - // no exported declarations (export var ...) or export specifiers (export {x}) - // check if we have any non star export declarations. - var hasExportDeclarationWithExportClause = false; - for (var _a = 0, externalImports_2 = externalImports; _a < externalImports_2.length; _a++) { - var externalImport = externalImports_2[_a]; - if (externalImport.kind === 236 /* ExportDeclaration */ && externalImport.exportClause) { - hasExportDeclarationWithExportClause = true; - break; - } - } - if (!hasExportDeclarationWithExportClause) { - // we still need to emit exportStar helper - return emitExportStarFunction(/*localNames*/ undefined); - } - } - var exportedNamesStorageRef = makeUniqueName("exportedNames"); - writeLine(); - write("var " + exportedNamesStorageRef + " = {"); - increaseIndent(); - var started = false; - if (exportedDeclarations) { - for (var i = 0; i < exportedDeclarations.length; i++) { - // write name of exported declaration, i.e 'export var x...' - writeExportedName(exportedDeclarations[i]); - } + // Set emitFlags on the name of the importEqualsDeclaration + // This is so the printer will not substitute the identifier + ts.setEmitFlags(node.name, 128 /* NoSubstitution */); + var statements = []; + if (moduleKind !== ts.ModuleKind.AMD) { + if (ts.hasModifier(node, 1 /* Export */)) { + statements.push(ts.createStatement(createExportAssignment(node.name, createRequireCall(node)), + /*location*/ node)); } - if (exportSpecifiers) { - for (var n in exportSpecifiers) { - for (var _b = 0, _c = exportSpecifiers[n]; _b < _c.length; _b++) { - var specifier = _c[_b]; - // write name of export specified, i.e. 'export {x}' - writeExportedName(specifier.name); - } - } + else { + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(ts.getSynthesizedClone(node.name), + /*type*/ undefined, createRequireCall(node)) + ], + /*location*/ undefined, + /*flags*/ languageVersion >= 2 /* ES6 */ ? 2 /* Const */ : 0 /* None */), + /*location*/ node)); } - for (var _d = 0, externalImports_3 = externalImports; _d < externalImports_3.length; _d++) { - var externalImport = externalImports_3[_d]; - if (externalImport.kind !== 236 /* ExportDeclaration */) { - continue; - } - var exportDecl = externalImport; - if (!exportDecl.exportClause) { - // export * from ... - continue; - } - for (var _e = 0, _f = exportDecl.exportClause.elements; _e < _f.length; _e++) { - var element = _f[_e]; - // write name of indirectly exported entry, i.e. 'export {x} from ...' - writeExportedName(element.name || element.propertyName); - } + } + else { + if (ts.hasModifier(node, 1 /* Export */)) { + statements.push(ts.createStatement(createExportAssignment(node.name, node.name), + /*location*/ node)); } - decreaseIndent(); - writeLine(); - write("};"); - return emitExportStarFunction(exportedNamesStorageRef); - function emitExportStarFunction(localNames) { - var exportStarFunction = makeUniqueName("exportStar"); - writeLine(); - // define an export star helper function - write("function " + exportStarFunction + "(m) {"); - increaseIndent(); - writeLine(); - write("var exports = {};"); - writeLine(); - write("for(var n in m) {"); - increaseIndent(); - writeLine(); - write("if (n !== \"default\""); - if (localNames) { - write("&& !" + localNames + ".hasOwnProperty(n)"); - } - write(") exports[n] = m[n];"); - decreaseIndent(); - writeLine(); - write("}"); - writeLine(); - write(exportFunctionForFile + "(exports);"); - decreaseIndent(); - writeLine(); - write("}"); - return exportStarFunction; + } + addExportImportAssignments(statements, node); + return statements; + } + function visitExportDeclaration(node) { + if (!ts.contains(externalImports, node)) { + return undefined; + } + var generatedName = ts.getGeneratedNameForNode(node); + if (node.exportClause) { + var statements = []; + // export { x, y } from "mod"; + if (moduleKind !== ts.ModuleKind.AMD) { + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(generatedName, + /*type*/ undefined, createRequireCall(node)) + ]), + /*location*/ node)); + } + for (var _i = 0, _a = node.exportClause.elements; _i < _a.length; _i++) { + var specifier = _a[_i]; + if (resolver.isValueAliasDeclaration(specifier)) { + var exportedValue = ts.createPropertyAccess(generatedName, specifier.propertyName || specifier.name); + statements.push(ts.createStatement(createExportAssignment(specifier.name, exportedValue), + /*location*/ specifier)); + } + } + return ts.singleOrMany(statements); + } + else if (resolver.moduleExportsSomeValue(node.moduleSpecifier)) { + // export * from "mod"; + return ts.createStatement(ts.createCall(ts.createIdentifier("__export"), + /*typeArguments*/ undefined, [ + moduleKind !== ts.ModuleKind.AMD + ? createRequireCall(node) + : generatedName + ]), + /*location*/ node); + } + } + function visitExportAssignment(node) { + if (!node.isExportEquals) { + if (ts.nodeIsSynthesized(node) || resolver.isValueAliasDeclaration(node)) { + var statements = []; + addExportDefault(statements, node.expression, /*location*/ node); + return statements; } - function writeExportedName(node) { - // do not record default exports - // they are local to module and never overwritten (explicitly skipped) by star export - if (node.kind !== 69 /* Identifier */ && node.flags & 512 /* Default */) { - return; - } - if (started) { - write(","); - } - else { - started = true; - } - writeLine(); - write("'"); - if (node.kind === 69 /* Identifier */) { - emitNodeWithCommentsAndWithoutSourcemap(node); - } - else { - emitDeclarationName(node); - } - write("': true"); - } - } - function processTopLevelVariableAndFunctionDeclarations(node) { - // per ES6 spec: - // 15.2.1.16.4 ModuleDeclarationInstantiation() Concrete Method - // - var declarations are initialized to undefined - 14.a.ii - // - function/generator declarations are instantiated - 16.a.iv - // this means that after module is instantiated but before its evaluation - // exported functions are already accessible at import sites - // in theory we should hoist only exported functions and its dependencies - // in practice to simplify things we'll hoist all source level functions and variable declaration - // including variables declarations for module and class declarations - var hoistedVars; - var hoistedFunctionDeclarations; - var exportedDeclarations; - visit(node); - if (hoistedVars) { - writeLine(); - write("var "); - var seen = ts.createMap(); - for (var i = 0; i < hoistedVars.length; i++) { - var local = hoistedVars[i]; - var name_34 = local.kind === 69 /* Identifier */ - ? local - : local.name; - if (name_34) { - // do not emit duplicate entries (in case of declaration merging) in the list of hoisted variables - var text = ts.unescapeIdentifier(name_34.text); - if (text in seen) { - continue; - } - else { - seen[text] = text; - } - } - if (i !== 0) { - write(", "); - } - if (local.kind === 221 /* ClassDeclaration */ || local.kind === 225 /* ModuleDeclaration */ || local.kind === 224 /* EnumDeclaration */) { - emitDeclarationName(local); - } - else { - emit(local); - } - var flags = ts.getCombinedNodeFlags(local.kind === 69 /* Identifier */ ? local.parent : local); - if (flags & 1 /* Export */) { - if (!exportedDeclarations) { - exportedDeclarations = []; - } - exportedDeclarations.push(local); - } - } - write(";"); + } + return undefined; + } + function addExportDefault(statements, expression, location) { + tryAddExportDefaultCompat(statements); + statements.push(ts.createStatement(createExportAssignment(ts.createIdentifier("default"), expression), location)); + } + function tryAddExportDefaultCompat(statements) { + var original = ts.getOriginalNode(currentSourceFile); + ts.Debug.assert(original.kind === 256 /* SourceFile */); + if (!original.symbol.exports["___esModule"]) { + if (languageVersion === 0 /* ES3 */) { + statements.push(ts.createStatement(createExportAssignment(ts.createIdentifier("__esModule"), ts.createLiteral(true)))); } - if (hoistedFunctionDeclarations) { - for (var _a = 0, hoistedFunctionDeclarations_1 = hoistedFunctionDeclarations; _a < hoistedFunctionDeclarations_1.length; _a++) { - var f = hoistedFunctionDeclarations_1[_a]; - writeLine(); - emit(f); - if (f.flags & 1 /* Export */) { - if (!exportedDeclarations) { - exportedDeclarations = []; - } - exportedDeclarations.push(f); - } - } + else { + statements.push(ts.createStatement(ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Object"), "defineProperty"), + /*typeArguments*/ undefined, [ + ts.createIdentifier("exports"), + ts.createLiteral("__esModule"), + ts.createObjectLiteral([ + ts.createPropertyAssignment("value", ts.createLiteral(true)) + ]) + ]))); } - return exportedDeclarations; - function visit(node) { - if (node.flags & 2 /* Ambient */) { - return; - } - if (node.kind === 220 /* FunctionDeclaration */) { - if (!hoistedFunctionDeclarations) { - hoistedFunctionDeclarations = []; - } - hoistedFunctionDeclarations.push(node); - return; - } - if (node.kind === 221 /* ClassDeclaration */) { - if (!hoistedVars) { - hoistedVars = []; - } - hoistedVars.push(node); - return; - } - if (node.kind === 224 /* EnumDeclaration */) { - if (shouldEmitEnumDeclaration(node)) { - if (!hoistedVars) { - hoistedVars = []; - } - hoistedVars.push(node); - } - return; - } - if (node.kind === 225 /* ModuleDeclaration */) { - if (shouldEmitModuleDeclaration(node)) { - if (!hoistedVars) { - hoistedVars = []; - } - hoistedVars.push(node); - } - return; - } - if (node.kind === 218 /* VariableDeclaration */ || node.kind === 169 /* BindingElement */) { - if (shouldHoistVariable(node, /*checkIfSourceFileLevelDecl*/ false)) { - var name_35 = node.name; - if (name_35.kind === 69 /* Identifier */) { - if (!hoistedVars) { - hoistedVars = []; - } - hoistedVars.push(name_35); - } - else { - ts.forEachChild(name_35, visit); - } - } - return; - } - if (ts.isInternalModuleImportEqualsDeclaration(node) && resolver.isValueAliasDeclaration(node)) { - if (!hoistedVars) { - hoistedVars = []; - } - hoistedVars.push(node.name); - return; - } - if (ts.isBindingPattern(node)) { - ts.forEach(node.elements, visit); - return; - } - if (!ts.isDeclaration(node)) { - ts.forEachChild(node, visit); - } + } + } + function addExportImportAssignments(statements, node) { + if (ts.isImportEqualsDeclaration(node)) { + addExportMemberAssignments(statements, node.name); + } + else { + var names = ts.reduceEachChild(node, collectExportMembers, []); + for (var _i = 0, names_1 = names; _i < names_1.length; _i++) { + var name_39 = names_1[_i]; + addExportMemberAssignments(statements, name_39); } } - function shouldHoistVariable(node, checkIfSourceFileLevelDecl) { - if (checkIfSourceFileLevelDecl && !shouldHoistDeclarationInSystemJsModule(node)) { - return false; + } + function collectExportMembers(names, node) { + if (ts.isAliasSymbolDeclaration(node) && resolver.isValueAliasDeclaration(node) && ts.isDeclaration(node)) { + var name_40 = node.name; + if (ts.isIdentifier(name_40)) { + names.push(name_40); } - // hoist variable if - // - it is not block scoped - // - it is top level block scoped - // if block scoped variables are nested in some another block then - // no other functions can use them except ones that are defined at least in the same block - return (ts.getCombinedNodeFlags(node) & 3072 /* BlockScoped */) === 0 || - ts.getEnclosingBlockScopeContainer(node).kind === 256 /* SourceFile */; - } - function isCurrentFileSystemExternalModule() { - return modulekind === ts.ModuleKind.System && isCurrentFileExternalModule; - } - function emitSystemModuleBody(node, dependencyGroups, startIndex) { - // shape of the body in system modules: - // function (exports) { - // - // - // - // return { - // setters: [ - // - // ], - // execute: function() { - // - // } - // } - // - // } - // I.e: - // import {x} from 'file1' - // var y = 1; - // export function foo() { return y + x(); } - // console.log(y); - // will be transformed to - // function(exports) { - // var file1; // local alias - // var y; - // function foo() { return y + file1.x(); } - // exports("foo", foo); - // return { - // setters: [ - // function(v) { file1 = v } - // ], - // execute(): function() { - // y = 1; - // console.log(y); - // } - // }; - // } - emitVariableDeclarationsForImports(); - writeLine(); - var exportedDeclarations = processTopLevelVariableAndFunctionDeclarations(node); - var exportStarFunction = emitLocalStorageForExportedNamesIfNecessary(exportedDeclarations); - writeLine(); - write("return {"); - increaseIndent(); - writeLine(); - emitSetters(exportStarFunction, dependencyGroups); - writeLine(); - emitExecute(node, startIndex); - decreaseIndent(); - writeLine(); - write("}"); // return - emitTempDeclarations(/*newLine*/ true); } - function emitSetters(exportStarFunction, dependencyGroups) { - write("setters:["); - for (var i = 0; i < dependencyGroups.length; i++) { - if (i !== 0) { - write(","); - } - writeLine(); - increaseIndent(); - var group = dependencyGroups[i]; - // derive a unique name for parameter from the first named entry in the group - var parameterName = makeUniqueName(ts.forEach(group, getLocalNameForExternalImport) || ""); - write("function (" + parameterName + ") {"); - increaseIndent(); - for (var _a = 0, group_1 = group; _a < group_1.length; _a++) { - var entry = group_1[_a]; - var importVariableName = getLocalNameForExternalImport(entry) || ""; - switch (entry.kind) { - case 230 /* ImportDeclaration */: - if (!entry.importClause) { - // 'import "..."' case - // module is imported only for side-effects, no emit required - break; - } - // fall-through - case 229 /* ImportEqualsDeclaration */: - ts.Debug.assert(importVariableName !== ""); - writeLine(); - // save import into the local - write(importVariableName + " = " + parameterName + ";"); - writeLine(); - break; - case 236 /* ExportDeclaration */: - ts.Debug.assert(importVariableName !== ""); - if (entry.exportClause) { - // export {a, b as c} from 'foo' - // emit as: - // exports_({ - // "a": _["a"], - // "c": _["b"] - // }); - writeLine(); - write(exportFunctionForFile + "({"); - writeLine(); - increaseIndent(); - for (var i_1 = 0, len = entry.exportClause.elements.length; i_1 < len; i_1++) { - if (i_1 !== 0) { - write(","); - writeLine(); - } - var e = entry.exportClause.elements[i_1]; - write("\""); - emitNodeWithCommentsAndWithoutSourcemap(e.name); - write("\": " + parameterName + "[\""); - emitNodeWithCommentsAndWithoutSourcemap(e.propertyName || e.name); - write("\"]"); - } - decreaseIndent(); - writeLine(); - write("});"); - } - else { - // collectExternalModuleInfo prefilters star exports to keep only ones that export values - // this means that check 'resolver.moduleExportsSomeValue' is redundant and can be omitted here - writeLine(); - // export * from 'foo' - // emit as: - // exportStar(_foo); - write(exportStarFunction + "(" + parameterName + ");"); - } - writeLine(); - break; - } - } - decreaseIndent(); - write("}"); - decreaseIndent(); + return ts.reduceEachChild(node, collectExportMembers, names); + } + function addExportMemberAssignments(statements, name) { + if (!exportEquals && exportSpecifiers && ts.hasProperty(exportSpecifiers, name.text)) { + for (var _i = 0, _a = exportSpecifiers[name.text]; _i < _a.length; _i++) { + var specifier = _a[_i]; + statements.push(ts.startOnNewLine(ts.createStatement(createExportAssignment(specifier.name, name), + /*location*/ specifier.name))); } - write("],"); } - function emitExecute(node, startIndex) { - write("execute: function() {"); - increaseIndent(); - writeLine(); - for (var i = startIndex; i < node.statements.length; i++) { - var statement = node.statements[i]; - switch (statement.kind) { - // - function declarations are not emitted because they were already hoisted - // - import declarations are not emitted since they are already handled in setters - // - export declarations with module specifiers are not emitted since they were already written in setters - // - export declarations without module specifiers are emitted preserving the order - case 220 /* FunctionDeclaration */: - case 230 /* ImportDeclaration */: - continue; - case 236 /* ExportDeclaration */: - if (!statement.moduleSpecifier) { - for (var _a = 0, _b = statement.exportClause.elements; _a < _b.length; _a++) { - var element = _b[_a]; - // write call to exporter function for every export specifier in exports list - emitExportSpecifierInSystemModule(element); - } - } - continue; - case 229 /* ImportEqualsDeclaration */: - if (!ts.isInternalModuleImportEqualsDeclaration(statement)) { - // - import equals declarations that import external modules are not emitted - continue; - } - // fall-though for import declarations that import internal modules - default: - writeLine(); - emit(statement); - } + } + function addExportMemberAssignment(statements, node) { + if (ts.hasModifier(node, 512 /* Default */)) { + addExportDefault(statements, getDeclarationName(node), /*location*/ node); + } + else { + statements.push(createExportStatement(node.name, ts.setEmitFlags(ts.getSynthesizedClone(node.name), 262144 /* LocalName */), /*location*/ node)); + } + } + function visitVariableStatement(node) { + // If the variable is for a generated declaration, + // we should maintain it and just strip off the 'export' modifier if necessary. + var originalKind = ts.getOriginalNode(node).kind; + if (originalKind === 225 /* ModuleDeclaration */ || + originalKind === 224 /* EnumDeclaration */ || + originalKind === 221 /* ClassDeclaration */) { + if (!ts.hasModifier(node, 1 /* Export */)) { + return node; } - decreaseIndent(); - writeLine(); - write("}"); // execute - } - function writeModuleName(node, emitRelativePathAsModuleName) { - var moduleName = node.moduleName; - if (moduleName || (emitRelativePathAsModuleName && (moduleName = getResolvedExternalModuleName(host, node)))) { - write("\"" + moduleName + "\", "); - } - } - function emitSystemModule(node, emitRelativePathAsModuleName) { - collectExternalModuleInfo(node); - // System modules has the following shape - // System.register(['dep-1', ... 'dep-n'], function(exports) {/* module body function */}) - // 'exports' here is a function 'exports(name: string, value: T): T' that is used to publish exported values. - // 'exports' returns its 'value' argument so in most cases expressions - // that mutate exported values can be rewritten as: - // expr -> exports('name', expr). - // The only exception in this rule is postfix unary operators, - // see comment to 'emitPostfixUnaryExpression' for more details - ts.Debug.assert(!exportFunctionForFile); - // make sure that name of 'exports' function does not conflict with existing identifiers - exportFunctionForFile = makeUniqueName("exports"); - contextObjectForFile = makeUniqueName("context"); - writeLine(); - write("System.register("); - writeModuleName(node, emitRelativePathAsModuleName); - write("["); - var groupIndices = ts.createMap(); - var dependencyGroups = []; - for (var i = 0; i < externalImports.length; i++) { - var text = getExternalModuleNameText(externalImports[i], emitRelativePathAsModuleName); - if (text === undefined) { - continue; - } - // text should be quoted string - // for deduplication purposes in key remove leading and trailing quotes so 'a' and "a" will be considered the same - var key = text.substr(1, text.length - 2); - if (key in groupIndices) { - // deduplicate/group entries in dependency list by the dependency name - var groupIndex = groupIndices[key]; - dependencyGroups[groupIndex].push(externalImports[i]); - continue; - } - else { - groupIndices[key] = dependencyGroups.length; - dependencyGroups.push([externalImports[i]]); - } - if (i !== 0) { - write(", "); - } - write(text); + return ts.setOriginalNode(ts.createVariableStatement( + /*modifiers*/ undefined, node.declarationList), node); + } + var resultStatements = []; + // If we're exporting these variables, then these just become assignments to 'exports.blah'. + // We only want to emit assignments for variables with initializers. + if (ts.hasModifier(node, 1 /* Export */)) { + var variables = ts.getInitializedVariables(node.declarationList); + if (variables.length > 0) { + var inlineAssignments = ts.createStatement(ts.inlineExpressions(ts.map(variables, transformInitializedVariable)), node); + resultStatements.push(inlineAssignments); } - write("], function(" + exportFunctionForFile + ", " + contextObjectForFile + ") {"); - writeLine(); - increaseIndent(); - var startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ true, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict); - writeLine(); - write("var __moduleName = " + contextObjectForFile + " && " + contextObjectForFile + ".id;"); - writeLine(); - emitEmitHelpers(node); - emitCaptureThisForNodeIfNecessary(node); - emitSystemModuleBody(node, dependencyGroups, startIndex); - decreaseIndent(); - writeLine(); - write("});"); - } - function getAMDDependencyNames(node, includeNonAmdDependencies, emitRelativePathAsModuleName) { - // names of modules with corresponding parameter in the factory function - var aliasedModuleNames = []; - // names of modules with no corresponding parameters in factory function - var unaliasedModuleNames = []; - var importAliasNames = []; // names of the parameters in the factory function; these - // parameters need to match the indexes of the corresponding - // module names in aliasedModuleNames. - // Fill in amd-dependency tags - for (var _a = 0, _b = node.amdDependencies; _a < _b.length; _a++) { - var amdDependency = _b[_a]; - if (amdDependency.name) { - aliasedModuleNames.push('"' + amdDependency.path + '"'); - importAliasNames.push(amdDependency.name); - } - else { - unaliasedModuleNames.push('"' + amdDependency.path + '"'); + } + else { + resultStatements.push(node); + } + // While we might not have been exported here, each variable might have been exported + // later on in an export specifier (e.g. `export {foo as blah, bar}`). + for (var _i = 0, _a = node.declarationList.declarations; _i < _a.length; _i++) { + var decl = _a[_i]; + addExportMemberAssignmentsForBindingName(resultStatements, decl.name); + } + return resultStatements; + } + /** + * Creates appropriate assignments for each binding identifier that is exported in an export specifier, + * and inserts it into 'resultStatements'. + */ + function addExportMemberAssignmentsForBindingName(resultStatements, name) { + if (ts.isBindingPattern(name)) { + for (var _i = 0, _a = name.elements; _i < _a.length; _i++) { + var element = _a[_i]; + if (!ts.isOmittedExpression(element)) { + addExportMemberAssignmentsForBindingName(resultStatements, element.name); } } - for (var _c = 0, externalImports_4 = externalImports; _c < externalImports_4.length; _c++) { - var importNode = externalImports_4[_c]; - // Find the name of the external module - var externalModuleName = getExternalModuleNameText(importNode, emitRelativePathAsModuleName); - // Find the name of the module alias, if there is one - var importAliasName = getLocalNameForExternalImport(importNode); - if (includeNonAmdDependencies && importAliasName) { - aliasedModuleNames.push(externalModuleName); - importAliasNames.push(importAliasName); - } - else { - unaliasedModuleNames.push(externalModuleName); + } + else { + if (!exportEquals && exportSpecifiers && ts.hasProperty(exportSpecifiers, name.text)) { + var sourceFileId = ts.getOriginalNodeId(currentSourceFile); + if (!bindingNameExportSpecifiersForFileMap[sourceFileId]) { + bindingNameExportSpecifiersForFileMap[sourceFileId] = ts.createMap(); } + bindingNameExportSpecifiersForFileMap[sourceFileId][name.text] = exportSpecifiers[name.text]; + addExportMemberAssignments(resultStatements, name); } - return { aliasedModuleNames: aliasedModuleNames, unaliasedModuleNames: unaliasedModuleNames, importAliasNames: importAliasNames }; } - function emitAMDDependencies(node, includeNonAmdDependencies, emitRelativePathAsModuleName) { - // An AMD define function has the following shape: - // define(id?, dependencies?, factory); - // - // This has the shape of - // define(name, ["module1", "module2"], function (module1Alias) { - // The location of the alias in the parameter list in the factory function needs to - // match the position of the module name in the dependency list. - // - // To ensure this is true in cases of modules with no aliases, e.g.: - // `import "module"` or `` - // we need to add modules without alias names to the end of the dependencies list - var dependencyNames = getAMDDependencyNames(node, includeNonAmdDependencies, emitRelativePathAsModuleName); - emitAMDDependencyList(dependencyNames); - write(", "); - emitAMDFactoryHeader(dependencyNames); + } + function transformInitializedVariable(node) { + var name = node.name; + if (ts.isBindingPattern(name)) { + return ts.flattenVariableDestructuringToExpression(context, node, hoistVariableDeclaration, getModuleMemberName, visitor); } - function emitAMDDependencyList(_a) { - var aliasedModuleNames = _a.aliasedModuleNames, unaliasedModuleNames = _a.unaliasedModuleNames; - write('["require", "exports"'); - if (aliasedModuleNames.length) { - write(", "); - write(aliasedModuleNames.join(", ")); - } - if (unaliasedModuleNames.length) { - write(", "); - write(unaliasedModuleNames.join(", ")); + else { + return ts.createAssignment(getModuleMemberName(name), ts.visitNode(node.initializer, visitor, ts.isExpression)); + } + } + function visitFunctionDeclaration(node) { + var statements = []; + var name = node.name || ts.getGeneratedNameForNode(node); + if (ts.hasModifier(node, 1 /* Export */)) { + statements.push(ts.setOriginalNode(ts.createFunctionDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, node.asteriskToken, name, + /*typeParameters*/ undefined, node.parameters, + /*type*/ undefined, node.body, + /*location*/ node), + /*original*/ node)); + addExportMemberAssignment(statements, node); + } + else { + statements.push(node); + } + if (node.name) { + addExportMemberAssignments(statements, node.name); + } + return ts.singleOrMany(statements); + } + function visitClassDeclaration(node) { + var statements = []; + var name = node.name || ts.getGeneratedNameForNode(node); + if (ts.hasModifier(node, 1 /* Export */)) { + statements.push(ts.setOriginalNode(ts.createClassDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, name, + /*typeParameters*/ undefined, node.heritageClauses, node.members, + /*location*/ node), + /*original*/ node)); + addExportMemberAssignment(statements, node); + } + else { + statements.push(node); + } + // Decorators end up creating a series of assignment expressions which overwrite + // the local binding that we export, so we need to defer from exporting decorated classes + // until the decoration assignments take place. We do this when visiting expression-statements. + if (node.name && !(node.decorators && node.decorators.length)) { + addExportMemberAssignments(statements, node.name); + } + return ts.singleOrMany(statements); + } + function visitExpressionStatement(node) { + var original = ts.getOriginalNode(node); + var origKind = original.kind; + if (origKind === 224 /* EnumDeclaration */ || origKind === 225 /* ModuleDeclaration */) { + return visitExpressionStatementForEnumOrNamespaceDeclaration(node, original); + } + else if (origKind === 221 /* ClassDeclaration */) { + // The decorated assignment for a class name may need to be transformed. + var classDecl = original; + if (classDecl.name) { + var statements = [node]; + addExportMemberAssignments(statements, classDecl.name); + return statements; } - write("]"); } - function emitAMDFactoryHeader(_a) { - var importAliasNames = _a.importAliasNames; - write("function (require, exports"); - if (importAliasNames.length) { - write(", "); - write(importAliasNames.join(", ")); + return node; + } + function visitExpressionStatementForEnumOrNamespaceDeclaration(node, original) { + var statements = [node]; + // Preserve old behavior for enums in which a variable statement is emitted after the body itself. + if (ts.hasModifier(original, 1 /* Export */) && + original.kind === 224 /* EnumDeclaration */ && + ts.isFirstDeclarationOfKind(original, 224 /* EnumDeclaration */)) { + addVarForExportedEnumOrNamespaceDeclaration(statements, original); + } + addExportMemberAssignments(statements, original.name); + return statements; + } + /** + * Adds a trailing VariableStatement for an enum or module declaration. + */ + function addVarForExportedEnumOrNamespaceDeclaration(statements, node) { + var transformedStatement = ts.createVariableStatement( + /*modifiers*/ undefined, [ts.createVariableDeclaration(getDeclarationName(node), + /*type*/ undefined, ts.createPropertyAccess(ts.createIdentifier("exports"), getDeclarationName(node)))], + /*location*/ node); + ts.setEmitFlags(transformedStatement, 49152 /* NoComments */); + statements.push(transformedStatement); + } + function getDeclarationName(node) { + return node.name ? ts.getSynthesizedClone(node.name) : ts.getGeneratedNameForNode(node); + } + function onEmitNode(emitContext, node, emitCallback) { + if (node.kind === 256 /* SourceFile */) { + bindingNameExportSpecifiersMap = bindingNameExportSpecifiersForFileMap[ts.getOriginalNodeId(node)]; + previousOnEmitNode(emitContext, node, emitCallback); + bindingNameExportSpecifiersMap = undefined; + } + else { + previousOnEmitNode(emitContext, node, emitCallback); + } + } + /** + * Hooks node substitutions. + * + * @param node The node to substitute. + * @param isExpression A value indicating whether the node is to be used in an expression + * position. + */ + function onSubstituteNode(emitContext, node) { + node = previousOnSubstituteNode(emitContext, node); + if (emitContext === 1 /* Expression */) { + return substituteExpression(node); + } + else if (ts.isShorthandPropertyAssignment(node)) { + return substituteShorthandPropertyAssignment(node); + } + return node; + } + function substituteShorthandPropertyAssignment(node) { + var name = node.name; + var exportedOrImportedName = substituteExpressionIdentifier(name); + if (exportedOrImportedName !== name) { + // A shorthand property with an assignment initializer is probably part of a + // destructuring assignment + if (node.objectAssignmentInitializer) { + var initializer = ts.createAssignment(exportedOrImportedName, node.objectAssignmentInitializer); + return ts.createPropertyAssignment(name, initializer, /*location*/ node); } - write(") {"); + return ts.createPropertyAssignment(name, exportedOrImportedName, /*location*/ node); } - function emitAMDModule(node, emitRelativePathAsModuleName) { - emitEmitHelpers(node); - collectExternalModuleInfo(node); - writeLine(); - write("define("); - writeModuleName(node, emitRelativePathAsModuleName); - emitAMDDependencies(node, /*includeNonAmdDependencies*/ true, emitRelativePathAsModuleName); - increaseIndent(); - var startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ true, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict); - emitExportStarHelper(); - emitCaptureThisForNodeIfNecessary(node); - emitLinesStartingAt(node.statements, startIndex); - emitExportEquals(/*emitAsReturn*/ true); - emitTempDeclarations(/*newLine*/ true); - decreaseIndent(); - writeLine(); - write("});"); - } - function emitCommonJSModule(node) { - var startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ false, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict); - emitEmitHelpers(node); - collectExternalModuleInfo(node); - emitExportStarHelper(); - emitCaptureThisForNodeIfNecessary(node); - emitLinesStartingAt(node.statements, startIndex); - emitExportEquals(/*emitAsReturn*/ false); - emitTempDeclarations(/*newLine*/ true); - } - function emitUMDModule(node) { - emitEmitHelpers(node); - collectExternalModuleInfo(node); - var dependencyNames = getAMDDependencyNames(node, /*includeNonAmdDependencies*/ false); - // Module is detected first to support Browserify users that load into a browser with an AMD loader - writeLines("(function (factory) {\n if (typeof module === 'object' && typeof module.exports === 'object') {\n var v = factory(require, exports); if (v !== undefined) module.exports = v;\n }\n else if (typeof define === 'function' && define.amd) {\n define("); - emitAMDDependencyList(dependencyNames); - write(", factory);"); - writeLines(" }\n})("); - emitAMDFactoryHeader(dependencyNames); - increaseIndent(); - var startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ true, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict); - emitExportStarHelper(); - emitCaptureThisForNodeIfNecessary(node); - emitLinesStartingAt(node.statements, startIndex); - emitExportEquals(/*emitAsReturn*/ true); - emitTempDeclarations(/*newLine*/ true); - decreaseIndent(); - writeLine(); - write("});"); + return node; + } + function substituteExpression(node) { + switch (node.kind) { + case 69 /* Identifier */: + return substituteExpressionIdentifier(node); + case 187 /* BinaryExpression */: + return substituteBinaryExpression(node); + case 186 /* PostfixUnaryExpression */: + case 185 /* PrefixUnaryExpression */: + return substituteUnaryExpression(node); } - function emitES6Module(node) { - externalImports = undefined; - exportSpecifiers = undefined; - exportEquals = undefined; - hasExportStarsToExportValues = false; - var startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ false); - emitEmitHelpers(node); - emitCaptureThisForNodeIfNecessary(node); - emitLinesStartingAt(node.statements, startIndex); - emitTempDeclarations(/*newLine*/ true); - // Emit exportDefault if it exists will happen as part - // or normal statement emit. - } - function emitExportEquals(emitAsReturn) { - if (exportEquals && resolver.isValueAliasDeclaration(exportEquals)) { - writeLine(); - emitStart(exportEquals); - write(emitAsReturn ? "return " : "module.exports = "); - emit(exportEquals.expression); - write(";"); - emitEnd(exportEquals); + return node; + } + function substituteExpressionIdentifier(node) { + return trySubstituteExportedName(node) + || trySubstituteImportedName(node) + || node; + } + function substituteBinaryExpression(node) { + var left = node.left; + // If the left-hand-side of the binaryExpression is an identifier and its is export through export Specifier + if (ts.isIdentifier(left) && ts.isAssignmentOperator(node.operatorToken.kind)) { + if (bindingNameExportSpecifiersMap && ts.hasProperty(bindingNameExportSpecifiersMap, left.text)) { + ts.setEmitFlags(node, 128 /* NoSubstitution */); + var nestedExportAssignment = void 0; + for (var _i = 0, _a = bindingNameExportSpecifiersMap[left.text]; _i < _a.length; _i++) { + var specifier = _a[_i]; + nestedExportAssignment = nestedExportAssignment ? + createExportAssignment(specifier.name, nestedExportAssignment) : + createExportAssignment(specifier.name, node); + } + return nestedExportAssignment; + } + } + return node; + } + function substituteUnaryExpression(node) { + // Because how the compiler only parse plusplus and minusminus to be either prefixUnaryExpression or postFixUnaryExpression depended on where they are + // We don't need to check that the operator has SyntaxKind.plusplus or SyntaxKind.minusminus + var operator = node.operator; + var operand = node.operand; + if (ts.isIdentifier(operand) && bindingNameExportSpecifiersForFileMap) { + if (bindingNameExportSpecifiersMap && ts.hasProperty(bindingNameExportSpecifiersMap, operand.text)) { + ts.setEmitFlags(node, 128 /* NoSubstitution */); + var transformedUnaryExpression = void 0; + if (node.kind === 186 /* PostfixUnaryExpression */) { + transformedUnaryExpression = ts.createBinary(operand, ts.createNode(operator === 41 /* PlusPlusToken */ ? 57 /* PlusEqualsToken */ : 58 /* MinusEqualsToken */), ts.createLiteral(1), + /*location*/ node); + // We have to set no substitution flag here to prevent visit the binary expression and substitute it again as we will preform all necessary substitution in here + ts.setEmitFlags(transformedUnaryExpression, 128 /* NoSubstitution */); + } + var nestedExportAssignment = void 0; + for (var _i = 0, _a = bindingNameExportSpecifiersMap[operand.text]; _i < _a.length; _i++) { + var specifier = _a[_i]; + nestedExportAssignment = nestedExportAssignment ? + createExportAssignment(specifier.name, nestedExportAssignment) : + createExportAssignment(specifier.name, transformedUnaryExpression || node); + } + return nestedExportAssignment; } } - function emitJsxElement(node) { - switch (compilerOptions.jsx) { - case 2 /* React */: - jsxEmitReact(node); - break; - case 1 /* Preserve */: - // Fall back to preserve if None was specified (we'll error earlier) - default: - jsxEmitPreserve(node); - break; + return node; + } + function trySubstituteExportedName(node) { + var emitFlags = ts.getEmitFlags(node); + if ((emitFlags & 262144 /* LocalName */) === 0) { + var container = resolver.getReferencedExportContainer(node, (emitFlags & 131072 /* ExportName */) !== 0); + if (container) { + if (container.kind === 256 /* SourceFile */) { + return ts.createPropertyAccess(ts.createIdentifier("exports"), ts.getSynthesizedClone(node), + /*location*/ node); + } } } - function trimReactWhitespaceAndApplyEntities(node) { - var result = undefined; - var text = ts.getTextOfNode(node, /*includeTrivia*/ true); - var firstNonWhitespace = 0; - var lastNonWhitespace = -1; - // JSX trims whitespace at the end and beginning of lines, except that the - // start/end of a tag is considered a start/end of a line only if that line is - // on the same line as the closing tag. See examples in tests/cases/conformance/jsx/tsxReactEmitWhitespace.tsx - for (var i = 0; i < text.length; i++) { - var c = text.charCodeAt(i); - if (ts.isLineBreak(c)) { - if (firstNonWhitespace !== -1 && (lastNonWhitespace - firstNonWhitespace + 1 > 0)) { - var part = text.substr(firstNonWhitespace, lastNonWhitespace - firstNonWhitespace + 1); - result = (result ? result + "\" + ' ' + \"" : "") + ts.escapeString(part); + return undefined; + } + function trySubstituteImportedName(node) { + if ((ts.getEmitFlags(node) & 262144 /* LocalName */) === 0) { + var declaration = resolver.getReferencedImportDeclaration(node); + if (declaration) { + if (ts.isImportClause(declaration)) { + if (languageVersion >= 1 /* ES5 */) { + return ts.createPropertyAccess(ts.getGeneratedNameForNode(declaration.parent), ts.createIdentifier("default"), + /*location*/ node); } - firstNonWhitespace = -1; - } - else if (!ts.isWhiteSpaceSingleLine(c)) { - lastNonWhitespace = i; - if (firstNonWhitespace === -1) { - firstNonWhitespace = i; + else { + // TODO: ES3 transform to handle x.default -> x["default"] + return ts.createElementAccess(ts.getGeneratedNameForNode(declaration.parent), ts.createLiteral("default"), + /*location*/ node); } } - } - if (firstNonWhitespace !== -1) { - var part = text.substr(firstNonWhitespace); - result = (result ? result + "\" + ' ' + \"" : "") + ts.escapeString(part); - } - if (result) { - // Replace entities like   - result = result.replace(/&(\w+);/g, function (s, m) { - if (entities[m] !== undefined) { - var ch = String.fromCharCode(entities[m]); - // " needs to be escaped - return ch === '"' ? "\\\"" : ch; + else if (ts.isImportSpecifier(declaration)) { + var name_41 = declaration.propertyName || declaration.name; + if (name_41.originalKeywordKind === 77 /* DefaultKeyword */ && languageVersion <= 0 /* ES3 */) { + // TODO: ES3 transform to handle x.default -> x["default"] + return ts.createElementAccess(ts.getGeneratedNameForNode(declaration.parent.parent.parent), ts.createLiteral(name_41.text), + /*location*/ node); } else { - return s; + return ts.createPropertyAccess(ts.getGeneratedNameForNode(declaration.parent.parent.parent), ts.getSynthesizedClone(name_41), + /*location*/ node); } - }); + } } - return result; } - function isJsxChildEmittable(child) { - if (child.kind === 248 /* JsxExpression */) { - // Don't emit empty expressions - return !!child.expression; + return undefined; + } + function getModuleMemberName(name) { + return ts.createPropertyAccess(ts.createIdentifier("exports"), name, + /*location*/ name); + } + function createRequireCall(importNode) { + var moduleName = ts.getExternalModuleNameLiteral(importNode, currentSourceFile, host, resolver, compilerOptions); + var args = []; + if (ts.isDefined(moduleName)) { + args.push(moduleName); + } + return ts.createCall(ts.createIdentifier("require"), /*typeArguments*/ undefined, args); + } + function createExportStatement(name, value, location) { + var statement = ts.createStatement(createExportAssignment(name, value)); + statement.startsOnNewLine = true; + if (location) { + ts.setSourceMapRange(statement, location); + } + return statement; + } + function createExportAssignment(name, value) { + return ts.createAssignment(name.originalKeywordKind === 77 /* DefaultKeyword */ && languageVersion === 0 /* ES3 */ + ? ts.createElementAccess(ts.createIdentifier("exports"), ts.createLiteral(name.text)) + : ts.createPropertyAccess(ts.createIdentifier("exports"), ts.getSynthesizedClone(name)), value); + } + function collectAsynchronousDependencies(node, includeNonAmdDependencies) { + // names of modules with corresponding parameter in the factory function + var aliasedModuleNames = []; + // names of modules with no corresponding parameters in factory function + var unaliasedModuleNames = []; + // names of the parameters in the factory function; these + // parameters need to match the indexes of the corresponding + // module names in aliasedModuleNames. + var importAliasNames = []; + // Fill in amd-dependency tags + for (var _i = 0, _a = node.amdDependencies; _i < _a.length; _i++) { + var amdDependency = _a[_i]; + if (amdDependency.name) { + aliasedModuleNames.push(ts.createLiteral(amdDependency.path)); + importAliasNames.push(ts.createParameter(amdDependency.name)); } - else if (child.kind === 244 /* JsxText */) { - // Don't emit empty strings - return !!getTextToEmit(child); + else { + unaliasedModuleNames.push(ts.createLiteral(amdDependency.path)); + } + } + for (var _b = 0, externalImports_1 = externalImports; _b < externalImports_1.length; _b++) { + var importNode = externalImports_1[_b]; + // Find the name of the external module + var externalModuleName = ts.getExternalModuleNameLiteral(importNode, currentSourceFile, host, resolver, compilerOptions); + // Find the name of the module alias, if there is one + var importAliasName = ts.getLocalNameForExternalImport(importNode, currentSourceFile); + if (includeNonAmdDependencies && importAliasName) { + // Set emitFlags on the name of the classDeclaration + // This is so that when printer will not substitute the identifier + ts.setEmitFlags(importAliasName, 128 /* NoSubstitution */); + aliasedModuleNames.push(externalModuleName); + importAliasNames.push(ts.createParameter(importAliasName)); } - return true; - } - ; - function getTextToEmit(node) { - switch (compilerOptions.jsx) { - case 2 /* React */: - var text = trimReactWhitespaceAndApplyEntities(node); - if (text === undefined || text.length === 0) { - return undefined; - } - else { - return text; - } - case 1 /* Preserve */: - default: - return ts.getTextOfNode(node, /*includeTrivia*/ true); + else { + unaliasedModuleNames.push(externalModuleName); } } - function emitJsxText(node) { - switch (compilerOptions.jsx) { - case 2 /* React */: - write('"'); - write(trimReactWhitespaceAndApplyEntities(node)); - write('"'); - break; - case 1 /* Preserve */: - default: - writer.writeLiteral(ts.getTextOfNode(node, /*includeTrivia*/ true)); - break; - } + return { aliasedModuleNames: aliasedModuleNames, unaliasedModuleNames: unaliasedModuleNames, importAliasNames: importAliasNames }; + } + function updateSourceFile(node, statements) { + var updated = ts.getMutableClone(node); + updated.statements = ts.createNodeArray(statements, node.statements); + return updated; + } + var _a; + } + ts.transformModule = transformModule; +})(ts || (ts = {})); +/// +/// +/*@internal*/ +var ts; +(function (ts) { + function transformSystemModule(context) { + var startLexicalEnvironment = context.startLexicalEnvironment, endLexicalEnvironment = context.endLexicalEnvironment, hoistVariableDeclaration = context.hoistVariableDeclaration, hoistFunctionDeclaration = context.hoistFunctionDeclaration; + var compilerOptions = context.getCompilerOptions(); + var resolver = context.getEmitResolver(); + var host = context.getEmitHost(); + var languageVersion = ts.getEmitScriptTarget(compilerOptions); + var previousOnSubstituteNode = context.onSubstituteNode; + var previousOnEmitNode = context.onEmitNode; + context.onSubstituteNode = onSubstituteNode; + context.onEmitNode = onEmitNode; + context.enableSubstitution(69 /* Identifier */); + context.enableSubstitution(187 /* BinaryExpression */); + context.enableSubstitution(185 /* PrefixUnaryExpression */); + context.enableSubstitution(186 /* PostfixUnaryExpression */); + context.enableEmitNotification(256 /* SourceFile */); + var exportFunctionForFileMap = []; + var currentSourceFile; + var externalImports; + var exportSpecifiers; + var exportEquals; + var hasExportStarsToExportValues; + var exportFunctionForFile; + var contextObjectForFile; + var exportedLocalNames; + var exportedFunctionDeclarations; + var enclosingBlockScopedContainer; + var currentParent; + var currentNode; + return transformSourceFile; + function transformSourceFile(node) { + if (ts.isDeclarationFile(node)) { + return node; } - function emitJsxExpression(node) { - if (node.expression) { - switch (compilerOptions.jsx) { - case 1 /* Preserve */: - default: - write("{"); - emit(node.expression); - write("}"); - break; - case 2 /* React */: - emit(node.expression); - break; - } - } + if (ts.isExternalModule(node) || compilerOptions.isolatedModules) { + currentSourceFile = node; + currentNode = node; + // Perform the transformation. + var updated = transformSystemModuleWorker(node); + ts.aggregateTransformFlags(updated); + currentSourceFile = undefined; + externalImports = undefined; + exportSpecifiers = undefined; + exportEquals = undefined; + hasExportStarsToExportValues = false; + exportFunctionForFile = undefined; + contextObjectForFile = undefined; + exportedLocalNames = undefined; + exportedFunctionDeclarations = undefined; + return updated; } - function isUseStrictPrologue(node) { - return node.expression.text === "use strict"; + return node; + } + function transformSystemModuleWorker(node) { + // System modules have the following shape: + // + // System.register(['dep-1', ... 'dep-n'], function(exports) {/* module body function */}) + // + // The parameter 'exports' here is a callback '(name: string, value: T) => T' that + // is used to publish exported values. 'exports' returns its 'value' argument so in + // most cases expressions that mutate exported values can be rewritten as: + // + // expr -> exports('name', expr) + // + // The only exception in this rule is postfix unary operators, + // see comment to 'substitutePostfixUnaryExpression' for more details + ts.Debug.assert(!exportFunctionForFile); + // Collect information about the external module and dependency groups. + (_a = ts.collectExternalModuleInfo(node, resolver), externalImports = _a.externalImports, exportSpecifiers = _a.exportSpecifiers, exportEquals = _a.exportEquals, hasExportStarsToExportValues = _a.hasExportStarsToExportValues, _a); + // Make sure that the name of the 'exports' function does not conflict with + // existing identifiers. + exportFunctionForFile = ts.createUniqueName("exports"); + contextObjectForFile = ts.createUniqueName("context"); + exportFunctionForFileMap[ts.getOriginalNodeId(node)] = exportFunctionForFile; + var dependencyGroups = collectDependencyGroups(externalImports); + var statements = []; + // Add the body of the module. + addSystemModuleBody(statements, node, dependencyGroups); + var moduleName = ts.tryGetModuleNameFromFile(node, host, compilerOptions); + var dependencies = ts.createArrayLiteral(ts.map(dependencyGroups, getNameOfDependencyGroup)); + var body = ts.createFunctionExpression( + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ + ts.createParameter(exportFunctionForFile), + ts.createParameter(contextObjectForFile) + ], + /*type*/ undefined, ts.setEmitFlags(ts.createBlock(statements, /*location*/ undefined, /*multiLine*/ true), 1 /* EmitEmitHelpers */)); + // Write the call to `System.register` + // Clear the emit-helpers flag for later passes since we'll have already used it in the module body + // So the helper will be emit at the correct position instead of at the top of the source-file + return updateSourceFile(node, [ + ts.createStatement(ts.createCall(ts.createPropertyAccess(ts.createIdentifier("System"), "register"), + /*typeArguments*/ undefined, moduleName + ? [moduleName, dependencies, body] + : [dependencies, body])) + ], /*nodeEmitFlags*/ ~1 /* EmitEmitHelpers */ & ts.getEmitFlags(node)); + var _a; + } + /** + * Adds the statements for the module body function for the source file. + * + * @param statements The output statements for the module body. + * @param node The source file for the module. + * @param statementOffset The offset at which to begin visiting the statements of the SourceFile. + */ + function addSystemModuleBody(statements, node, dependencyGroups) { + // Shape of the body in system modules: + // + // function (exports) { + // + // + // + // return { + // setters: [ + // + // ], + // execute: function() { + // + // } + // } + // + // } + // + // i.e: + // + // import {x} from 'file1' + // var y = 1; + // export function foo() { return y + x(); } + // console.log(y); + // + // Will be transformed to: + // + // function(exports) { + // var file_1; // local alias + // var y; + // function foo() { return y + file_1.x(); } + // exports("foo", foo); + // return { + // setters: [ + // function(v) { file_1 = v } + // ], + // execute(): function() { + // y = 1; + // console.log(y); + // } + // }; + // } + // We start a new lexical environment in this function body, but *not* in the + // body of the execute function. This allows us to emit temporary declarations + // only in the outer module body and not in the inner one. + startLexicalEnvironment(); + // Add any prologue directives. + var statementOffset = ts.addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, visitSourceElement); + // var __moduleName = context_1 && context_1.id; + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration("__moduleName", + /*type*/ undefined, ts.createLogicalAnd(contextObjectForFile, ts.createPropertyAccess(contextObjectForFile, "id"))) + ]))); + // Visit the statements of the source file, emitting any transformations into + // the `executeStatements` array. We do this *before* we fill the `setters` array + // as we both emit transformations as well as aggregate some data used when creating + // setters. This allows us to reduce the number of times we need to loop through the + // statements of the source file. + var executeStatements = ts.visitNodes(node.statements, visitSourceElement, ts.isStatement, statementOffset); + // We emit the lexical environment (hoisted variables and function declarations) + // early to align roughly with our previous emit output. + // Two key differences in this approach are: + // - Temporary variables will appear at the top rather than at the bottom of the file + // - Calls to the exporter for exported function declarations are grouped after + // the declarations. + ts.addRange(statements, endLexicalEnvironment()); + // Emit early exports for function declarations. + ts.addRange(statements, exportedFunctionDeclarations); + var exportStarFunction = addExportStarIfNeeded(statements); + statements.push(ts.createReturn(ts.setMultiLine(ts.createObjectLiteral([ + ts.createPropertyAssignment("setters", generateSetters(exportStarFunction, dependencyGroups)), + ts.createPropertyAssignment("execute", ts.createFunctionExpression( + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, + /*parameters*/ [], + /*type*/ undefined, ts.createBlock(executeStatements, + /*location*/ undefined, + /*multiLine*/ true))) + ]), + /*multiLine*/ true))); + } + function addExportStarIfNeeded(statements) { + if (!hasExportStarsToExportValues) { + return; } - function ensureUseStrictPrologue(startWithNewLine, writeUseStrict) { - if (writeUseStrict) { - if (startWithNewLine) { - writeLine(); + // when resolving exports local exported entries/indirect exported entries in the module + // should always win over entries with similar names that were added via star exports + // to support this we store names of local/indirect exported entries in a set. + // this set is used to filter names brought by star expors. + // local names set should only be added if we have anything exported + if (!exportedLocalNames && ts.isEmpty(exportSpecifiers)) { + // no exported declarations (export var ...) or export specifiers (export {x}) + // check if we have any non star export declarations. + var hasExportDeclarationWithExportClause = false; + for (var _i = 0, externalImports_2 = externalImports; _i < externalImports_2.length; _i++) { + var externalImport = externalImports_2[_i]; + if (externalImport.kind === 236 /* ExportDeclaration */ && externalImport.exportClause) { + hasExportDeclarationWithExportClause = true; + break; } - write("\"use strict\";"); } - } - function emitDirectivePrologues(statements, startWithNewLine, ensureUseStrict) { - var foundUseStrict = false; - for (var i = 0; i < statements.length; i++) { - if (ts.isPrologueDirective(statements[i])) { - if (isUseStrictPrologue(statements[i])) { - foundUseStrict = true; - } - if (startWithNewLine || i > 0) { - writeLine(); - } - emit(statements[i]); - } - else { - ensureUseStrictPrologue(startWithNewLine || i > 0, !foundUseStrict && ensureUseStrict); - // return index of the first non prologue directive - return i; - } + if (!hasExportDeclarationWithExportClause) { + // we still need to emit exportStar helper + return addExportStarFunction(statements, /*localNames*/ undefined); } - ensureUseStrictPrologue(startWithNewLine, !foundUseStrict && ensureUseStrict); - return statements.length; } - function writeLines(text) { - var lines = text.split(/\r\n|\r|\n/g); - for (var i = 0; i < lines.length; i++) { - var line = lines[i]; - if (line.length) { - writeLine(); - write(line); - } + var exportedNames = []; + if (exportedLocalNames) { + for (var _a = 0, exportedLocalNames_1 = exportedLocalNames; _a < exportedLocalNames_1.length; _a++) { + var exportedLocalName = exportedLocalNames_1[_a]; + // write name of exported declaration, i.e 'export var x...' + exportedNames.push(ts.createPropertyAssignment(ts.createLiteral(exportedLocalName.text), ts.createLiteral(true))); } } - function emitEmitHelpers(node) { - // Only emit helpers if the user did not say otherwise. - if (!compilerOptions.noEmitHelpers) { - // Only Emit __extends function when target ES5. - // For target ES6 and above, we can emit classDeclaration as is. - if (languageVersion < 2 /* ES6 */ && !extendsEmitted && node.flags & 262144 /* HasClassExtends */) { - writeLines(extendsHelper); - extendsEmitted = true; - } - if (compilerOptions.jsx !== 1 /* Preserve */ && !assignEmitted && (node.flags & 1073741824 /* HasJsxSpreadAttribute */)) { - writeLines(assignHelper); - assignEmitted = true; - } - if (!decorateEmitted && node.flags & 524288 /* HasDecorators */) { - writeLines(decorateHelper); - if (compilerOptions.emitDecoratorMetadata) { - writeLines(metadataHelper); - } - decorateEmitted = true; - } - if (!paramEmitted && node.flags & 1048576 /* HasParamDecorators */) { - writeLines(paramHelper); - paramEmitted = true; - } - if (!awaiterEmitted && node.flags & 2097152 /* HasAsyncFunctions */) { - writeLines(awaiterHelper); - awaiterEmitted = true; - } + for (var _b = 0, externalImports_3 = externalImports; _b < externalImports_3.length; _b++) { + var externalImport = externalImports_3[_b]; + if (externalImport.kind !== 236 /* ExportDeclaration */) { + continue; } - } - function emitSourceFileNode(node) { - // Start new file on new line - writeLine(); - emitShebang(); - emitDetachedCommentsAndUpdateCommentsInfo(node); - if (ts.isExternalModule(node) || compilerOptions.isolatedModules) { - if (isOwnFileEmit || (!ts.isExternalModule(node) && compilerOptions.isolatedModules)) { - var emitModule = moduleEmitDelegates[modulekind] || moduleEmitDelegates[ts.ModuleKind.CommonJS]; - emitModule(node); - } - else { - bundleEmitDelegates[modulekind](node, /*emitRelativePathAsModuleName*/ true); - } + var exportDecl = externalImport; + if (!exportDecl.exportClause) { + // export * from ... + continue; } - else { - // emit prologue directives prior to __extends - var startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ false); - externalImports = undefined; - exportSpecifiers = undefined; - exportEquals = undefined; - hasExportStarsToExportValues = false; - emitEmitHelpers(node); - emitCaptureThisForNodeIfNecessary(node); - emitLinesStartingAt(node.statements, startIndex); - emitTempDeclarations(/*newLine*/ true); - } - emitLeadingComments(node.endOfFileToken); - } - function emit(node) { - emitNodeConsideringCommentsOption(node, emitNodeWithSourceMap); - } - function emitNodeWithCommentsAndWithoutSourcemap(node) { - emitNodeConsideringCommentsOption(node, emitNodeWithoutSourceMap); - } - function emitNodeConsideringCommentsOption(node, emitNodeConsideringSourcemap) { - if (node) { - if (node.flags & 2 /* Ambient */) { - return emitCommentsOnNotEmittedNode(node); - } - if (isSpecializedCommentHandling(node)) { - // This is the node that will handle its own comments and sourcemap - return emitNodeWithoutSourceMap(node); - } - var emitComments_1 = shouldEmitLeadingAndTrailingComments(node); - if (emitComments_1) { - emitLeadingComments(node); - } - emitNodeConsideringSourcemap(node); - if (emitComments_1) { - emitTrailingComments(node); - } + for (var _c = 0, _d = exportDecl.exportClause.elements; _c < _d.length; _c++) { + var element = _d[_c]; + // write name of indirectly exported entry, i.e. 'export {x} from ...' + exportedNames.push(ts.createPropertyAssignment(ts.createLiteral((element.name || element.propertyName).text), ts.createLiteral(true))); } } - function emitNodeWithSourceMap(node) { - if (node) { - emitStart(node); - emitNodeWithoutSourceMap(node); - emitEnd(node); + var exportedNamesStorageRef = ts.createUniqueName("exportedNames"); + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(exportedNamesStorageRef, + /*type*/ undefined, ts.createObjectLiteral(exportedNames, /*location*/ undefined, /*multiline*/ true)) + ]))); + return addExportStarFunction(statements, exportedNamesStorageRef); + } + /** + * Emits a setter callback for each dependency group. + * @param write The callback used to write each callback. + */ + function generateSetters(exportStarFunction, dependencyGroups) { + var setters = []; + for (var _i = 0, dependencyGroups_1 = dependencyGroups; _i < dependencyGroups_1.length; _i++) { + var group = dependencyGroups_1[_i]; + // derive a unique name for parameter from the first named entry in the group + var localName = ts.forEach(group.externalImports, function (i) { return ts.getLocalNameForExternalImport(i, currentSourceFile); }); + var parameterName = localName ? ts.getGeneratedNameForNode(localName) : ts.createUniqueName(""); + var statements = []; + for (var _a = 0, _b = group.externalImports; _a < _b.length; _a++) { + var entry = _b[_a]; + var importVariableName = ts.getLocalNameForExternalImport(entry, currentSourceFile); + switch (entry.kind) { + case 230 /* ImportDeclaration */: + if (!entry.importClause) { + // 'import "..."' case + // module is imported only for side-effects, no emit required + break; + } + // fall-through + case 229 /* ImportEqualsDeclaration */: + ts.Debug.assert(importVariableName !== undefined); + // save import into the local + statements.push(ts.createStatement(ts.createAssignment(importVariableName, parameterName))); + break; + case 236 /* ExportDeclaration */: + ts.Debug.assert(importVariableName !== undefined); + if (entry.exportClause) { + // export {a, b as c} from 'foo' + // + // emit as: + // + // exports_({ + // "a": _["a"], + // "c": _["b"] + // }); + var properties = []; + for (var _c = 0, _d = entry.exportClause.elements; _c < _d.length; _c++) { + var e = _d[_c]; + properties.push(ts.createPropertyAssignment(ts.createLiteral(e.name.text), ts.createElementAccess(parameterName, ts.createLiteral((e.propertyName || e.name).text)))); + } + statements.push(ts.createStatement(ts.createCall(exportFunctionForFile, + /*typeArguments*/ undefined, [ts.createObjectLiteral(properties, /*location*/ undefined, /*multiline*/ true)]))); + } + else { + // export * from 'foo' + // + // emit as: + // + // exportStar(foo_1_1); + statements.push(ts.createStatement(ts.createCall(exportStarFunction, + /*typeArguments*/ undefined, [parameterName]))); + } + break; + } } + setters.push(ts.createFunctionExpression( + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ts.createParameter(parameterName)], + /*type*/ undefined, ts.createBlock(statements, /*location*/ undefined, /*multiLine*/ true))); } - function emitNodeWithoutSourceMap(node) { - if (node) { - emitJavaScriptWorker(node); - } + return ts.createArrayLiteral(setters, /*location*/ undefined, /*multiLine*/ true); + } + function visitSourceElement(node) { + switch (node.kind) { + case 230 /* ImportDeclaration */: + return visitImportDeclaration(node); + case 229 /* ImportEqualsDeclaration */: + return visitImportEqualsDeclaration(node); + case 236 /* ExportDeclaration */: + return visitExportDeclaration(node); + case 235 /* ExportAssignment */: + return visitExportAssignment(node); + default: + return visitNestedNode(node); + } + } + function visitNestedNode(node) { + var savedEnclosingBlockScopedContainer = enclosingBlockScopedContainer; + var savedCurrentParent = currentParent; + var savedCurrentNode = currentNode; + var currentGrandparent = currentParent; + currentParent = currentNode; + currentNode = node; + if (currentParent && ts.isBlockScope(currentParent, currentGrandparent)) { + enclosingBlockScopedContainer = currentParent; + } + var result = visitNestedNodeWorker(node); + enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer; + currentParent = savedCurrentParent; + currentNode = savedCurrentNode; + return result; + } + function visitNestedNodeWorker(node) { + switch (node.kind) { + case 200 /* VariableStatement */: + return visitVariableStatement(node); + case 220 /* FunctionDeclaration */: + return visitFunctionDeclaration(node); + case 221 /* ClassDeclaration */: + return visitClassDeclaration(node); + case 206 /* ForStatement */: + return visitForStatement(node); + case 207 /* ForInStatement */: + return visitForInStatement(node); + case 208 /* ForOfStatement */: + return visitForOfStatement(node); + case 204 /* DoStatement */: + return visitDoStatement(node); + case 205 /* WhileStatement */: + return visitWhileStatement(node); + case 214 /* LabeledStatement */: + return visitLabeledStatement(node); + case 212 /* WithStatement */: + return visitWithStatement(node); + case 213 /* SwitchStatement */: + return visitSwitchStatement(node); + case 227 /* CaseBlock */: + return visitCaseBlock(node); + case 249 /* CaseClause */: + return visitCaseClause(node); + case 250 /* DefaultClause */: + return visitDefaultClause(node); + case 216 /* TryStatement */: + return visitTryStatement(node); + case 252 /* CatchClause */: + return visitCatchClause(node); + case 199 /* Block */: + return visitBlock(node); + case 202 /* ExpressionStatement */: + return visitExpressionStatement(node); + default: + return node; } - function changeSourceMapEmit(writer) { - sourceMap = writer; - emitStart = writer.emitStart; - emitEnd = writer.emitEnd; - emitPos = writer.emitPos; - setSourceFile = writer.setSourceFile; + } + function visitImportDeclaration(node) { + if (node.importClause && ts.contains(externalImports, node)) { + hoistVariableDeclaration(ts.getLocalNameForExternalImport(node, currentSourceFile)); } - function withTemporaryNoSourceMap(callback) { - var prevSourceMap = sourceMap; - setSourceMapWriterEmit(ts.getNullSourceMapWriter()); - callback(); - setSourceMapWriterEmit(prevSourceMap); + return undefined; + } + function visitImportEqualsDeclaration(node) { + if (ts.contains(externalImports, node)) { + hoistVariableDeclaration(ts.getLocalNameForExternalImport(node, currentSourceFile)); } - function isSpecializedCommentHandling(node) { - switch (node.kind) { - // All of these entities are emitted in a specialized fashion. As such, we allow - // the specialized methods for each to handle the comments on the nodes. - case 222 /* InterfaceDeclaration */: - case 220 /* FunctionDeclaration */: - case 230 /* ImportDeclaration */: - case 229 /* ImportEqualsDeclaration */: - case 223 /* TypeAliasDeclaration */: - case 235 /* ExportAssignment */: - return true; - } + // NOTE(rbuckton): Do we support export import = require('') in System? + return undefined; + } + function visitExportDeclaration(node) { + if (!node.moduleSpecifier) { + var statements = []; + ts.addRange(statements, ts.map(node.exportClause.elements, visitExportSpecifier)); + return statements; } - function shouldEmitLeadingAndTrailingComments(node) { - switch (node.kind) { - case 200 /* VariableStatement */: - return shouldEmitLeadingAndTrailingCommentsForVariableStatement(node); - case 225 /* ModuleDeclaration */: - // Only emit the leading/trailing comments for a module if we're actually - // emitting the module as well. - return shouldEmitModuleDeclaration(node); - case 224 /* EnumDeclaration */: - // Only emit the leading/trailing comments for an enum if we're actually - // emitting the module as well. - return shouldEmitEnumDeclaration(node); - } - // If the node is emitted in specialized fashion, dont emit comments as this node will handle - // emitting comments when emitting itself - ts.Debug.assert(!isSpecializedCommentHandling(node)); - // If this is the expression body of an arrow function that we're down-leveling, - // then we don't want to emit comments when we emit the body. It will have already - // been taken care of when we emitted the 'return' statement for the function - // expression body. - if (node.kind !== 199 /* Block */ && - node.parent && - node.parent.kind === 180 /* ArrowFunction */ && - node.parent.body === node && - languageVersion <= 1 /* ES5 */) { - return false; - } - // Emit comments for everything else. - return true; + return undefined; + } + function visitExportSpecifier(specifier) { + if (resolver.getReferencedValueDeclaration(specifier.propertyName || specifier.name) + || resolver.isValueAliasDeclaration(specifier)) { + recordExportName(specifier.name); + return createExportStatement(specifier.name, specifier.propertyName || specifier.name); } - function emitJavaScriptWorker(node) { - // Check if the node can be emitted regardless of the ScriptTarget - switch (node.kind) { - case 69 /* Identifier */: - return emitIdentifier(node); - case 142 /* Parameter */: - return emitParameter(node); - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - return emitMethod(node); - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - return emitAccessor(node); - case 97 /* ThisKeyword */: - return emitThis(node); - case 95 /* SuperKeyword */: - return emitSuper(node); - case 93 /* NullKeyword */: - return write("null"); - case 99 /* TrueKeyword */: - return write("true"); - case 84 /* FalseKeyword */: - return write("false"); - case 8 /* NumericLiteral */: - case 9 /* StringLiteral */: - case 10 /* RegularExpressionLiteral */: - case 11 /* NoSubstitutionTemplateLiteral */: - case 12 /* TemplateHead */: - case 13 /* TemplateMiddle */: - case 14 /* TemplateTail */: - return emitLiteral(node); - case 189 /* TemplateExpression */: - return emitTemplateExpression(node); - case 197 /* TemplateSpan */: - return emitTemplateSpan(node); - case 241 /* JsxElement */: - case 242 /* JsxSelfClosingElement */: - return emitJsxElement(node); - case 244 /* JsxText */: - return emitJsxText(node); - case 248 /* JsxExpression */: - return emitJsxExpression(node); - case 139 /* QualifiedName */: - return emitQualifiedName(node); - case 167 /* ObjectBindingPattern */: - return emitObjectBindingPattern(node); - case 168 /* ArrayBindingPattern */: - return emitArrayBindingPattern(node); - case 169 /* BindingElement */: - return emitBindingElement(node); - case 170 /* ArrayLiteralExpression */: - return emitArrayLiteral(node); - case 171 /* ObjectLiteralExpression */: - return emitObjectLiteral(node); - case 253 /* PropertyAssignment */: - return emitPropertyAssignment(node); - case 254 /* ShorthandPropertyAssignment */: - return emitShorthandPropertyAssignment(node); - case 140 /* ComputedPropertyName */: - return emitComputedPropertyName(node); - case 172 /* PropertyAccessExpression */: - return emitPropertyAccess(node); - case 173 /* ElementAccessExpression */: - return emitIndexedAccess(node); - case 174 /* CallExpression */: - return emitCallExpression(node); - case 175 /* NewExpression */: - return emitNewExpression(node); - case 176 /* TaggedTemplateExpression */: - return emitTaggedTemplateExpression(node); - case 177 /* TypeAssertionExpression */: - case 195 /* AsExpression */: - case 196 /* NonNullExpression */: - return emit(node.expression); - case 178 /* ParenthesizedExpression */: - return emitParenExpression(node); - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - case 180 /* ArrowFunction */: - return emitFunctionDeclaration(node); - case 181 /* DeleteExpression */: - return emitDeleteExpression(node); - case 182 /* TypeOfExpression */: - return emitTypeOfExpression(node); - case 183 /* VoidExpression */: - return emitVoidExpression(node); - case 184 /* AwaitExpression */: - return emitAwaitExpression(node); - case 185 /* PrefixUnaryExpression */: - return emitPrefixUnaryExpression(node); - case 186 /* PostfixUnaryExpression */: - return emitPostfixUnaryExpression(node); - case 187 /* BinaryExpression */: - return emitBinaryExpression(node); - case 188 /* ConditionalExpression */: - return emitConditionalExpression(node); - case 191 /* SpreadElementExpression */: - return emitSpreadElementExpression(node); - case 190 /* YieldExpression */: - return emitYieldExpression(node); - case 193 /* OmittedExpression */: - return; - case 199 /* Block */: - case 226 /* ModuleBlock */: - return emitBlock(node); - case 200 /* VariableStatement */: - return emitVariableStatement(node); - case 201 /* EmptyStatement */: - return write(";"); - case 202 /* ExpressionStatement */: - return emitExpressionStatement(node); - case 203 /* IfStatement */: - return emitIfStatement(node); - case 204 /* DoStatement */: - return emitDoStatement(node); - case 205 /* WhileStatement */: - return emitWhileStatement(node); - case 206 /* ForStatement */: - return emitForStatement(node); - case 208 /* ForOfStatement */: - case 207 /* ForInStatement */: - return emitForInOrForOfStatement(node); - case 209 /* ContinueStatement */: - case 210 /* BreakStatement */: - return emitBreakOrContinueStatement(node); - case 211 /* ReturnStatement */: - return emitReturnStatement(node); - case 212 /* WithStatement */: - return emitWithStatement(node); - case 213 /* SwitchStatement */: - return emitSwitchStatement(node); - case 249 /* CaseClause */: - case 250 /* DefaultClause */: - return emitCaseOrDefaultClause(node); - case 214 /* LabeledStatement */: - return emitLabeledStatement(node); - case 215 /* ThrowStatement */: - return emitThrowStatement(node); - case 216 /* TryStatement */: - return emitTryStatement(node); - case 252 /* CatchClause */: - return emitCatchClause(node); - case 217 /* DebuggerStatement */: - return emitDebuggerStatement(node); - case 218 /* VariableDeclaration */: - return emitVariableDeclaration(node); - case 192 /* ClassExpression */: - return emitClassExpression(node); - case 221 /* ClassDeclaration */: - return emitClassDeclaration(node); - case 222 /* InterfaceDeclaration */: - return emitInterfaceDeclaration(node); - case 224 /* EnumDeclaration */: - return emitEnumDeclaration(node); - case 255 /* EnumMember */: - return emitEnumMember(node); - case 225 /* ModuleDeclaration */: - return emitModuleDeclaration(node); - case 230 /* ImportDeclaration */: - return emitImportDeclaration(node); - case 229 /* ImportEqualsDeclaration */: - return emitImportEqualsDeclaration(node); - case 236 /* ExportDeclaration */: - return emitExportDeclaration(node); - case 235 /* ExportAssignment */: - return emitExportAssignment(node); - case 256 /* SourceFile */: - return emitSourceFileNode(node); + return undefined; + } + function visitExportAssignment(node) { + if (!node.isExportEquals) { + if (ts.nodeIsSynthesized(node) || resolver.isValueAliasDeclaration(node)) { + return createExportStatement(ts.createLiteral("default"), node.expression); } } - function hasDetachedComments(pos) { - return detachedCommentsInfo !== undefined && ts.lastOrUndefined(detachedCommentsInfo).nodePos === pos; + return undefined; + } + /** + * Visits a variable statement, hoisting declared names to the top-level module body. + * Each declaration is rewritten into an assignment expression. + * + * @param node The variable statement to visit. + */ + function visitVariableStatement(node) { + // hoist only non-block scoped declarations or block scoped declarations parented by source file + var shouldHoist = ((ts.getCombinedNodeFlags(ts.getOriginalNode(node.declarationList)) & 3 /* BlockScoped */) == 0) || + enclosingBlockScopedContainer.kind === 256 /* SourceFile */; + if (!shouldHoist) { + return node; } - function getLeadingCommentsWithoutDetachedComments() { - // get the leading comments from detachedPos - var leadingComments = ts.getLeadingCommentRanges(currentText, ts.lastOrUndefined(detachedCommentsInfo).detachedCommentEndPos); - if (detachedCommentsInfo.length - 1) { - detachedCommentsInfo.pop(); - } - else { - detachedCommentsInfo = undefined; + var isExported = ts.hasModifier(node, 1 /* Export */); + var expressions = []; + for (var _i = 0, _a = node.declarationList.declarations; _i < _a.length; _i++) { + var variable = _a[_i]; + var visited = transformVariable(variable, isExported); + if (visited) { + expressions.push(visited); } - return leadingComments; } - /** - * Determine if the given comment is a triple-slash - * - * @return true if the comment is a triple-slash comment else false - **/ - function isTripleSlashComment(comment) { - // Verify this is /// comment, but do the regexp match only when we first can find /// in the comment text - // so that we don't end up computing comment string and doing match for all // comments - if (currentText.charCodeAt(comment.pos + 1) === 47 /* slash */ && - comment.pos + 2 < comment.end && - currentText.charCodeAt(comment.pos + 2) === 47 /* slash */) { - var textSubStr = currentText.substring(comment.pos, comment.end); - return textSubStr.match(ts.fullTripleSlashReferencePathRegEx) || - textSubStr.match(ts.fullTripleSlashAMDReferencePathRegEx) ? - true : false; - } - return false; + if (expressions.length) { + return ts.createStatement(ts.inlineExpressions(expressions), node); } - function getLeadingCommentsToEmit(node) { - // Emit the leading comments only if the parent's pos doesn't match because parent should take care of emitting these comments - if (node.parent) { - if (node.parent.kind === 256 /* SourceFile */ || node.pos !== node.parent.pos) { - if (hasDetachedComments(node.pos)) { - // get comments without detached comments - return getLeadingCommentsWithoutDetachedComments(); - } - else { - // get the leading comments from the node - return ts.getLeadingCommentRangesOfNodeFromText(node, currentText); - } - } - } + return undefined; + } + /** + * Transforms a VariableDeclaration into one or more assignment expressions. + * + * @param node The VariableDeclaration to transform. + * @param isExported A value used to indicate whether the containing statement was exported. + */ + function transformVariable(node, isExported) { + // Hoist any bound names within the declaration. + hoistBindingElement(node, isExported); + if (!node.initializer) { + // If the variable has no initializer, ignore it. + return; } - function getTrailingCommentsToEmit(node) { - // Emit the trailing comments only if the parent's pos doesn't match because parent should take care of emitting these comments - if (node.parent) { - if (node.parent.kind === 256 /* SourceFile */ || node.end !== node.parent.end) { - return ts.getTrailingCommentRanges(currentText, node.end); - } - } + var name = node.name; + if (ts.isIdentifier(name)) { + // If the variable has an IdentifierName, write out an assignment expression in its place. + return ts.createAssignment(name, node.initializer); } - /** - * Emit comments associated with node that will not be emitted into JS file - */ - function emitCommentsOnNotEmittedNode(node) { - emitLeadingCommentsWorker(node, /*isEmittedNode*/ false); + else { + // If the variable has a BindingPattern, flatten the variable into multiple assignment expressions. + return ts.flattenVariableDestructuringToExpression(context, node, hoistVariableDeclaration); } - function emitLeadingComments(node) { - return emitLeadingCommentsWorker(node, /*isEmittedNode*/ true); + } + /** + * Visits a FunctionDeclaration, hoisting it to the outer module body function. + * + * @param node The function declaration to visit. + */ + function visitFunctionDeclaration(node) { + if (ts.hasModifier(node, 1 /* Export */)) { + // If the function is exported, ensure it has a name and rewrite the function without any export flags. + var name_42 = node.name || ts.getGeneratedNameForNode(node); + var newNode = ts.createFunctionDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, node.asteriskToken, name_42, + /*typeParameters*/ undefined, node.parameters, + /*type*/ undefined, node.body, + /*location*/ node); + // Record a declaration export in the outer module body function. + recordExportedFunctionDeclaration(node); + if (!ts.hasModifier(node, 512 /* Default */)) { + recordExportName(name_42); + } + ts.setOriginalNode(newNode, node); + node = newNode; + } + // Hoist the function declaration to the outer module body function. + hoistFunctionDeclaration(node); + return undefined; + } + function visitExpressionStatement(node) { + var originalNode = ts.getOriginalNode(node); + if ((originalNode.kind === 225 /* ModuleDeclaration */ || originalNode.kind === 224 /* EnumDeclaration */) && ts.hasModifier(originalNode, 1 /* Export */)) { + var name_43 = getDeclarationName(originalNode); + // We only need to hoistVariableDeclaration for EnumDeclaration + // as ModuleDeclaration is already hoisted when the transformer call visitVariableStatement + // which then call transformsVariable for each declaration in declarationList + if (originalNode.kind === 224 /* EnumDeclaration */) { + hoistVariableDeclaration(name_43); + } + return [ + node, + createExportStatement(name_43, name_43) + ]; } - function emitLeadingCommentsWorker(node, isEmittedNode) { - if (compilerOptions.removeComments) { - return; - } - var leadingComments; - if (isEmittedNode) { - leadingComments = getLeadingCommentsToEmit(node); - } - else { - // If the node will not be emitted in JS, remove all the comments(normal, pinned and ///) associated with the node, - // unless it is a triple slash comment at the top of the file. - // For Example: - // /// - // declare var x; - // /// - // interface F {} - // The first /// will NOT be removed while the second one will be removed even though both node will not be emitted - if (node.pos === 0) { - leadingComments = ts.filter(getLeadingCommentsToEmit(node), isTripleSlashComment); - } - } - ts.emitNewLineBeforeLeadingComments(currentLineMap, writer, node, leadingComments); - // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space - ts.emitComments(currentText, currentLineMap, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment); - } - function emitTrailingComments(node) { - if (compilerOptions.removeComments) { - return; + return node; + } + /** + * Visits a ClassDeclaration, hoisting its name to the outer module body function. + * + * @param node The class declaration to visit. + */ + function visitClassDeclaration(node) { + // Hoist the name of the class declaration to the outer module body function. + var name = getDeclarationName(node); + hoistVariableDeclaration(name); + var statements = []; + // Rewrite the class declaration into an assignment of a class expression. + statements.push(ts.createStatement(ts.createAssignment(name, ts.createClassExpression( + /*modifiers*/ undefined, node.name, + /*typeParameters*/ undefined, node.heritageClauses, node.members, + /*location*/ node)), + /*location*/ node)); + // If the class was exported, write a declaration export to the inner module body function. + if (ts.hasModifier(node, 1 /* Export */)) { + if (!ts.hasModifier(node, 512 /* Default */)) { + recordExportName(name); + } + statements.push(createDeclarationExport(node)); + } + return statements; + } + function shouldHoistLoopInitializer(node) { + return ts.isVariableDeclarationList(node) && (ts.getCombinedNodeFlags(node) & 3 /* BlockScoped */) === 0; + } + /** + * Visits the body of a ForStatement to hoist declarations. + * + * @param node The statement to visit. + */ + function visitForStatement(node) { + var initializer = node.initializer; + if (shouldHoistLoopInitializer(initializer)) { + var expressions = []; + for (var _i = 0, _a = initializer.declarations; _i < _a.length; _i++) { + var variable = _a[_i]; + var visited = transformVariable(variable, /*isExported*/ false); + if (visited) { + expressions.push(visited); + } } - // Emit the trailing comments only if the parent's end doesn't match - var trailingComments = getTrailingCommentsToEmit(node); - // trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/ - ts.emitComments(currentText, currentLineMap, writer, trailingComments, /*trailingSeparator*/ false, newLine, writeComment); + ; + return ts.createFor(expressions.length + ? ts.inlineExpressions(expressions) + : ts.createSynthesizedNode(193 /* OmittedExpression */), node.condition, node.incrementor, ts.visitNode(node.statement, visitNestedNode, ts.isStatement), + /*location*/ node); } - /** - * Emit trailing comments at the position. The term trailing comment is used here to describe following comment: - * x, /comment1/ y - * ^ => pos; the function will emit "comment1" in the emitJS - */ - function emitTrailingCommentsOfPosition(pos) { - if (compilerOptions.removeComments) { - return; - } - var trailingComments = ts.getTrailingCommentRanges(currentText, pos); - // trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/ - ts.emitComments(currentText, currentLineMap, writer, trailingComments, /*trailingSeparator*/ true, newLine, writeComment); + else { + return ts.visitEachChild(node, visitNestedNode, context); } - function emitLeadingCommentsOfPositionWorker(pos) { - if (compilerOptions.removeComments) { - return; - } - var leadingComments; - if (hasDetachedComments(pos)) { - // get comments without detached comments - leadingComments = getLeadingCommentsWithoutDetachedComments(); - } - else { - // get the leading comments from the node - leadingComments = ts.getLeadingCommentRanges(currentText, pos); - } - ts.emitNewLineBeforeLeadingComments(currentLineMap, writer, { pos: pos, end: pos }, leadingComments); - // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space - ts.emitComments(currentText, currentLineMap, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment); + } + /** + * Transforms and hoists the declaration list of a ForInStatement or ForOfStatement into an expression. + * + * @param node The decalaration list to transform. + */ + function transformForBinding(node) { + var firstDeclaration = ts.firstOrUndefined(node.declarations); + hoistBindingElement(firstDeclaration, /*isExported*/ false); + var name = firstDeclaration.name; + return ts.isIdentifier(name) + ? name + : ts.flattenVariableDestructuringToExpression(context, firstDeclaration, hoistVariableDeclaration); + } + /** + * Visits the body of a ForInStatement to hoist declarations. + * + * @param node The statement to visit. + */ + function visitForInStatement(node) { + var initializer = node.initializer; + if (shouldHoistLoopInitializer(initializer)) { + var updated = ts.getMutableClone(node); + updated.initializer = transformForBinding(initializer); + updated.statement = ts.visitNode(node.statement, visitNestedNode, ts.isStatement, /*optional*/ false, ts.liftToBlock); + return updated; } - function emitDetachedCommentsAndUpdateCommentsInfo(node) { - var currentDetachedCommentInfo = ts.emitDetachedComments(currentText, currentLineMap, writer, writeComment, node, newLine, compilerOptions.removeComments); - if (currentDetachedCommentInfo) { - if (detachedCommentsInfo) { - detachedCommentsInfo.push(currentDetachedCommentInfo); - } - else { - detachedCommentsInfo = [currentDetachedCommentInfo]; - } - } + else { + return ts.visitEachChild(node, visitNestedNode, context); } - function writeComment(text, lineMap, writer, comment, newLine) { - emitPos(comment.pos); - ts.writeCommentRange(text, lineMap, writer, comment, newLine); - emitPos(comment.end); + } + /** + * Visits the body of a ForOfStatement to hoist declarations. + * + * @param node The statement to visit. + */ + function visitForOfStatement(node) { + var initializer = node.initializer; + if (shouldHoistLoopInitializer(initializer)) { + var updated = ts.getMutableClone(node); + updated.initializer = transformForBinding(initializer); + updated.statement = ts.visitNode(node.statement, visitNestedNode, ts.isStatement, /*optional*/ false, ts.liftToBlock); + return updated; } - function emitShebang() { - var shebang = ts.getShebang(currentText); - if (shebang) { - write(shebang); - writeLine(); - } + else { + return ts.visitEachChild(node, visitNestedNode, context); } - var _a, _b; } - function emitFile(_a, sourceFiles, isBundledEmit) { - var jsFilePath = _a.jsFilePath, sourceMapFilePath = _a.sourceMapFilePath, declarationFilePath = _a.declarationFilePath; - // Make sure not to write js File and source map file if any of them cannot be written - if (!host.isEmitBlocked(jsFilePath) && !compilerOptions.noEmit) { - emitJavaScript(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit); + /** + * Visits the body of a DoStatement to hoist declarations. + * + * @param node The statement to visit. + */ + function visitDoStatement(node) { + var statement = ts.visitNode(node.statement, visitNestedNode, ts.isStatement, /*optional*/ false, ts.liftToBlock); + if (statement !== node.statement) { + var updated = ts.getMutableClone(node); + updated.statement = statement; + return updated; } - else { - emitSkipped = true; + return node; + } + /** + * Visits the body of a WhileStatement to hoist declarations. + * + * @param node The statement to visit. + */ + function visitWhileStatement(node) { + var statement = ts.visitNode(node.statement, visitNestedNode, ts.isStatement, /*optional*/ false, ts.liftToBlock); + if (statement !== node.statement) { + var updated = ts.getMutableClone(node); + updated.statement = statement; + return updated; } - if (declarationFilePath) { - emitSkipped = ts.writeDeclarationFile(declarationFilePath, sourceFiles, isBundledEmit, host, resolver, emitterDiagnostics) || emitSkipped; + return node; + } + /** + * Visits the body of a LabeledStatement to hoist declarations. + * + * @param node The statement to visit. + */ + function visitLabeledStatement(node) { + var statement = ts.visitNode(node.statement, visitNestedNode, ts.isStatement, /*optional*/ false, ts.liftToBlock); + if (statement !== node.statement) { + var updated = ts.getMutableClone(node); + updated.statement = statement; + return updated; } - if (!emitSkipped && emittedFilesList) { - emittedFilesList.push(jsFilePath); - if (sourceMapFilePath) { - emittedFilesList.push(sourceMapFilePath); - } - if (declarationFilePath) { - emittedFilesList.push(declarationFilePath); - } + return node; + } + /** + * Visits the body of a WithStatement to hoist declarations. + * + * @param node The statement to visit. + */ + function visitWithStatement(node) { + var statement = ts.visitNode(node.statement, visitNestedNode, ts.isStatement, /*optional*/ false, ts.liftToBlock); + if (statement !== node.statement) { + var updated = ts.getMutableClone(node); + updated.statement = statement; + return updated; } + return node; } - } - ts.emitFiles = emitFiles; -})(ts || (ts = {})); -/// -/// -/// -var ts; -(function (ts) { - /** The version of the TypeScript compiler release */ - ts.version = "2.1.0"; - var emptyArray = []; - function findConfigFile(searchPath, fileExists) { - while (true) { - var fileName = ts.combinePaths(searchPath, "tsconfig.json"); - if (fileExists(fileName)) { - return fileName; + /** + * Visits the body of a SwitchStatement to hoist declarations. + * + * @param node The statement to visit. + */ + function visitSwitchStatement(node) { + var caseBlock = ts.visitNode(node.caseBlock, visitNestedNode, ts.isCaseBlock); + if (caseBlock !== node.caseBlock) { + var updated = ts.getMutableClone(node); + updated.caseBlock = caseBlock; + return updated; } - var parentPath = ts.getDirectoryPath(searchPath); - if (parentPath === searchPath) { - break; + return node; + } + /** + * Visits the body of a CaseBlock to hoist declarations. + * + * @param node The node to visit. + */ + function visitCaseBlock(node) { + var clauses = ts.visitNodes(node.clauses, visitNestedNode, ts.isCaseOrDefaultClause); + if (clauses !== node.clauses) { + var updated = ts.getMutableClone(node); + updated.clauses = clauses; + return updated; } - searchPath = parentPath; + return node; } - return undefined; - } - ts.findConfigFile = findConfigFile; - function resolveTripleslashReference(moduleName, containingFile) { - var basePath = ts.getDirectoryPath(containingFile); - var referencedFileName = ts.isRootedDiskPath(moduleName) ? moduleName : ts.combinePaths(basePath, moduleName); - return ts.normalizePath(referencedFileName); - } - ts.resolveTripleslashReference = resolveTripleslashReference; - /* @internal */ - function computeCommonSourceDirectoryOfFilenames(fileNames, currentDirectory, getCanonicalFileName) { - var commonPathComponents; - var failed = ts.forEach(fileNames, function (sourceFile) { - // Each file contributes into common source file path - var sourcePathComponents = ts.getNormalizedPathComponents(sourceFile, currentDirectory); - sourcePathComponents.pop(); // The base file name is not part of the common directory path - if (!commonPathComponents) { - // first file - commonPathComponents = sourcePathComponents; - return; + /** + * Visits the body of a CaseClause to hoist declarations. + * + * @param node The clause to visit. + */ + function visitCaseClause(node) { + var statements = ts.visitNodes(node.statements, visitNestedNode, ts.isStatement); + if (statements !== node.statements) { + var updated = ts.getMutableClone(node); + updated.statements = statements; + return updated; } - for (var i = 0, n = Math.min(commonPathComponents.length, sourcePathComponents.length); i < n; i++) { - if (getCanonicalFileName(commonPathComponents[i]) !== getCanonicalFileName(sourcePathComponents[i])) { - if (i === 0) { - // Failed to find any common path component - return true; - } - // New common path found that is 0 -> i-1 - commonPathComponents.length = i; - break; - } + return node; + } + /** + * Visits the body of a DefaultClause to hoist declarations. + * + * @param node The clause to visit. + */ + function visitDefaultClause(node) { + return ts.visitEachChild(node, visitNestedNode, context); + } + /** + * Visits the body of a TryStatement to hoist declarations. + * + * @param node The statement to visit. + */ + function visitTryStatement(node) { + return ts.visitEachChild(node, visitNestedNode, context); + } + /** + * Visits the body of a CatchClause to hoist declarations. + * + * @param node The clause to visit. + */ + function visitCatchClause(node) { + var block = ts.visitNode(node.block, visitNestedNode, ts.isBlock); + if (block !== node.block) { + var updated = ts.getMutableClone(node); + updated.block = block; + return updated; } - // If the sourcePathComponents was shorter than the commonPathComponents, truncate to the sourcePathComponents - if (sourcePathComponents.length < commonPathComponents.length) { - commonPathComponents.length = sourcePathComponents.length; + return node; + } + /** + * Visits the body of a Block to hoist declarations. + * + * @param node The block to visit. + */ + function visitBlock(node) { + return ts.visitEachChild(node, visitNestedNode, context); + } + // + // Substitutions + // + function onEmitNode(emitContext, node, emitCallback) { + if (node.kind === 256 /* SourceFile */) { + exportFunctionForFile = exportFunctionForFileMap[ts.getOriginalNodeId(node)]; + previousOnEmitNode(emitContext, node, emitCallback); + exportFunctionForFile = undefined; + } + else { + previousOnEmitNode(emitContext, node, emitCallback); } - }); - // A common path can not be found when paths span multiple drives on windows, for example - if (failed) { - return ""; } - if (!commonPathComponents) { - return currentDirectory; + /** + * Hooks node substitutions. + * + * @param node The node to substitute. + * @param isExpression A value indicating whether the node is to be used in an expression + * position. + */ + function onSubstituteNode(emitContext, node) { + node = previousOnSubstituteNode(emitContext, node); + if (emitContext === 1 /* Expression */) { + return substituteExpression(node); + } + return node; } - return ts.getNormalizedPathFromPathComponents(commonPathComponents); - } - ts.computeCommonSourceDirectoryOfFilenames = computeCommonSourceDirectoryOfFilenames; - function trace(host, message) { - host.trace(ts.formatMessage.apply(undefined, arguments)); - } - function isTraceEnabled(compilerOptions, host) { - return compilerOptions.traceResolution && host.trace !== undefined; - } - /* @internal */ - function hasZeroOrOneAsteriskCharacter(str) { - var seenAsterisk = false; - for (var i = 0; i < str.length; i++) { - if (str.charCodeAt(i) === 42 /* asterisk */) { - if (!seenAsterisk) { - seenAsterisk = true; - } - else { - // have already seen asterisk - return false; + /** + * Substitute the expression, if necessary. + * + * @param node The node to substitute. + */ + function substituteExpression(node) { + switch (node.kind) { + case 69 /* Identifier */: + return substituteExpressionIdentifier(node); + case 187 /* BinaryExpression */: + return substituteBinaryExpression(node); + case 185 /* PrefixUnaryExpression */: + case 186 /* PostfixUnaryExpression */: + return substituteUnaryExpression(node); + } + return node; + } + /** + * Substitution for identifiers exported at the top level of a module. + */ + function substituteExpressionIdentifier(node) { + var importDeclaration = resolver.getReferencedImportDeclaration(node); + if (importDeclaration) { + var importBinding = createImportBinding(importDeclaration); + if (importBinding) { + return importBinding; } } + return node; } - return true; - } - ts.hasZeroOrOneAsteriskCharacter = hasZeroOrOneAsteriskCharacter; - function createResolvedModule(resolvedFileName, isExternalLibraryImport, failedLookupLocations) { - return { resolvedModule: resolvedFileName ? { resolvedFileName: resolvedFileName, isExternalLibraryImport: isExternalLibraryImport } : undefined, failedLookupLocations: failedLookupLocations }; - } - function moduleHasNonRelativeName(moduleName) { - return !(ts.isRootedDiskPath(moduleName) || ts.isExternalModuleNameRelative(moduleName)); - } - function tryReadTypesSection(packageJsonPath, baseDirectory, state) { - var jsonContent = readJson(packageJsonPath, state.host); - function tryReadFromField(fieldName) { - if (ts.hasProperty(jsonContent, fieldName)) { - var typesFile = jsonContent[fieldName]; - if (typeof typesFile === "string") { - var typesFilePath_1 = ts.normalizePath(ts.combinePaths(baseDirectory, typesFile)); - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.package_json_has_0_field_1_that_references_2, fieldName, typesFile, typesFilePath_1); + function substituteBinaryExpression(node) { + if (ts.isAssignmentOperator(node.operatorToken.kind)) { + return substituteAssignmentExpression(node); + } + return node; + } + function substituteAssignmentExpression(node) { + ts.setEmitFlags(node, 128 /* NoSubstitution */); + var left = node.left; + switch (left.kind) { + case 69 /* Identifier */: + var exportDeclaration = resolver.getReferencedExportContainer(left); + if (exportDeclaration) { + return createExportExpression(left, node); } - return typesFilePath_1; - } - else { - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, fieldName, typeof typesFile); + break; + case 171 /* ObjectLiteralExpression */: + case 170 /* ArrayLiteralExpression */: + if (hasExportedReferenceInDestructuringPattern(left)) { + return substituteDestructuring(node); } - } + break; } + return node; } - var typesFilePath = tryReadFromField("typings") || tryReadFromField("types"); - if (typesFilePath) { - return typesFilePath; + function isExportedBinding(name) { + var container = resolver.getReferencedExportContainer(name); + return container && container.kind === 256 /* SourceFile */; } - // Use the main module for inferring types if no types package specified and the allowJs is set - if (state.compilerOptions.allowJs && jsonContent.main && typeof jsonContent.main === "string") { - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.No_types_specified_in_package_json_but_allowJs_is_set_so_returning_main_value_of_0, jsonContent.main); + function hasExportedReferenceInDestructuringPattern(node) { + switch (node.kind) { + case 69 /* Identifier */: + return isExportedBinding(node); + case 171 /* ObjectLiteralExpression */: + for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { + var property = _a[_i]; + if (hasExportedReferenceInObjectDestructuringElement(property)) { + return true; + } + } + break; + case 170 /* ArrayLiteralExpression */: + for (var _b = 0, _c = node.elements; _b < _c.length; _b++) { + var element = _c[_b]; + if (hasExportedReferenceInArrayDestructuringElement(element)) { + return true; + } + } + break; } - var mainFilePath = ts.normalizePath(ts.combinePaths(baseDirectory, jsonContent.main)); - return mainFilePath; + return false; } - return undefined; - } - function readJson(path, host) { - try { - var jsonText = host.readFile(path); - return jsonText ? JSON.parse(jsonText) : {}; + function hasExportedReferenceInObjectDestructuringElement(node) { + if (ts.isShorthandPropertyAssignment(node)) { + return isExportedBinding(node.name); + } + else if (ts.isPropertyAssignment(node)) { + return hasExportedReferenceInDestructuringElement(node.initializer); + } + else { + return false; + } } - catch (e) { - // gracefully handle if readFile fails or returns not JSON - return {}; + function hasExportedReferenceInArrayDestructuringElement(node) { + if (ts.isSpreadElementExpression(node)) { + var expression = node.expression; + return ts.isIdentifier(expression) && isExportedBinding(expression); + } + else { + return hasExportedReferenceInDestructuringElement(node); + } } - } - var typeReferenceExtensions = [".d.ts"]; - function getEffectiveTypeRoots(options, host) { - if (options.typeRoots) { - return options.typeRoots; + function hasExportedReferenceInDestructuringElement(node) { + if (ts.isBinaryExpression(node)) { + var left = node.left; + return node.operatorToken.kind === 56 /* EqualsToken */ + && isDestructuringPattern(left) + && hasExportedReferenceInDestructuringPattern(left); + } + else if (ts.isIdentifier(node)) { + return isExportedBinding(node); + } + else if (ts.isSpreadElementExpression(node)) { + var expression = node.expression; + return ts.isIdentifier(expression) && isExportedBinding(expression); + } + else if (isDestructuringPattern(node)) { + return hasExportedReferenceInDestructuringPattern(node); + } + else { + return false; + } } - var currentDirectory; - if (options.configFilePath) { - currentDirectory = ts.getDirectoryPath(options.configFilePath); + function isDestructuringPattern(node) { + var kind = node.kind; + return kind === 69 /* Identifier */ + || kind === 171 /* ObjectLiteralExpression */ + || kind === 170 /* ArrayLiteralExpression */; + } + function substituteDestructuring(node) { + return ts.flattenDestructuringAssignment(context, node, /*needsValue*/ true, hoistVariableDeclaration); + } + function substituteUnaryExpression(node) { + var operand = node.operand; + var operator = node.operator; + var substitute = ts.isIdentifier(operand) && + (node.kind === 186 /* PostfixUnaryExpression */ || + (node.kind === 185 /* PrefixUnaryExpression */ && (operator === 41 /* PlusPlusToken */ || operator === 42 /* MinusMinusToken */))); + if (substitute) { + var exportDeclaration = resolver.getReferencedExportContainer(operand); + if (exportDeclaration) { + var expr = ts.createPrefix(node.operator, operand, node); + ts.setEmitFlags(expr, 128 /* NoSubstitution */); + var call = createExportExpression(operand, expr); + if (node.kind === 185 /* PrefixUnaryExpression */) { + return call; + } + else { + // export function returns the value that was passes as the second argument + // however for postfix unary expressions result value should be the value before modification. + // emit 'x++' as '(export('x', ++x) - 1)' and 'x--' as '(export('x', --x) + 1)' + return operator === 41 /* PlusPlusToken */ + ? ts.createSubtract(call, ts.createLiteral(1)) + : ts.createAdd(call, ts.createLiteral(1)); + } + } + } + return node; } - else if (host.getCurrentDirectory) { - currentDirectory = host.getCurrentDirectory(); + /** + * Gets a name to use for a DeclarationStatement. + * @param node The declaration statement. + */ + function getDeclarationName(node) { + return node.name ? ts.getSynthesizedClone(node.name) : ts.getGeneratedNameForNode(node); + } + function addExportStarFunction(statements, localNames) { + var exportStarFunction = ts.createUniqueName("exportStar"); + var m = ts.createIdentifier("m"); + var n = ts.createIdentifier("n"); + var exports = ts.createIdentifier("exports"); + var condition = ts.createStrictInequality(n, ts.createLiteral("default")); + if (localNames) { + condition = ts.createLogicalAnd(condition, ts.createLogicalNot(ts.createHasOwnProperty(localNames, n))); + } + statements.push(ts.createFunctionDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, exportStarFunction, + /*typeParameters*/ undefined, [ts.createParameter(m)], + /*type*/ undefined, ts.createBlock([ + ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(exports, + /*type*/ undefined, ts.createObjectLiteral([])) + ])), + ts.createForIn(ts.createVariableDeclarationList([ + ts.createVariableDeclaration(n, /*type*/ undefined) + ]), m, ts.createBlock([ + ts.setEmitFlags(ts.createIf(condition, ts.createStatement(ts.createAssignment(ts.createElementAccess(exports, n), ts.createElementAccess(m, n)))), 32 /* SingleLine */) + ])), + ts.createStatement(ts.createCall(exportFunctionForFile, + /*typeArguments*/ undefined, [exports])) + ], + /*location*/ undefined, + /*multiline*/ true))); + return exportStarFunction; } - return currentDirectory && getDefaultTypeRoots(currentDirectory, host); - } - /** - * Returns the path to every node_modules/@types directory from some ancestor directory. - * Returns undefined if there are none. - */ - function getDefaultTypeRoots(currentDirectory, host) { - if (!host.directoryExists) { - return [ts.combinePaths(currentDirectory, "node_modules")]; + /** + * Creates a call to the current file's export function to export a value. + * @param name The bound name of the export. + * @param value The exported value. + */ + function createExportExpression(name, value) { + var exportName = ts.isIdentifier(name) ? ts.createLiteral(name.text) : name; + return ts.createCall(exportFunctionForFile, /*typeArguments*/ undefined, [exportName, value]); } - var typeRoots; - while (true) { - var atTypes = ts.combinePaths(currentDirectory, nodeModulesAtTypes); - if (host.directoryExists(atTypes)) { - (typeRoots || (typeRoots = [])).push(atTypes); + /** + * Creates a call to the current file's export function to export a value. + * @param name The bound name of the export. + * @param value The exported value. + */ + function createExportStatement(name, value) { + return ts.createStatement(createExportExpression(name, value)); + } + /** + * Creates a call to the current file's export function to export a declaration. + * @param node The declaration to export. + */ + function createDeclarationExport(node) { + var declarationName = getDeclarationName(node); + var exportName = ts.hasModifier(node, 512 /* Default */) ? ts.createLiteral("default") : declarationName; + return createExportStatement(exportName, declarationName); + } + function createImportBinding(importDeclaration) { + var importAlias; + var name; + if (ts.isImportClause(importDeclaration)) { + importAlias = ts.getGeneratedNameForNode(importDeclaration.parent); + name = ts.createIdentifier("default"); + } + else if (ts.isImportSpecifier(importDeclaration)) { + importAlias = ts.getGeneratedNameForNode(importDeclaration.parent.parent.parent); + name = importDeclaration.propertyName || importDeclaration.name; } - var parent_15 = ts.getDirectoryPath(currentDirectory); - if (parent_15 === currentDirectory) { - break; + else { + return undefined; } - currentDirectory = parent_15; - } - return typeRoots; - } - var nodeModulesAtTypes = ts.combinePaths("node_modules", "@types"); - /** - * @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. - * This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups - * is assumed to be the same as root directory of the project. - */ - function resolveTypeReferenceDirective(typeReferenceDirectiveName, containingFile, options, host) { - var traceEnabled = isTraceEnabled(options, host); - var moduleResolutionState = { - compilerOptions: options, - host: host, - skipTsx: true, - traceEnabled: traceEnabled - }; - var typeRoots = getEffectiveTypeRoots(options, host); - if (traceEnabled) { - if (containingFile === undefined) { - if (typeRoots === undefined) { - trace(host, ts.Diagnostics.Resolving_type_reference_directive_0_containing_file_not_set_root_directory_not_set, typeReferenceDirectiveName); - } - else { - trace(host, ts.Diagnostics.Resolving_type_reference_directive_0_containing_file_not_set_root_directory_1, typeReferenceDirectiveName, typeRoots); - } + if (name.originalKeywordKind && languageVersion === 0 /* ES3 */) { + return ts.createElementAccess(importAlias, ts.createLiteral(name.text)); } else { - if (typeRoots === undefined) { - trace(host, ts.Diagnostics.Resolving_type_reference_directive_0_containing_file_1_root_directory_not_set, typeReferenceDirectiveName, containingFile); + return ts.createPropertyAccess(importAlias, ts.getSynthesizedClone(name)); + } + } + function collectDependencyGroups(externalImports) { + var groupIndices = ts.createMap(); + var dependencyGroups = []; + for (var i = 0; i < externalImports.length; i++) { + var externalImport = externalImports[i]; + var externalModuleName = ts.getExternalModuleNameLiteral(externalImport, currentSourceFile, host, resolver, compilerOptions); + var text = externalModuleName.text; + if (ts.hasProperty(groupIndices, text)) { + // deduplicate/group entries in dependency list by the dependency name + var groupIndex = groupIndices[text]; + dependencyGroups[groupIndex].externalImports.push(externalImport); + continue; } else { - trace(host, ts.Diagnostics.Resolving_type_reference_directive_0_containing_file_1_root_directory_2, typeReferenceDirectiveName, containingFile, typeRoots); + groupIndices[text] = dependencyGroups.length; + dependencyGroups.push({ + name: externalModuleName, + externalImports: [externalImport] + }); } } + return dependencyGroups; } - var failedLookupLocations = []; - // Check primary library paths - if (typeRoots && typeRoots.length) { - if (traceEnabled) { - trace(host, ts.Diagnostics.Resolving_with_primary_search_path_0, typeRoots.join(", ")); + function getNameOfDependencyGroup(dependencyGroup) { + return dependencyGroup.name; + } + function recordExportName(name) { + if (!exportedLocalNames) { + exportedLocalNames = []; } - var primarySearchPaths = typeRoots; - for (var _i = 0, primarySearchPaths_1 = primarySearchPaths; _i < primarySearchPaths_1.length; _i++) { - var typeRoot = primarySearchPaths_1[_i]; - var candidate = ts.combinePaths(typeRoot, typeReferenceDirectiveName); - var candidateDirectory = ts.getDirectoryPath(candidate); - var resolvedFile_1 = loadNodeModuleFromDirectory(typeReferenceExtensions, candidate, failedLookupLocations, !directoryProbablyExists(candidateDirectory, host), moduleResolutionState); - if (resolvedFile_1) { - if (traceEnabled) { - trace(host, ts.Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, resolvedFile_1, true); - } - return { - resolvedTypeReferenceDirective: { primary: true, resolvedFileName: resolvedFile_1 }, - failedLookupLocations: failedLookupLocations - }; - } + exportedLocalNames.push(name); + } + function recordExportedFunctionDeclaration(node) { + if (!exportedFunctionDeclarations) { + exportedFunctionDeclarations = []; } + exportedFunctionDeclarations.push(createDeclarationExport(node)); } - else { - if (traceEnabled) { - trace(host, ts.Diagnostics.Root_directory_cannot_be_determined_skipping_primary_search_paths); + function hoistBindingElement(node, isExported) { + if (ts.isOmittedExpression(node)) { + return; + } + var name = node.name; + if (ts.isIdentifier(name)) { + hoistVariableDeclaration(ts.getSynthesizedClone(name)); + if (isExported) { + recordExportName(name); + } + } + else if (ts.isBindingPattern(name)) { + ts.forEach(name.elements, isExported ? hoistExportedBindingElement : hoistNonExportedBindingElement); } } - var resolvedFile; - var initialLocationForSecondaryLookup; - if (containingFile) { - initialLocationForSecondaryLookup = ts.getDirectoryPath(containingFile); + function hoistExportedBindingElement(node) { + hoistBindingElement(node, /*isExported*/ true); } - if (initialLocationForSecondaryLookup !== undefined) { - // check secondary locations - if (traceEnabled) { - trace(host, ts.Diagnostics.Looking_up_in_node_modules_folder_initial_location_0, initialLocationForSecondaryLookup); + function hoistNonExportedBindingElement(node) { + hoistBindingElement(node, /*isExported*/ false); + } + function updateSourceFile(node, statements, nodeEmitFlags) { + var updated = ts.getMutableClone(node); + updated.statements = ts.createNodeArray(statements, node.statements); + ts.setEmitFlags(updated, nodeEmitFlags); + return updated; + } + } + ts.transformSystemModule = transformSystemModule; +})(ts || (ts = {})); +/// +/// +/*@internal*/ +var ts; +(function (ts) { + function transformES6Module(context) { + var compilerOptions = context.getCompilerOptions(); + var resolver = context.getEmitResolver(); + var currentSourceFile; + return transformSourceFile; + function transformSourceFile(node) { + if (ts.isDeclarationFile(node)) { + return node; } - resolvedFile = loadModuleFromNodeModules(typeReferenceDirectiveName, initialLocationForSecondaryLookup, failedLookupLocations, moduleResolutionState); - if (traceEnabled) { - if (resolvedFile) { - trace(host, ts.Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, resolvedFile, false); - } - else { - trace(host, ts.Diagnostics.Type_reference_directive_0_was_not_resolved, typeReferenceDirectiveName); - } + if (ts.isExternalModule(node) || compilerOptions.isolatedModules) { + currentSourceFile = node; + return ts.visitEachChild(node, visitor, context); } + return node; } - else { - if (traceEnabled) { - trace(host, ts.Diagnostics.Containing_file_is_not_specified_and_root_directory_cannot_be_determined_skipping_lookup_in_node_modules_folder); + function visitor(node) { + switch (node.kind) { + case 230 /* ImportDeclaration */: + return visitImportDeclaration(node); + case 229 /* ImportEqualsDeclaration */: + return visitImportEqualsDeclaration(node); + case 231 /* ImportClause */: + return visitImportClause(node); + case 233 /* NamedImports */: + case 232 /* NamespaceImport */: + return visitNamedBindings(node); + case 234 /* ImportSpecifier */: + return visitImportSpecifier(node); + case 235 /* ExportAssignment */: + return visitExportAssignment(node); + case 236 /* ExportDeclaration */: + return visitExportDeclaration(node); + case 237 /* NamedExports */: + return visitNamedExports(node); + case 238 /* ExportSpecifier */: + return visitExportSpecifier(node); } + return node; } - return { - resolvedTypeReferenceDirective: resolvedFile - ? { primary: false, resolvedFileName: resolvedFile } - : undefined, - failedLookupLocations: failedLookupLocations - }; - } - ts.resolveTypeReferenceDirective = resolveTypeReferenceDirective; - function resolveModuleName(moduleName, containingFile, compilerOptions, host) { - var traceEnabled = isTraceEnabled(compilerOptions, host); - if (traceEnabled) { - trace(host, ts.Diagnostics.Resolving_module_0_from_1, moduleName, containingFile); + function visitExportAssignment(node) { + if (node.isExportEquals) { + return undefined; // do not emit export equals for ES6 + } + var original = ts.getOriginalNode(node); + return ts.nodeIsSynthesized(original) || resolver.isValueAliasDeclaration(original) ? node : undefined; } - var moduleResolution = compilerOptions.moduleResolution; - if (moduleResolution === undefined) { - moduleResolution = ts.getEmitModuleKind(compilerOptions) === ts.ModuleKind.CommonJS ? ts.ModuleResolutionKind.NodeJs : ts.ModuleResolutionKind.Classic; - if (traceEnabled) { - trace(host, ts.Diagnostics.Module_resolution_kind_is_not_specified_using_0, ts.ModuleResolutionKind[moduleResolution]); + function visitExportDeclaration(node) { + if (!node.exportClause) { + return resolver.moduleExportsSomeValue(node.moduleSpecifier) ? node : undefined; + } + if (!resolver.isValueAliasDeclaration(node)) { + return undefined; + } + var newExportClause = ts.visitNode(node.exportClause, visitor, ts.isNamedExports, /*optional*/ true); + if (node.exportClause === newExportClause) { + return node; } + return newExportClause + ? ts.createExportDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, newExportClause, node.moduleSpecifier) + : undefined; } - else { - if (traceEnabled) { - trace(host, ts.Diagnostics.Explicitly_specified_module_resolution_kind_Colon_0, ts.ModuleResolutionKind[moduleResolution]); + function visitNamedExports(node) { + var newExports = ts.visitNodes(node.elements, visitor, ts.isExportSpecifier); + if (node.elements === newExports) { + return node; } + return newExports.length ? ts.createNamedExports(newExports) : undefined; } - var result; - switch (moduleResolution) { - case ts.ModuleResolutionKind.NodeJs: - result = nodeModuleNameResolver(moduleName, containingFile, compilerOptions, host); - break; - case ts.ModuleResolutionKind.Classic: - result = classicNameResolver(moduleName, containingFile, compilerOptions, host); - break; + function visitExportSpecifier(node) { + return resolver.isValueAliasDeclaration(node) ? node : undefined; } - if (traceEnabled) { - if (result.resolvedModule) { - trace(host, ts.Diagnostics.Module_name_0_was_successfully_resolved_to_1, moduleName, result.resolvedModule.resolvedFileName); + function visitImportEqualsDeclaration(node) { + return !ts.isExternalModuleImportEqualsDeclaration(node) || resolver.isReferencedAliasDeclaration(node) ? node : undefined; + } + function visitImportDeclaration(node) { + if (node.importClause) { + var newImportClause = ts.visitNode(node.importClause, visitor, ts.isImportClause); + if (!newImportClause.name && !newImportClause.namedBindings) { + return undefined; + } + else if (newImportClause !== node.importClause) { + return ts.createImportDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, newImportClause, node.moduleSpecifier); + } + } + return node; + } + function visitImportClause(node) { + var newDefaultImport = node.name; + if (!resolver.isReferencedAliasDeclaration(node)) { + newDefaultImport = undefined; + } + var newNamedBindings = ts.visitNode(node.namedBindings, visitor, ts.isNamedImportBindings, /*optional*/ true); + return newDefaultImport !== node.name || newNamedBindings !== node.namedBindings + ? ts.createImportClause(newDefaultImport, newNamedBindings) + : node; + } + function visitNamedBindings(node) { + if (node.kind === 232 /* NamespaceImport */) { + return resolver.isReferencedAliasDeclaration(node) ? node : undefined; } else { - trace(host, ts.Diagnostics.Module_name_0_was_not_resolved, moduleName); + var newNamedImportElements = ts.visitNodes(node.elements, visitor, ts.isImportSpecifier); + if (!newNamedImportElements || newNamedImportElements.length == 0) { + return undefined; + } + if (newNamedImportElements === node.elements) { + return node; + } + return ts.createNamedImports(newNamedImportElements); } } - return result; + function visitImportSpecifier(node) { + return resolver.isReferencedAliasDeclaration(node) ? node : undefined; + } } - ts.resolveModuleName = resolveModuleName; + ts.transformES6Module = transformES6Module; +})(ts || (ts = {})); +/// +/// +/// +/// +/// +/// +/// +/// +/// +/* @internal */ +var ts; +(function (ts) { + var moduleTransformerMap = ts.createMap((_a = {}, + _a[ts.ModuleKind.ES6] = ts.transformES6Module, + _a[ts.ModuleKind.System] = ts.transformSystemModule, + _a[ts.ModuleKind.AMD] = ts.transformModule, + _a[ts.ModuleKind.CommonJS] = ts.transformModule, + _a[ts.ModuleKind.UMD] = ts.transformModule, + _a[ts.ModuleKind.None] = ts.transformModule, + _a)); + var SyntaxKindFeatureFlags; + (function (SyntaxKindFeatureFlags) { + SyntaxKindFeatureFlags[SyntaxKindFeatureFlags["Substitution"] = 1] = "Substitution"; + SyntaxKindFeatureFlags[SyntaxKindFeatureFlags["EmitNotifications"] = 2] = "EmitNotifications"; + })(SyntaxKindFeatureFlags || (SyntaxKindFeatureFlags = {})); + function getTransformers(compilerOptions) { + var jsx = compilerOptions.jsx; + var languageVersion = ts.getEmitScriptTarget(compilerOptions); + var moduleKind = ts.getEmitModuleKind(compilerOptions); + var transformers = []; + transformers.push(ts.transformTypeScript); + transformers.push(moduleTransformerMap[moduleKind] || moduleTransformerMap[ts.ModuleKind.None]); + if (jsx === 2 /* React */) { + transformers.push(ts.transformJsx); + } + transformers.push(ts.transformES7); + if (languageVersion < 2 /* ES6 */) { + transformers.push(ts.transformES6); + transformers.push(ts.transformGenerators); + } + return transformers; + } + ts.getTransformers = getTransformers; /** - * Any module resolution kind can be augmented with optional settings: 'baseUrl', 'paths' and 'rootDirs' - they are used to - * mitigate differences between design time structure of the project and its runtime counterpart so the same import name - * can be resolved successfully by TypeScript compiler and runtime module loader. - * If these settings are set then loading procedure will try to use them to resolve module name and it can of failure it will - * fallback to standard resolution routine. - * - * - baseUrl - this setting controls how non-relative module names are resolved. If this setting is specified then non-relative - * names will be resolved relative to baseUrl: i.e. if baseUrl is '/a/b' then candidate location to resolve module name 'c/d' will - * be '/a/b/c/d' - * - paths - this setting can only be used when baseUrl is specified. allows to tune how non-relative module names - * will be resolved based on the content of the module name. - * Structure of 'paths' compiler options - * 'paths': { - * pattern-1: [...substitutions], - * pattern-2: [...substitutions], - * ... - * pattern-n: [...substitutions] - * } - * Pattern here is a string that can contain zero or one '*' character. During module resolution module name will be matched against - * all patterns in the list. Matching for patterns that don't contain '*' means that module name must be equal to pattern respecting the case. - * If pattern contains '*' then to match pattern "*" module name must start with the and end with . - * denotes part of the module name between and . - * If module name can be matches with multiple patterns then pattern with the longest prefix will be picked. - * After selecting pattern we'll use list of substitutions to get candidate locations of the module and the try to load module - * from the candidate location. - * Substitution is a string that can contain zero or one '*'. To get candidate location from substitution we'll pick every - * substitution in the list and replace '*' with string. If candidate location is not rooted it - * will be converted to absolute using baseUrl. - * For example: - * baseUrl: /a/b/c - * "paths": { - * // match all module names - * "*": [ - * "*", // use matched name as is, - * // will be looked as /a/b/c/ - * - * "folder1/*" // substitution will convert matched name to 'folder1/', - * // since it is not rooted then final candidate location will be /a/b/c/folder1/ - * ], - * // match module names that start with 'components/' - * "components/*": [ "/root/components/*" ] // substitution will convert /components/folder1/ to '/root/components/folder1/', - * // it is rooted so it will be final candidate location - * } + * Transforms an array of SourceFiles by passing them through each transformer. * - * 'rootDirs' allows the project to be spreaded across multiple locations and resolve modules with relative names as if - * they were in the same location. For example lets say there are two files - * '/local/src/content/file1.ts' - * '/shared/components/contracts/src/content/protocols/file2.ts' - * After bundling content of '/shared/components/contracts/src' will be merged with '/local/src' so - * if file1 has the following import 'import {x} from "./protocols/file2"' it will be resolved successfully in runtime. - * 'rootDirs' provides the way to tell compiler that in order to get the whole project it should behave as if content of all - * root dirs were merged together. - * I.e. for the example above 'rootDirs' will have two entries: [ '/local/src', '/shared/components/contracts/src' ]. - * Compiler will first convert './protocols/file2' into absolute path relative to the location of containing file: - * '/local/src/content/protocols/file2' and try to load it - failure. - * Then it will search 'rootDirs' looking for a longest matching prefix of this absolute path and if such prefix is found - absolute path will - * be converted to a path relative to found rootDir entry './content/protocols/file2' (*). As a last step compiler will check all remaining - * entries in 'rootDirs', use them to build absolute path out of (*) and try to resolve module from this location. + * @param resolver The emit resolver provided by the checker. + * @param host The emit host. + * @param sourceFiles An array of source files + * @param transforms An array of Transformers. */ - function tryLoadModuleUsingOptionalResolutionSettings(moduleName, containingDirectory, loader, failedLookupLocations, supportedExtensions, state) { - if (moduleHasNonRelativeName(moduleName)) { - return tryLoadModuleUsingBaseUrl(moduleName, loader, failedLookupLocations, supportedExtensions, state); + function transformFiles(resolver, host, sourceFiles, transformers) { + var lexicalEnvironmentVariableDeclarationsStack = []; + var lexicalEnvironmentFunctionDeclarationsStack = []; + var enabledSyntaxKindFeatures = new Array(289 /* Count */); + var lexicalEnvironmentStackOffset = 0; + var hoistedVariableDeclarations; + var hoistedFunctionDeclarations; + var lexicalEnvironmentDisabled; + // The transformation context is provided to each transformer as part of transformer + // initialization. + var context = { + getCompilerOptions: function () { return host.getCompilerOptions(); }, + getEmitResolver: function () { return resolver; }, + getEmitHost: function () { return host; }, + hoistVariableDeclaration: hoistVariableDeclaration, + hoistFunctionDeclaration: hoistFunctionDeclaration, + startLexicalEnvironment: startLexicalEnvironment, + endLexicalEnvironment: endLexicalEnvironment, + onSubstituteNode: function (emitContext, node) { return node; }, + enableSubstitution: enableSubstitution, + isSubstitutionEnabled: isSubstitutionEnabled, + onEmitNode: function (node, emitContext, emitCallback) { return emitCallback(node, emitContext); }, + enableEmitNotification: enableEmitNotification, + isEmitNotificationEnabled: isEmitNotificationEnabled + }; + // Chain together and initialize each transformer. + var transformation = ts.chain.apply(void 0, transformers)(context); + // Transform each source file. + var transformed = ts.map(sourceFiles, transformSourceFile); + // Disable modification of the lexical environment. + lexicalEnvironmentDisabled = true; + return { + transformed: transformed, + emitNodeWithSubstitution: emitNodeWithSubstitution, + emitNodeWithNotification: emitNodeWithNotification + }; + /** + * Transforms a source file. + * + * @param sourceFile The source file to transform. + */ + function transformSourceFile(sourceFile) { + if (ts.isDeclarationFile(sourceFile)) { + return sourceFile; + } + return transformation(sourceFile); } - else { - return tryLoadModuleUsingRootDirs(moduleName, containingDirectory, loader, failedLookupLocations, supportedExtensions, state); + /** + * Enables expression substitutions in the pretty printer for the provided SyntaxKind. + */ + function enableSubstitution(kind) { + enabledSyntaxKindFeatures[kind] |= 1 /* Substitution */; } - } - function tryLoadModuleUsingRootDirs(moduleName, containingDirectory, loader, failedLookupLocations, supportedExtensions, state) { - if (!state.compilerOptions.rootDirs) { - return undefined; + /** + * Determines whether expression substitutions are enabled for the provided node. + */ + function isSubstitutionEnabled(node) { + return (enabledSyntaxKindFeatures[node.kind] & 1 /* Substitution */) !== 0 + && (ts.getEmitFlags(node) & 128 /* NoSubstitution */) === 0; } - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.rootDirs_option_is_set_using_it_to_resolve_relative_module_name_0, moduleName); + /** + * Emits a node with possible substitution. + * + * @param emitContext The current emit context. + * @param node The node to emit. + * @param emitCallback The callback used to emit the node or its substitute. + */ + function emitNodeWithSubstitution(emitContext, node, emitCallback) { + if (node) { + if (isSubstitutionEnabled(node)) { + var substitute = context.onSubstituteNode(emitContext, node); + if (substitute && substitute !== node) { + emitCallback(emitContext, substitute); + return; + } + } + emitCallback(emitContext, node); + } } - var candidate = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName)); - var matchedRootDir; - var matchedNormalizedPrefix; - for (var _i = 0, _a = state.compilerOptions.rootDirs; _i < _a.length; _i++) { - var rootDir = _a[_i]; - // rootDirs are expected to be absolute - // in case of tsconfig.json this will happen automatically - compiler will expand relative names - // using location of tsconfig.json as base location - var normalizedRoot = ts.normalizePath(rootDir); - if (!ts.endsWith(normalizedRoot, ts.directorySeparator)) { - normalizedRoot += ts.directorySeparator; + /** + * Enables before/after emit notifications in the pretty printer for the provided SyntaxKind. + */ + function enableEmitNotification(kind) { + enabledSyntaxKindFeatures[kind] |= 2 /* EmitNotifications */; + } + /** + * Determines whether before/after emit notifications should be raised in the pretty + * printer when it emits a node. + */ + function isEmitNotificationEnabled(node) { + return (enabledSyntaxKindFeatures[node.kind] & 2 /* EmitNotifications */) !== 0 + || (ts.getEmitFlags(node) & 64 /* AdviseOnEmitNode */) !== 0; + } + /** + * Emits a node with possible emit notification. + * + * @param emitContext The current emit context. + * @param node The node to emit. + * @param emitCallback The callback used to emit the node. + */ + function emitNodeWithNotification(emitContext, node, emitCallback) { + if (node) { + if (isEmitNotificationEnabled(node)) { + context.onEmitNode(emitContext, node, emitCallback); + } + else { + emitCallback(emitContext, node); + } } - var isLongestMatchingPrefix = ts.startsWith(candidate, normalizedRoot) && - (matchedNormalizedPrefix === undefined || matchedNormalizedPrefix.length < normalizedRoot.length); - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Checking_if_0_is_the_longest_matching_prefix_for_1_2, normalizedRoot, candidate, isLongestMatchingPrefix); + } + /** + * Records a hoisted variable declaration for the provided name within a lexical environment. + */ + function hoistVariableDeclaration(name) { + ts.Debug.assert(!lexicalEnvironmentDisabled, "Cannot modify the lexical environment during the print phase."); + var decl = ts.createVariableDeclaration(name); + if (!hoistedVariableDeclarations) { + hoistedVariableDeclarations = [decl]; } - if (isLongestMatchingPrefix) { - matchedNormalizedPrefix = normalizedRoot; - matchedRootDir = rootDir; + else { + hoistedVariableDeclarations.push(decl); } } - if (matchedNormalizedPrefix) { - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Longest_matching_prefix_for_0_is_1, candidate, matchedNormalizedPrefix); + /** + * Records a hoisted function declaration within a lexical environment. + */ + function hoistFunctionDeclaration(func) { + ts.Debug.assert(!lexicalEnvironmentDisabled, "Cannot modify the lexical environment during the print phase."); + if (!hoistedFunctionDeclarations) { + hoistedFunctionDeclarations = [func]; } - var suffix = candidate.substr(matchedNormalizedPrefix.length); - // first - try to load from a initial location - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Loading_0_from_the_root_dir_1_candidate_location_2, suffix, matchedNormalizedPrefix, candidate); + else { + hoistedFunctionDeclarations.push(func); } - var resolvedFileName = loader(candidate, supportedExtensions, failedLookupLocations, !directoryProbablyExists(containingDirectory, state.host), state); - if (resolvedFileName) { - return resolvedFileName; + } + /** + * Starts a new lexical environment. Any existing hoisted variable or function declarations + * are pushed onto a stack, and the related storage variables are reset. + */ + function startLexicalEnvironment() { + ts.Debug.assert(!lexicalEnvironmentDisabled, "Cannot start a lexical environment during the print phase."); + // Save the current lexical environment. Rather than resizing the array we adjust the + // stack size variable. This allows us to reuse existing array slots we've + // already allocated between transformations to avoid allocation and GC overhead during + // transformation. + lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset] = hoistedVariableDeclarations; + lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset] = hoistedFunctionDeclarations; + lexicalEnvironmentStackOffset++; + hoistedVariableDeclarations = undefined; + hoistedFunctionDeclarations = undefined; + } + /** + * Ends a lexical environment. The previous set of hoisted declarations are restored and + * any hoisted declarations added in this environment are returned. + */ + function endLexicalEnvironment() { + ts.Debug.assert(!lexicalEnvironmentDisabled, "Cannot end a lexical environment during the print phase."); + var statements; + if (hoistedVariableDeclarations || hoistedFunctionDeclarations) { + if (hoistedFunctionDeclarations) { + statements = hoistedFunctionDeclarations.slice(); + } + if (hoistedVariableDeclarations) { + var statement = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList(hoistedVariableDeclarations)); + if (!statements) { + statements = [statement]; + } + else { + statements.push(statement); + } + } } - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Trying_other_entries_in_rootDirs); + // Restore the previous lexical environment. + lexicalEnvironmentStackOffset--; + hoistedVariableDeclarations = lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset]; + hoistedFunctionDeclarations = lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset]; + return statements; + } + } + ts.transformFiles = transformFiles; + var _a; +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + // Used for initialize lastEncodedSourceMapSpan and reset lastEncodedSourceMapSpan when updateLastEncodedAndRecordedSpans + var defaultLastEncodedSourceMapSpan = { + emittedLine: 1, + emittedColumn: 1, + sourceLine: 1, + sourceColumn: 1, + sourceIndex: 0 + }; + function createSourceMapWriter(host, writer) { + var compilerOptions = host.getCompilerOptions(); + var extendedDiagnostics = compilerOptions.extendedDiagnostics; + var currentSourceFile; + var currentSourceText; + var sourceMapDir; // The directory in which sourcemap will be + // Current source map file and its index in the sources list + var sourceMapSourceIndex; + // Last recorded and encoded spans + var lastRecordedSourceMapSpan; + var lastEncodedSourceMapSpan; + var lastEncodedNameIndex; + // Source map data + var sourceMapData; + var disabled = !(compilerOptions.sourceMap || compilerOptions.inlineSourceMap); + return { + initialize: initialize, + reset: reset, + getSourceMapData: function () { return sourceMapData; }, + setSourceFile: setSourceFile, + emitPos: emitPos, + emitNodeWithSourceMap: emitNodeWithSourceMap, + emitTokenWithSourceMap: emitTokenWithSourceMap, + getText: getText, + getSourceMappingURL: getSourceMappingURL, + }; + /** + * Initialize the SourceMapWriter for a new output file. + * + * @param filePath The path to the generated output file. + * @param sourceMapFilePath The path to the output source map file. + * @param sourceFiles The input source files for the program. + * @param isBundledEmit A value indicating whether the generated output file is a bundle. + */ + function initialize(filePath, sourceMapFilePath, sourceFiles, isBundledEmit) { + if (disabled) { + return; + } + if (sourceMapData) { + reset(); + } + currentSourceFile = undefined; + currentSourceText = undefined; + // Current source map file and its index in the sources list + sourceMapSourceIndex = -1; + // Last recorded and encoded spans + lastRecordedSourceMapSpan = undefined; + lastEncodedSourceMapSpan = defaultLastEncodedSourceMapSpan; + lastEncodedNameIndex = 0; + // Initialize source map data + sourceMapData = { + sourceMapFilePath: sourceMapFilePath, + jsSourceMappingURL: !compilerOptions.inlineSourceMap ? ts.getBaseFileName(ts.normalizeSlashes(sourceMapFilePath)) : undefined, + sourceMapFile: ts.getBaseFileName(ts.normalizeSlashes(filePath)), + sourceMapSourceRoot: compilerOptions.sourceRoot || "", + sourceMapSources: [], + inputSourceFileNames: [], + sourceMapNames: [], + sourceMapMappings: "", + sourceMapSourcesContent: compilerOptions.inlineSources ? [] : undefined, + sourceMapDecodedMappings: [] + }; + // Normalize source root and make sure it has trailing "/" so that it can be used to combine paths with the + // relative paths of the sources list in the sourcemap + sourceMapData.sourceMapSourceRoot = ts.normalizeSlashes(sourceMapData.sourceMapSourceRoot); + if (sourceMapData.sourceMapSourceRoot.length && sourceMapData.sourceMapSourceRoot.charCodeAt(sourceMapData.sourceMapSourceRoot.length - 1) !== 47 /* slash */) { + sourceMapData.sourceMapSourceRoot += ts.directorySeparator; } - // then try to resolve using remaining entries in rootDirs - for (var _b = 0, _c = state.compilerOptions.rootDirs; _b < _c.length; _b++) { - var rootDir = _c[_b]; - if (rootDir === matchedRootDir) { - // skip the initially matched entry - continue; + if (compilerOptions.mapRoot) { + sourceMapDir = ts.normalizeSlashes(compilerOptions.mapRoot); + if (!isBundledEmit) { + ts.Debug.assert(sourceFiles.length === 1); + // For modules or multiple emit files the mapRoot will have directory structure like the sources + // So if src\a.ts and src\lib\b.ts are compiled together user would be moving the maps into mapRoot\a.js.map and mapRoot\lib\b.js.map + sourceMapDir = ts.getDirectoryPath(ts.getSourceFilePathInNewDir(sourceFiles[0], host, sourceMapDir)); } - var candidate_1 = ts.combinePaths(ts.normalizePath(rootDir), suffix); - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Loading_0_from_the_root_dir_1_candidate_location_2, suffix, rootDir, candidate_1); + if (!ts.isRootedDiskPath(sourceMapDir) && !ts.isUrl(sourceMapDir)) { + // The relative paths are relative to the common directory + sourceMapDir = ts.combinePaths(host.getCommonSourceDirectory(), sourceMapDir); + sourceMapData.jsSourceMappingURL = ts.getRelativePathToDirectoryOrUrl(ts.getDirectoryPath(ts.normalizePath(filePath)), // get the relative sourceMapDir path based on jsFilePath + ts.combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL), // this is where user expects to see sourceMap + host.getCurrentDirectory(), host.getCanonicalFileName, + /*isAbsolutePathAnUrl*/ true); } - var baseDirectory = ts.getDirectoryPath(candidate_1); - var resolvedFileName_1 = loader(candidate_1, supportedExtensions, failedLookupLocations, !directoryProbablyExists(baseDirectory, state.host), state); - if (resolvedFileName_1) { - return resolvedFileName_1; + else { + sourceMapData.jsSourceMappingURL = ts.combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL); } } - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Module_resolution_using_rootDirs_has_failed); + else { + sourceMapDir = ts.getDirectoryPath(ts.normalizePath(filePath)); } } - return undefined; - } - function tryLoadModuleUsingBaseUrl(moduleName, loader, failedLookupLocations, supportedExtensions, state) { - if (!state.compilerOptions.baseUrl) { - return undefined; - } - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.baseUrl_option_is_set_to_0_using_this_value_to_resolve_non_relative_module_name_1, state.compilerOptions.baseUrl, moduleName); - } - // string is for exact match - var matchedPattern = undefined; - if (state.compilerOptions.paths) { - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.paths_option_is_specified_looking_for_a_pattern_to_match_module_name_0, moduleName); + /** + * Reset the SourceMapWriter to an empty state. + */ + function reset() { + if (disabled) { + return; } - matchedPattern = matchPatternOrExact(ts.getOwnKeys(state.compilerOptions.paths), moduleName); + currentSourceFile = undefined; + sourceMapDir = undefined; + sourceMapSourceIndex = undefined; + lastRecordedSourceMapSpan = undefined; + lastEncodedSourceMapSpan = undefined; + lastEncodedNameIndex = undefined; + sourceMapData = undefined; } - if (matchedPattern) { - var matchedStar = typeof matchedPattern === "string" ? undefined : matchedText(matchedPattern, moduleName); - var matchedPatternText = typeof matchedPattern === "string" ? matchedPattern : patternText(matchedPattern); - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Module_name_0_matched_pattern_1, moduleName, matchedPatternText); + // Encoding for sourcemap span + function encodeLastRecordedSourceMapSpan() { + if (!lastRecordedSourceMapSpan || lastRecordedSourceMapSpan === lastEncodedSourceMapSpan) { + return; } - for (var _i = 0, _a = state.compilerOptions.paths[matchedPatternText]; _i < _a.length; _i++) { - var subst = _a[_i]; - var path = matchedStar ? subst.replace("*", matchedStar) : subst; - var candidate = ts.normalizePath(ts.combinePaths(state.compilerOptions.baseUrl, path)); - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Trying_substitution_0_candidate_module_location_Colon_1, subst, path); + var prevEncodedEmittedColumn = lastEncodedSourceMapSpan.emittedColumn; + // Line/Comma delimiters + if (lastEncodedSourceMapSpan.emittedLine === lastRecordedSourceMapSpan.emittedLine) { + // Emit comma to separate the entry + if (sourceMapData.sourceMapMappings) { + sourceMapData.sourceMapMappings += ","; } - var resolvedFileName = loader(candidate, supportedExtensions, failedLookupLocations, !directoryProbablyExists(ts.getDirectoryPath(candidate), state.host), state); - if (resolvedFileName) { - return resolvedFileName; + } + else { + // Emit line delimiters + for (var encodedLine = lastEncodedSourceMapSpan.emittedLine; encodedLine < lastRecordedSourceMapSpan.emittedLine; encodedLine++) { + sourceMapData.sourceMapMappings += ";"; } + prevEncodedEmittedColumn = 1; } - return undefined; - } - else { - var candidate = ts.normalizePath(ts.combinePaths(state.compilerOptions.baseUrl, moduleName)); - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Resolving_module_name_0_relative_to_base_url_1_2, moduleName, state.compilerOptions.baseUrl, candidate); + // 1. Relative Column 0 based + sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.emittedColumn - prevEncodedEmittedColumn); + // 2. Relative sourceIndex + sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceIndex - lastEncodedSourceMapSpan.sourceIndex); + // 3. Relative sourceLine 0 based + sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceLine - lastEncodedSourceMapSpan.sourceLine); + // 4. Relative sourceColumn 0 based + sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceColumn - lastEncodedSourceMapSpan.sourceColumn); + // 5. Relative namePosition 0 based + if (lastRecordedSourceMapSpan.nameIndex >= 0) { + ts.Debug.assert(false, "We do not support name index right now, Make sure to update updateLastEncodedAndRecordedSpans when we start using this"); + sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.nameIndex - lastEncodedNameIndex); + lastEncodedNameIndex = lastRecordedSourceMapSpan.nameIndex; } - return loader(candidate, supportedExtensions, failedLookupLocations, !directoryProbablyExists(ts.getDirectoryPath(candidate), state.host), state); + lastEncodedSourceMapSpan = lastRecordedSourceMapSpan; + sourceMapData.sourceMapDecodedMappings.push(lastEncodedSourceMapSpan); } - } - /** - * patternStrings contains both pattern strings (containing "*") and regular strings. - * Return an exact match if possible, or a pattern match, or undefined. - * (These are verified by verifyCompilerOptions to have 0 or 1 "*" characters.) - */ - function matchPatternOrExact(patternStrings, candidate) { - var patterns = []; - for (var _i = 0, patternStrings_1 = patternStrings; _i < patternStrings_1.length; _i++) { - var patternString = patternStrings_1[_i]; - var pattern = tryParsePattern(patternString); - if (pattern) { - patterns.push(pattern); - } - else if (patternString === candidate) { - // pattern was matched as is - no need to search further - return patternString; + /** + * Emits a mapping. + * + * If the position is synthetic (undefined or a negative value), no mapping will be + * created. + * + * @param pos The position. + */ + function emitPos(pos) { + if (disabled || ts.positionIsSynthesized(pos)) { + return; } - } - return findBestPatternMatch(patterns, function (_) { return _; }, candidate); - } - function patternText(_a) { - var prefix = _a.prefix, suffix = _a.suffix; - return prefix + "*" + suffix; - } - /** - * Given that candidate matches pattern, returns the text matching the '*'. - * E.g.: matchedText(tryParsePattern("foo*baz"), "foobarbaz") === "bar" - */ - function matchedText(pattern, candidate) { - ts.Debug.assert(isPatternMatch(pattern, candidate)); - return candidate.substr(pattern.prefix.length, candidate.length - pattern.suffix.length); - } - /** Return the object corresponding to the best pattern to match `candidate`. */ - /* @internal */ - function findBestPatternMatch(values, getPattern, candidate) { - var matchedValue = undefined; - // use length of prefix as betterness criteria - var longestMatchPrefixLength = -1; - for (var _i = 0, values_1 = values; _i < values_1.length; _i++) { - var v = values_1[_i]; - var pattern = getPattern(v); - if (isPatternMatch(pattern, candidate) && pattern.prefix.length > longestMatchPrefixLength) { - longestMatchPrefixLength = pattern.prefix.length; - matchedValue = v; + if (extendedDiagnostics) { + ts.performance.mark("beforeSourcemap"); } - } - return matchedValue; - } - ts.findBestPatternMatch = findBestPatternMatch; - function isPatternMatch(_a, candidate) { - var prefix = _a.prefix, suffix = _a.suffix; - return candidate.length >= prefix.length + suffix.length && - ts.startsWith(candidate, prefix) && - ts.endsWith(candidate, suffix); - } - /* @internal */ - function tryParsePattern(pattern) { - // This should be verified outside of here and a proper error thrown. - ts.Debug.assert(hasZeroOrOneAsteriskCharacter(pattern)); - var indexOfStar = pattern.indexOf("*"); - return indexOfStar === -1 ? undefined : { - prefix: pattern.substr(0, indexOfStar), - suffix: pattern.substr(indexOfStar + 1) - }; - } - ts.tryParsePattern = tryParsePattern; - function nodeModuleNameResolver(moduleName, containingFile, compilerOptions, host) { - var containingDirectory = ts.getDirectoryPath(containingFile); - var supportedExtensions = ts.getSupportedExtensions(compilerOptions); - var traceEnabled = isTraceEnabled(compilerOptions, host); - var failedLookupLocations = []; - var state = { compilerOptions: compilerOptions, host: host, traceEnabled: traceEnabled, skipTsx: false }; - var resolvedFileName = tryLoadModuleUsingOptionalResolutionSettings(moduleName, containingDirectory, nodeLoadModuleByRelativeName, failedLookupLocations, supportedExtensions, state); - var isExternalLibraryImport = false; - if (!resolvedFileName) { - if (moduleHasNonRelativeName(moduleName)) { - if (traceEnabled) { - trace(host, ts.Diagnostics.Loading_module_0_from_node_modules_folder, moduleName); - } - resolvedFileName = loadModuleFromNodeModules(moduleName, containingDirectory, failedLookupLocations, state); - isExternalLibraryImport = resolvedFileName !== undefined; + var sourceLinePos = ts.getLineAndCharacterOfPosition(currentSourceFile, pos); + // Convert the location to be one-based. + sourceLinePos.line++; + sourceLinePos.character++; + var emittedLine = writer.getLine(); + var emittedColumn = writer.getColumn(); + // If this location wasn't recorded or the location in source is going backwards, record the span + if (!lastRecordedSourceMapSpan || + lastRecordedSourceMapSpan.emittedLine !== emittedLine || + lastRecordedSourceMapSpan.emittedColumn !== emittedColumn || + (lastRecordedSourceMapSpan.sourceIndex === sourceMapSourceIndex && + (lastRecordedSourceMapSpan.sourceLine > sourceLinePos.line || + (lastRecordedSourceMapSpan.sourceLine === sourceLinePos.line && lastRecordedSourceMapSpan.sourceColumn > sourceLinePos.character)))) { + // Encode the last recordedSpan before assigning new + encodeLastRecordedSourceMapSpan(); + // New span + lastRecordedSourceMapSpan = { + emittedLine: emittedLine, + emittedColumn: emittedColumn, + sourceLine: sourceLinePos.line, + sourceColumn: sourceLinePos.character, + sourceIndex: sourceMapSourceIndex + }; } else { - var candidate = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName)); - resolvedFileName = nodeLoadModuleByRelativeName(candidate, supportedExtensions, failedLookupLocations, /*onlyRecordFailures*/ false, state); + // Take the new pos instead since there is no change in emittedLine and column since last location + lastRecordedSourceMapSpan.sourceLine = sourceLinePos.line; + lastRecordedSourceMapSpan.sourceColumn = sourceLinePos.character; + lastRecordedSourceMapSpan.sourceIndex = sourceMapSourceIndex; } - } - if (resolvedFileName && host.realpath) { - var originalFileName = resolvedFileName; - resolvedFileName = ts.normalizePath(host.realpath(resolvedFileName)); - if (traceEnabled) { - trace(host, ts.Diagnostics.Resolving_real_path_for_0_result_1, originalFileName, resolvedFileName); + if (extendedDiagnostics) { + ts.performance.mark("afterSourcemap"); + ts.performance.measure("Source Map", "beforeSourcemap", "afterSourcemap"); } } - return createResolvedModule(resolvedFileName, isExternalLibraryImport, failedLookupLocations); - } - ts.nodeModuleNameResolver = nodeModuleNameResolver; - function nodeLoadModuleByRelativeName(candidate, supportedExtensions, failedLookupLocations, onlyRecordFailures, state) { - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Loading_module_as_file_Slash_folder_candidate_module_location_0, candidate); - } - var resolvedFileName = loadModuleFromFile(candidate, supportedExtensions, failedLookupLocations, onlyRecordFailures, state); - return resolvedFileName || loadNodeModuleFromDirectory(supportedExtensions, candidate, failedLookupLocations, onlyRecordFailures, state); - } - /* @internal */ - function directoryProbablyExists(directoryName, host) { - // if host does not support 'directoryExists' assume that directory will exist - return !host.directoryExists || host.directoryExists(directoryName); - } - ts.directoryProbablyExists = directoryProbablyExists; - /** - * @param {boolean} onlyRecordFailures - if true then function won't try to actually load files but instead record all attempts as failures. This flag is necessary - * in cases when we know upfront that all load attempts will fail (because containing folder does not exists) however we still need to record all failed lookup locations. - */ - function loadModuleFromFile(candidate, extensions, failedLookupLocation, onlyRecordFailures, state) { - // First, try adding an extension. An import of "foo" could be matched by a file "foo.ts", or "foo.js" by "foo.js.ts" - var resolvedByAddingExtension = tryAddingExtensions(candidate, extensions, failedLookupLocation, onlyRecordFailures, state); - if (resolvedByAddingExtension) { - return resolvedByAddingExtension; - } - // If that didn't work, try stripping a ".js" or ".jsx" extension and replacing it with a TypeScript one; - // e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts" - if (ts.hasJavaScriptFileExtension(candidate)) { - var extensionless = ts.removeFileExtension(candidate); - if (state.traceEnabled) { - var extension = candidate.substring(extensionless.length); - trace(state.host, ts.Diagnostics.File_name_0_has_a_1_extension_stripping_it, candidate, extension); + /** + * Emits a node with possible leading and trailing source maps. + * + * @param node The node to emit. + * @param emitCallback The callback used to emit the node. + */ + function emitNodeWithSourceMap(emitContext, node, emitCallback) { + if (disabled) { + return emitCallback(emitContext, node); } - return tryAddingExtensions(extensionless, extensions, failedLookupLocation, onlyRecordFailures, state); - } - } - /** Try to return an existing file that adds one of the `extensions` to `candidate`. */ - function tryAddingExtensions(candidate, extensions, failedLookupLocation, onlyRecordFailures, state) { - if (!onlyRecordFailures) { - // check if containing folder exists - if it doesn't then just record failures for all supported extensions without disk probing - var directory = ts.getDirectoryPath(candidate); - if (directory) { - onlyRecordFailures = !directoryProbablyExists(directory, state.host); + if (node) { + var emitNode = node.emitNode; + var emitFlags = emitNode && emitNode.flags; + var _a = emitNode && emitNode.sourceMapRange || node, pos = _a.pos, end = _a.end; + if (node.kind !== 287 /* NotEmittedStatement */ + && (emitFlags & 512 /* NoLeadingSourceMap */) === 0 + && pos >= 0) { + emitPos(ts.skipTrivia(currentSourceText, pos)); + } + if (emitFlags & 2048 /* NoNestedSourceMaps */) { + disabled = true; + emitCallback(emitContext, node); + disabled = false; + } + else { + emitCallback(emitContext, node); + } + if (node.kind !== 287 /* NotEmittedStatement */ + && (emitFlags & 1024 /* NoTrailingSourceMap */) === 0 + && end >= 0) { + emitPos(end); + } } } - return ts.forEach(extensions, function (ext) { - return !(state.skipTsx && ts.isJsxOrTsxExtension(ext)) && tryFile(candidate + ext, failedLookupLocation, onlyRecordFailures, state); - }); - } - /** Return the file if it exists. */ - function tryFile(fileName, failedLookupLocation, onlyRecordFailures, state) { - if (!onlyRecordFailures && state.host.fileExists(fileName)) { - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.File_0_exist_use_it_as_a_name_resolution_result, fileName); + /** + * Emits a token of a node with possible leading and trailing source maps. + * + * @param node The node containing the token. + * @param token The token to emit. + * @param tokenStartPos The start pos of the token. + * @param emitCallback The callback used to emit the token. + */ + function emitTokenWithSourceMap(node, token, tokenPos, emitCallback) { + if (disabled) { + return emitCallback(token, tokenPos); } - return fileName; - } - else { - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.File_0_does_not_exist, fileName); + var emitNode = node && node.emitNode; + var emitFlags = emitNode && emitNode.flags; + var range = emitNode && emitNode.tokenSourceMapRanges && emitNode.tokenSourceMapRanges[token]; + tokenPos = ts.skipTrivia(currentSourceText, range ? range.pos : tokenPos); + if ((emitFlags & 4096 /* NoTokenLeadingSourceMaps */) === 0 && tokenPos >= 0) { + emitPos(tokenPos); } - failedLookupLocation.push(fileName); - return undefined; - } - } - function loadNodeModuleFromDirectory(extensions, candidate, failedLookupLocation, onlyRecordFailures, state) { - var packageJsonPath = pathToPackageJson(candidate); - var directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, state.host); - if (directoryExists && state.host.fileExists(packageJsonPath)) { - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Found_package_json_at_0, packageJsonPath); + tokenPos = emitCallback(token, tokenPos); + if (range) + tokenPos = range.end; + if ((emitFlags & 8192 /* NoTokenTrailingSourceMaps */) === 0 && tokenPos >= 0) { + emitPos(tokenPos); } - var typesFile = tryReadTypesSection(packageJsonPath, candidate, state); - if (typesFile) { - var onlyRecordFailures_1 = !directoryProbablyExists(ts.getDirectoryPath(typesFile), state.host); - // A package.json "typings" may specify an exact filename, or may choose to omit an extension. - var result = tryFile(typesFile, failedLookupLocation, onlyRecordFailures_1, state) || - tryAddingExtensions(typesFile, extensions, failedLookupLocation, onlyRecordFailures_1, state); - if (result) { - return result; - } + return tokenPos; + } + /** + * Set the current source file. + * + * @param sourceFile The source file. + */ + function setSourceFile(sourceFile) { + if (disabled) { + return; } - else { - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.package_json_does_not_have_types_field); + currentSourceFile = sourceFile; + currentSourceText = currentSourceFile.text; + // Add the file to tsFilePaths + // If sourceroot option: Use the relative path corresponding to the common directory path + // otherwise source locations relative to map file location + var sourcesDirectoryPath = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir; + var source = ts.getRelativePathToDirectoryOrUrl(sourcesDirectoryPath, currentSourceFile.fileName, host.getCurrentDirectory(), host.getCanonicalFileName, + /*isAbsolutePathAnUrl*/ true); + sourceMapSourceIndex = ts.indexOf(sourceMapData.sourceMapSources, source); + if (sourceMapSourceIndex === -1) { + sourceMapSourceIndex = sourceMapData.sourceMapSources.length; + sourceMapData.sourceMapSources.push(source); + // The one that can be used from program to get the actual source file + sourceMapData.inputSourceFileNames.push(currentSourceFile.fileName); + if (compilerOptions.inlineSources) { + sourceMapData.sourceMapSourcesContent.push(currentSourceFile.text); } } } - else { - if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.File_0_does_not_exist, packageJsonPath); + /** + * Gets the text for the source map. + */ + function getText() { + if (disabled) { + return; } - // record package json as one of failed lookup locations - in the future if this file will appear it will invalidate resolution results - failedLookupLocation.push(packageJsonPath); - } - return loadModuleFromFile(ts.combinePaths(candidate, "index"), extensions, failedLookupLocation, !directoryExists, state); - } - function pathToPackageJson(directory) { - return ts.combinePaths(directory, "package.json"); - } - function loadModuleFromNodeModulesFolder(moduleName, directory, failedLookupLocations, state) { - var nodeModulesFolder = ts.combinePaths(directory, "node_modules"); - var nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, state.host); - var candidate = ts.normalizePath(ts.combinePaths(nodeModulesFolder, moduleName)); - var supportedExtensions = ts.getSupportedExtensions(state.compilerOptions); - var result = loadModuleFromFile(candidate, supportedExtensions, failedLookupLocations, !nodeModulesFolderExists, state); - if (result) { - return result; - } - result = loadNodeModuleFromDirectory(supportedExtensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state); - if (result) { - return result; + encodeLastRecordedSourceMapSpan(); + return ts.stringify({ + version: 3, + file: sourceMapData.sourceMapFile, + sourceRoot: sourceMapData.sourceMapSourceRoot, + sources: sourceMapData.sourceMapSources, + names: sourceMapData.sourceMapNames, + mappings: sourceMapData.sourceMapMappings, + sourcesContent: sourceMapData.sourceMapSourcesContent, + }); } - } - function loadModuleFromNodeModules(moduleName, directory, failedLookupLocations, state) { - directory = ts.normalizeSlashes(directory); - while (true) { - var baseName = ts.getBaseFileName(directory); - if (baseName !== "node_modules") { - // Try to load source from the package - var packageResult = loadModuleFromNodeModulesFolder(moduleName, directory, failedLookupLocations, state); - if (packageResult && ts.hasTypeScriptFileExtension(packageResult)) { - // Always prefer a TypeScript (.ts, .tsx, .d.ts) file shipped with the package - return packageResult; - } - else { - // Else prefer a types package over non-TypeScript results (e.g. JavaScript files) - var typesResult = loadModuleFromNodeModulesFolder(ts.combinePaths("@types", moduleName), directory, failedLookupLocations, state); - if (typesResult || packageResult) { - return typesResult || packageResult; - } - } + /** + * Gets the SourceMappingURL for the source map. + */ + function getSourceMappingURL() { + if (disabled) { + return; } - var parentPath = ts.getDirectoryPath(directory); - if (parentPath === directory) { - break; + if (compilerOptions.inlineSourceMap) { + // Encode the sourceMap into the sourceMap url + var base64SourceMapText = ts.convertToBase64(getText()); + return sourceMapData.jsSourceMappingURL = "data:application/json;base64," + base64SourceMapText; + } + else { + return sourceMapData.jsSourceMappingURL; } - directory = parentPath; } - return undefined; } - function classicNameResolver(moduleName, containingFile, compilerOptions, host) { - var traceEnabled = isTraceEnabled(compilerOptions, host); - var state = { compilerOptions: compilerOptions, host: host, traceEnabled: traceEnabled, skipTsx: !compilerOptions.jsx }; - var failedLookupLocations = []; - var supportedExtensions = ts.getSupportedExtensions(compilerOptions); - var containingDirectory = ts.getDirectoryPath(containingFile); - var resolvedFileName = tryLoadModuleUsingOptionalResolutionSettings(moduleName, containingDirectory, loadModuleFromFile, failedLookupLocations, supportedExtensions, state); - if (resolvedFileName) { - return createResolvedModule(resolvedFileName, /*isExternalLibraryImport*/ false, failedLookupLocations); + ts.createSourceMapWriter = createSourceMapWriter; + var base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + function base64FormatEncode(inValue) { + if (inValue < 64) { + return base64Chars.charAt(inValue); } - var referencedSourceFile; - if (moduleHasNonRelativeName(moduleName)) { - while (true) { - var searchName = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName)); - referencedSourceFile = loadModuleFromFile(searchName, supportedExtensions, failedLookupLocations, /*onlyRecordFailures*/ false, state); - if (referencedSourceFile) { - break; - } - var parentPath = ts.getDirectoryPath(containingDirectory); - if (parentPath === containingDirectory) { - break; - } - containingDirectory = parentPath; - } + throw TypeError(inValue + ": not a 64 based value"); + } + function base64VLQFormatEncode(inValue) { + // Add a new least significant bit that has the sign of the value. + // if negative number the least significant bit that gets added to the number has value 1 + // else least significant bit value that gets added is 0 + // eg. -1 changes to binary : 01 [1] => 3 + // +1 changes to binary : 01 [0] => 2 + if (inValue < 0) { + inValue = ((-inValue) << 1) + 1; } else { - var candidate = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName)); - referencedSourceFile = loadModuleFromFile(candidate, supportedExtensions, failedLookupLocations, /*onlyRecordFailures*/ false, state); + inValue = inValue << 1; } - return referencedSourceFile - ? { resolvedModule: { resolvedFileName: referencedSourceFile }, failedLookupLocations: failedLookupLocations } - : { resolvedModule: undefined, failedLookupLocations: failedLookupLocations }; + // Encode 5 bits at a time starting from least significant bits + var encodedStr = ""; + do { + var currentDigit = inValue & 31; // 11111 + inValue = inValue >> 5; + if (inValue > 0) { + // There are still more digits to decode, set the msb (6th bit) + currentDigit = currentDigit | 32; + } + encodedStr = encodedStr + base64FormatEncode(currentDigit); + } while (inValue > 0); + return encodedStr; } - ts.classicNameResolver = classicNameResolver; - function createCompilerHost(options, setParentNodes) { - var existingDirectories = ts.createMap(); - function getCanonicalFileName(fileName) { - // if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form. - // otherwise use toLowerCase as a canonical form. - return ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); - } - // returned by CScript sys environment - var unsupportedFileEncodingErrorCode = -2147024809; - function getSourceFile(fileName, languageVersion, onError) { - var text; - try { - ts.performance.mark("beforeIORead"); - text = ts.sys.readFile(fileName, options.charset); - ts.performance.mark("afterIORead"); - ts.performance.measure("I/O Read", "beforeIORead", "afterIORead"); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + function createCommentWriter(host, writer, sourceMap) { + var compilerOptions = host.getCompilerOptions(); + var extendedDiagnostics = compilerOptions.extendedDiagnostics; + var newLine = host.getNewLine(); + var emitPos = sourceMap.emitPos; + var containerPos = -1; + var containerEnd = -1; + var declarationListContainerEnd = -1; + var currentSourceFile; + var currentText; + var currentLineMap; + var detachedCommentsInfo; + var hasWrittenComment = false; + var disabled = compilerOptions.removeComments; + return { + reset: reset, + setSourceFile: setSourceFile, + emitNodeWithComments: emitNodeWithComments, + emitBodyWithDetachedComments: emitBodyWithDetachedComments, + emitTrailingCommentsOfPosition: emitTrailingCommentsOfPosition, + }; + function emitNodeWithComments(emitContext, node, emitCallback) { + if (disabled) { + emitCallback(emitContext, node); + return; } - catch (e) { - if (onError) { - onError(e.number === unsupportedFileEncodingErrorCode - ? ts.createCompilerDiagnostic(ts.Diagnostics.Unsupported_file_encoding).messageText - : e.message); + if (node) { + var _a = ts.getCommentRange(node), pos = _a.pos, end = _a.end; + var emitFlags = ts.getEmitFlags(node); + if ((pos < 0 && end < 0) || (pos === end)) { + // Both pos and end are synthesized, so just emit the node without comments. + if (emitFlags & 65536 /* NoNestedComments */) { + disabled = true; + emitCallback(emitContext, node); + disabled = false; + } + else { + emitCallback(emitContext, node); + } + } + else { + if (extendedDiagnostics) { + ts.performance.mark("preEmitNodeWithComment"); + } + var isEmittedNode = node.kind !== 287 /* NotEmittedStatement */; + var skipLeadingComments = pos < 0 || (emitFlags & 16384 /* NoLeadingComments */) !== 0; + var skipTrailingComments = end < 0 || (emitFlags & 32768 /* NoTrailingComments */) !== 0; + // Emit leading comments if the position is not synthesized and the node + // has not opted out from emitting leading comments. + if (!skipLeadingComments) { + emitLeadingComments(pos, isEmittedNode); + } + // Save current container state on the stack. + var savedContainerPos = containerPos; + var savedContainerEnd = containerEnd; + var savedDeclarationListContainerEnd = declarationListContainerEnd; + if (!skipLeadingComments) { + containerPos = pos; + } + if (!skipTrailingComments) { + containerEnd = end; + // To avoid invalid comment emit in a down-level binding pattern, we + // keep track of the last declaration list container's end + if (node.kind === 219 /* VariableDeclarationList */) { + declarationListContainerEnd = end; + } + } + if (extendedDiagnostics) { + ts.performance.measure("commentTime", "preEmitNodeWithComment"); + } + if (emitFlags & 65536 /* NoNestedComments */) { + disabled = true; + emitCallback(emitContext, node); + disabled = false; + } + else { + emitCallback(emitContext, node); + } + if (extendedDiagnostics) { + ts.performance.mark("beginEmitNodeWithComment"); + } + // Restore previous container state. + containerPos = savedContainerPos; + containerEnd = savedContainerEnd; + declarationListContainerEnd = savedDeclarationListContainerEnd; + // Emit trailing comments if the position is not synthesized and the node + // has not opted out from emitting leading comments and is an emitted node. + if (!skipTrailingComments && isEmittedNode) { + emitTrailingComments(end); + } + if (extendedDiagnostics) { + ts.performance.measure("commentTime", "beginEmitNodeWithComment"); + } } - text = ""; } - return text !== undefined ? ts.createSourceFile(fileName, text, languageVersion, setParentNodes) : undefined; } - function directoryExists(directoryPath) { - if (directoryPath in existingDirectories) { - return true; + function emitBodyWithDetachedComments(node, detachedRange, emitCallback) { + if (extendedDiagnostics) { + ts.performance.mark("preEmitBodyWithDetachedComments"); } - if (ts.sys.directoryExists(directoryPath)) { - existingDirectories[directoryPath] = true; - return true; + var pos = detachedRange.pos, end = detachedRange.end; + var emitFlags = ts.getEmitFlags(node); + var skipLeadingComments = pos < 0 || (emitFlags & 16384 /* NoLeadingComments */) !== 0; + var skipTrailingComments = disabled || end < 0 || (emitFlags & 32768 /* NoTrailingComments */) !== 0; + if (!skipLeadingComments) { + emitDetachedCommentsAndUpdateCommentsInfo(detachedRange); } - return false; - } - function ensureDirectoriesExist(directoryPath) { - if (directoryPath.length > ts.getRootLength(directoryPath) && !directoryExists(directoryPath)) { - var parentDirectory = ts.getDirectoryPath(directoryPath); - ensureDirectoriesExist(parentDirectory); - ts.sys.createDirectory(directoryPath); + if (extendedDiagnostics) { + ts.performance.measure("commentTime", "preEmitBodyWithDetachedComments"); } - } - var outputFingerprints; - function writeFileIfUpdated(fileName, data, writeByteOrderMark) { - if (!outputFingerprints) { - outputFingerprints = ts.createMap(); + if (emitFlags & 65536 /* NoNestedComments */ && !disabled) { + disabled = true; + emitCallback(node); + disabled = false; } - var hash = ts.sys.createHash(data); - var mtimeBefore = ts.sys.getModifiedTime(fileName); - if (mtimeBefore && fileName in outputFingerprints) { - var fingerprint = outputFingerprints[fileName]; - // If output has not been changed, and the file has no external modification - if (fingerprint.byteOrderMark === writeByteOrderMark && - fingerprint.hash === hash && - fingerprint.mtime.getTime() === mtimeBefore.getTime()) { - return; - } + else { + emitCallback(node); } - ts.sys.writeFile(fileName, data, writeByteOrderMark); - var mtimeAfter = ts.sys.getModifiedTime(fileName); - outputFingerprints[fileName] = { - hash: hash, - byteOrderMark: writeByteOrderMark, - mtime: mtimeAfter - }; - } - function writeFile(fileName, data, writeByteOrderMark, onError) { - try { - ts.performance.mark("beforeIOWrite"); - ensureDirectoriesExist(ts.getDirectoryPath(ts.normalizePath(fileName))); - if (ts.isWatchSet(options) && ts.sys.createHash && ts.sys.getModifiedTime) { - writeFileIfUpdated(fileName, data, writeByteOrderMark); - } - else { - ts.sys.writeFile(fileName, data, writeByteOrderMark); - } - ts.performance.mark("afterIOWrite"); - ts.performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite"); + if (extendedDiagnostics) { + ts.performance.mark("beginEmitBodyWithDetachedCommetns"); } - catch (e) { - if (onError) { - onError(e.message); - } + if (!skipTrailingComments) { + emitLeadingComments(detachedRange.end, /*isEmittedNode*/ true); + } + if (extendedDiagnostics) { + ts.performance.measure("commentTime", "beginEmitBodyWithDetachedCommetns"); } } - function getDefaultLibLocation() { - return ts.getDirectoryPath(ts.normalizePath(ts.sys.getExecutingFilePath())); + function emitLeadingComments(pos, isEmittedNode) { + hasWrittenComment = false; + if (isEmittedNode) { + forEachLeadingCommentToEmit(pos, emitLeadingComment); + } + else if (pos === 0) { + // If the node will not be emitted in JS, remove all the comments(normal, pinned and ///) associated with the node, + // unless it is a triple slash comment at the top of the file. + // For Example: + // /// + // declare var x; + // /// + // interface F {} + // The first /// will NOT be removed while the second one will be removed even though both node will not be emitted + forEachLeadingCommentToEmit(pos, emitTripleSlashLeadingComment); + } } - var newLine = ts.getNewLineCharacter(options); - var realpath = ts.sys.realpath && (function (path) { return ts.sys.realpath(path); }); - return { - getSourceFile: getSourceFile, - getDefaultLibLocation: getDefaultLibLocation, - getDefaultLibFileName: function (options) { return ts.combinePaths(getDefaultLibLocation(), ts.getDefaultLibFileName(options)); }, - writeFile: writeFile, - getCurrentDirectory: ts.memoize(function () { return ts.sys.getCurrentDirectory(); }), - useCaseSensitiveFileNames: function () { return ts.sys.useCaseSensitiveFileNames; }, - getCanonicalFileName: getCanonicalFileName, - getNewLine: function () { return newLine; }, - fileExists: function (fileName) { return ts.sys.fileExists(fileName); }, - readFile: function (fileName) { return ts.sys.readFile(fileName); }, - trace: function (s) { return ts.sys.write(s + newLine); }, - directoryExists: function (directoryName) { return ts.sys.directoryExists(directoryName); }, - getDirectories: function (path) { return ts.sys.getDirectories(path); }, - realpath: realpath - }; - } - ts.createCompilerHost = createCompilerHost; - function getPreEmitDiagnostics(program, sourceFile, cancellationToken) { - var diagnostics = program.getOptionsDiagnostics(cancellationToken).concat(program.getSyntacticDiagnostics(sourceFile, cancellationToken), program.getGlobalDiagnostics(cancellationToken), program.getSemanticDiagnostics(sourceFile, cancellationToken)); - if (program.getCompilerOptions().declaration) { - diagnostics = diagnostics.concat(program.getDeclarationDiagnostics(sourceFile, cancellationToken)); + function emitTripleSlashLeadingComment(commentPos, commentEnd, kind, hasTrailingNewLine, rangePos) { + if (isTripleSlashComment(commentPos, commentEnd)) { + emitLeadingComment(commentPos, commentEnd, kind, hasTrailingNewLine, rangePos); + } } - return ts.sortAndDeduplicateDiagnostics(diagnostics); - } - ts.getPreEmitDiagnostics = getPreEmitDiagnostics; - function formatDiagnostics(diagnostics, host) { - var output = ""; - for (var _i = 0, diagnostics_2 = diagnostics; _i < diagnostics_2.length; _i++) { - var diagnostic = diagnostics_2[_i]; - if (diagnostic.file) { - var _a = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start), line = _a.line, character = _a.character; - var fileName = diagnostic.file.fileName; - var relativeFileName = ts.convertToRelativePath(fileName, host.getCurrentDirectory(), function (fileName) { return host.getCanonicalFileName(fileName); }); - output += relativeFileName + "(" + (line + 1) + "," + (character + 1) + "): "; + function emitLeadingComment(commentPos, commentEnd, kind, hasTrailingNewLine, rangePos) { + if (!hasWrittenComment) { + ts.emitNewLineBeforeLeadingCommentOfPosition(currentLineMap, writer, rangePos, commentPos); + hasWrittenComment = true; + } + // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space + emitPos(commentPos); + ts.writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine); + emitPos(commentEnd); + if (hasTrailingNewLine) { + writer.writeLine(); + } + else { + writer.write(" "); } - var category = ts.DiagnosticCategory[diagnostic.category].toLowerCase(); - output += category + " TS" + diagnostic.code + ": " + flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine()) + host.getNewLine(); } - return output; - } - ts.formatDiagnostics = formatDiagnostics; - function flattenDiagnosticMessageText(messageText, newLine) { - if (typeof messageText === "string") { - return messageText; + function emitTrailingComments(pos) { + forEachTrailingCommentToEmit(pos, emitTrailingComment); } - else { - var diagnosticChain = messageText; - var result = ""; - var indent = 0; - while (diagnosticChain) { - if (indent) { - result += newLine; - for (var i = 0; i < indent; i++) { - result += " "; - } - } - result += diagnosticChain.messageText; - indent++; - diagnosticChain = diagnosticChain.next; + function emitTrailingComment(commentPos, commentEnd, kind, hasTrailingNewLine) { + // trailing comments are emitted at space/*trailing comment1 */space/*trailing comment2*/ + if (!writer.isAtStartOfLine()) { + writer.write(" "); + } + emitPos(commentPos); + ts.writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine); + emitPos(commentEnd); + if (hasTrailingNewLine) { + writer.writeLine(); } - return result; - } - } - ts.flattenDiagnosticMessageText = flattenDiagnosticMessageText; - function loadWithLocalCache(names, containingFile, loader) { - if (names.length === 0) { - return []; } - var resolutions = []; - var cache = ts.createMap(); - for (var _i = 0, names_1 = names; _i < names_1.length; _i++) { - var name_36 = names_1[_i]; - var result = name_36 in cache - ? cache[name_36] - : cache[name_36] = loader(name_36, containingFile); - resolutions.push(result); + function emitTrailingCommentsOfPosition(pos) { + if (disabled) { + return; + } + if (extendedDiagnostics) { + ts.performance.mark("beforeEmitTrailingCommentsOfPosition"); + } + forEachTrailingCommentToEmit(pos, emitTrailingCommentOfPosition); + if (extendedDiagnostics) { + ts.performance.measure("commentTime", "beforeEmitTrailingCommentsOfPosition"); + } } - return resolutions; - } - /** - * Given a set of options, returns the set of type directive names - * that should be included for this program automatically. - * This list could either come from the config file, - * or from enumerating the types root + initial secondary types lookup location. - * More type directives might appear in the program later as a result of loading actual source files; - * this list is only the set of defaults that are implicitly included. - */ - function getAutomaticTypeDirectiveNames(options, host) { - // Use explicit type list from tsconfig.json - if (options.types) { - return options.types; + function emitTrailingCommentOfPosition(commentPos, commentEnd, kind, hasTrailingNewLine) { + // trailing comments of a position are emitted at /*trailing comment1 */space/*trailing comment*/space + emitPos(commentPos); + ts.writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine); + emitPos(commentEnd); + if (hasTrailingNewLine) { + writer.writeLine(); + } + else { + writer.write(" "); + } } - // Walk the primary type lookup locations - var result = []; - if (host.directoryExists && host.getDirectories) { - var typeRoots = getEffectiveTypeRoots(options, host); - if (typeRoots) { - for (var _i = 0, typeRoots_1 = typeRoots; _i < typeRoots_1.length; _i++) { - var root = typeRoots_1[_i]; - if (host.directoryExists(root)) { - for (var _a = 0, _b = host.getDirectories(root); _a < _b.length; _a++) { - var typeDirectivePath = _b[_a]; - var normalized = ts.normalizePath(typeDirectivePath); - var packageJsonPath = pathToPackageJson(ts.combinePaths(root, normalized)); - // tslint:disable-next-line:no-null-keyword - var isNotNeededPackage = host.fileExists(packageJsonPath) && readJson(packageJsonPath, host).typings === null; - if (!isNotNeededPackage) { - // Return just the type directive names - result.push(ts.getBaseFileName(normalized)); - } - } - } + function forEachLeadingCommentToEmit(pos, cb) { + // Emit the leading comments only if the container's pos doesn't match because the container should take care of emitting these comments + if (containerPos === -1 || pos !== containerPos) { + if (hasDetachedComments(pos)) { + forEachLeadingCommentWithoutDetachedComments(cb); + } + else { + ts.forEachLeadingCommentRange(currentText, pos, cb, /*state*/ pos); } } } - return result; - } - ts.getAutomaticTypeDirectiveNames = getAutomaticTypeDirectiveNames; - function createProgram(rootNames, options, host, oldProgram) { - var program; - var files = []; - var commonSourceDirectory; - var diagnosticsProducingTypeChecker; - var noDiagnosticsTypeChecker; - var classifiableNames; - var resolvedTypeReferenceDirectives = ts.createMap(); - var fileProcessingDiagnostics = ts.createDiagnosticCollection(); - // The below settings are to track if a .js file should be add to the program if loaded via searching under node_modules. - // This works as imported modules are discovered recursively in a depth first manner, specifically: - // - For each root file, findSourceFile is called. - // - This calls processImportedModules for each module imported in the source file. - // - This calls resolveModuleNames, and then calls findSourceFile for each resolved module. - // As all these operations happen - and are nested - within the createProgram call, they close over the below variables. - // The current resolution depth is tracked by incrementing/decrementing as the depth first search progresses. - var maxNodeModulesJsDepth = typeof options.maxNodeModuleJsDepth === "number" ? options.maxNodeModuleJsDepth : 0; - var currentNodeModulesDepth = 0; - // If a module has some of its imports skipped due to being at the depth limit under node_modules, then track - // this, as it may be imported at a shallower depth later, and then it will need its skipped imports processed. - var modulesWithElidedImports = ts.createMap(); - // Track source files that are source files found by searching under node_modules, as these shouldn't be compiled. - var sourceFilesFoundSearchingNodeModules = ts.createMap(); - ts.performance.mark("beforeProgram"); - host = host || createCompilerHost(options); - var skipDefaultLib = options.noLib; - var programDiagnostics = ts.createDiagnosticCollection(); - var currentDirectory = host.getCurrentDirectory(); - var supportedExtensions = ts.getSupportedExtensions(options); - // Map storing if there is emit blocking diagnostics for given input - var hasEmitBlockingDiagnostics = ts.createFileMap(getCanonicalFileName); - var resolveModuleNamesWorker; - if (host.resolveModuleNames) { - resolveModuleNamesWorker = function (moduleNames, containingFile) { return host.resolveModuleNames(moduleNames, containingFile); }; + function forEachTrailingCommentToEmit(end, cb) { + // Emit the trailing comments only if the container's end doesn't match because the container should take care of emitting these comments + if (containerEnd === -1 || (end !== containerEnd && end !== declarationListContainerEnd)) { + ts.forEachTrailingCommentRange(currentText, end, cb); + } } - else { - var loader_1 = function (moduleName, containingFile) { return resolveModuleName(moduleName, containingFile, options, host).resolvedModule; }; - resolveModuleNamesWorker = function (moduleNames, containingFile) { return loadWithLocalCache(moduleNames, containingFile, loader_1); }; + function reset() { + currentSourceFile = undefined; + currentText = undefined; + currentLineMap = undefined; + detachedCommentsInfo = undefined; } - var resolveTypeReferenceDirectiveNamesWorker; - if (host.resolveTypeReferenceDirectives) { - resolveTypeReferenceDirectiveNamesWorker = function (typeDirectiveNames, containingFile) { return host.resolveTypeReferenceDirectives(typeDirectiveNames, containingFile); }; + function setSourceFile(sourceFile) { + currentSourceFile = sourceFile; + currentText = currentSourceFile.text; + currentLineMap = ts.getLineStarts(currentSourceFile); + detachedCommentsInfo = undefined; } - else { - var loader_2 = function (typesRef, containingFile) { return resolveTypeReferenceDirective(typesRef, containingFile, options, host).resolvedTypeReferenceDirective; }; - resolveTypeReferenceDirectiveNamesWorker = function (typeReferenceDirectiveNames, containingFile) { return loadWithLocalCache(typeReferenceDirectiveNames, containingFile, loader_2); }; + function hasDetachedComments(pos) { + return detachedCommentsInfo !== undefined && ts.lastOrUndefined(detachedCommentsInfo).nodePos === pos; } - var filesByName = ts.createFileMap(); - // stores 'filename -> file association' ignoring case - // used to track cases when two file names differ only in casing - var filesByNameIgnoreCase = host.useCaseSensitiveFileNames() ? ts.createFileMap(function (fileName) { return fileName.toLowerCase(); }) : undefined; - if (!tryReuseStructureFromOldProgram()) { - ts.forEach(rootNames, function (name) { return processRootFile(name, /*isDefaultLib*/ false); }); - // load type declarations specified via 'types' argument or implicitly from types/ and node_modules/@types folders - var typeReferences = getAutomaticTypeDirectiveNames(options, host); - if (typeReferences) { - // This containingFilename needs to match with the one used in managed-side - var containingFilename = ts.combinePaths(host.getCurrentDirectory(), "__inferred type names__.ts"); - var resolutions = resolveTypeReferenceDirectiveNamesWorker(typeReferences, containingFilename); - for (var i = 0; i < typeReferences.length; i++) { - processTypeReferenceDirective(typeReferences[i], resolutions[i]); - } + function forEachLeadingCommentWithoutDetachedComments(cb) { + // get the leading comments from detachedPos + var pos = ts.lastOrUndefined(detachedCommentsInfo).detachedCommentEndPos; + if (detachedCommentsInfo.length - 1) { + detachedCommentsInfo.pop(); } - // Do not process the default library if: - // - The '--noLib' flag is used. - // - A 'no-default-lib' reference comment is encountered in - // processing the root files. - if (!skipDefaultLib) { - // If '--lib' is not specified, include default library file according to '--target' - // otherwise, using options specified in '--lib' instead of '--target' default library file - if (!options.lib) { - processRootFile(host.getDefaultLibFileName(options), /*isDefaultLib*/ true); - } - else { - var libDirectory_1 = host.getDefaultLibLocation ? host.getDefaultLibLocation() : ts.getDirectoryPath(host.getDefaultLibFileName(options)); - ts.forEach(options.lib, function (libFileName) { - processRootFile(ts.combinePaths(libDirectory_1, libFileName), /*isDefaultLib*/ true); - }); - } + else { + detachedCommentsInfo = undefined; } + ts.forEachLeadingCommentRange(currentText, pos, cb, /*state*/ pos); } - // unconditionally set oldProgram to undefined to prevent it from being captured in closure - oldProgram = undefined; - program = { - getRootFileNames: function () { return rootNames; }, - getSourceFile: getSourceFile, - getSourceFileByPath: getSourceFileByPath, - getSourceFiles: function () { return files; }, - getCompilerOptions: function () { return options; }, - getSyntacticDiagnostics: getSyntacticDiagnostics, - getOptionsDiagnostics: getOptionsDiagnostics, - getGlobalDiagnostics: getGlobalDiagnostics, - getSemanticDiagnostics: getSemanticDiagnostics, - getDeclarationDiagnostics: getDeclarationDiagnostics, - getTypeChecker: getTypeChecker, - getClassifiableNames: getClassifiableNames, - getDiagnosticsProducingTypeChecker: getDiagnosticsProducingTypeChecker, - getCommonSourceDirectory: getCommonSourceDirectory, - emit: emit, - getCurrentDirectory: function () { return currentDirectory; }, - getNodeCount: function () { return getDiagnosticsProducingTypeChecker().getNodeCount(); }, - getIdentifierCount: function () { return getDiagnosticsProducingTypeChecker().getIdentifierCount(); }, - getSymbolCount: function () { return getDiagnosticsProducingTypeChecker().getSymbolCount(); }, - getTypeCount: function () { return getDiagnosticsProducingTypeChecker().getTypeCount(); }, - getFileProcessingDiagnostics: function () { return fileProcessingDiagnostics; }, - getResolvedTypeReferenceDirectives: function () { return resolvedTypeReferenceDirectives; } - }; - verifyCompilerOptions(); - ts.performance.mark("afterProgram"); - ts.performance.measure("Program", "beforeProgram", "afterProgram"); - return program; - function getCommonSourceDirectory() { - if (typeof commonSourceDirectory === "undefined") { - if (options.rootDir && checkSourceFilesBelongToPath(files, options.rootDir)) { - // If a rootDir is specified and is valid use it as the commonSourceDirectory - commonSourceDirectory = ts.getNormalizedAbsolutePath(options.rootDir, currentDirectory); + function emitDetachedCommentsAndUpdateCommentsInfo(range) { + var currentDetachedCommentInfo = ts.emitDetachedComments(currentText, currentLineMap, writer, writeComment, range, newLine, disabled); + if (currentDetachedCommentInfo) { + if (detachedCommentsInfo) { + detachedCommentsInfo.push(currentDetachedCommentInfo); } else { - commonSourceDirectory = computeCommonSourceDirectory(files); - } - if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== ts.directorySeparator) { - // Make sure directory path ends with directory separator so this string can directly - // used to replace with "" to get the relative path of the source file and the relative path doesn't - // start with / making it rooted path - commonSourceDirectory += ts.directorySeparator; + detachedCommentsInfo = [currentDetachedCommentInfo]; } } - return commonSourceDirectory; } - function getClassifiableNames() { - if (!classifiableNames) { - // Initialize a checker so that all our files are bound. - getTypeChecker(); - classifiableNames = ts.createMap(); - for (var _i = 0, files_2 = files; _i < files_2.length; _i++) { - var sourceFile = files_2[_i]; - ts.copyProperties(sourceFile.classifiableNames, classifiableNames); - } - } - return classifiableNames; + function writeComment(text, lineMap, writer, commentPos, commentEnd, newLine) { + emitPos(commentPos); + ts.writeCommentRange(text, lineMap, writer, commentPos, commentEnd, newLine); + emitPos(commentEnd); } - function tryReuseStructureFromOldProgram() { - if (!oldProgram) { - return false; + /** + * Determine if the given comment is a triple-slash + * + * @return true if the comment is a triple-slash comment else false + **/ + function isTripleSlashComment(commentPos, commentEnd) { + // Verify this is /// comment, but do the regexp match only when we first can find /// in the comment text + // so that we don't end up computing comment string and doing match for all // comments + if (currentText.charCodeAt(commentPos + 1) === 47 /* slash */ && + commentPos + 2 < commentEnd && + currentText.charCodeAt(commentPos + 2) === 47 /* slash */) { + var textSubStr = currentText.substring(commentPos, commentEnd); + return textSubStr.match(ts.fullTripleSlashReferencePathRegEx) || + textSubStr.match(ts.fullTripleSlashAMDReferencePathRegEx) ? + true : false; } - // check properties that can affect structure of the program or module resolution strategy - // if any of these properties has changed - structure cannot be reused - var oldOptions = oldProgram.getCompilerOptions(); - if ((oldOptions.module !== options.module) || - (oldOptions.moduleResolution !== options.moduleResolution) || - (oldOptions.noResolve !== options.noResolve) || - (oldOptions.target !== options.target) || - (oldOptions.noLib !== options.noLib) || - (oldOptions.jsx !== options.jsx) || - (oldOptions.allowJs !== options.allowJs) || - (oldOptions.rootDir !== options.rootDir) || - (oldOptions.configFilePath !== options.configFilePath) || - (oldOptions.baseUrl !== options.baseUrl) || - (oldOptions.maxNodeModuleJsDepth !== options.maxNodeModuleJsDepth) || - !ts.arrayIsEqualTo(oldOptions.typeRoots, oldOptions.typeRoots) || - !ts.arrayIsEqualTo(oldOptions.rootDirs, options.rootDirs) || - !ts.equalOwnProperties(oldOptions.paths, options.paths)) { - return false; + return false; + } + } + ts.createCommentWriter = createCommentWriter; +})(ts || (ts = {})); +/// +/// +/// +/// +/// +/* @internal */ +var ts; +(function (ts) { + // Flags enum to track count of temp variables and a few dedicated names + var TempFlags; + (function (TempFlags) { + TempFlags[TempFlags["Auto"] = 0] = "Auto"; + TempFlags[TempFlags["CountMask"] = 268435455] = "CountMask"; + TempFlags[TempFlags["_i"] = 268435456] = "_i"; + })(TempFlags || (TempFlags = {})); + var id = function (s) { return s; }; + var nullTransformers = [function (ctx) { return id; }]; + // targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature + function emitFiles(resolver, host, targetSourceFile, emitOnlyDtsFiles) { + var delimiters = createDelimiterMap(); + var brackets = createBracketsMap(); + // emit output for the __extends helper function + var extendsHelper = "\nvar __extends = (this && this.__extends) || function (d, b) {\n for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n};"; + // Emit output for the __assign helper function. + // This is typically used for JSX spread attributes, + // and can be used for object literal spread properties. + var assignHelper = "\nvar __assign = (this && this.__assign) || Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n};"; + // emit output for the __decorate helper function + var decorateHelper = "\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};"; + // emit output for the __metadata helper function + var metadataHelper = "\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};"; + // emit output for the __param helper function + var paramHelper = "\nvar __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};"; + // emit output for the __awaiter helper function + var awaiterHelper = "\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments)).next());\n });\n};"; + // The __generator helper is used by down-level transformations to emulate the runtime + // semantics of an ES2015 generator function. When called, this helper returns an + // object that implements the Iterator protocol, in that it has `next`, `return`, and + // `throw` methods that step through the generator when invoked. + // + // parameters: + // thisArg The value to use as the `this` binding for the transformed generator body. + // body A function that acts as the transformed generator body. + // + // variables: + // _ Persistent state for the generator that is shared between the helper and the + // generator body. The state object has the following members: + // sent() - A method that returns or throws the current completion value. + // label - The next point at which to resume evaluation of the generator body. + // trys - A stack of protected regions (try/catch/finally blocks). + // ops - A stack of pending instructions when inside of a finally block. + // f A value indicating whether the generator is executing. + // y An iterator to delegate for a yield*. + // t A temporary variable that holds one of the following values (note that these + // cases do not overlap): + // - The completion value when resuming from a `yield` or `yield*`. + // - The error value for a catch block. + // - The current protected region (array of try/catch/finally/end labels). + // - The verb (`next`, `throw`, or `return` method) to delegate to the expression + // of a `yield*`. + // - The result of evaluating the verb delegated to the expression of a `yield*`. + // + // functions: + // verb(n) Creates a bound callback to the `step` function for opcode `n`. + // step(op) Evaluates opcodes in a generator body until execution is suspended or + // completed. + // + // The __generator helper understands a limited set of instructions: + // 0: next(value?) - Start or resume the generator with the specified value. + // 1: throw(error) - Resume the generator with an exception. If the generator is + // suspended inside of one or more protected regions, evaluates + // any intervening finally blocks between the current label and + // the nearest catch block or function boundary. If uncaught, the + // exception is thrown to the caller. + // 2: return(value?) - Resume the generator as if with a return. If the generator is + // suspended inside of one or more protected regions, evaluates any + // intervening finally blocks. + // 3: break(label) - Jump to the specified label. If the label is outside of the + // current protected region, evaluates any intervening finally + // blocks. + // 4: yield(value?) - Yield execution to the caller with an optional value. When + // resumed, the generator will continue at the next label. + // 5: yield*(value) - Delegates evaluation to the supplied iterator. When + // delegation completes, the generator will continue at the next + // label. + // 6: catch(error) - Handles an exception thrown from within the generator body. If + // the current label is inside of one or more protected regions, + // evaluates any intervening finally blocks between the current + // label and the nearest catch block or function boundary. If + // uncaught, the exception is thrown to the caller. + // 7: endfinally - Ends a finally block, resuming the last instruction prior to + // entering a finally block. + // + // For examples of how these are used, see the comments in ./transformers/generators.ts + var generatorHelper = "\nvar __generator = (this && this.__generator) || function (thisArg, body) {\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t;\n return { next: verb(0), \"throw\": verb(1), \"return\": verb(2) };\n function verb(n) { return function (v) { return step([n, v]); }; }\n function step(op) {\n if (f) throw new TypeError(\"Generator is already executing.\");\n while (_) try {\n if (f = 1, y && (t = y[op[0] & 2 ? \"return\" : op[0] ? \"throw\" : \"next\"]) && !(t = t.call(y, op[1])).done) return t;\n if (y = 0, t) op = [0, t.value];\n switch (op[0]) {\n case 0: case 1: t = op; break;\n case 4: _.label++; return { value: op[1], done: false };\n case 5: _.label++; y = op[1]; op = [0]; continue;\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\n default:\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n if (t[2]) _.ops.pop();\n _.trys.pop(); continue;\n }\n op = body.call(thisArg, _);\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n }\n};"; + // emit output for the __export helper function + var exportStarHelper = "\nfunction __export(m) {\n for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];\n}"; + // emit output for the UMD helper function. + var umdHelper = "\n(function (dependencies, factory) {\n if (typeof module === 'object' && typeof module.exports === 'object') {\n var v = factory(require, exports); if (v !== undefined) module.exports = v;\n }\n else if (typeof define === 'function' && define.amd) {\n define(dependencies, factory);\n }\n})"; + var superHelper = "\nconst _super = name => super[name];"; + var advancedSuperHelper = "\nconst _super = (function (geti, seti) {\n const cache = Object.create(null);\n return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });\n})(name => super[name], (name, value) => super[name] = value);"; + var compilerOptions = host.getCompilerOptions(); + var languageVersion = ts.getEmitScriptTarget(compilerOptions); + var moduleKind = ts.getEmitModuleKind(compilerOptions); + var sourceMapDataList = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? [] : undefined; + var emittedFilesList = compilerOptions.listEmittedFiles ? [] : undefined; + var emitterDiagnostics = ts.createDiagnosticCollection(); + var newLine = host.getNewLine(); + var transformers = emitOnlyDtsFiles ? nullTransformers : ts.getTransformers(compilerOptions); + var writer = ts.createTextWriter(newLine); + var write = writer.write, writeLine = writer.writeLine, increaseIndent = writer.increaseIndent, decreaseIndent = writer.decreaseIndent; + var sourceMap = ts.createSourceMapWriter(host, writer); + var emitNodeWithSourceMap = sourceMap.emitNodeWithSourceMap, emitTokenWithSourceMap = sourceMap.emitTokenWithSourceMap; + var comments = ts.createCommentWriter(host, writer, sourceMap); + var emitNodeWithComments = comments.emitNodeWithComments, emitBodyWithDetachedComments = comments.emitBodyWithDetachedComments, emitTrailingCommentsOfPosition = comments.emitTrailingCommentsOfPosition; + var nodeIdToGeneratedName; + var autoGeneratedIdToGeneratedName; + var generatedNameSet; + var tempFlags; + var currentSourceFile; + var currentText; + var currentFileIdentifiers; + var extendsEmitted; + var assignEmitted; + var decorateEmitted; + var paramEmitted; + var awaiterEmitted; + var isOwnFileEmit; + var emitSkipped = false; + var sourceFiles = ts.getSourceFilesToEmit(host, targetSourceFile); + // Transform the source files + ts.performance.mark("beforeTransform"); + var _a = ts.transformFiles(resolver, host, sourceFiles, transformers), transformed = _a.transformed, emitNodeWithSubstitution = _a.emitNodeWithSubstitution, emitNodeWithNotification = _a.emitNodeWithNotification; + ts.performance.measure("transformTime", "beforeTransform"); + // Emit each output file + ts.performance.mark("beforePrint"); + ts.forEachTransformedEmitFile(host, transformed, emitFile, emitOnlyDtsFiles); + ts.performance.measure("printTime", "beforePrint"); + // Clean up emit nodes on parse tree + for (var _b = 0, sourceFiles_4 = sourceFiles; _b < sourceFiles_4.length; _b++) { + var sourceFile = sourceFiles_4[_b]; + ts.disposeEmitNodes(sourceFile); + } + return { + emitSkipped: emitSkipped, + diagnostics: emitterDiagnostics.getDiagnostics(), + emittedFiles: emittedFilesList, + sourceMaps: sourceMapDataList + }; + function emitFile(jsFilePath, sourceMapFilePath, declarationFilePath, sourceFiles, isBundledEmit) { + // Make sure not to write js file and source map file if any of them cannot be written + if (!host.isEmitBlocked(jsFilePath) && !compilerOptions.noEmit) { + if (!emitOnlyDtsFiles) { + printFile(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit); + } } - ts.Debug.assert(!oldProgram.structureIsReused); - // there is an old program, check if we can reuse its structure - var oldRootNames = oldProgram.getRootFileNames(); - if (!ts.arrayIsEqualTo(oldRootNames, rootNames)) { - return false; + else { + emitSkipped = true; } - if (!ts.arrayIsEqualTo(options.types, oldOptions.types)) { - return false; + if (declarationFilePath) { + emitSkipped = ts.writeDeclarationFile(declarationFilePath, ts.getOriginalSourceFiles(sourceFiles), isBundledEmit, host, resolver, emitterDiagnostics, emitOnlyDtsFiles) || emitSkipped; } - // check if program source files has changed in the way that can affect structure of the program - var newSourceFiles = []; - var filePaths = []; - var modifiedSourceFiles = []; - for (var _i = 0, _a = oldProgram.getSourceFiles(); _i < _a.length; _i++) { - var oldSourceFile = _a[_i]; - var newSourceFile = host.getSourceFileByPath - ? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.path, options.target) - : host.getSourceFile(oldSourceFile.fileName, options.target); - if (!newSourceFile) { - return false; - } - newSourceFile.path = oldSourceFile.path; - filePaths.push(newSourceFile.path); - if (oldSourceFile !== newSourceFile) { - if (oldSourceFile.hasNoDefaultLib !== newSourceFile.hasNoDefaultLib) { - // value of no-default-lib has changed - // this will affect if default library is injected into the list of files - return false; - } - // check tripleslash references - if (!ts.arrayIsEqualTo(oldSourceFile.referencedFiles, newSourceFile.referencedFiles, fileReferenceIsEqualTo)) { - // tripleslash references has changed - return false; - } - // check imports and module augmentations - collectExternalModuleReferences(newSourceFile); - if (!ts.arrayIsEqualTo(oldSourceFile.imports, newSourceFile.imports, moduleNameIsEqualTo)) { - // imports has changed - return false; - } - if (!ts.arrayIsEqualTo(oldSourceFile.moduleAugmentations, newSourceFile.moduleAugmentations, moduleNameIsEqualTo)) { - // moduleAugmentations has changed - return false; - } - if (!ts.arrayIsEqualTo(oldSourceFile.typeReferenceDirectives, newSourceFile.typeReferenceDirectives, fileReferenceIsEqualTo)) { - // 'types' references has changed - return false; - } - var newSourceFilePath = ts.getNormalizedAbsolutePath(newSourceFile.fileName, currentDirectory); - if (resolveModuleNamesWorker) { - var moduleNames = ts.map(ts.concatenate(newSourceFile.imports, newSourceFile.moduleAugmentations), getTextOfLiteral); - var resolutions = resolveModuleNamesWorker(moduleNames, newSourceFilePath); - // ensure that module resolution results are still correct - var resolutionsChanged = ts.hasChangesInResolutions(moduleNames, resolutions, oldSourceFile.resolvedModules, ts.moduleResolutionIsEqualTo); - if (resolutionsChanged) { - return false; - } - } - if (resolveTypeReferenceDirectiveNamesWorker) { - var typesReferenceDirectives = ts.map(newSourceFile.typeReferenceDirectives, function (x) { return x.fileName; }); - var resolutions = resolveTypeReferenceDirectiveNamesWorker(typesReferenceDirectives, newSourceFilePath); - // ensure that types resolutions are still correct - var resolutionsChanged = ts.hasChangesInResolutions(typesReferenceDirectives, resolutions, oldSourceFile.resolvedTypeReferenceDirectiveNames, ts.typeDirectiveIsEqualTo); - if (resolutionsChanged) { - return false; - } - } - // pass the cache of module/types resolutions from the old source file - newSourceFile.resolvedModules = oldSourceFile.resolvedModules; - newSourceFile.resolvedTypeReferenceDirectiveNames = oldSourceFile.resolvedTypeReferenceDirectiveNames; - modifiedSourceFiles.push(newSourceFile); + if (!emitSkipped && emittedFilesList) { + if (!emitOnlyDtsFiles) { + emittedFilesList.push(jsFilePath); } - else { - // file has no changes - use it as is - newSourceFile = oldSourceFile; + if (sourceMapFilePath) { + emittedFilesList.push(sourceMapFilePath); } - // if file has passed all checks it should be safe to reuse it - newSourceFiles.push(newSourceFile); - } - // update fileName -> file mapping - for (var i = 0, len = newSourceFiles.length; i < len; i++) { - filesByName.set(filePaths[i], newSourceFiles[i]); - } - files = newSourceFiles; - fileProcessingDiagnostics = oldProgram.getFileProcessingDiagnostics(); - for (var _b = 0, modifiedSourceFiles_1 = modifiedSourceFiles; _b < modifiedSourceFiles_1.length; _b++) { - var modifiedFile = modifiedSourceFiles_1[_b]; - fileProcessingDiagnostics.reattachFileDiagnostics(modifiedFile); - } - resolvedTypeReferenceDirectives = oldProgram.getResolvedTypeReferenceDirectives(); - oldProgram.structureIsReused = true; - return true; - } - function getEmitHost(writeFileCallback) { - return { - getCanonicalFileName: getCanonicalFileName, - getCommonSourceDirectory: program.getCommonSourceDirectory, - getCompilerOptions: program.getCompilerOptions, - getCurrentDirectory: function () { return currentDirectory; }, - getNewLine: function () { return host.getNewLine(); }, - getSourceFile: program.getSourceFile, - getSourceFileByPath: program.getSourceFileByPath, - getSourceFiles: program.getSourceFiles, - isSourceFileFromExternalLibrary: function (file) { return !!sourceFilesFoundSearchingNodeModules[file.path]; }, - writeFile: writeFileCallback || (function (fileName, data, writeByteOrderMark, onError, sourceFiles) { return host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles); }), - isEmitBlocked: isEmitBlocked, - }; + if (declarationFilePath) { + emittedFilesList.push(declarationFilePath); + } + } } - function getDiagnosticsProducingTypeChecker() { - return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = ts.createTypeChecker(program, /*produceDiagnostics:*/ true)); + function printFile(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit) { + sourceMap.initialize(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit); + nodeIdToGeneratedName = []; + autoGeneratedIdToGeneratedName = []; + generatedNameSet = ts.createMap(); + isOwnFileEmit = !isBundledEmit; + // Emit helpers from all the files + if (isBundledEmit && moduleKind) { + for (var _a = 0, sourceFiles_5 = sourceFiles; _a < sourceFiles_5.length; _a++) { + var sourceFile = sourceFiles_5[_a]; + emitEmitHelpers(sourceFile); + } + } + // Print each transformed source file. + ts.forEach(sourceFiles, printSourceFile); + writeLine(); + var sourceMappingURL = sourceMap.getSourceMappingURL(); + if (sourceMappingURL) { + write("//# " + "sourceMappingURL" + "=" + sourceMappingURL); // Sometimes tools can sometimes see this line as a source mapping url comment + } + // Write the source map + if (compilerOptions.sourceMap && !compilerOptions.inlineSourceMap) { + ts.writeFile(host, emitterDiagnostics, sourceMapFilePath, sourceMap.getText(), /*writeByteOrderMark*/ false); + } + // Record source map data for the test harness. + if (sourceMapDataList) { + sourceMapDataList.push(sourceMap.getSourceMapData()); + } + // Write the output file + ts.writeFile(host, emitterDiagnostics, jsFilePath, writer.getText(), compilerOptions.emitBOM); + // Reset state + sourceMap.reset(); + comments.reset(); + writer.reset(); + tempFlags = 0 /* Auto */; + currentSourceFile = undefined; + currentText = undefined; + extendsEmitted = false; + assignEmitted = false; + decorateEmitted = false; + paramEmitted = false; + awaiterEmitted = false; + isOwnFileEmit = false; + } + function printSourceFile(node) { + currentSourceFile = node; + currentText = node.text; + currentFileIdentifiers = node.identifiers; + sourceMap.setSourceFile(node); + comments.setSourceFile(node); + pipelineEmitWithNotification(0 /* SourceFile */, node); } - function getTypeChecker() { - return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = ts.createTypeChecker(program, /*produceDiagnostics:*/ false)); + /** + * Emits a node. + */ + function emit(node) { + pipelineEmitWithNotification(3 /* Unspecified */, node); + } + /** + * Emits an IdentifierName. + */ + function emitIdentifierName(node) { + pipelineEmitWithNotification(2 /* IdentifierName */, node); } - function emit(sourceFile, writeFileCallback, cancellationToken) { - return runWithCancellationToken(function () { return emitWorker(program, sourceFile, writeFileCallback, cancellationToken); }); + /** + * Emits an expression node. + */ + function emitExpression(node) { + pipelineEmitWithNotification(1 /* Expression */, node); } - function isEmitBlocked(emitFileName) { - return hasEmitBlockingDiagnostics.contains(ts.toPath(emitFileName, currentDirectory, getCanonicalFileName)); + /** + * Emits a node with possible notification. + * + * NOTE: Do not call this method directly. It is part of the emit pipeline + * and should only be called from printSourceFile, emit, emitExpression, or + * emitIdentifierName. + */ + function pipelineEmitWithNotification(emitContext, node) { + emitNodeWithNotification(emitContext, node, pipelineEmitWithComments); } - function emitWorker(program, sourceFile, writeFileCallback, cancellationToken) { - var declarationDiagnostics = []; - if (options.noEmit) { - return { diagnostics: declarationDiagnostics, sourceMaps: undefined, emittedFiles: undefined, emitSkipped: true }; + /** + * Emits a node with comments. + * + * NOTE: Do not call this method directly. It is part of the emit pipeline + * and should only be called indirectly from pipelineEmitWithNotification. + */ + function pipelineEmitWithComments(emitContext, node) { + // Do not emit comments for SourceFile + if (emitContext === 0 /* SourceFile */) { + pipelineEmitWithSourceMap(emitContext, node); + return; } - // If the noEmitOnError flag is set, then check if we have any errors so far. If so, - // immediately bail out. Note that we pass 'undefined' for 'sourceFile' so that we - // get any preEmit diagnostics, not just the ones - if (options.noEmitOnError) { - var diagnostics = program.getOptionsDiagnostics(cancellationToken).concat(program.getSyntacticDiagnostics(sourceFile, cancellationToken), program.getGlobalDiagnostics(cancellationToken), program.getSemanticDiagnostics(sourceFile, cancellationToken)); - if (diagnostics.length === 0 && program.getCompilerOptions().declaration) { - declarationDiagnostics = program.getDeclarationDiagnostics(/*sourceFile*/ undefined, cancellationToken); - } - if (diagnostics.length > 0 || declarationDiagnostics.length > 0) { - return { - diagnostics: ts.concatenate(diagnostics, declarationDiagnostics), - sourceMaps: undefined, - emittedFiles: undefined, - emitSkipped: true - }; - } + emitNodeWithComments(emitContext, node, pipelineEmitWithSourceMap); + } + /** + * Emits a node with source maps. + * + * NOTE: Do not call this method directly. It is part of the emit pipeline + * and should only be called indirectly from pipelineEmitWithComments. + */ + function pipelineEmitWithSourceMap(emitContext, node) { + // Do not emit source mappings for SourceFile or IdentifierName + if (emitContext === 0 /* SourceFile */ + || emitContext === 2 /* IdentifierName */) { + pipelineEmitWithSubstitution(emitContext, node); + return; } - // Create the emit resolver outside of the "emitTime" tracking code below. That way - // any cost associated with it (like type checking) are appropriate associated with - // the type-checking counter. - // - // If the -out option is specified, we should not pass the source file to getEmitResolver. - // This is because in the -out scenario all files need to be emitted, and therefore all - // files need to be type checked. And the way to specify that all files need to be type - // checked is to not pass the file to getEmitResolver. - var emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver((options.outFile || options.out) ? undefined : sourceFile); - ts.performance.mark("beforeEmit"); - var emitResult = ts.emitFiles(emitResolver, getEmitHost(writeFileCallback), sourceFile); - ts.performance.mark("afterEmit"); - ts.performance.measure("Emit", "beforeEmit", "afterEmit"); - return emitResult; + emitNodeWithSourceMap(emitContext, node, pipelineEmitWithSubstitution); } - function getSourceFile(fileName) { - return getSourceFileByPath(ts.toPath(fileName, currentDirectory, getCanonicalFileName)); + /** + * Emits a node with possible substitution. + * + * NOTE: Do not call this method directly. It is part of the emit pipeline + * and should only be called indirectly from pipelineEmitWithSourceMap or + * pipelineEmitInUnspecifiedContext (when picking a more specific context). + */ + function pipelineEmitWithSubstitution(emitContext, node) { + emitNodeWithSubstitution(emitContext, node, pipelineEmitForContext); } - function getSourceFileByPath(path) { - return filesByName.get(path); + /** + * Emits a node. + * + * NOTE: Do not call this method directly. It is part of the emit pipeline + * and should only be called indirectly from pipelineEmitWithSubstitution. + */ + function pipelineEmitForContext(emitContext, node) { + switch (emitContext) { + case 0 /* SourceFile */: return pipelineEmitInSourceFileContext(node); + case 2 /* IdentifierName */: return pipelineEmitInIdentifierNameContext(node); + case 3 /* Unspecified */: return pipelineEmitInUnspecifiedContext(node); + case 1 /* Expression */: return pipelineEmitInExpressionContext(node); + } } - function getDiagnosticsHelper(sourceFile, getDiagnostics, cancellationToken) { - if (sourceFile) { - return getDiagnostics(sourceFile, cancellationToken); + /** + * Emits a node in the SourceFile EmitContext. + * + * NOTE: Do not call this method directly. It is part of the emit pipeline + * and should only be called indirectly from pipelineEmitForContext. + */ + function pipelineEmitInSourceFileContext(node) { + var kind = node.kind; + switch (kind) { + // Top-level nodes + case 256 /* SourceFile */: + return emitSourceFile(node); } - var allDiagnostics = []; - ts.forEach(program.getSourceFiles(), function (sourceFile) { - if (cancellationToken) { - cancellationToken.throwIfCancellationRequested(); - } - ts.addRange(allDiagnostics, getDiagnostics(sourceFile, cancellationToken)); - }); - return ts.sortAndDeduplicateDiagnostics(allDiagnostics); } - function getSyntacticDiagnostics(sourceFile, cancellationToken) { - return getDiagnosticsHelper(sourceFile, getSyntacticDiagnosticsForFile, cancellationToken); + /** + * Emits a node in the IdentifierName EmitContext. + * + * NOTE: Do not call this method directly. It is part of the emit pipeline + * and should only be called indirectly from pipelineEmitForContext. + */ + function pipelineEmitInIdentifierNameContext(node) { + var kind = node.kind; + switch (kind) { + // Identifiers + case 69 /* Identifier */: + return emitIdentifier(node); + } } - function getSemanticDiagnostics(sourceFile, cancellationToken) { - return getDiagnosticsHelper(sourceFile, getSemanticDiagnosticsForFile, cancellationToken); + /** + * Emits a node in the Unspecified EmitContext. + * + * NOTE: Do not call this method directly. It is part of the emit pipeline + * and should only be called indirectly from pipelineEmitForContext. + */ + function pipelineEmitInUnspecifiedContext(node) { + var kind = node.kind; + switch (kind) { + // Pseudo-literals + case 12 /* TemplateHead */: + case 13 /* TemplateMiddle */: + case 14 /* TemplateTail */: + return emitLiteral(node); + // Identifiers + case 69 /* Identifier */: + return emitIdentifier(node); + // Reserved words + case 74 /* ConstKeyword */: + case 77 /* DefaultKeyword */: + case 82 /* ExportKeyword */: + case 103 /* VoidKeyword */: + // Strict mode reserved words + case 110 /* PrivateKeyword */: + case 111 /* ProtectedKeyword */: + case 112 /* PublicKeyword */: + case 113 /* StaticKeyword */: + // Contextual keywords + case 115 /* AbstractKeyword */: + case 117 /* AnyKeyword */: + case 118 /* AsyncKeyword */: + case 120 /* BooleanKeyword */: + case 122 /* DeclareKeyword */: + case 130 /* NumberKeyword */: + case 128 /* ReadonlyKeyword */: + case 132 /* StringKeyword */: + case 133 /* SymbolKeyword */: + case 137 /* GlobalKeyword */: + writeTokenText(kind); + return; + // Parse tree nodes + // Names + case 139 /* QualifiedName */: + return emitQualifiedName(node); + case 140 /* ComputedPropertyName */: + return emitComputedPropertyName(node); + // Signature elements + case 141 /* TypeParameter */: + return emitTypeParameter(node); + case 142 /* Parameter */: + return emitParameter(node); + case 143 /* Decorator */: + return emitDecorator(node); + // Type members + case 144 /* PropertySignature */: + return emitPropertySignature(node); + case 145 /* PropertyDeclaration */: + return emitPropertyDeclaration(node); + case 146 /* MethodSignature */: + return emitMethodSignature(node); + case 147 /* MethodDeclaration */: + return emitMethodDeclaration(node); + case 148 /* Constructor */: + return emitConstructor(node); + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + return emitAccessorDeclaration(node); + case 151 /* CallSignature */: + return emitCallSignature(node); + case 152 /* ConstructSignature */: + return emitConstructSignature(node); + case 153 /* IndexSignature */: + return emitIndexSignature(node); + // Types + case 154 /* TypePredicate */: + return emitTypePredicate(node); + case 155 /* TypeReference */: + return emitTypeReference(node); + case 156 /* FunctionType */: + return emitFunctionType(node); + case 157 /* ConstructorType */: + return emitConstructorType(node); + case 158 /* TypeQuery */: + return emitTypeQuery(node); + case 159 /* TypeLiteral */: + return emitTypeLiteral(node); + case 160 /* ArrayType */: + return emitArrayType(node); + case 161 /* TupleType */: + return emitTupleType(node); + case 162 /* UnionType */: + return emitUnionType(node); + case 163 /* IntersectionType */: + return emitIntersectionType(node); + case 164 /* ParenthesizedType */: + return emitParenthesizedType(node); + case 194 /* ExpressionWithTypeArguments */: + return emitExpressionWithTypeArguments(node); + case 165 /* ThisType */: + return emitThisType(node); + case 166 /* LiteralType */: + return emitLiteralType(node); + // Binding patterns + case 167 /* ObjectBindingPattern */: + return emitObjectBindingPattern(node); + case 168 /* ArrayBindingPattern */: + return emitArrayBindingPattern(node); + case 169 /* BindingElement */: + return emitBindingElement(node); + // Misc + case 197 /* TemplateSpan */: + return emitTemplateSpan(node); + case 198 /* SemicolonClassElement */: + return emitSemicolonClassElement(node); + // Statements + case 199 /* Block */: + return emitBlock(node); + case 200 /* VariableStatement */: + return emitVariableStatement(node); + case 201 /* EmptyStatement */: + return emitEmptyStatement(node); + case 202 /* ExpressionStatement */: + return emitExpressionStatement(node); + case 203 /* IfStatement */: + return emitIfStatement(node); + case 204 /* DoStatement */: + return emitDoStatement(node); + case 205 /* WhileStatement */: + return emitWhileStatement(node); + case 206 /* ForStatement */: + return emitForStatement(node); + case 207 /* ForInStatement */: + return emitForInStatement(node); + case 208 /* ForOfStatement */: + return emitForOfStatement(node); + case 209 /* ContinueStatement */: + return emitContinueStatement(node); + case 210 /* BreakStatement */: + return emitBreakStatement(node); + case 211 /* ReturnStatement */: + return emitReturnStatement(node); + case 212 /* WithStatement */: + return emitWithStatement(node); + case 213 /* SwitchStatement */: + return emitSwitchStatement(node); + case 214 /* LabeledStatement */: + return emitLabeledStatement(node); + case 215 /* ThrowStatement */: + return emitThrowStatement(node); + case 216 /* TryStatement */: + return emitTryStatement(node); + case 217 /* DebuggerStatement */: + return emitDebuggerStatement(node); + // Declarations + case 218 /* VariableDeclaration */: + return emitVariableDeclaration(node); + case 219 /* VariableDeclarationList */: + return emitVariableDeclarationList(node); + case 220 /* FunctionDeclaration */: + return emitFunctionDeclaration(node); + case 221 /* ClassDeclaration */: + return emitClassDeclaration(node); + case 222 /* InterfaceDeclaration */: + return emitInterfaceDeclaration(node); + case 223 /* TypeAliasDeclaration */: + return emitTypeAliasDeclaration(node); + case 224 /* EnumDeclaration */: + return emitEnumDeclaration(node); + case 225 /* ModuleDeclaration */: + return emitModuleDeclaration(node); + case 226 /* ModuleBlock */: + return emitModuleBlock(node); + case 227 /* CaseBlock */: + return emitCaseBlock(node); + case 229 /* ImportEqualsDeclaration */: + return emitImportEqualsDeclaration(node); + case 230 /* ImportDeclaration */: + return emitImportDeclaration(node); + case 231 /* ImportClause */: + return emitImportClause(node); + case 232 /* NamespaceImport */: + return emitNamespaceImport(node); + case 233 /* NamedImports */: + return emitNamedImports(node); + case 234 /* ImportSpecifier */: + return emitImportSpecifier(node); + case 235 /* ExportAssignment */: + return emitExportAssignment(node); + case 236 /* ExportDeclaration */: + return emitExportDeclaration(node); + case 237 /* NamedExports */: + return emitNamedExports(node); + case 238 /* ExportSpecifier */: + return emitExportSpecifier(node); + case 239 /* MissingDeclaration */: + return; + // Module references + case 240 /* ExternalModuleReference */: + return emitExternalModuleReference(node); + // JSX (non-expression) + case 244 /* JsxText */: + return emitJsxText(node); + case 243 /* JsxOpeningElement */: + return emitJsxOpeningElement(node); + case 245 /* JsxClosingElement */: + return emitJsxClosingElement(node); + case 246 /* JsxAttribute */: + return emitJsxAttribute(node); + case 247 /* JsxSpreadAttribute */: + return emitJsxSpreadAttribute(node); + case 248 /* JsxExpression */: + return emitJsxExpression(node); + // Clauses + case 249 /* CaseClause */: + return emitCaseClause(node); + case 250 /* DefaultClause */: + return emitDefaultClause(node); + case 251 /* HeritageClause */: + return emitHeritageClause(node); + case 252 /* CatchClause */: + return emitCatchClause(node); + // Property assignments + case 253 /* PropertyAssignment */: + return emitPropertyAssignment(node); + case 254 /* ShorthandPropertyAssignment */: + return emitShorthandPropertyAssignment(node); + // Enum + case 255 /* EnumMember */: + return emitEnumMember(node); + } + // If the node is an expression, try to emit it as an expression with + // substitution. + if (ts.isExpression(node)) { + return pipelineEmitWithSubstitution(1 /* Expression */, node); + } } - function getDeclarationDiagnostics(sourceFile, cancellationToken) { - var options = program.getCompilerOptions(); - // collect diagnostics from the program only once if either no source file was specified or out/outFile is set (bundled emit) - if (!sourceFile || options.out || options.outFile) { - return getDeclarationDiagnosticsWorker(sourceFile, cancellationToken); + /** + * Emits a node in the Expression EmitContext. + * + * NOTE: Do not call this method directly. It is part of the emit pipeline + * and should only be called indirectly from pipelineEmitForContext. + */ + function pipelineEmitInExpressionContext(node) { + var kind = node.kind; + switch (kind) { + // Literals + case 8 /* NumericLiteral */: + return emitNumericLiteral(node); + case 9 /* StringLiteral */: + case 10 /* RegularExpressionLiteral */: + case 11 /* NoSubstitutionTemplateLiteral */: + return emitLiteral(node); + // Identifiers + case 69 /* Identifier */: + return emitIdentifier(node); + // Reserved words + case 84 /* FalseKeyword */: + case 93 /* NullKeyword */: + case 95 /* SuperKeyword */: + case 99 /* TrueKeyword */: + case 97 /* ThisKeyword */: + writeTokenText(kind); + return; + // Expressions + case 170 /* ArrayLiteralExpression */: + return emitArrayLiteralExpression(node); + case 171 /* ObjectLiteralExpression */: + return emitObjectLiteralExpression(node); + case 172 /* PropertyAccessExpression */: + return emitPropertyAccessExpression(node); + case 173 /* ElementAccessExpression */: + return emitElementAccessExpression(node); + case 174 /* CallExpression */: + return emitCallExpression(node); + case 175 /* NewExpression */: + return emitNewExpression(node); + case 176 /* TaggedTemplateExpression */: + return emitTaggedTemplateExpression(node); + case 177 /* TypeAssertionExpression */: + return emitTypeAssertionExpression(node); + case 178 /* ParenthesizedExpression */: + return emitParenthesizedExpression(node); + case 179 /* FunctionExpression */: + return emitFunctionExpression(node); + case 180 /* ArrowFunction */: + return emitArrowFunction(node); + case 181 /* DeleteExpression */: + return emitDeleteExpression(node); + case 182 /* TypeOfExpression */: + return emitTypeOfExpression(node); + case 183 /* VoidExpression */: + return emitVoidExpression(node); + case 184 /* AwaitExpression */: + return emitAwaitExpression(node); + case 185 /* PrefixUnaryExpression */: + return emitPrefixUnaryExpression(node); + case 186 /* PostfixUnaryExpression */: + return emitPostfixUnaryExpression(node); + case 187 /* BinaryExpression */: + return emitBinaryExpression(node); + case 188 /* ConditionalExpression */: + return emitConditionalExpression(node); + case 189 /* TemplateExpression */: + return emitTemplateExpression(node); + case 190 /* YieldExpression */: + return emitYieldExpression(node); + case 191 /* SpreadElementExpression */: + return emitSpreadElementExpression(node); + case 192 /* ClassExpression */: + return emitClassExpression(node); + case 193 /* OmittedExpression */: + return; + case 195 /* AsExpression */: + return emitAsExpression(node); + case 196 /* NonNullExpression */: + return emitNonNullExpression(node); + // JSX + case 241 /* JsxElement */: + return emitJsxElement(node); + case 242 /* JsxSelfClosingElement */: + return emitJsxSelfClosingElement(node); + // Transformation nodes + case 288 /* PartiallyEmittedExpression */: + return emitPartiallyEmittedExpression(node); + } + } + // + // Literals/Pseudo-literals + // + // SyntaxKind.NumericLiteral + function emitNumericLiteral(node) { + emitLiteral(node); + if (node.trailingComment) { + write(" /*" + node.trailingComment + "*/"); + } + } + // SyntaxKind.StringLiteral + // SyntaxKind.RegularExpressionLiteral + // SyntaxKind.NoSubstitutionTemplateLiteral + // SyntaxKind.TemplateHead + // SyntaxKind.TemplateMiddle + // SyntaxKind.TemplateTail + function emitLiteral(node) { + var text = getLiteralTextOfNode(node); + if ((compilerOptions.sourceMap || compilerOptions.inlineSourceMap) + && (node.kind === 9 /* StringLiteral */ || ts.isTemplateLiteralKind(node.kind))) { + writer.writeLiteral(text); } else { - return getDiagnosticsHelper(sourceFile, getDeclarationDiagnosticsForFile, cancellationToken); + write(text); } } - function getSyntacticDiagnosticsForFile(sourceFile, cancellationToken) { - return sourceFile.parseDiagnostics; + // + // Identifiers + // + function emitIdentifier(node) { + if (ts.getEmitFlags(node) & 16 /* UMDDefine */) { + writeLines(umdHelper); + } + else { + write(getTextOfNode(node, /*includeTrivia*/ false)); + } } - function runWithCancellationToken(func) { - try { - return func(); + // + // Names + // + function emitQualifiedName(node) { + emitEntityName(node.left); + write("."); + emit(node.right); + } + function emitEntityName(node) { + if (node.kind === 69 /* Identifier */) { + emitExpression(node); } - catch (e) { - if (e instanceof ts.OperationCanceledException) { - // We were canceled while performing the operation. Because our type checker - // might be a bad state, we need to throw it away. - // - // Note: we are overly aggressive here. We do not actually *have* to throw away - // the "noDiagnosticsTypeChecker". However, for simplicity, i'd like to keep - // the lifetimes of these two TypeCheckers the same. Also, we generally only - // cancel when the user has made a change anyways. And, in that case, we (the - // program instance) will get thrown away anyways. So trying to keep one of - // these type checkers alive doesn't serve much purpose. - noDiagnosticsTypeChecker = undefined; - diagnosticsProducingTypeChecker = undefined; - } - throw e; + else { + emit(node); } } - function getSemanticDiagnosticsForFile(sourceFile, cancellationToken) { - return runWithCancellationToken(function () { - var typeChecker = getDiagnosticsProducingTypeChecker(); - ts.Debug.assert(!!sourceFile.bindDiagnostics); - var bindDiagnostics = sourceFile.bindDiagnostics; - // For JavaScript files, we don't want to report the normal typescript semantic errors. - // Instead, we just report errors for using TypeScript-only constructs from within a - // JavaScript file. - var checkDiagnostics = ts.isSourceFileJavaScript(sourceFile) ? - getJavaScriptSemanticDiagnosticsForFile(sourceFile, cancellationToken) : - typeChecker.getDiagnostics(sourceFile, cancellationToken); - var fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName); - var programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName); - return bindDiagnostics.concat(checkDiagnostics).concat(fileProcessingDiagnosticsInFile).concat(programDiagnosticsInFile); - }); + function emitComputedPropertyName(node) { + write("["); + emitExpression(node.expression); + write("]"); } - function getJavaScriptSemanticDiagnosticsForFile(sourceFile, cancellationToken) { - return runWithCancellationToken(function () { - var diagnostics = []; - walk(sourceFile); - return diagnostics; - function walk(node) { - if (!node) { - return false; - } - switch (node.kind) { - case 229 /* ImportEqualsDeclaration */: - diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.import_can_only_be_used_in_a_ts_file)); - return true; - case 235 /* ExportAssignment */: - if (node.isExportEquals) { - diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.export_can_only_be_used_in_a_ts_file)); - return true; - } - break; - case 221 /* ClassDeclaration */: - var classDeclaration = node; - if (checkModifiers(classDeclaration.modifiers) || - checkTypeParameters(classDeclaration.typeParameters)) { - return true; - } - break; - case 251 /* HeritageClause */: - var heritageClause = node; - if (heritageClause.token === 106 /* ImplementsKeyword */) { - diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.implements_clauses_can_only_be_used_in_a_ts_file)); - return true; - } - break; - case 222 /* InterfaceDeclaration */: - diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.interface_declarations_can_only_be_used_in_a_ts_file)); - return true; - case 225 /* ModuleDeclaration */: - diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.module_declarations_can_only_be_used_in_a_ts_file)); - return true; - case 223 /* TypeAliasDeclaration */: - diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.type_aliases_can_only_be_used_in_a_ts_file)); - return true; - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - case 148 /* Constructor */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 179 /* FunctionExpression */: - case 220 /* FunctionDeclaration */: - case 180 /* ArrowFunction */: - case 220 /* FunctionDeclaration */: - var functionDeclaration = node; - if (checkModifiers(functionDeclaration.modifiers) || - checkTypeParameters(functionDeclaration.typeParameters) || - checkTypeAnnotation(functionDeclaration.type)) { - return true; - } - break; - case 200 /* VariableStatement */: - var variableStatement = node; - if (checkModifiers(variableStatement.modifiers)) { - return true; - } - break; - case 218 /* VariableDeclaration */: - var variableDeclaration = node; - if (checkTypeAnnotation(variableDeclaration.type)) { - return true; - } - break; - case 174 /* CallExpression */: - case 175 /* NewExpression */: - var expression = node; - if (expression.typeArguments && expression.typeArguments.length > 0) { - var start = expression.typeArguments.pos; - diagnostics.push(ts.createFileDiagnostic(sourceFile, start, expression.typeArguments.end - start, ts.Diagnostics.type_arguments_can_only_be_used_in_a_ts_file)); - return true; - } - break; - case 142 /* Parameter */: - var parameter = node; - if (parameter.modifiers) { - var start = parameter.modifiers.pos; - diagnostics.push(ts.createFileDiagnostic(sourceFile, start, parameter.modifiers.end - start, ts.Diagnostics.parameter_modifiers_can_only_be_used_in_a_ts_file)); - return true; - } - if (parameter.questionToken) { - diagnostics.push(ts.createDiagnosticForNode(parameter.questionToken, ts.Diagnostics._0_can_only_be_used_in_a_ts_file, "?")); - return true; - } - if (parameter.type) { - diagnostics.push(ts.createDiagnosticForNode(parameter.type, ts.Diagnostics.types_can_only_be_used_in_a_ts_file)); - return true; - } - break; - case 145 /* PropertyDeclaration */: - var propertyDeclaration = node; - if (propertyDeclaration.modifiers) { - for (var _i = 0, _a = propertyDeclaration.modifiers; _i < _a.length; _i++) { - var modifier = _a[_i]; - if (modifier.kind !== 113 /* StaticKeyword */) { - diagnostics.push(ts.createDiagnosticForNode(modifier, ts.Diagnostics._0_can_only_be_used_in_a_ts_file, ts.tokenToString(modifier.kind))); - return true; - } - } - } - if (checkTypeAnnotation(node.type)) { - return true; - } - break; - case 224 /* EnumDeclaration */: - diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.enum_declarations_can_only_be_used_in_a_ts_file)); - return true; - case 177 /* TypeAssertionExpression */: - var typeAssertionExpression = node; - diagnostics.push(ts.createDiagnosticForNode(typeAssertionExpression.type, ts.Diagnostics.type_assertion_expressions_can_only_be_used_in_a_ts_file)); - return true; - case 143 /* Decorator */: - if (!options.experimentalDecorators) { - diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_to_remove_this_warning)); - } - return true; - } - return ts.forEachChild(node, walk); - } - function checkTypeParameters(typeParameters) { - if (typeParameters) { - var start = typeParameters.pos; - diagnostics.push(ts.createFileDiagnostic(sourceFile, start, typeParameters.end - start, ts.Diagnostics.type_parameter_declarations_can_only_be_used_in_a_ts_file)); - return true; - } - return false; - } - function checkTypeAnnotation(type) { - if (type) { - diagnostics.push(ts.createDiagnosticForNode(type, ts.Diagnostics.types_can_only_be_used_in_a_ts_file)); - return true; - } - return false; - } - function checkModifiers(modifiers) { - if (modifiers) { - for (var _i = 0, modifiers_1 = modifiers; _i < modifiers_1.length; _i++) { - var modifier = modifiers_1[_i]; - switch (modifier.kind) { - case 112 /* PublicKeyword */: - case 110 /* PrivateKeyword */: - case 111 /* ProtectedKeyword */: - case 128 /* ReadonlyKeyword */: - case 122 /* DeclareKeyword */: - diagnostics.push(ts.createDiagnosticForNode(modifier, ts.Diagnostics._0_can_only_be_used_in_a_ts_file, ts.tokenToString(modifier.kind))); - return true; - // These are all legal modifiers. - case 113 /* StaticKeyword */: - case 82 /* ExportKeyword */: - case 74 /* ConstKeyword */: - case 77 /* DefaultKeyword */: - case 115 /* AbstractKeyword */: - } - } - } - return false; - } - }); + // + // Signature elements + // + function emitTypeParameter(node) { + emit(node.name); + emitWithPrefix(" extends ", node.constraint); + } + function emitParameter(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + writeIfPresent(node.dotDotDotToken, "..."); + emit(node.name); + writeIfPresent(node.questionToken, "?"); + emitExpressionWithPrefix(" = ", node.initializer); + emitWithPrefix(": ", node.type); + } + function emitDecorator(decorator) { + write("@"); + emitExpression(decorator.expression); } - function getDeclarationDiagnosticsWorker(sourceFile, cancellationToken) { - return runWithCancellationToken(function () { - var resolver = getDiagnosticsProducingTypeChecker().getEmitResolver(sourceFile, cancellationToken); - // Don't actually write any files since we're just getting diagnostics. - var writeFile = function () { }; - return ts.getDeclarationDiagnostics(getEmitHost(writeFile), resolver, sourceFile); - }); + // + // Type members + // + function emitPropertySignature(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + emit(node.name); + writeIfPresent(node.questionToken, "?"); + emitWithPrefix(": ", node.type); + write(";"); + } + function emitPropertyDeclaration(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + emit(node.name); + emitWithPrefix(": ", node.type); + emitExpressionWithPrefix(" = ", node.initializer); + write(";"); + } + function emitMethodSignature(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + emit(node.name); + writeIfPresent(node.questionToken, "?"); + emitTypeParameters(node, node.typeParameters); + emitParameters(node, node.parameters); + emitWithPrefix(": ", node.type); + write(";"); + } + function emitMethodDeclaration(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + writeIfPresent(node.asteriskToken, "*"); + emit(node.name); + emitSignatureAndBody(node, emitSignatureHead); + } + function emitConstructor(node) { + emitModifiers(node, node.modifiers); + write("constructor"); + emitSignatureAndBody(node, emitSignatureHead); + } + function emitAccessorDeclaration(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + write(node.kind === 149 /* GetAccessor */ ? "get " : "set "); + emit(node.name); + emitSignatureAndBody(node, emitSignatureHead); + } + function emitCallSignature(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + emitTypeParameters(node, node.typeParameters); + emitParameters(node, node.parameters); + emitWithPrefix(": ", node.type); + write(";"); + } + function emitConstructSignature(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + write("new "); + emitTypeParameters(node, node.typeParameters); + emitParameters(node, node.parameters); + emitWithPrefix(": ", node.type); + write(";"); + } + function emitIndexSignature(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + emitParametersForIndexSignature(node, node.parameters); + emitWithPrefix(": ", node.type); + write(";"); } - function getDeclarationDiagnosticsForFile(sourceFile, cancellationToken) { - return ts.isDeclarationFile(sourceFile) ? [] : getDeclarationDiagnosticsWorker(sourceFile, cancellationToken); + function emitSemicolonClassElement(node) { + write(";"); } - function getOptionsDiagnostics() { - var allDiagnostics = []; - ts.addRange(allDiagnostics, fileProcessingDiagnostics.getGlobalDiagnostics()); - ts.addRange(allDiagnostics, programDiagnostics.getGlobalDiagnostics()); - return ts.sortAndDeduplicateDiagnostics(allDiagnostics); + // + // Types + // + function emitTypePredicate(node) { + emit(node.parameterName); + write(" is "); + emit(node.type); + } + function emitTypeReference(node) { + emit(node.typeName); + emitTypeArguments(node, node.typeArguments); + } + function emitFunctionType(node) { + emitTypeParameters(node, node.typeParameters); + emitParametersForArrow(node, node.parameters); + write(" => "); + emit(node.type); + } + function emitConstructorType(node) { + write("new "); + emitTypeParameters(node, node.typeParameters); + emitParametersForArrow(node, node.parameters); + write(" => "); + emit(node.type); + } + function emitTypeQuery(node) { + write("typeof "); + emit(node.exprName); + } + function emitTypeLiteral(node) { + write("{"); + emitList(node, node.members, 65 /* TypeLiteralMembers */); + write("}"); } - function getGlobalDiagnostics() { - var allDiagnostics = []; - ts.addRange(allDiagnostics, getDiagnosticsProducingTypeChecker().getGlobalDiagnostics()); - return ts.sortAndDeduplicateDiagnostics(allDiagnostics); + function emitArrayType(node) { + emit(node.elementType); + write("[]"); } - function hasExtension(fileName) { - return ts.getBaseFileName(fileName).indexOf(".") >= 0; + function emitTupleType(node) { + write("["); + emitList(node, node.elementTypes, 336 /* TupleTypeElements */); + write("]"); } - function processRootFile(fileName, isDefaultLib) { - processSourceFile(ts.normalizePath(fileName), isDefaultLib, /*isReference*/ true); + function emitUnionType(node) { + emitList(node, node.types, 260 /* UnionTypeConstituents */); } - function fileReferenceIsEqualTo(a, b) { - return a.fileName === b.fileName; + function emitIntersectionType(node) { + emitList(node, node.types, 264 /* IntersectionTypeConstituents */); } - function moduleNameIsEqualTo(a, b) { - return a.text === b.text; + function emitParenthesizedType(node) { + write("("); + emit(node.type); + write(")"); } - function getTextOfLiteral(literal) { - return literal.text; + function emitThisType(node) { + write("this"); } - function collectExternalModuleReferences(file) { - if (file.imports) { - return; + function emitLiteralType(node) { + emitExpression(node.literal); + } + // + // Binding patterns + // + function emitObjectBindingPattern(node) { + var elements = node.elements; + if (elements.length === 0) { + write("{}"); } - var isJavaScriptFile = ts.isSourceFileJavaScript(file); - var isExternalModuleFile = ts.isExternalModule(file); - var imports; - var moduleAugmentations; - for (var _i = 0, _a = file.statements; _i < _a.length; _i++) { - var node = _a[_i]; - collectModuleReferences(node, /*inAmbientModule*/ false); - if (isJavaScriptFile) { - collectRequireCalls(node); - } + else { + write("{"); + emitList(node, elements, 432 /* ObjectBindingPatternElements */); + write("}"); } - file.imports = imports || emptyArray; - file.moduleAugmentations = moduleAugmentations || emptyArray; - return; - function collectModuleReferences(node, inAmbientModule) { - switch (node.kind) { - case 230 /* ImportDeclaration */: - case 229 /* ImportEqualsDeclaration */: - case 236 /* ExportDeclaration */: - var moduleNameExpr = ts.getExternalModuleName(node); - if (!moduleNameExpr || moduleNameExpr.kind !== 9 /* StringLiteral */) { - break; - } - if (!moduleNameExpr.text) { - break; - } - // TypeScript 1.0 spec (April 2014): 12.1.6 - // An ExternalImportDeclaration in an AmbientExternalModuleDeclaration may reference other external modules - // only through top - level external module names. Relative external module names are not permitted. - if (!inAmbientModule || !ts.isExternalModuleNameRelative(moduleNameExpr.text)) { - (imports || (imports = [])).push(moduleNameExpr); - } - break; - case 225 /* ModuleDeclaration */: - if (ts.isAmbientModule(node) && (inAmbientModule || node.flags & 2 /* Ambient */ || ts.isDeclarationFile(file))) { - var moduleName = node.name; - // Ambient module declarations can be interpreted as augmentations for some existing external modules. - // This will happen in two cases: - // - if current file is external module then module augmentation is a ambient module declaration defined in the top level scope - // - if current file is not external module then module augmentation is an ambient module declaration with non-relative module name - // immediately nested in top level ambient module declaration . - if (isExternalModuleFile || (inAmbientModule && !ts.isExternalModuleNameRelative(moduleName.text))) { - (moduleAugmentations || (moduleAugmentations = [])).push(moduleName); - } - else if (!inAmbientModule) { - // An AmbientExternalModuleDeclaration declares an external module. - // This type of declaration is permitted only in the global module. - // The StringLiteral must specify a top - level external module name. - // Relative external module names are not permitted - // NOTE: body of ambient module is always a module block, if it exists - var body = node.body; - if (body) { - for (var _i = 0, _a = body.statements; _i < _a.length; _i++) { - var statement = _a[_i]; - collectModuleReferences(statement, /*inAmbientModule*/ true); - } - } - } - } - } + } + function emitArrayBindingPattern(node) { + var elements = node.elements; + if (elements.length === 0) { + write("[]"); } - function collectRequireCalls(node) { - if (ts.isRequireCall(node, /*checkArgumentIsStringLiteral*/ true)) { - (imports || (imports = [])).push(node.arguments[0]); - } - else { - ts.forEachChild(node, collectRequireCalls); - } + else { + write("["); + emitList(node, node.elements, 304 /* ArrayBindingPatternElements */); + write("]"); } } - /** - * 'isReference' indicates whether the file was brought in via a reference directive (rather than an import declaration) - */ - function processSourceFile(fileName, isDefaultLib, isReference, refFile, refPos, refEnd) { - var diagnosticArgument; - var diagnostic; - if (hasExtension(fileName)) { - if (!options.allowNonTsExtensions && !ts.forEach(supportedExtensions, function (extension) { return ts.fileExtensionIs(host.getCanonicalFileName(fileName), extension); })) { - diagnostic = ts.Diagnostics.File_0_has_unsupported_extension_The_only_supported_extensions_are_1; - diagnosticArgument = [fileName, "'" + supportedExtensions.join("', '") + "'"]; - } - else if (!findSourceFile(fileName, ts.toPath(fileName, currentDirectory, getCanonicalFileName), isDefaultLib, isReference, refFile, refPos, refEnd)) { - diagnostic = ts.Diagnostics.File_0_not_found; - diagnosticArgument = [fileName]; - } - else if (refFile && host.getCanonicalFileName(fileName) === host.getCanonicalFileName(refFile.fileName)) { - diagnostic = ts.Diagnostics.A_file_cannot_have_a_reference_to_itself; - diagnosticArgument = [fileName]; - } + function emitBindingElement(node) { + emitWithSuffix(node.propertyName, ": "); + writeIfPresent(node.dotDotDotToken, "..."); + emit(node.name); + emitExpressionWithPrefix(" = ", node.initializer); + } + // + // Expressions + // + function emitArrayLiteralExpression(node) { + var elements = node.elements; + if (elements.length === 0) { + write("[]"); } else { - var nonTsFile = options.allowNonTsExtensions && findSourceFile(fileName, ts.toPath(fileName, currentDirectory, getCanonicalFileName), isDefaultLib, isReference, refFile, refPos, refEnd); - if (!nonTsFile) { - if (options.allowNonTsExtensions) { - diagnostic = ts.Diagnostics.File_0_not_found; - diagnosticArgument = [fileName]; - } - else if (!ts.forEach(supportedExtensions, function (extension) { return findSourceFile(fileName + extension, ts.toPath(fileName + extension, currentDirectory, getCanonicalFileName), isDefaultLib, isReference, refFile, refPos, refEnd); })) { - diagnostic = ts.Diagnostics.File_0_not_found; - fileName += ".ts"; - diagnosticArgument = [fileName]; - } - } + var preferNewLine = node.multiLine ? 32768 /* PreferNewLine */ : 0 /* None */; + emitExpressionList(node, elements, 4466 /* ArrayLiteralExpressionElements */ | preferNewLine); } - if (diagnostic) { - if (refFile !== undefined && refEnd !== undefined && refPos !== undefined) { - fileProcessingDiagnostics.add(ts.createFileDiagnostic.apply(void 0, [refFile, refPos, refEnd - refPos, diagnostic].concat(diagnosticArgument))); + } + function emitObjectLiteralExpression(node) { + var properties = node.properties; + if (properties.length === 0) { + write("{}"); + } + else { + var indentedFlag = ts.getEmitFlags(node) & 524288 /* Indented */; + if (indentedFlag) { + increaseIndent(); } - else { - fileProcessingDiagnostics.add(ts.createCompilerDiagnostic.apply(void 0, [diagnostic].concat(diagnosticArgument))); + var preferNewLine = node.multiLine ? 32768 /* PreferNewLine */ : 0 /* None */; + var allowTrailingComma = languageVersion >= 1 /* ES5 */ ? 32 /* AllowTrailingComma */ : 0 /* None */; + emitList(node, properties, 978 /* ObjectLiteralExpressionProperties */ | allowTrailingComma | preferNewLine); + if (indentedFlag) { + decreaseIndent(); } } } - function reportFileNamesDifferOnlyInCasingError(fileName, existingFileName, refFile, refPos, refEnd) { - if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) { - fileProcessingDiagnostics.add(ts.createFileDiagnostic(refFile, refPos, refEnd - refPos, ts.Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, fileName, existingFileName)); + function emitPropertyAccessExpression(node) { + var indentBeforeDot = false; + var indentAfterDot = false; + if (!(ts.getEmitFlags(node) & 1048576 /* NoIndentation */)) { + var dotRangeStart = node.expression.end; + var dotRangeEnd = ts.skipTrivia(currentText, node.expression.end) + 1; + var dotToken = { kind: 21 /* DotToken */, pos: dotRangeStart, end: dotRangeEnd }; + indentBeforeDot = needsIndentation(node, node.expression, dotToken); + indentAfterDot = needsIndentation(node, dotToken, node.name); + } + emitExpression(node.expression); + increaseIndentIf(indentBeforeDot); + var shouldEmitDotDot = !indentBeforeDot && needsDotDotForPropertyAccess(node.expression); + write(shouldEmitDotDot ? ".." : "."); + increaseIndentIf(indentAfterDot); + emit(node.name); + decreaseIndentIf(indentBeforeDot, indentAfterDot); + } + // 1..toString is a valid property access, emit a dot after the literal + // Also emit a dot if expression is a integer const enum value - it will appear in generated code as numeric literal + function needsDotDotForPropertyAccess(expression) { + if (expression.kind === 8 /* NumericLiteral */) { + // check if numeric literal was originally written with a dot + var text = getLiteralTextOfNode(expression); + return text.indexOf(ts.tokenToString(21 /* DotToken */)) < 0; + } + else if (ts.isPropertyAccessExpression(expression) || ts.isElementAccessExpression(expression)) { + // check if constant enum value is integer + var constantValue = ts.getConstantValue(expression); + // isFinite handles cases when constantValue is undefined + return isFinite(constantValue) + && Math.floor(constantValue) === constantValue + && compilerOptions.removeComments; + } + } + function emitElementAccessExpression(node) { + emitExpression(node.expression); + write("["); + emitExpression(node.argumentExpression); + write("]"); + } + function emitCallExpression(node) { + emitExpression(node.expression); + emitExpressionList(node, node.arguments, 1296 /* CallExpressionArguments */); + } + function emitNewExpression(node) { + write("new "); + emitExpression(node.expression); + emitExpressionList(node, node.arguments, 9488 /* NewExpressionArguments */); + } + function emitTaggedTemplateExpression(node) { + emitExpression(node.tag); + write(" "); + emitExpression(node.template); + } + function emitTypeAssertionExpression(node) { + if (node.type) { + write("<"); + emit(node.type); + write(">"); + } + emitExpression(node.expression); + } + function emitParenthesizedExpression(node) { + write("("); + emitExpression(node.expression); + write(")"); + } + function emitFunctionExpression(node) { + emitFunctionDeclarationOrExpression(node); + } + function emitArrowFunction(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + emitSignatureAndBody(node, emitArrowFunctionHead); + } + function emitArrowFunctionHead(node) { + emitTypeParameters(node, node.typeParameters); + emitParametersForArrow(node, node.parameters); + emitWithPrefix(": ", node.type); + write(" =>"); + } + function emitDeleteExpression(node) { + write("delete "); + emitExpression(node.expression); + } + function emitTypeOfExpression(node) { + write("typeof "); + emitExpression(node.expression); + } + function emitVoidExpression(node) { + write("void "); + emitExpression(node.expression); + } + function emitAwaitExpression(node) { + write("await "); + emitExpression(node.expression); + } + function emitPrefixUnaryExpression(node) { + writeTokenText(node.operator); + if (shouldEmitWhitespaceBeforeOperand(node)) { + write(" "); + } + emitExpression(node.operand); + } + function shouldEmitWhitespaceBeforeOperand(node) { + // In some cases, we need to emit a space between the operator and the operand. One obvious case + // is when the operator is an identifier, like delete or typeof. We also need to do this for plus + // and minus expressions in certain cases. Specifically, consider the following two cases (parens + // are just for clarity of exposition, and not part of the source code): + // + // (+(+1)) + // (+(++1)) + // + // We need to emit a space in both cases. In the first case, the absence of a space will make + // the resulting expression a prefix increment operation. And in the second, it will make the resulting + // expression a prefix increment whose operand is a plus expression - (++(+x)) + // The same is true of minus of course. + var operand = node.operand; + return operand.kind === 185 /* PrefixUnaryExpression */ + && ((node.operator === 35 /* PlusToken */ && (operand.operator === 35 /* PlusToken */ || operand.operator === 41 /* PlusPlusToken */)) + || (node.operator === 36 /* MinusToken */ && (operand.operator === 36 /* MinusToken */ || operand.operator === 42 /* MinusMinusToken */))); + } + function emitPostfixUnaryExpression(node) { + emitExpression(node.operand); + writeTokenText(node.operator); + } + function emitBinaryExpression(node) { + var isCommaOperator = node.operatorToken.kind !== 24 /* CommaToken */; + var indentBeforeOperator = needsIndentation(node, node.left, node.operatorToken); + var indentAfterOperator = needsIndentation(node, node.operatorToken, node.right); + emitExpression(node.left); + increaseIndentIf(indentBeforeOperator, isCommaOperator ? " " : undefined); + writeTokenText(node.operatorToken.kind); + increaseIndentIf(indentAfterOperator, " "); + emitExpression(node.right); + decreaseIndentIf(indentBeforeOperator, indentAfterOperator); + } + function emitConditionalExpression(node) { + var indentBeforeQuestion = needsIndentation(node, node.condition, node.questionToken); + var indentAfterQuestion = needsIndentation(node, node.questionToken, node.whenTrue); + var indentBeforeColon = needsIndentation(node, node.whenTrue, node.colonToken); + var indentAfterColon = needsIndentation(node, node.colonToken, node.whenFalse); + emitExpression(node.condition); + increaseIndentIf(indentBeforeQuestion, " "); + write("?"); + increaseIndentIf(indentAfterQuestion, " "); + emitExpression(node.whenTrue); + decreaseIndentIf(indentBeforeQuestion, indentAfterQuestion); + increaseIndentIf(indentBeforeColon, " "); + write(":"); + increaseIndentIf(indentAfterColon, " "); + emitExpression(node.whenFalse); + decreaseIndentIf(indentBeforeColon, indentAfterColon); + } + function emitTemplateExpression(node) { + emit(node.head); + emitList(node, node.templateSpans, 131072 /* TemplateExpressionSpans */); + } + function emitYieldExpression(node) { + write(node.asteriskToken ? "yield*" : "yield"); + emitExpressionWithPrefix(" ", node.expression); + } + function emitSpreadElementExpression(node) { + write("..."); + emitExpression(node.expression); + } + function emitClassExpression(node) { + emitClassDeclarationOrExpression(node); + } + function emitExpressionWithTypeArguments(node) { + emitExpression(node.expression); + emitTypeArguments(node, node.typeArguments); + } + function emitAsExpression(node) { + emitExpression(node.expression); + if (node.type) { + write(" as "); + emit(node.type); + } + } + function emitNonNullExpression(node) { + emitExpression(node.expression); + write("!"); + } + // + // Misc + // + function emitTemplateSpan(node) { + emitExpression(node.expression); + emit(node.literal); + } + // + // Statements + // + function emitBlock(node, format) { + if (isSingleLineEmptyBlock(node)) { + writeToken(15 /* OpenBraceToken */, node.pos, /*contextNode*/ node); + write(" "); + writeToken(16 /* CloseBraceToken */, node.statements.end, /*contextNode*/ node); } else { - fileProcessingDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, fileName, existingFileName)); + writeToken(15 /* OpenBraceToken */, node.pos, /*contextNode*/ node); + emitBlockStatements(node); + writeToken(16 /* CloseBraceToken */, node.statements.end, /*contextNode*/ node); } } - // Get source file from normalized fileName - function findSourceFile(fileName, path, isDefaultLib, isReference, refFile, refPos, refEnd) { - if (filesByName.contains(path)) { - var file_1 = filesByName.get(path); - // try to check if we've already seen this file but with a different casing in path - // NOTE: this only makes sense for case-insensitive file systems - if (file_1 && options.forceConsistentCasingInFileNames && ts.getNormalizedAbsolutePath(file_1.fileName, currentDirectory) !== ts.getNormalizedAbsolutePath(fileName, currentDirectory)) { - reportFileNamesDifferOnlyInCasingError(fileName, file_1.fileName, refFile, refPos, refEnd); - } - // If the file was previously found via a node_modules search, but is now being processed as a root file, - // then everything it sucks in may also be marked incorrectly, and needs to be checked again. - if (file_1 && sourceFilesFoundSearchingNodeModules[file_1.path] && currentNodeModulesDepth == 0) { - sourceFilesFoundSearchingNodeModules[file_1.path] = false; - if (!options.noResolve) { - processReferencedFiles(file_1, ts.getDirectoryPath(fileName), isDefaultLib); - processTypeReferenceDirectives(file_1); - } - modulesWithElidedImports[file_1.path] = false; - processImportedModules(file_1, ts.getDirectoryPath(fileName)); + function emitBlockStatements(node) { + if (ts.getEmitFlags(node) & 32 /* SingleLine */) { + emitList(node, node.statements, 384 /* SingleLineBlockStatements */); + } + else { + emitList(node, node.statements, 65 /* MultiLineBlockStatements */); + } + } + function emitVariableStatement(node) { + emitModifiers(node, node.modifiers); + emit(node.declarationList); + write(";"); + } + function emitEmptyStatement(node) { + write(";"); + } + function emitExpressionStatement(node) { + emitExpression(node.expression); + write(";"); + } + function emitIfStatement(node) { + var openParenPos = writeToken(88 /* IfKeyword */, node.pos, node); + write(" "); + writeToken(17 /* OpenParenToken */, openParenPos, node); + emitExpression(node.expression); + writeToken(18 /* CloseParenToken */, node.expression.end, node); + emitEmbeddedStatement(node.thenStatement); + if (node.elseStatement) { + writeLine(); + writeToken(80 /* ElseKeyword */, node.thenStatement.end, node); + if (node.elseStatement.kind === 203 /* IfStatement */) { + write(" "); + emit(node.elseStatement); } - else if (file_1 && modulesWithElidedImports[file_1.path]) { - if (currentNodeModulesDepth < maxNodeModulesJsDepth) { - modulesWithElidedImports[file_1.path] = false; - processImportedModules(file_1, ts.getDirectoryPath(fileName)); - } + else { + emitEmbeddedStatement(node.elseStatement); } - return file_1; } - // We haven't looked for this file, do so now and cache result - var file = host.getSourceFile(fileName, options.target, function (hostErrorMessage) { - if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) { - fileProcessingDiagnostics.add(ts.createFileDiagnostic(refFile, refPos, refEnd - refPos, ts.Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage)); + } + function emitDoStatement(node) { + write("do"); + emitEmbeddedStatement(node.statement); + if (ts.isBlock(node.statement)) { + write(" "); + } + else { + writeLine(); + } + write("while ("); + emitExpression(node.expression); + write(");"); + } + function emitWhileStatement(node) { + write("while ("); + emitExpression(node.expression); + write(")"); + emitEmbeddedStatement(node.statement); + } + function emitForStatement(node) { + var openParenPos = writeToken(86 /* ForKeyword */, node.pos); + write(" "); + writeToken(17 /* OpenParenToken */, openParenPos, /*contextNode*/ node); + emitForBinding(node.initializer); + write(";"); + emitExpressionWithPrefix(" ", node.condition); + write(";"); + emitExpressionWithPrefix(" ", node.incrementor); + write(")"); + emitEmbeddedStatement(node.statement); + } + function emitForInStatement(node) { + var openParenPos = writeToken(86 /* ForKeyword */, node.pos); + write(" "); + writeToken(17 /* OpenParenToken */, openParenPos); + emitForBinding(node.initializer); + write(" in "); + emitExpression(node.expression); + writeToken(18 /* CloseParenToken */, node.expression.end); + emitEmbeddedStatement(node.statement); + } + function emitForOfStatement(node) { + var openParenPos = writeToken(86 /* ForKeyword */, node.pos); + write(" "); + writeToken(17 /* OpenParenToken */, openParenPos); + emitForBinding(node.initializer); + write(" of "); + emitExpression(node.expression); + writeToken(18 /* CloseParenToken */, node.expression.end); + emitEmbeddedStatement(node.statement); + } + function emitForBinding(node) { + if (node !== undefined) { + if (node.kind === 219 /* VariableDeclarationList */) { + emit(node); } else { - fileProcessingDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage)); + emitExpression(node); } - }); - filesByName.set(path, file); - if (file) { - sourceFilesFoundSearchingNodeModules[path] = (currentNodeModulesDepth > 0); - file.path = path; - if (host.useCaseSensitiveFileNames()) { - // for case-sensitive file systems check if we've already seen some file with similar filename ignoring case - var existingFile = filesByNameIgnoreCase.get(path); - if (existingFile) { - reportFileNamesDifferOnlyInCasingError(fileName, existingFile.fileName, refFile, refPos, refEnd); + } + } + function emitContinueStatement(node) { + writeToken(75 /* ContinueKeyword */, node.pos); + emitWithPrefix(" ", node.label); + write(";"); + } + function emitBreakStatement(node) { + writeToken(70 /* BreakKeyword */, node.pos); + emitWithPrefix(" ", node.label); + write(";"); + } + function emitReturnStatement(node) { + writeToken(94 /* ReturnKeyword */, node.pos, /*contextNode*/ node); + emitExpressionWithPrefix(" ", node.expression); + write(";"); + } + function emitWithStatement(node) { + write("with ("); + emitExpression(node.expression); + write(")"); + emitEmbeddedStatement(node.statement); + } + function emitSwitchStatement(node) { + var openParenPos = writeToken(96 /* SwitchKeyword */, node.pos); + write(" "); + writeToken(17 /* OpenParenToken */, openParenPos); + emitExpression(node.expression); + writeToken(18 /* CloseParenToken */, node.expression.end); + write(" "); + emit(node.caseBlock); + } + function emitLabeledStatement(node) { + emit(node.label); + write(": "); + emit(node.statement); + } + function emitThrowStatement(node) { + write("throw"); + emitExpressionWithPrefix(" ", node.expression); + write(";"); + } + function emitTryStatement(node) { + write("try "); + emit(node.tryBlock); + emit(node.catchClause); + if (node.finallyBlock) { + writeLine(); + write("finally "); + emit(node.finallyBlock); + } + } + function emitDebuggerStatement(node) { + writeToken(76 /* DebuggerKeyword */, node.pos); + write(";"); + } + // + // Declarations + // + function emitVariableDeclaration(node) { + emit(node.name); + emitExpressionWithPrefix(" = ", node.initializer); + } + function emitVariableDeclarationList(node) { + write(ts.isLet(node) ? "let " : ts.isConst(node) ? "const " : "var "); + emitList(node, node.declarations, 272 /* VariableDeclarationList */); + } + function emitFunctionDeclaration(node) { + emitFunctionDeclarationOrExpression(node); + } + function emitFunctionDeclarationOrExpression(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + write(node.asteriskToken ? "function* " : "function "); + emitIdentifierName(node.name); + emitSignatureAndBody(node, emitSignatureHead); + } + function emitSignatureAndBody(node, emitSignatureHead) { + var body = node.body; + if (body) { + if (ts.isBlock(body)) { + var indentedFlag = ts.getEmitFlags(node) & 524288 /* Indented */; + if (indentedFlag) { + increaseIndent(); + } + if (ts.getEmitFlags(node) & 4194304 /* ReuseTempVariableScope */) { + emitSignatureHead(node); + emitBlockFunctionBody(node, body); } else { - filesByNameIgnoreCase.set(path, file); + var savedTempFlags = tempFlags; + tempFlags = 0; + emitSignatureHead(node); + emitBlockFunctionBody(node, body); + tempFlags = savedTempFlags; + } + if (indentedFlag) { + decreaseIndent(); } - } - skipDefaultLib = skipDefaultLib || file.hasNoDefaultLib; - var basePath = ts.getDirectoryPath(fileName); - if (!options.noResolve) { - processReferencedFiles(file, basePath, isDefaultLib); - processTypeReferenceDirectives(file); - } - // always process imported modules to record module name resolutions - processImportedModules(file, basePath); - if (isDefaultLib) { - files.unshift(file); } else { - files.push(file); + emitSignatureHead(node); + write(" "); + emitExpression(body); } } - return file; + else { + emitSignatureHead(node); + write(";"); + } } - function processReferencedFiles(file, basePath, isDefaultLib) { - ts.forEach(file.referencedFiles, function (ref) { - var referencedFileName = resolveTripleslashReference(ref.fileName, file.fileName); - processSourceFile(referencedFileName, isDefaultLib, /*isReference*/ true, file, ref.pos, ref.end); - }); + function emitSignatureHead(node) { + emitTypeParameters(node, node.typeParameters); + emitParameters(node, node.parameters); + emitWithPrefix(": ", node.type); } - function processTypeReferenceDirectives(file) { - // We lower-case all type references because npm automatically lowercases all packages. See GH#9824. - var typeDirectives = ts.map(file.typeReferenceDirectives, function (ref) { return ref.fileName.toLocaleLowerCase(); }); - var resolutions = resolveTypeReferenceDirectiveNamesWorker(typeDirectives, file.fileName); - for (var i = 0; i < typeDirectives.length; i++) { - var ref = file.typeReferenceDirectives[i]; - var resolvedTypeReferenceDirective = resolutions[i]; - // store resolved type directive on the file - var fileName = ref.fileName.toLocaleLowerCase(); - ts.setResolvedTypeReferenceDirective(file, fileName, resolvedTypeReferenceDirective); - processTypeReferenceDirective(fileName, resolvedTypeReferenceDirective, file, ref.pos, ref.end); + function shouldEmitBlockFunctionBodyOnSingleLine(parentNode, body) { + // We must emit a function body as a single-line body in the following case: + // * The body has NodeEmitFlags.SingleLine specified. + // We must emit a function body as a multi-line body in the following cases: + // * The body is explicitly marked as multi-line. + // * A non-synthesized body's start and end position are on different lines. + // * Any statement in the body starts on a new line. + if (ts.getEmitFlags(body) & 32 /* SingleLine */) { + return true; } - } - function processTypeReferenceDirective(typeReferenceDirective, resolvedTypeReferenceDirective, refFile, refPos, refEnd) { - // If we already found this library as a primary reference - nothing to do - var previousResolution = resolvedTypeReferenceDirectives[typeReferenceDirective]; - if (previousResolution && previousResolution.primary) { - return; + if (body.multiLine) { + return false; } - var saveResolution = true; - if (resolvedTypeReferenceDirective) { - if (resolvedTypeReferenceDirective.primary) { - // resolved from the primary path - processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, /*isDefaultLib*/ false, /*isReference*/ true, refFile, refPos, refEnd); - } - else { - // If we already resolved to this file, it must have been a secondary reference. Check file contents - // for sameness and possibly issue an error - if (previousResolution) { - var otherFileText = host.readFile(resolvedTypeReferenceDirective.resolvedFileName); - if (otherFileText !== getSourceFile(previousResolution.resolvedFileName).text) { - fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd, ts.Diagnostics.Conflicting_definitions_for_0_found_at_1_and_2_Consider_installing_a_specific_version_of_this_library_to_resolve_the_conflict, typeReferenceDirective, resolvedTypeReferenceDirective.resolvedFileName, previousResolution.resolvedFileName)); - } - // don't overwrite previous resolution result - saveResolution = false; - } - else { - // First resolution of this library - processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, /*isDefaultLib*/ false, /*isReference*/ true, refFile, refPos, refEnd); - } + if (!ts.nodeIsSynthesized(body) && !ts.rangeIsOnSingleLine(body, currentSourceFile)) { + return false; + } + if (shouldWriteLeadingLineTerminator(body, body.statements, 2 /* PreserveLines */) + || shouldWriteClosingLineTerminator(body, body.statements, 2 /* PreserveLines */)) { + return false; + } + var previousStatement; + for (var _a = 0, _b = body.statements; _a < _b.length; _a++) { + var statement = _b[_a]; + if (shouldWriteSeparatingLineTerminator(previousStatement, statement, 2 /* PreserveLines */)) { + return false; } + previousStatement = statement; + } + return true; + } + function emitBlockFunctionBody(parentNode, body) { + write(" {"); + increaseIndent(); + emitBodyWithDetachedComments(body, body.statements, shouldEmitBlockFunctionBodyOnSingleLine(parentNode, body) + ? emitBlockFunctionBodyOnSingleLine + : emitBlockFunctionBodyWorker); + decreaseIndent(); + writeToken(16 /* CloseBraceToken */, body.statements.end, body); + } + function emitBlockFunctionBodyOnSingleLine(body) { + emitBlockFunctionBodyWorker(body, /*emitBlockFunctionBodyOnSingleLine*/ true); + } + function emitBlockFunctionBodyWorker(body, emitBlockFunctionBodyOnSingleLine) { + // Emit all the prologue directives (like "use strict"). + var statementOffset = emitPrologueDirectives(body.statements, /*startWithNewLine*/ true); + var helpersEmitted = emitHelpers(body); + if (statementOffset === 0 && !helpersEmitted && emitBlockFunctionBodyOnSingleLine) { + decreaseIndent(); + emitList(body, body.statements, 384 /* SingleLineFunctionBodyStatements */); + increaseIndent(); } else { - fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd, ts.Diagnostics.Cannot_find_type_definition_file_for_0, typeReferenceDirective)); + emitList(body, body.statements, 1 /* MultiLineFunctionBodyStatements */, statementOffset); } - if (saveResolution) { - resolvedTypeReferenceDirectives[typeReferenceDirective] = resolvedTypeReferenceDirective; + } + function emitClassDeclaration(node) { + emitClassDeclarationOrExpression(node); + } + function emitClassDeclarationOrExpression(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + write("class"); + emitNodeWithPrefix(" ", node.name, emitIdentifierName); + var indentedFlag = ts.getEmitFlags(node) & 524288 /* Indented */; + if (indentedFlag) { + increaseIndent(); + } + emitTypeParameters(node, node.typeParameters); + emitList(node, node.heritageClauses, 256 /* ClassHeritageClauses */); + var savedTempFlags = tempFlags; + tempFlags = 0; + write(" {"); + emitList(node, node.members, 65 /* ClassMembers */); + write("}"); + if (indentedFlag) { + decreaseIndent(); } + tempFlags = savedTempFlags; } - function createDiagnostic(refFile, refPos, refEnd, message) { - var args = []; - for (var _i = 4; _i < arguments.length; _i++) { - args[_i - 4] = arguments[_i]; + function emitInterfaceDeclaration(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + write("interface "); + emit(node.name); + emitTypeParameters(node, node.typeParameters); + emitList(node, node.heritageClauses, 256 /* HeritageClauses */); + write(" {"); + emitList(node, node.members, 65 /* InterfaceMembers */); + write("}"); + } + function emitTypeAliasDeclaration(node) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + write("type "); + emit(node.name); + emitTypeParameters(node, node.typeParameters); + write(" = "); + emit(node.type); + write(";"); + } + function emitEnumDeclaration(node) { + emitModifiers(node, node.modifiers); + write("enum "); + emit(node.name); + var savedTempFlags = tempFlags; + tempFlags = 0; + write(" {"); + emitList(node, node.members, 81 /* EnumMembers */); + write("}"); + tempFlags = savedTempFlags; + } + function emitModuleDeclaration(node) { + emitModifiers(node, node.modifiers); + write(node.flags & 16 /* Namespace */ ? "namespace " : "module "); + emit(node.name); + var body = node.body; + while (body.kind === 225 /* ModuleDeclaration */) { + write("."); + emit(body.name); + body = body.body; } - if (refFile === undefined || refPos === undefined || refEnd === undefined) { - return ts.createCompilerDiagnostic.apply(void 0, [message].concat(args)); + write(" "); + emit(body); + } + function emitModuleBlock(node) { + if (isSingleLineEmptyBlock(node)) { + write("{ }"); } else { - return ts.createFileDiagnostic.apply(void 0, [refFile, refPos, refEnd - refPos, message].concat(args)); + var savedTempFlags = tempFlags; + tempFlags = 0; + write("{"); + increaseIndent(); + emitBlockStatements(node); + write("}"); + tempFlags = savedTempFlags; } } - function getCanonicalFileName(fileName) { - return host.getCanonicalFileName(fileName); + function emitCaseBlock(node) { + writeToken(15 /* OpenBraceToken */, node.pos); + emitList(node, node.clauses, 65 /* CaseBlockClauses */); + writeToken(16 /* CloseBraceToken */, node.clauses.end); } - function processImportedModules(file, basePath) { - collectExternalModuleReferences(file); - if (file.imports.length || file.moduleAugmentations.length) { - file.resolvedModules = ts.createMap(); - var moduleNames = ts.map(ts.concatenate(file.imports, file.moduleAugmentations), getTextOfLiteral); - var resolutions = resolveModuleNamesWorker(moduleNames, ts.getNormalizedAbsolutePath(file.fileName, currentDirectory)); - for (var i = 0; i < moduleNames.length; i++) { - var resolution = resolutions[i]; - ts.setResolvedModule(file, moduleNames[i], resolution); - var resolvedPath = resolution ? ts.toPath(resolution.resolvedFileName, currentDirectory, getCanonicalFileName) : undefined; - // add file to program only if: - // - resolution was successful - // - noResolve is falsy - // - module name comes from the list of imports - // - it's not a top level JavaScript module that exceeded the search max - var isFromNodeModulesSearch = resolution && resolution.isExternalLibraryImport; - var isJsFileFromNodeModules = isFromNodeModulesSearch && ts.hasJavaScriptFileExtension(resolution.resolvedFileName); - if (isFromNodeModulesSearch) { - currentNodeModulesDepth++; - } - var elideImport = isJsFileFromNodeModules && currentNodeModulesDepth > maxNodeModulesJsDepth; - var shouldAddFile = resolution && !options.noResolve && i < file.imports.length && !elideImport; - if (elideImport) { - modulesWithElidedImports[file.path] = true; - } - else if (shouldAddFile) { - findSourceFile(resolution.resolvedFileName, resolvedPath, - /*isDefaultLib*/ false, /*isReference*/ false, file, ts.skipTrivia(file.text, file.imports[i].pos), file.imports[i].end); - } - if (isFromNodeModulesSearch) { - currentNodeModulesDepth--; - } - } + function emitImportEqualsDeclaration(node) { + emitModifiers(node, node.modifiers); + write("import "); + emit(node.name); + write(" = "); + emitModuleReference(node.moduleReference); + write(";"); + } + function emitModuleReference(node) { + if (node.kind === 69 /* Identifier */) { + emitExpression(node); } else { - // no imports - drop cached module resolutions - file.resolvedModules = undefined; + emit(node); } - return; } - function computeCommonSourceDirectory(sourceFiles) { - var fileNames = []; - for (var _i = 0, sourceFiles_2 = sourceFiles; _i < sourceFiles_2.length; _i++) { - var file = sourceFiles_2[_i]; - if (!file.isDeclarationFile) { - fileNames.push(file.fileName); - } + function emitImportDeclaration(node) { + emitModifiers(node, node.modifiers); + write("import "); + if (node.importClause) { + emit(node.importClause); + write(" from "); } - return computeCommonSourceDirectoryOfFilenames(fileNames, currentDirectory, getCanonicalFileName); + emitExpression(node.moduleSpecifier); + write(";"); } - function checkSourceFilesBelongToPath(sourceFiles, rootDirectory) { - var allFilesBelongToPath = true; - if (sourceFiles) { - var absoluteRootDirectoryPath = host.getCanonicalFileName(ts.getNormalizedAbsolutePath(rootDirectory, currentDirectory)); - for (var _i = 0, sourceFiles_3 = sourceFiles; _i < sourceFiles_3.length; _i++) { - var sourceFile = sourceFiles_3[_i]; - if (!ts.isDeclarationFile(sourceFile)) { - var absoluteSourceFilePath = host.getCanonicalFileName(ts.getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory)); - if (absoluteSourceFilePath.indexOf(absoluteRootDirectoryPath) !== 0) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, sourceFile.fileName, options.rootDir)); - allFilesBelongToPath = false; - } - } - } + function emitImportClause(node) { + emit(node.name); + if (node.name && node.namedBindings) { + write(", "); + } + emit(node.namedBindings); + } + function emitNamespaceImport(node) { + write("* as "); + emit(node.name); + } + function emitNamedImports(node) { + emitNamedImportsOrExports(node); + } + function emitImportSpecifier(node) { + emitImportOrExportSpecifier(node); + } + function emitExportAssignment(node) { + write(node.isExportEquals ? "export = " : "export default "); + emitExpression(node.expression); + write(";"); + } + function emitExportDeclaration(node) { + write("export "); + if (node.exportClause) { + emit(node.exportClause); + } + else { + write("*"); + } + if (node.moduleSpecifier) { + write(" from "); + emitExpression(node.moduleSpecifier); + } + write(";"); + } + function emitNamedExports(node) { + emitNamedImportsOrExports(node); + } + function emitExportSpecifier(node) { + emitImportOrExportSpecifier(node); + } + function emitNamedImportsOrExports(node) { + write("{"); + emitList(node, node.elements, 432 /* NamedImportsOrExportsElements */); + write("}"); + } + function emitImportOrExportSpecifier(node) { + if (node.propertyName) { + emit(node.propertyName); + write(" as "); + } + emit(node.name); + } + // + // Module references + // + function emitExternalModuleReference(node) { + write("require("); + emitExpression(node.expression); + write(")"); + } + // + // JSX + // + function emitJsxElement(node) { + emit(node.openingElement); + emitList(node, node.children, 131072 /* JsxElementChildren */); + emit(node.closingElement); + } + function emitJsxSelfClosingElement(node) { + write("<"); + emitJsxTagName(node.tagName); + write(" "); + emitList(node, node.attributes, 131328 /* JsxElementAttributes */); + write("/>"); + } + function emitJsxOpeningElement(node) { + write("<"); + emitJsxTagName(node.tagName); + writeIfAny(node.attributes, " "); + emitList(node, node.attributes, 131328 /* JsxElementAttributes */); + write(">"); + } + function emitJsxText(node) { + writer.writeLiteral(getTextOfNode(node, /*includeTrivia*/ true)); + } + function emitJsxClosingElement(node) { + write(""); + } + function emitJsxAttribute(node) { + emit(node.name); + emitWithPrefix("=", node.initializer); + } + function emitJsxSpreadAttribute(node) { + write("{..."); + emitExpression(node.expression); + write("}"); + } + function emitJsxExpression(node) { + if (node.expression) { + write("{"); + emitExpression(node.expression); + write("}"); + } + } + function emitJsxTagName(node) { + if (node.kind === 69 /* Identifier */) { + emitExpression(node); + } + else { + emit(node); } - return allFilesBelongToPath; } - function verifyCompilerOptions() { - if (options.isolatedModules) { - if (options.declaration) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "declaration", "isolatedModules")); - } - if (options.noEmitOnError) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "noEmitOnError", "isolatedModules")); - } - if (options.out) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "out", "isolatedModules")); - } - if (options.outFile) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "outFile", "isolatedModules")); - } + // + // Clauses + // + function emitCaseClause(node) { + write("case "); + emitExpression(node.expression); + write(":"); + emitCaseOrDefaultClauseStatements(node, node.statements); + } + function emitDefaultClause(node) { + write("default:"); + emitCaseOrDefaultClauseStatements(node, node.statements); + } + function emitCaseOrDefaultClauseStatements(parentNode, statements) { + var emitAsSingleStatement = statements.length === 1 && + ( + // treat synthesized nodes as located on the same line for emit purposes + ts.nodeIsSynthesized(parentNode) || + ts.nodeIsSynthesized(statements[0]) || + ts.rangeStartPositionsAreOnSameLine(parentNode, statements[0], currentSourceFile)); + if (emitAsSingleStatement) { + write(" "); + emit(statements[0]); } - if (options.inlineSourceMap) { - if (options.sourceMap) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "sourceMap", "inlineSourceMap")); - } - if (options.mapRoot) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "mapRoot", "inlineSourceMap")); - } + else { + emitList(parentNode, statements, 81985 /* CaseOrDefaultClauseStatements */); } - if (options.paths && options.baseUrl === undefined) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_paths_cannot_be_used_without_specifying_baseUrl_option)); + } + function emitHeritageClause(node) { + write(" "); + writeTokenText(node.token); + write(" "); + emitList(node, node.types, 272 /* HeritageClauseTypes */); + } + function emitCatchClause(node) { + writeLine(); + var openParenPos = writeToken(72 /* CatchKeyword */, node.pos); + write(" "); + writeToken(17 /* OpenParenToken */, openParenPos); + emit(node.variableDeclaration); + writeToken(18 /* CloseParenToken */, node.variableDeclaration ? node.variableDeclaration.end : openParenPos); + write(" "); + emit(node.block); + } + // + // Property assignments + // + function emitPropertyAssignment(node) { + emit(node.name); + write(": "); + // This is to ensure that we emit comment in the following case: + // For example: + // obj = { + // id: /*comment1*/ ()=>void + // } + // "comment1" is not considered to be leading comment for node.initializer + // but rather a trailing comment on the previous node. + var initializer = node.initializer; + if ((ts.getEmitFlags(initializer) & 16384 /* NoLeadingComments */) === 0) { + var commentRange = ts.getCommentRange(initializer); + emitTrailingCommentsOfPosition(commentRange.pos); } - if (options.paths) { - for (var key in options.paths) { - if (!ts.hasProperty(options.paths, key)) { - continue; - } - if (!hasZeroOrOneAsteriskCharacter(key)) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, key)); - } - if (ts.isArray(options.paths[key])) { - if (options.paths[key].length === 0) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Substitutions_for_pattern_0_shouldn_t_be_an_empty_array, key)); - } - for (var _i = 0, _a = options.paths[key]; _i < _a.length; _i++) { - var subst = _a[_i]; - var typeOfSubst = typeof subst; - if (typeOfSubst === "string") { - if (!hasZeroOrOneAsteriskCharacter(subst)) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Substitution_0_in_pattern_1_in_can_have_at_most_one_Asterisk_character, subst, key)); - } - } - else { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Substitution_0_for_pattern_1_has_incorrect_type_expected_string_got_2, subst, key, typeOfSubst)); - } - } - } - else { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Substitutions_for_pattern_0_should_be_an_array, key)); - } - } + emitExpression(initializer); + } + function emitShorthandPropertyAssignment(node) { + emit(node.name); + if (node.objectAssignmentInitializer) { + write(" = "); + emitExpression(node.objectAssignmentInitializer); } - if (!options.sourceMap && !options.inlineSourceMap) { - if (options.inlineSources) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided, "inlineSources")); + } + // + // Enum + // + function emitEnumMember(node) { + emit(node.name); + emitExpressionWithPrefix(" = ", node.initializer); + } + // + // Top-level nodes + // + function emitSourceFile(node) { + writeLine(); + emitShebang(); + emitBodyWithDetachedComments(node, node.statements, emitSourceFileWorker); + } + function emitSourceFileWorker(node) { + var statements = node.statements; + var statementOffset = emitPrologueDirectives(statements); + var savedTempFlags = tempFlags; + tempFlags = 0; + emitHelpers(node); + emitList(node, statements, 1 /* MultiLine */, statementOffset); + tempFlags = savedTempFlags; + } + // Transformation nodes + function emitPartiallyEmittedExpression(node) { + emitExpression(node.expression); + } + /** + * Emits any prologue directives at the start of a Statement list, returning the + * number of prologue directives written to the output. + */ + function emitPrologueDirectives(statements, startWithNewLine) { + for (var i = 0; i < statements.length; i++) { + if (ts.isPrologueDirective(statements[i])) { + if (startWithNewLine || i > 0) { + writeLine(); + } + emit(statements[i]); } - if (options.sourceRoot) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided, "sourceRoot")); + else { + // return index of the first non prologue directive + return i; } } - if (options.out && options.outFile) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "out", "outFile")); + return statements.length; + } + function emitHelpers(node) { + var emitFlags = ts.getEmitFlags(node); + var helpersEmitted = false; + if (emitFlags & 1 /* EmitEmitHelpers */) { + helpersEmitted = emitEmitHelpers(currentSourceFile); } - if (options.mapRoot && !options.sourceMap) { - // Error to specify --mapRoot without --sourcemap - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "mapRoot", "sourceMap")); + if (emitFlags & 2 /* EmitExportStar */) { + writeLines(exportStarHelper); + helpersEmitted = true; } - if (options.declarationDir) { - if (!options.declaration) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "declarationDir", "declaration")); - } - if (options.out || options.outFile) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "declarationDir", options.out ? "out" : "outFile")); - } + if (emitFlags & 4 /* EmitSuperHelper */) { + writeLines(superHelper); + helpersEmitted = true; } - if (options.lib && options.noLib) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "lib", "noLib")); + if (emitFlags & 8 /* EmitAdvancedSuperHelper */) { + writeLines(advancedSuperHelper); + helpersEmitted = true; } - var languageVersion = options.target || 0 /* ES3 */; - var outFile = options.outFile || options.out; - var firstNonAmbientExternalModuleSourceFile = ts.forEach(files, function (f) { return ts.isExternalModule(f) && !ts.isDeclarationFile(f) ? f : undefined; }); - if (options.isolatedModules) { - if (options.module === ts.ModuleKind.None && languageVersion < 2 /* ES6 */) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_isolatedModules_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES2015_or_higher)); - } - var firstNonExternalModuleSourceFile = ts.forEach(files, function (f) { return !ts.isExternalModule(f) && !ts.isDeclarationFile(f) ? f : undefined; }); - if (firstNonExternalModuleSourceFile) { - var span = ts.getErrorSpanForNode(firstNonExternalModuleSourceFile, firstNonExternalModuleSourceFile); - programDiagnostics.add(ts.createFileDiagnostic(firstNonExternalModuleSourceFile, span.start, span.length, ts.Diagnostics.Cannot_compile_namespaces_when_the_isolatedModules_flag_is_provided)); - } + return helpersEmitted; + } + function emitEmitHelpers(node) { + // Only emit helpers if the user did not say otherwise. + if (compilerOptions.noEmitHelpers) { + return false; } - else if (firstNonAmbientExternalModuleSourceFile && languageVersion < 2 /* ES6 */ && options.module === ts.ModuleKind.None) { - // We cannot use createDiagnosticFromNode because nodes do not have parents yet - var span = ts.getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, firstNonAmbientExternalModuleSourceFile.externalModuleIndicator); - programDiagnostics.add(ts.createFileDiagnostic(firstNonAmbientExternalModuleSourceFile, span.start, span.length, ts.Diagnostics.Cannot_use_imports_exports_or_module_augmentations_when_module_is_none)); + // Don't emit helpers if we can import them. + if (compilerOptions.importHelpers + && (ts.isExternalModule(node) || compilerOptions.isolatedModules)) { + return false; } - // Cannot specify module gen that isn't amd or system with --out - if (outFile) { - if (options.module && !(options.module === ts.ModuleKind.AMD || options.module === ts.ModuleKind.System)) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Only_amd_and_system_modules_are_supported_alongside_0, options.out ? "out" : "outFile")); - } - else if (options.module === undefined && firstNonAmbientExternalModuleSourceFile) { - var span = ts.getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, firstNonAmbientExternalModuleSourceFile.externalModuleIndicator); - programDiagnostics.add(ts.createFileDiagnostic(firstNonAmbientExternalModuleSourceFile, span.start, span.length, ts.Diagnostics.Cannot_compile_modules_using_option_0_unless_the_module_flag_is_amd_or_system, options.out ? "out" : "outFile")); - } + var helpersEmitted = false; + // Only Emit __extends function when target ES5. + // For target ES6 and above, we can emit classDeclaration as is. + if ((languageVersion < 2 /* ES6 */) && (!extendsEmitted && node.flags & 1024 /* HasClassExtends */)) { + writeLines(extendsHelper); + extendsEmitted = true; + helpersEmitted = true; } - // there has to be common source directory if user specified --outdir || --sourceRoot - // if user specified --mapRoot, there needs to be common source directory if there would be multiple files being emitted - if (options.outDir || - options.sourceRoot || - options.mapRoot) { - // Precalculate and cache the common source directory - var dir = getCommonSourceDirectory(); - // If we failed to find a good common directory, but outDir is specified and at least one of our files is on a windows drive/URL/other resource, add a failure - if (options.outDir && dir === "" && ts.forEach(files, function (file) { return ts.getRootLength(file.fileName) > 1; })) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files)); - } + if (compilerOptions.jsx !== 1 /* Preserve */ && !assignEmitted && (node.flags & 16384 /* HasJsxSpreadAttributes */)) { + writeLines(assignHelper); + assignEmitted = true; } - if (!options.noEmit && options.allowJs && options.declaration) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration")); + if (!decorateEmitted && node.flags & 2048 /* HasDecorators */) { + writeLines(decorateHelper); + if (compilerOptions.emitDecoratorMetadata) { + writeLines(metadataHelper); + } + decorateEmitted = true; + helpersEmitted = true; } - if (options.emitDecoratorMetadata && - !options.experimentalDecorators) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDecoratorMetadata", "experimentalDecorators")); + if (!paramEmitted && node.flags & 4096 /* HasParamDecorators */) { + writeLines(paramHelper); + paramEmitted = true; + helpersEmitted = true; } - if (options.reactNamespace && !ts.isIdentifier(options.reactNamespace, languageVersion)) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Invalid_value_for_reactNamespace_0_is_not_a_valid_identifier, options.reactNamespace)); + if (!awaiterEmitted && node.flags & 8192 /* HasAsyncFunctions */) { + writeLines(awaiterHelper); + if (languageVersion < 2 /* ES6 */) { + writeLines(generatorHelper); + } + awaiterEmitted = true; + helpersEmitted = true; } - // If the emit is enabled make sure that every output file is unique and not overwriting any of the input files - if (!options.noEmit && !options.suppressOutputPathCheck) { - var emitHost = getEmitHost(); - var emitFilesSeen_1 = ts.createFileMap(!host.useCaseSensitiveFileNames() ? function (key) { return key.toLocaleLowerCase(); } : undefined); - ts.forEachExpectedEmitFile(emitHost, function (emitFileNames, sourceFiles, isBundledEmit) { - verifyEmitFilePath(emitFileNames.jsFilePath, emitFilesSeen_1); - verifyEmitFilePath(emitFileNames.declarationFilePath, emitFilesSeen_1); - }); + if (helpersEmitted) { + writeLine(); } - // Verify that all the emit files are unique and don't overwrite input files - function verifyEmitFilePath(emitFileName, emitFilesSeen) { - if (emitFileName) { - var emitFilePath = ts.toPath(emitFileName, currentDirectory, getCanonicalFileName); - // Report error if the output overwrites input file - if (filesByName.contains(emitFilePath)) { - createEmitBlockingDiagnostics(emitFileName, emitFilePath, ts.Diagnostics.Cannot_write_file_0_because_it_would_overwrite_input_file); - } - // Report error if multiple files write into same file - if (emitFilesSeen.contains(emitFilePath)) { - // Already seen the same emit file - report error - createEmitBlockingDiagnostics(emitFileName, emitFilePath, ts.Diagnostics.Cannot_write_file_0_because_it_would_be_overwritten_by_multiple_input_files); - } - else { - emitFilesSeen.set(emitFilePath, true); + return helpersEmitted; + } + function writeLines(text) { + var lines = text.split(/\r\n|\r|\n/g); + for (var i = 0; i < lines.length; i++) { + var line = lines[i]; + if (line.length) { + if (i > 0) { + writeLine(); } + write(line); } } } - function createEmitBlockingDiagnostics(emitFileName, emitFilePath, message) { - hasEmitBlockingDiagnostics.set(ts.toPath(emitFileName, currentDirectory, getCanonicalFileName), true); - programDiagnostics.add(ts.createCompilerDiagnostic(message, emitFileName)); - } - } - ts.createProgram = createProgram; -})(ts || (ts = {})); -/// -/// -var ts; -(function (ts) { - var defaultFormatDiagnosticsHost = { - getCurrentDirectory: function () { return ts.sys.getCurrentDirectory(); }, - getNewLine: function () { return ts.sys.newLine; }, - getCanonicalFileName: ts.createGetCanonicalFileName(ts.sys.useCaseSensitiveFileNames) - }; - var reportDiagnosticWorker = reportDiagnosticSimply; - function reportDiagnostic(diagnostic, host) { - reportDiagnosticWorker(diagnostic, host || defaultFormatDiagnosticsHost); - } - function reportDiagnostics(diagnostics, host) { - for (var _i = 0, diagnostics_3 = diagnostics; _i < diagnostics_3.length; _i++) { - var diagnostic = diagnostics_3[_i]; - reportDiagnostic(diagnostic, host); - } - } - function reportEmittedFiles(files, host) { - if (!files || files.length == 0) { - return; + // + // Helpers + // + function emitShebang() { + var shebang = ts.getShebang(currentText); + if (shebang) { + write(shebang); + writeLine(); + } } - var currentDir = ts.sys.getCurrentDirectory(); - for (var _i = 0, files_3 = files; _i < files_3.length; _i++) { - var file = files_3[_i]; - var filepath = ts.getNormalizedAbsolutePath(file, currentDir); - ts.sys.write("TSFILE: " + filepath + ts.sys.newLine); + function emitModifiers(node, modifiers) { + if (modifiers && modifiers.length) { + emitList(node, modifiers, 256 /* Modifiers */); + write(" "); + } } - } - /** - * Checks to see if the locale is in the appropriate format, - * and if it is, attempts to set the appropriate language. - */ - function validateLocaleAndSetLanguage(locale, errors) { - var matchResult = /^([a-z]+)([_\-]([a-z]+))?$/.exec(locale.toLowerCase()); - if (!matchResult) { - errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Locale_must_be_of_the_form_language_or_language_territory_For_example_0_or_1, "en", "ja-jp")); - return false; + function emitWithPrefix(prefix, node) { + emitNodeWithPrefix(prefix, node, emit); } - var language = matchResult[1]; - var territory = matchResult[3]; - // First try the entire locale, then fall back to just language if that's all we have. - // Either ways do not fail, and fallback to the English diagnostic strings. - if (!trySetLanguageAndTerritory(language, territory, errors)) { - trySetLanguageAndTerritory(language, undefined, errors); + function emitExpressionWithPrefix(prefix, node) { + emitNodeWithPrefix(prefix, node, emitExpression); } - return true; - } - function trySetLanguageAndTerritory(language, territory, errors) { - var compilerFilePath = ts.normalizePath(ts.sys.getExecutingFilePath()); - var containingDirectoryPath = ts.getDirectoryPath(compilerFilePath); - var filePath = ts.combinePaths(containingDirectoryPath, language); - if (territory) { - filePath = filePath + "-" + territory; + function emitNodeWithPrefix(prefix, node, emit) { + if (node) { + write(prefix); + emit(node); + } } - filePath = ts.sys.resolvePath(ts.combinePaths(filePath, "diagnosticMessages.generated.json")); - if (!ts.sys.fileExists(filePath)) { - return false; + function emitWithSuffix(node, suffix) { + if (node) { + emit(node); + write(suffix); + } } - // TODO: Add codePage support for readFile? - var fileContents = ""; - try { - fileContents = ts.sys.readFile(filePath); + function emitEmbeddedStatement(node) { + if (ts.isBlock(node)) { + write(" "); + emit(node); + } + else { + writeLine(); + increaseIndent(); + emit(node); + decreaseIndent(); + } } - catch (e) { - errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unable_to_open_file_0, filePath)); - return false; + function emitDecorators(parentNode, decorators) { + emitList(parentNode, decorators, 24577 /* Decorators */); } - try { - ts.localizedDiagnosticMessages = JSON.parse(fileContents); + function emitTypeArguments(parentNode, typeArguments) { + emitList(parentNode, typeArguments, 26960 /* TypeArguments */); } - catch (e) { - errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Corrupted_locale_file_0, filePath)); - return false; + function emitTypeParameters(parentNode, typeParameters) { + emitList(parentNode, typeParameters, 26960 /* TypeParameters */); } - return true; - } - function countLines(program) { - var count = 0; - ts.forEach(program.getSourceFiles(), function (file) { - count += ts.getLineStarts(file).length; - }); - return count; - } - function getDiagnosticText(message) { - var args = []; - for (var _i = 1; _i < arguments.length; _i++) { - args[_i - 1] = arguments[_i]; + function emitParameters(parentNode, parameters) { + emitList(parentNode, parameters, 1360 /* Parameters */); } - var diagnostic = ts.createCompilerDiagnostic.apply(undefined, arguments); - return diagnostic.messageText; - } - function reportDiagnosticSimply(diagnostic, host) { - ts.sys.write(ts.formatDiagnostics([diagnostic], host)); - } - var redForegroundEscapeSequence = "\u001b[91m"; - var yellowForegroundEscapeSequence = "\u001b[93m"; - var blueForegroundEscapeSequence = "\u001b[93m"; - var gutterStyleSequence = "\u001b[100;30m"; - var gutterSeparator = " "; - var resetEscapeSequence = "\u001b[0m"; - var ellipsis = "..."; - var categoryFormatMap = ts.createMap((_a = {}, - _a[ts.DiagnosticCategory.Warning] = yellowForegroundEscapeSequence, - _a[ts.DiagnosticCategory.Error] = redForegroundEscapeSequence, - _a[ts.DiagnosticCategory.Message] = blueForegroundEscapeSequence, - _a - )); - function formatAndReset(text, formatStyle) { - return formatStyle + text + resetEscapeSequence; - } - function reportDiagnosticWithColorAndContext(diagnostic, host) { - var output = ""; - if (diagnostic.file) { - var start = diagnostic.start, length_4 = diagnostic.length, file = diagnostic.file; - var _a = ts.getLineAndCharacterOfPosition(file, start), firstLine = _a.line, firstLineChar = _a.character; - var _b = ts.getLineAndCharacterOfPosition(file, start + length_4), lastLine = _b.line, lastLineChar = _b.character; - var lastLineInFile = ts.getLineAndCharacterOfPosition(file, file.text.length).line; - var relativeFileName = host ? ts.convertToRelativePath(file.fileName, host.getCurrentDirectory(), function (fileName) { return host.getCanonicalFileName(fileName); }) : file.fileName; - var hasMoreThanFiveLines = (lastLine - firstLine) >= 4; - var gutterWidth = (lastLine + 1 + "").length; - if (hasMoreThanFiveLines) { - gutterWidth = Math.max(ellipsis.length, gutterWidth); + function emitParametersForArrow(parentNode, parameters) { + if (parameters && + parameters.length === 1 && + parameters[0].type === undefined && + parameters[0].pos === parentNode.pos) { + emit(parameters[0]); } - output += ts.sys.newLine; - for (var i = firstLine; i <= lastLine; i++) { - // If the error spans over 5 lines, we'll only show the first 2 and last 2 lines, - // so we'll skip ahead to the second-to-last line. - if (hasMoreThanFiveLines && firstLine + 1 < i && i < lastLine - 1) { - output += formatAndReset(padLeft(ellipsis, gutterWidth), gutterStyleSequence) + gutterSeparator + ts.sys.newLine; - i = lastLine - 1; - } - var lineStart = ts.getPositionOfLineAndCharacter(file, i, 0); - var lineEnd = i < lastLineInFile ? ts.getPositionOfLineAndCharacter(file, i + 1, 0) : file.text.length; - var lineContent = file.text.slice(lineStart, lineEnd); - lineContent = lineContent.replace(/\s+$/g, ""); // trim from end - lineContent = lineContent.replace("\t", " "); // convert tabs to single spaces - // Output the gutter and the actual contents of the line. - output += formatAndReset(padLeft(i + 1 + "", gutterWidth), gutterStyleSequence) + gutterSeparator; - output += lineContent + ts.sys.newLine; - // Output the gutter and the error span for the line using tildes. - output += formatAndReset(padLeft("", gutterWidth), gutterStyleSequence) + gutterSeparator; - output += redForegroundEscapeSequence; - if (i === firstLine) { - // If we're on the last line, then limit it to the last character of the last line. - // Otherwise, we'll just squiggle the rest of the line, giving 'slice' no end position. - var lastCharForLine = i === lastLine ? lastLineChar : undefined; - output += lineContent.slice(0, firstLineChar).replace(/\S/g, " "); - output += lineContent.slice(firstLineChar, lastCharForLine).replace(/./g, "~"); - } - else if (i === lastLine) { - output += lineContent.slice(0, lastLineChar).replace(/./g, "~"); - } - else { - // Squiggle the entire line. - output += lineContent.replace(/./g, "~"); - } - output += resetEscapeSequence; - output += ts.sys.newLine; + else { + emitParameters(parentNode, parameters); } - output += ts.sys.newLine; - output += relativeFileName + "(" + (firstLine + 1) + "," + (firstLineChar + 1) + "): "; } - var categoryColor = categoryFormatMap[diagnostic.category]; - var category = ts.DiagnosticCategory[diagnostic.category].toLowerCase(); - output += formatAndReset(category, categoryColor) + " TS" + diagnostic.code + ": " + ts.flattenDiagnosticMessageText(diagnostic.messageText, ts.sys.newLine); - output += ts.sys.newLine + ts.sys.newLine; - ts.sys.write(output); - } - function reportWatchDiagnostic(diagnostic) { - var output = new Date().toLocaleTimeString() + " - "; - if (diagnostic.file) { - var loc = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start); - output += diagnostic.file.fileName + "(" + (loc.line + 1) + "," + (loc.character + 1) + "): "; + function emitParametersForIndexSignature(parentNode, parameters) { + emitList(parentNode, parameters, 4432 /* IndexSignatureParameters */); } - output += "" + ts.flattenDiagnosticMessageText(diagnostic.messageText, ts.sys.newLine) + ts.sys.newLine; - ts.sys.write(output); - } - function padLeft(s, length) { - while (s.length < length) { - s = " " + s; + function emitList(parentNode, children, format, start, count) { + emitNodeList(emit, parentNode, children, format, start, count); } - return s; - } - function padRight(s, length) { - while (s.length < length) { - s = s + " "; + function emitExpressionList(parentNode, children, format, start, count) { + emitNodeList(emitExpression, parentNode, children, format, start, count); } - return s; - } - function reportStatisticalValue(name, value) { - ts.sys.write(padRight(name + ":", 12) + padLeft(value.toString(), 10) + ts.sys.newLine); - } - function reportCountStatistic(name, count) { - reportStatisticalValue(name, "" + count); - } - function reportTimeStatistic(name, time) { - reportStatisticalValue(name, (time / 1000).toFixed(2) + "s"); - } - function isJSONSupported() { - return typeof JSON === "object" && typeof JSON.parse === "function"; - } - function executeCommandLine(args) { - var commandLine = ts.parseCommandLine(args); - var configFileName; // Configuration file name (if any) - var cachedConfigFileText; // Cached configuration file text, used for reparsing (if any) - var configFileWatcher; // Configuration file watcher - var directoryWatcher; // Directory watcher to monitor source file addition/removal - var cachedProgram; // Program cached from last compilation - var rootFileNames; // Root fileNames for compilation - var compilerOptions; // Compiler options for compilation - var compilerHost; // Compiler host - var hostGetSourceFile; // getSourceFile method from default host - var timerHandleForRecompilation; // Handle for 0.25s wait timer to trigger recompilation - var timerHandleForDirectoryChanges; // Handle for 0.25s wait timer to trigger directory change handler - // This map stores and reuses results of fileExists check that happen inside 'createProgram' - // This allows to save time in module resolution heavy scenarios when existence of the same file might be checked multiple times. - var cachedExistingFiles; - var hostFileExists; - if (commandLine.options.locale) { - if (!isJSONSupported()) { - reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.The_current_host_does_not_support_the_0_option, "--locale"), /* host */ undefined); - return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + function emitNodeList(emit, parentNode, children, format, start, count) { + if (start === void 0) { start = 0; } + if (count === void 0) { count = children ? children.length - start : 0; } + var isUndefined = children === undefined; + if (isUndefined && format & 8192 /* OptionalIfUndefined */) { + return; } - validateLocaleAndSetLanguage(commandLine.options.locale, commandLine.errors); - } - // If there are any errors due to command line parsing and/or - // setting up localization, report them and quit. - if (commandLine.errors.length > 0) { - reportDiagnostics(commandLine.errors, compilerHost); - return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); - } - if (commandLine.options.init) { - writeConfigFile(commandLine.options, commandLine.fileNames); - return ts.sys.exit(ts.ExitStatus.Success); - } - if (commandLine.options.version) { - printVersion(); - return ts.sys.exit(ts.ExitStatus.Success); - } - if (commandLine.options.help) { - printVersion(); - printHelp(); - return ts.sys.exit(ts.ExitStatus.Success); - } - if (commandLine.options.project) { - if (!isJSONSupported()) { - reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.The_current_host_does_not_support_the_0_option, "--project"), /* host */ undefined); - return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + var isEmpty = isUndefined || children.length === 0 || start >= children.length || count === 0; + if (isEmpty && format & 16384 /* OptionalIfEmpty */) { + return; } - if (commandLine.fileNames.length !== 0) { - reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line), /* host */ undefined); - return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + if (format & 7680 /* BracketsMask */) { + write(getOpeningBracket(format)); } - var fileOrDirectory = ts.normalizePath(commandLine.options.project); - if (!fileOrDirectory /* current directory "." */ || ts.sys.directoryExists(fileOrDirectory)) { - configFileName = ts.combinePaths(fileOrDirectory, "tsconfig.json"); - if (!ts.sys.fileExists(configFileName)) { - reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_find_a_tsconfig_json_file_at_the_specified_directory_Colon_0, commandLine.options.project), /* host */ undefined); - return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + if (isEmpty) { + // Write a line terminator if the parent node was multi-line + if (format & 1 /* MultiLine */) { + writeLine(); + } + else if (format & 128 /* SpaceBetweenBraces */) { + write(" "); } } else { - configFileName = fileOrDirectory; - if (!ts.sys.fileExists(configFileName)) { - reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.The_specified_path_does_not_exist_Colon_0, commandLine.options.project), /* host */ undefined); - return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + // Write the opening line terminator or leading whitespace. + var mayEmitInterveningComments = (format & 131072 /* NoInterveningComments */) === 0; + var shouldEmitInterveningComments = mayEmitInterveningComments; + if (shouldWriteLeadingLineTerminator(parentNode, children, format)) { + writeLine(); + shouldEmitInterveningComments = false; + } + else if (format & 128 /* SpaceBetweenBraces */) { + write(" "); + } + // Increase the indent, if requested. + if (format & 64 /* Indented */) { + increaseIndent(); + } + // Emit each child. + var previousSibling = void 0; + var shouldDecreaseIndentAfterEmit = void 0; + var delimiter = getDelimiter(format); + for (var i = 0; i < count; i++) { + var child = children[start + i]; + // Write the delimiter if this is not the first node. + if (previousSibling) { + write(delimiter); + // Write either a line terminator or whitespace to separate the elements. + if (shouldWriteSeparatingLineTerminator(previousSibling, child, format)) { + // If a synthesized node in a single-line list starts on a new + // line, we should increase the indent. + if ((format & (3 /* LinesMask */ | 64 /* Indented */)) === 0 /* SingleLine */) { + increaseIndent(); + shouldDecreaseIndentAfterEmit = true; + } + writeLine(); + shouldEmitInterveningComments = false; + } + else if (previousSibling && format & 256 /* SpaceBetweenSiblings */) { + write(" "); + } + } + if (shouldEmitInterveningComments) { + var commentRange = ts.getCommentRange(child); + emitTrailingCommentsOfPosition(commentRange.pos); + } + else { + shouldEmitInterveningComments = mayEmitInterveningComments; + } + // Emit this child. + emit(child); + if (shouldDecreaseIndentAfterEmit) { + decreaseIndent(); + shouldDecreaseIndentAfterEmit = false; + } + previousSibling = child; + } + // Write a trailing comma, if requested. + var hasTrailingComma = (format & 32 /* AllowTrailingComma */) && children.hasTrailingComma; + if (format & 16 /* CommaDelimited */ && hasTrailingComma) { + write(","); + } + // Decrease the indent, if requested. + if (format & 64 /* Indented */) { + decreaseIndent(); + } + // Write the closing line terminator or closing whitespace. + if (shouldWriteClosingLineTerminator(parentNode, children, format)) { + writeLine(); + } + else if (format & 128 /* SpaceBetweenBraces */) { + write(" "); } } + if (format & 7680 /* BracketsMask */) { + write(getClosingBracket(format)); + } } - else if (commandLine.fileNames.length === 0 && isJSONSupported()) { - var searchPath = ts.normalizePath(ts.sys.getCurrentDirectory()); - configFileName = ts.findConfigFile(searchPath, ts.sys.fileExists); + function writeIfAny(nodes, text) { + if (nodes && nodes.length > 0) { + write(text); + } } - if (commandLine.fileNames.length === 0 && !configFileName) { - printVersion(); - printHelp(); - return ts.sys.exit(ts.ExitStatus.Success); + function writeIfPresent(node, text) { + if (node !== undefined) { + write(text); + } } - if (ts.isWatchSet(commandLine.options)) { - if (!ts.sys.watchFile) { - reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), /* host */ undefined); - return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + function writeToken(token, pos, contextNode) { + return emitTokenWithSourceMap(contextNode, token, pos, writeTokenText); + } + function writeTokenText(token, pos) { + var tokenString = ts.tokenToString(token); + write(tokenString); + return pos < 0 ? pos : pos + tokenString.length; + } + function increaseIndentIf(value, valueToWriteWhenNotIndenting) { + if (value) { + increaseIndent(); + writeLine(); } - if (configFileName) { - configFileWatcher = ts.sys.watchFile(configFileName, configFileChanged); + else if (valueToWriteWhenNotIndenting) { + write(valueToWriteWhenNotIndenting); } - if (ts.sys.watchDirectory && configFileName) { - var directory = ts.getDirectoryPath(configFileName); - directoryWatcher = ts.sys.watchDirectory( - // When the configFileName is just "tsconfig.json", the watched directory should be - // the current directory; if there is a given "project" parameter, then the configFileName - // is an absolute file name. - directory == "" ? "." : directory, watchedDirectoryChanged, /*recursive*/ true); + } + // Helper function to decrease the indent if we previously indented. Allows multiple + // previous indent values to be considered at a time. This also allows caller to just + // call this once, passing in all their appropriate indent values, instead of needing + // to call this helper function multiple times. + function decreaseIndentIf(value1, value2) { + if (value1) { + decreaseIndent(); + } + if (value2) { + decreaseIndent(); } } - performCompilation(); - function parseConfigFile() { - if (!cachedConfigFileText) { - try { - cachedConfigFileText = ts.sys.readFile(configFileName); + function shouldWriteLeadingLineTerminator(parentNode, children, format) { + if (format & 1 /* MultiLine */) { + return true; + } + if (format & 2 /* PreserveLines */) { + if (format & 32768 /* PreferNewLine */) { + return true; + } + var firstChild = children[0]; + if (firstChild === undefined) { + return !ts.rangeIsOnSingleLine(parentNode, currentSourceFile); } - catch (e) { - var error = ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_read_file_0_Colon_1, configFileName, e.message); - reportWatchDiagnostic(error); - ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); - return; + else if (ts.positionIsSynthesized(parentNode.pos) || ts.nodeIsSynthesized(firstChild)) { + return synthesizedNodeStartsOnNewLine(firstChild, format); + } + else { + return !ts.rangeStartPositionsAreOnSameLine(parentNode, firstChild, currentSourceFile); } } - if (!cachedConfigFileText) { - var error = ts.createCompilerDiagnostic(ts.Diagnostics.File_0_not_found, configFileName); - reportDiagnostics([error], /* compilerHost */ undefined); - ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); - return; - } - var result = ts.parseConfigFileTextToJson(configFileName, cachedConfigFileText); - var configObject = result.config; - if (!configObject) { - reportDiagnostics([result.error], /* compilerHost */ undefined); - ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); - return; + else { + return false; } - var cwd = ts.sys.getCurrentDirectory(); - var configParseResult = ts.parseJsonConfigFileContent(configObject, ts.sys, ts.getNormalizedAbsolutePath(ts.getDirectoryPath(configFileName), cwd), commandLine.options, ts.getNormalizedAbsolutePath(configFileName, cwd)); - if (configParseResult.errors.length > 0) { - reportDiagnostics(configParseResult.errors, /* compilerHost */ undefined); - ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); - return; + } + function shouldWriteSeparatingLineTerminator(previousNode, nextNode, format) { + if (format & 1 /* MultiLine */) { + return true; } - if (ts.isWatchSet(configParseResult.options)) { - if (!ts.sys.watchFile) { - reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), /* host */ undefined); - ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + else if (format & 2 /* PreserveLines */) { + if (previousNode === undefined || nextNode === undefined) { + return false; } - if (!directoryWatcher && ts.sys.watchDirectory && configFileName) { - var directory = ts.getDirectoryPath(configFileName); - directoryWatcher = ts.sys.watchDirectory( - // When the configFileName is just "tsconfig.json", the watched directory should be - // the current directory; if there is a given "project" parameter, then the configFileName - // is an absolute file name. - directory == "" ? "." : directory, watchedDirectoryChanged, /*recursive*/ true); + else if (ts.nodeIsSynthesized(previousNode) || ts.nodeIsSynthesized(nextNode)) { + return synthesizedNodeStartsOnNewLine(previousNode, format) || synthesizedNodeStartsOnNewLine(nextNode, format); + } + else { + return !ts.rangeEndIsOnSameLineAsRangeStart(previousNode, nextNode, currentSourceFile); } - ; } - return configParseResult; + else { + return nextNode.startsOnNewLine; + } } - // Invoked to perform initial compilation or re-compilation in watch mode - function performCompilation() { - if (!cachedProgram) { - if (configFileName) { - var configParseResult = parseConfigFile(); - rootFileNames = configParseResult.fileNames; - compilerOptions = configParseResult.options; + function shouldWriteClosingLineTerminator(parentNode, children, format) { + if (format & 1 /* MultiLine */) { + return (format & 65536 /* NoTrailingNewLine */) === 0; + } + else if (format & 2 /* PreserveLines */) { + if (format & 32768 /* PreferNewLine */) { + return true; + } + var lastChild = ts.lastOrUndefined(children); + if (lastChild === undefined) { + return !ts.rangeIsOnSingleLine(parentNode, currentSourceFile); + } + else if (ts.positionIsSynthesized(parentNode.pos) || ts.nodeIsSynthesized(lastChild)) { + return synthesizedNodeStartsOnNewLine(lastChild, format); } else { - rootFileNames = commandLine.fileNames; - compilerOptions = commandLine.options; + return !ts.rangeEndPositionsAreOnSameLine(parentNode, lastChild, currentSourceFile); } - compilerHost = ts.createCompilerHost(compilerOptions); - hostGetSourceFile = compilerHost.getSourceFile; - compilerHost.getSourceFile = getSourceFile; - hostFileExists = compilerHost.fileExists; - compilerHost.fileExists = cachedFileExists; } - if (compilerOptions.pretty) { - reportDiagnosticWorker = reportDiagnosticWithColorAndContext; + else { + return false; } - // reset the cache of existing files - cachedExistingFiles = ts.createMap(); - var compileResult = compile(rootFileNames, compilerOptions, compilerHost); - if (!ts.isWatchSet(compilerOptions)) { - return ts.sys.exit(compileResult.exitStatus); + } + function synthesizedNodeStartsOnNewLine(node, format) { + if (ts.nodeIsSynthesized(node)) { + var startsOnNewLine = node.startsOnNewLine; + if (startsOnNewLine === undefined) { + return (format & 32768 /* PreferNewLine */) !== 0; + } + return startsOnNewLine; } - setCachedProgram(compileResult.program); - reportWatchDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.Compilation_complete_Watching_for_file_changes)); + return (format & 32768 /* PreferNewLine */) !== 0; } - function cachedFileExists(fileName) { - return fileName in cachedExistingFiles - ? cachedExistingFiles[fileName] - : cachedExistingFiles[fileName] = hostFileExists(fileName); + function needsIndentation(parent, node1, node2) { + parent = skipSynthesizedParentheses(parent); + node1 = skipSynthesizedParentheses(node1); + node2 = skipSynthesizedParentheses(node2); + // Always use a newline for synthesized code if the synthesizer desires it. + if (node2.startsOnNewLine) { + return true; + } + return !ts.nodeIsSynthesized(parent) + && !ts.nodeIsSynthesized(node1) + && !ts.nodeIsSynthesized(node2) + && !ts.rangeEndIsOnSameLineAsRangeStart(node1, node2, currentSourceFile); } - function getSourceFile(fileName, languageVersion, onError) { - // Return existing SourceFile object if one is available - if (cachedProgram) { - var sourceFile_1 = cachedProgram.getSourceFile(fileName); - // A modified source file has no watcher and should not be reused - if (sourceFile_1 && sourceFile_1.fileWatcher) { - return sourceFile_1; + function skipSynthesizedParentheses(node) { + while (node.kind === 178 /* ParenthesizedExpression */ && ts.nodeIsSynthesized(node)) { + node = node.expression; + } + return node; + } + function getTextOfNode(node, includeTrivia) { + if (ts.isGeneratedIdentifier(node)) { + return getGeneratedIdentifier(node); + } + else if (ts.isIdentifier(node) && (ts.nodeIsSynthesized(node) || !node.parent)) { + return ts.unescapeIdentifier(node.text); + } + else if (node.kind === 9 /* StringLiteral */ && node.textSourceNode) { + return getTextOfNode(node.textSourceNode, includeTrivia); + } + else if (ts.isLiteralExpression(node) && (ts.nodeIsSynthesized(node) || !node.parent)) { + return node.text; + } + return ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node, includeTrivia); + } + function getLiteralTextOfNode(node) { + if (node.kind === 9 /* StringLiteral */ && node.textSourceNode) { + var textSourceNode = node.textSourceNode; + if (ts.isIdentifier(textSourceNode)) { + return "\"" + ts.escapeNonAsciiCharacters(ts.escapeString(getTextOfNode(textSourceNode))) + "\""; + } + else { + return getLiteralTextOfNode(textSourceNode); } } - // Use default host function - var sourceFile = hostGetSourceFile(fileName, languageVersion, onError); - if (sourceFile && ts.isWatchSet(compilerOptions) && ts.sys.watchFile) { - // Attach a file watcher - sourceFile.fileWatcher = ts.sys.watchFile(sourceFile.fileName, function (fileName, removed) { return sourceFileChanged(sourceFile, removed); }); + return ts.getLiteralText(node, currentSourceFile, languageVersion); + } + function isSingleLineEmptyBlock(block) { + return !block.multiLine + && block.statements.length === 0 + && ts.rangeEndIsOnSameLineAsRangeStart(block, block, currentSourceFile); + } + function isUniqueName(name) { + return !resolver.hasGlobalName(name) && + !ts.hasProperty(currentFileIdentifiers, name) && + !ts.hasProperty(generatedNameSet, name); + } + function isUniqueLocalName(name, container) { + for (var node = container; ts.isNodeDescendantOf(node, container); node = node.nextContainer) { + if (node.locals && ts.hasProperty(node.locals, name)) { + // We conservatively include alias symbols to cover cases where they're emitted as locals + if (node.locals[name].flags & (107455 /* Value */ | 1048576 /* ExportValue */ | 8388608 /* Alias */)) { + return false; + } + } } - return sourceFile; + return true; } - // Change cached program to the given program - function setCachedProgram(program) { - if (cachedProgram) { - var newSourceFiles_1 = program ? program.getSourceFiles() : undefined; - ts.forEach(cachedProgram.getSourceFiles(), function (sourceFile) { - if (!(newSourceFiles_1 && ts.contains(newSourceFiles_1, sourceFile))) { - if (sourceFile.fileWatcher) { - sourceFile.fileWatcher.close(); - sourceFile.fileWatcher = undefined; - } + /** + * Return the next available name in the pattern _a ... _z, _0, _1, ... + * TempFlags._i or TempFlags._n may be used to express a preference for that dedicated name. + * Note that names generated by makeTempVariableName and makeUniqueName will never conflict. + */ + function makeTempVariableName(flags) { + if (flags && !(tempFlags & flags)) { + var name_44 = flags === 268435456 /* _i */ ? "_i" : "_n"; + if (isUniqueName(name_44)) { + tempFlags |= flags; + return name_44; + } + } + while (true) { + var count = tempFlags & 268435455 /* CountMask */; + tempFlags++; + // Skip over 'i' and 'n' + if (count !== 8 && count !== 13) { + var name_45 = count < 26 + ? "_" + String.fromCharCode(97 /* a */ + count) + : "_" + (count - 26); + if (isUniqueName(name_45)) { + return name_45; } - }); + } } - cachedProgram = program; } - // If a source file changes, mark it as unwatched and start the recompilation timer - function sourceFileChanged(sourceFile, removed) { - sourceFile.fileWatcher.close(); - sourceFile.fileWatcher = undefined; - if (removed) { - ts.unorderedRemoveItem(rootFileNames, sourceFile.fileName); + // Generate a name that is unique within the current file and doesn't conflict with any names + // in global scope. The name is formed by adding an '_n' suffix to the specified base name, + // where n is a positive integer. Note that names generated by makeTempVariableName and + // makeUniqueName are guaranteed to never conflict. + function makeUniqueName(baseName) { + // Find the first unique 'name_n', where n is a positive number + if (baseName.charCodeAt(baseName.length - 1) !== 95 /* _ */) { + baseName += "_"; + } + var i = 1; + while (true) { + var generatedName = baseName + i; + if (isUniqueName(generatedName)) { + return generatedNameSet[generatedName] = generatedName; + } + i++; } - startTimerForRecompilation(); } - // If the configuration file changes, forget cached program and start the recompilation timer - function configFileChanged() { - setCachedProgram(undefined); - cachedConfigFileText = undefined; - startTimerForRecompilation(); + function generateNameForModuleOrEnum(node) { + var name = getTextOfNode(node.name); + // Use module/enum name itself if it is unique, otherwise make a unique variation + return isUniqueLocalName(name, node) ? name : makeUniqueName(name); } - function watchedDirectoryChanged(fileName) { - if (fileName && !ts.isSupportedSourceFileName(fileName, compilerOptions)) { - return; + function generateNameForImportOrExportDeclaration(node) { + var expr = ts.getExternalModuleName(node); + var baseName = expr.kind === 9 /* StringLiteral */ ? + ts.escapeIdentifier(ts.makeIdentifierFromModuleName(expr.text)) : "module"; + return makeUniqueName(baseName); + } + function generateNameForExportDefault() { + return makeUniqueName("default"); + } + function generateNameForClassExpression() { + return makeUniqueName("class"); + } + /** + * Generates a unique name from a node. + * + * @param node A node. + */ + function generateNameForNode(node) { + switch (node.kind) { + case 69 /* Identifier */: + return makeUniqueName(getTextOfNode(node)); + case 225 /* ModuleDeclaration */: + case 224 /* EnumDeclaration */: + return generateNameForModuleOrEnum(node); + case 230 /* ImportDeclaration */: + case 236 /* ExportDeclaration */: + return generateNameForImportOrExportDeclaration(node); + case 220 /* FunctionDeclaration */: + case 221 /* ClassDeclaration */: + case 235 /* ExportAssignment */: + return generateNameForExportDefault(); + case 192 /* ClassExpression */: + return generateNameForClassExpression(); + default: + return makeTempVariableName(0 /* Auto */); } - startTimerForHandlingDirectoryChanges(); } - function startTimerForHandlingDirectoryChanges() { - if (timerHandleForDirectoryChanges) { - clearTimeout(timerHandleForDirectoryChanges); + /** + * Generates a unique identifier for a node. + * + * @param name A generated name. + */ + function generateName(name) { + switch (name.autoGenerateKind) { + case 1 /* Auto */: + return makeTempVariableName(0 /* Auto */); + case 2 /* Loop */: + return makeTempVariableName(268435456 /* _i */); + case 3 /* Unique */: + return makeUniqueName(name.text); } - timerHandleForDirectoryChanges = setTimeout(directoryChangeHandler, 250); + ts.Debug.fail("Unsupported GeneratedIdentifierKind."); } - function directoryChangeHandler() { - var parsedCommandLine = parseConfigFile(); - var newFileNames = ts.map(parsedCommandLine.fileNames, compilerHost.getCanonicalFileName); - var canonicalRootFileNames = ts.map(rootFileNames, compilerHost.getCanonicalFileName); - // We check if the project file list has changed. If so, we just throw away the old program and start fresh. - if (!ts.arrayIsEqualTo(newFileNames && newFileNames.sort(), canonicalRootFileNames && canonicalRootFileNames.sort())) { - setCachedProgram(undefined); - startTimerForRecompilation(); + /** + * Gets the node from which a name should be generated. + * + * @param name A generated name wrapper. + */ + function getNodeForGeneratedName(name) { + var autoGenerateId = name.autoGenerateId; + var node = name; + var original = node.original; + while (original) { + node = original; + // if "node" is a different generated name (having a different + // "autoGenerateId"), use it and stop traversing. + if (ts.isIdentifier(node) + && node.autoGenerateKind === 4 /* Node */ + && node.autoGenerateId !== autoGenerateId) { + break; + } + original = node.original; } + // otherwise, return the original node for the source; + return node; } - // Upon detecting a file change, wait for 250ms and then perform a recompilation. This gives batch - // operations (such as saving all modified files in an editor) a chance to complete before we kick - // off a new compilation. - function startTimerForRecompilation() { - if (timerHandleForRecompilation) { - clearTimeout(timerHandleForRecompilation); + /** + * Gets the generated identifier text from a generated identifier. + * + * @param name The generated identifier. + */ + function getGeneratedIdentifier(name) { + if (name.autoGenerateKind === 4 /* Node */) { + // Generated names generate unique names based on their original node + // and are cached based on that node's id + var node = getNodeForGeneratedName(name); + var nodeId = ts.getNodeId(node); + return nodeIdToGeneratedName[nodeId] || (nodeIdToGeneratedName[nodeId] = ts.unescapeIdentifier(generateNameForNode(node))); + } + else { + // Auto, Loop, and Unique names are cached based on their unique + // autoGenerateId. + var autoGenerateId = name.autoGenerateId; + return autoGeneratedIdToGeneratedName[autoGenerateId] || (autoGeneratedIdToGeneratedName[autoGenerateId] = ts.unescapeIdentifier(generateName(name))); } - timerHandleForRecompilation = setTimeout(recompile, 250); } - function recompile() { - timerHandleForRecompilation = undefined; - reportWatchDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.File_change_detected_Starting_incremental_compilation)); - performCompilation(); + function createDelimiterMap() { + var delimiters = []; + delimiters[0 /* None */] = ""; + delimiters[16 /* CommaDelimited */] = ","; + delimiters[4 /* BarDelimited */] = " |"; + delimiters[8 /* AmpersandDelimited */] = " &"; + return delimiters; + } + function getDelimiter(format) { + return delimiters[format & 28 /* DelimitersMask */]; + } + function createBracketsMap() { + var brackets = []; + brackets[512 /* Braces */] = ["{", "}"]; + brackets[1024 /* Parenthesis */] = ["(", ")"]; + brackets[2048 /* AngleBrackets */] = ["<", ">"]; + brackets[4096 /* SquareBrackets */] = ["[", "]"]; + return brackets; + } + function getOpeningBracket(format) { + return brackets[format & 7680 /* BracketsMask */][0]; + } + function getClosingBracket(format) { + return brackets[format & 7680 /* BracketsMask */][1]; } } - ts.executeCommandLine = executeCommandLine; - function compile(fileNames, compilerOptions, compilerHost) { - var hasDiagnostics = compilerOptions.diagnostics || compilerOptions.extendedDiagnostics; - if (hasDiagnostics) - ts.performance.enable(); - var program = ts.createProgram(fileNames, compilerOptions, compilerHost); - var exitStatus = compileProgram(); - if (compilerOptions.listFiles) { - ts.forEach(program.getSourceFiles(), function (file) { - ts.sys.write(file.fileName + ts.sys.newLine); - }); + ts.emitFiles = emitFiles; + var ListFormat; + (function (ListFormat) { + ListFormat[ListFormat["None"] = 0] = "None"; + // Line separators + ListFormat[ListFormat["SingleLine"] = 0] = "SingleLine"; + ListFormat[ListFormat["MultiLine"] = 1] = "MultiLine"; + ListFormat[ListFormat["PreserveLines"] = 2] = "PreserveLines"; + ListFormat[ListFormat["LinesMask"] = 3] = "LinesMask"; + // Delimiters + ListFormat[ListFormat["NotDelimited"] = 0] = "NotDelimited"; + ListFormat[ListFormat["BarDelimited"] = 4] = "BarDelimited"; + ListFormat[ListFormat["AmpersandDelimited"] = 8] = "AmpersandDelimited"; + ListFormat[ListFormat["CommaDelimited"] = 16] = "CommaDelimited"; + ListFormat[ListFormat["DelimitersMask"] = 28] = "DelimitersMask"; + ListFormat[ListFormat["AllowTrailingComma"] = 32] = "AllowTrailingComma"; + // Whitespace + ListFormat[ListFormat["Indented"] = 64] = "Indented"; + ListFormat[ListFormat["SpaceBetweenBraces"] = 128] = "SpaceBetweenBraces"; + ListFormat[ListFormat["SpaceBetweenSiblings"] = 256] = "SpaceBetweenSiblings"; + // Brackets/Braces + ListFormat[ListFormat["Braces"] = 512] = "Braces"; + ListFormat[ListFormat["Parenthesis"] = 1024] = "Parenthesis"; + ListFormat[ListFormat["AngleBrackets"] = 2048] = "AngleBrackets"; + ListFormat[ListFormat["SquareBrackets"] = 4096] = "SquareBrackets"; + ListFormat[ListFormat["BracketsMask"] = 7680] = "BracketsMask"; + ListFormat[ListFormat["OptionalIfUndefined"] = 8192] = "OptionalIfUndefined"; + ListFormat[ListFormat["OptionalIfEmpty"] = 16384] = "OptionalIfEmpty"; + ListFormat[ListFormat["Optional"] = 24576] = "Optional"; + // Other + ListFormat[ListFormat["PreferNewLine"] = 32768] = "PreferNewLine"; + ListFormat[ListFormat["NoTrailingNewLine"] = 65536] = "NoTrailingNewLine"; + ListFormat[ListFormat["NoInterveningComments"] = 131072] = "NoInterveningComments"; + // Precomputed Formats + ListFormat[ListFormat["Modifiers"] = 256] = "Modifiers"; + ListFormat[ListFormat["HeritageClauses"] = 256] = "HeritageClauses"; + ListFormat[ListFormat["TypeLiteralMembers"] = 65] = "TypeLiteralMembers"; + ListFormat[ListFormat["TupleTypeElements"] = 336] = "TupleTypeElements"; + ListFormat[ListFormat["UnionTypeConstituents"] = 260] = "UnionTypeConstituents"; + ListFormat[ListFormat["IntersectionTypeConstituents"] = 264] = "IntersectionTypeConstituents"; + ListFormat[ListFormat["ObjectBindingPatternElements"] = 432] = "ObjectBindingPatternElements"; + ListFormat[ListFormat["ArrayBindingPatternElements"] = 304] = "ArrayBindingPatternElements"; + ListFormat[ListFormat["ObjectLiteralExpressionProperties"] = 978] = "ObjectLiteralExpressionProperties"; + ListFormat[ListFormat["ArrayLiteralExpressionElements"] = 4466] = "ArrayLiteralExpressionElements"; + ListFormat[ListFormat["CallExpressionArguments"] = 1296] = "CallExpressionArguments"; + ListFormat[ListFormat["NewExpressionArguments"] = 9488] = "NewExpressionArguments"; + ListFormat[ListFormat["TemplateExpressionSpans"] = 131072] = "TemplateExpressionSpans"; + ListFormat[ListFormat["SingleLineBlockStatements"] = 384] = "SingleLineBlockStatements"; + ListFormat[ListFormat["MultiLineBlockStatements"] = 65] = "MultiLineBlockStatements"; + ListFormat[ListFormat["VariableDeclarationList"] = 272] = "VariableDeclarationList"; + ListFormat[ListFormat["SingleLineFunctionBodyStatements"] = 384] = "SingleLineFunctionBodyStatements"; + ListFormat[ListFormat["MultiLineFunctionBodyStatements"] = 1] = "MultiLineFunctionBodyStatements"; + ListFormat[ListFormat["ClassHeritageClauses"] = 256] = "ClassHeritageClauses"; + ListFormat[ListFormat["ClassMembers"] = 65] = "ClassMembers"; + ListFormat[ListFormat["InterfaceMembers"] = 65] = "InterfaceMembers"; + ListFormat[ListFormat["EnumMembers"] = 81] = "EnumMembers"; + ListFormat[ListFormat["CaseBlockClauses"] = 65] = "CaseBlockClauses"; + ListFormat[ListFormat["NamedImportsOrExportsElements"] = 432] = "NamedImportsOrExportsElements"; + ListFormat[ListFormat["JsxElementChildren"] = 131072] = "JsxElementChildren"; + ListFormat[ListFormat["JsxElementAttributes"] = 131328] = "JsxElementAttributes"; + ListFormat[ListFormat["CaseOrDefaultClauseStatements"] = 81985] = "CaseOrDefaultClauseStatements"; + ListFormat[ListFormat["HeritageClauseTypes"] = 272] = "HeritageClauseTypes"; + ListFormat[ListFormat["SourceFileStatements"] = 65537] = "SourceFileStatements"; + ListFormat[ListFormat["Decorators"] = 24577] = "Decorators"; + ListFormat[ListFormat["TypeArguments"] = 26960] = "TypeArguments"; + ListFormat[ListFormat["TypeParameters"] = 26960] = "TypeParameters"; + ListFormat[ListFormat["Parameters"] = 1360] = "Parameters"; + ListFormat[ListFormat["IndexSignatureParameters"] = 4432] = "IndexSignatureParameters"; + })(ListFormat || (ListFormat = {})); +})(ts || (ts = {})); +/// +/// +/// +var ts; +(function (ts) { + /** The version of the TypeScript compiler release */ + ts.version = "2.1.0"; + var emptyArray = []; + function findConfigFile(searchPath, fileExists, configName) { + if (configName === void 0) { configName = "tsconfig.json"; } + while (true) { + var fileName = ts.combinePaths(searchPath, configName); + if (fileExists(fileName)) { + return fileName; + } + var parentPath = ts.getDirectoryPath(searchPath); + if (parentPath === searchPath) { + break; + } + searchPath = parentPath; } - if (hasDiagnostics) { - var memoryUsed = ts.sys.getMemoryUsage ? ts.sys.getMemoryUsage() : -1; - reportCountStatistic("Files", program.getSourceFiles().length); - reportCountStatistic("Lines", countLines(program)); - reportCountStatistic("Nodes", program.getNodeCount()); - reportCountStatistic("Identifiers", program.getIdentifierCount()); - reportCountStatistic("Symbols", program.getSymbolCount()); - reportCountStatistic("Types", program.getTypeCount()); - if (memoryUsed >= 0) { - reportStatisticalValue("Memory used", Math.round(memoryUsed / 1000) + "K"); + return undefined; + } + ts.findConfigFile = findConfigFile; + function resolveTripleslashReference(moduleName, containingFile) { + var basePath = ts.getDirectoryPath(containingFile); + var referencedFileName = ts.isRootedDiskPath(moduleName) ? moduleName : ts.combinePaths(basePath, moduleName); + return ts.normalizePath(referencedFileName); + } + ts.resolveTripleslashReference = resolveTripleslashReference; + /* @internal */ + function computeCommonSourceDirectoryOfFilenames(fileNames, currentDirectory, getCanonicalFileName) { + var commonPathComponents; + var failed = ts.forEach(fileNames, function (sourceFile) { + // Each file contributes into common source file path + var sourcePathComponents = ts.getNormalizedPathComponents(sourceFile, currentDirectory); + sourcePathComponents.pop(); // The base file name is not part of the common directory path + if (!commonPathComponents) { + // first file + commonPathComponents = sourcePathComponents; + return; } - var programTime = ts.performance.getDuration("Program"); - var bindTime = ts.performance.getDuration("Bind"); - var checkTime = ts.performance.getDuration("Check"); - var emitTime = ts.performance.getDuration("Emit"); - if (compilerOptions.extendedDiagnostics) { - ts.performance.forEachMeasure(function (name, duration) { return reportTimeStatistic(name + " time", duration); }); + for (var i = 0, n = Math.min(commonPathComponents.length, sourcePathComponents.length); i < n; i++) { + if (getCanonicalFileName(commonPathComponents[i]) !== getCanonicalFileName(sourcePathComponents[i])) { + if (i === 0) { + // Failed to find any common path component + return true; + } + // New common path found that is 0 -> i-1 + commonPathComponents.length = i; + break; + } } - else { - // Individual component times. - // Note: To match the behavior of previous versions of the compiler, the reported parse time includes - // I/O read time and processing time for triple-slash references and module imports, and the reported - // emit time includes I/O write time. We preserve this behavior so we can accurately compare times. - reportTimeStatistic("I/O read", ts.performance.getDuration("I/O Read")); - reportTimeStatistic("I/O write", ts.performance.getDuration("I/O Write")); - reportTimeStatistic("Parse time", programTime); - reportTimeStatistic("Bind time", bindTime); - reportTimeStatistic("Check time", checkTime); - reportTimeStatistic("Emit time", emitTime); + // If the sourcePathComponents was shorter than the commonPathComponents, truncate to the sourcePathComponents + if (sourcePathComponents.length < commonPathComponents.length) { + commonPathComponents.length = sourcePathComponents.length; } - reportTimeStatistic("Total time", programTime + bindTime + checkTime + emitTime); - ts.performance.disable(); + }); + // A common path can not be found when paths span multiple drives on windows, for example + if (failed) { + return ""; } - return { program: program, exitStatus: exitStatus }; - function compileProgram() { - var diagnostics; - // First get and report any syntactic errors. - diagnostics = program.getSyntacticDiagnostics(); - // If we didn't have any syntactic errors, then also try getting the global and - // semantic errors. - if (diagnostics.length === 0) { - diagnostics = program.getOptionsDiagnostics().concat(program.getGlobalDiagnostics()); - if (diagnostics.length === 0) { - diagnostics = program.getSemanticDiagnostics(); + if (!commonPathComponents) { + return currentDirectory; + } + return ts.getNormalizedPathFromPathComponents(commonPathComponents); + } + ts.computeCommonSourceDirectoryOfFilenames = computeCommonSourceDirectoryOfFilenames; + function createCompilerHost(options, setParentNodes) { + var existingDirectories = ts.createMap(); + function getCanonicalFileName(fileName) { + // if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form. + // otherwise use toLowerCase as a canonical form. + return ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); + } + // returned by CScript sys environment + var unsupportedFileEncodingErrorCode = -2147024809; + function getSourceFile(fileName, languageVersion, onError) { + var text; + try { + ts.performance.mark("beforeIORead"); + text = ts.sys.readFile(fileName, options.charset); + ts.performance.mark("afterIORead"); + ts.performance.measure("I/O Read", "beforeIORead", "afterIORead"); + } + catch (e) { + if (onError) { + onError(e.number === unsupportedFileEncodingErrorCode + ? ts.createCompilerDiagnostic(ts.Diagnostics.Unsupported_file_encoding).messageText + : e.message); } + text = ""; } - // Otherwise, emit and report any errors we ran into. - var emitOutput = program.emit(); - diagnostics = diagnostics.concat(emitOutput.diagnostics); - reportDiagnostics(ts.sortAndDeduplicateDiagnostics(diagnostics), compilerHost); - reportEmittedFiles(emitOutput.emittedFiles, compilerHost); - if (emitOutput.emitSkipped && diagnostics.length > 0) { - // If the emitter didn't emit anything, then pass that value along. - return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped; + return text !== undefined ? ts.createSourceFile(fileName, text, languageVersion, setParentNodes) : undefined; + } + function directoryExists(directoryPath) { + if (directoryPath in existingDirectories) { + return true; } - else if (diagnostics.length > 0) { - // The emitter emitted something, inform the caller if that happened in the presence - // of diagnostics or not. - return ts.ExitStatus.DiagnosticsPresent_OutputsGenerated; + if (ts.sys.directoryExists(directoryPath)) { + existingDirectories[directoryPath] = true; + return true; } - return ts.ExitStatus.Success; + return false; } - } - function printVersion() { - ts.sys.write(getDiagnosticText(ts.Diagnostics.Version_0, ts.version) + ts.sys.newLine); - } - function printHelp() { - var output = ""; - // We want to align our "syntax" and "examples" commands to a certain margin. - var syntaxLength = getDiagnosticText(ts.Diagnostics.Syntax_Colon_0, "").length; - var examplesLength = getDiagnosticText(ts.Diagnostics.Examples_Colon_0, "").length; - var marginLength = Math.max(syntaxLength, examplesLength); - // Build up the syntactic skeleton. - var syntax = makePadding(marginLength - syntaxLength); - syntax += "tsc [" + getDiagnosticText(ts.Diagnostics.options) + "] [" + getDiagnosticText(ts.Diagnostics.file) + " ...]"; - output += getDiagnosticText(ts.Diagnostics.Syntax_Colon_0, syntax); - output += ts.sys.newLine + ts.sys.newLine; - // Build up the list of examples. - var padding = makePadding(marginLength); - output += getDiagnosticText(ts.Diagnostics.Examples_Colon_0, makePadding(marginLength - examplesLength) + "tsc hello.ts") + ts.sys.newLine; - output += padding + "tsc --outFile file.js file.ts" + ts.sys.newLine; - output += padding + "tsc @args.txt" + ts.sys.newLine; - output += ts.sys.newLine; - output += getDiagnosticText(ts.Diagnostics.Options_Colon) + ts.sys.newLine; - // Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch") - var optsList = ts.filter(ts.optionDeclarations.slice(), function (v) { return !v.experimental; }); - optsList.sort(function (a, b) { return ts.compareValues(a.name.toLowerCase(), b.name.toLowerCase()); }); - // We want our descriptions to align at the same column in our output, - // so we keep track of the longest option usage string. - marginLength = 0; - var usageColumn = []; // Things like "-d, --declaration" go in here. - var descriptionColumn = []; - var optionsDescriptionMap = ts.createMap(); // Map between option.description and list of option.type if it is a kind - for (var i = 0; i < optsList.length; i++) { - var option = optsList[i]; - // If an option lacks a description, - // it is not officially supported. - if (!option.description) { - continue; + function ensureDirectoriesExist(directoryPath) { + if (directoryPath.length > ts.getRootLength(directoryPath) && !directoryExists(directoryPath)) { + var parentDirectory = ts.getDirectoryPath(directoryPath); + ensureDirectoriesExist(parentDirectory); + ts.sys.createDirectory(directoryPath); } - var usageText_1 = " "; - if (option.shortName) { - usageText_1 += "-" + option.shortName; - usageText_1 += getParamType(option); - usageText_1 += ", "; + } + var outputFingerprints; + function writeFileIfUpdated(fileName, data, writeByteOrderMark) { + if (!outputFingerprints) { + outputFingerprints = ts.createMap(); } - usageText_1 += "--" + option.name; - usageText_1 += getParamType(option); - usageColumn.push(usageText_1); - var description = void 0; - if (option.name === "lib") { - description = getDiagnosticText(option.description); - var options = []; - var element = option.element; - var typeMap = element.type; - for (var key in typeMap) { - options.push("'" + key + "'"); + var hash = ts.sys.createHash(data); + var mtimeBefore = ts.sys.getModifiedTime(fileName); + if (mtimeBefore && fileName in outputFingerprints) { + var fingerprint = outputFingerprints[fileName]; + // If output has not been changed, and the file has no external modification + if (fingerprint.byteOrderMark === writeByteOrderMark && + fingerprint.hash === hash && + fingerprint.mtime.getTime() === mtimeBefore.getTime()) { + return; } - optionsDescriptionMap[description] = options; } - else { - description = getDiagnosticText(option.description); + ts.sys.writeFile(fileName, data, writeByteOrderMark); + var mtimeAfter = ts.sys.getModifiedTime(fileName); + outputFingerprints[fileName] = { + hash: hash, + byteOrderMark: writeByteOrderMark, + mtime: mtimeAfter + }; + } + function writeFile(fileName, data, writeByteOrderMark, onError) { + try { + ts.performance.mark("beforeIOWrite"); + ensureDirectoriesExist(ts.getDirectoryPath(ts.normalizePath(fileName))); + if (ts.isWatchSet(options) && ts.sys.createHash && ts.sys.getModifiedTime) { + writeFileIfUpdated(fileName, data, writeByteOrderMark); + } + else { + ts.sys.writeFile(fileName, data, writeByteOrderMark); + } + ts.performance.mark("afterIOWrite"); + ts.performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite"); } - descriptionColumn.push(description); - // Set the new margin for the description column if necessary. - marginLength = Math.max(usageText_1.length, marginLength); + catch (e) { + if (onError) { + onError(e.message); + } + } + } + function getDefaultLibLocation() { + return ts.getDirectoryPath(ts.normalizePath(ts.sys.getExecutingFilePath())); + } + var newLine = ts.getNewLineCharacter(options); + var realpath = ts.sys.realpath && (function (path) { return ts.sys.realpath(path); }); + return { + getSourceFile: getSourceFile, + getDefaultLibLocation: getDefaultLibLocation, + getDefaultLibFileName: function (options) { return ts.combinePaths(getDefaultLibLocation(), ts.getDefaultLibFileName(options)); }, + writeFile: writeFile, + getCurrentDirectory: ts.memoize(function () { return ts.sys.getCurrentDirectory(); }), + useCaseSensitiveFileNames: function () { return ts.sys.useCaseSensitiveFileNames; }, + getCanonicalFileName: getCanonicalFileName, + getNewLine: function () { return newLine; }, + fileExists: function (fileName) { return ts.sys.fileExists(fileName); }, + readFile: function (fileName) { return ts.sys.readFile(fileName); }, + trace: function (s) { return ts.sys.write(s + newLine); }, + directoryExists: function (directoryName) { return ts.sys.directoryExists(directoryName); }, + getEnvironmentVariable: function (name) { return ts.getEnvironmentVariable(name, /*host*/ undefined); }, + getDirectories: function (path) { return ts.sys.getDirectories(path); }, + realpath: realpath + }; + } + ts.createCompilerHost = createCompilerHost; + function getPreEmitDiagnostics(program, sourceFile, cancellationToken) { + var diagnostics = program.getOptionsDiagnostics(cancellationToken).concat(program.getSyntacticDiagnostics(sourceFile, cancellationToken), program.getGlobalDiagnostics(cancellationToken), program.getSemanticDiagnostics(sourceFile, cancellationToken)); + if (program.getCompilerOptions().declaration) { + diagnostics = diagnostics.concat(program.getDeclarationDiagnostics(sourceFile, cancellationToken)); + } + return ts.sortAndDeduplicateDiagnostics(diagnostics); + } + ts.getPreEmitDiagnostics = getPreEmitDiagnostics; + function formatDiagnostics(diagnostics, host) { + var output = ""; + for (var _i = 0, diagnostics_1 = diagnostics; _i < diagnostics_1.length; _i++) { + var diagnostic = diagnostics_1[_i]; + if (diagnostic.file) { + var _a = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start), line = _a.line, character = _a.character; + var fileName = diagnostic.file.fileName; + var relativeFileName = ts.convertToRelativePath(fileName, host.getCurrentDirectory(), function (fileName) { return host.getCanonicalFileName(fileName); }); + output += relativeFileName + "(" + (line + 1) + "," + (character + 1) + "): "; + } + var category = ts.DiagnosticCategory[diagnostic.category].toLowerCase(); + output += category + " TS" + diagnostic.code + ": " + flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine()) + host.getNewLine(); + } + return output; + } + ts.formatDiagnostics = formatDiagnostics; + function flattenDiagnosticMessageText(messageText, newLine) { + if (typeof messageText === "string") { + return messageText; } - // Special case that can't fit in the loop. - var usageText = " @<" + getDiagnosticText(ts.Diagnostics.file) + ">"; - usageColumn.push(usageText); - descriptionColumn.push(getDiagnosticText(ts.Diagnostics.Insert_command_line_options_and_files_from_a_file)); - marginLength = Math.max(usageText.length, marginLength); - // Print out each row, aligning all the descriptions on the same column. - for (var i = 0; i < usageColumn.length; i++) { - var usage = usageColumn[i]; - var description = descriptionColumn[i]; - var kindsList = optionsDescriptionMap[description]; - output += usage + makePadding(marginLength - usage.length + 2) + description + ts.sys.newLine; - if (kindsList) { - output += makePadding(marginLength + 4); - for (var _i = 0, kindsList_1 = kindsList; _i < kindsList_1.length; _i++) { - var kind = kindsList_1[_i]; - output += kind + " "; + else { + var diagnosticChain = messageText; + var result = ""; + var indent = 0; + while (diagnosticChain) { + if (indent) { + result += newLine; + for (var i = 0; i < indent; i++) { + result += " "; + } } - output += ts.sys.newLine; + result += diagnosticChain.messageText; + indent++; + diagnosticChain = diagnosticChain.next; } + return result; } - ts.sys.write(output); - return; - function getParamType(option) { - if (option.paramType !== undefined) { - return " " + getDiagnosticText(option.paramType); - } - return ""; + } + ts.flattenDiagnosticMessageText = flattenDiagnosticMessageText; + function loadWithLocalCache(names, containingFile, loader) { + if (names.length === 0) { + return []; } - function makePadding(paddingLength) { - return Array(paddingLength + 1).join(" "); + var resolutions = []; + var cache = ts.createMap(); + for (var _i = 0, names_2 = names; _i < names_2.length; _i++) { + var name_46 = names_2[_i]; + var result = name_46 in cache + ? cache[name_46] + : cache[name_46] = loader(name_46, containingFile); + resolutions.push(result); } + return resolutions; } - function writeConfigFile(options, fileNames) { - var currentDirectory = ts.sys.getCurrentDirectory(); - var file = ts.normalizePath(ts.combinePaths(currentDirectory, "tsconfig.json")); - if (ts.sys.fileExists(file)) { - reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file), /* host */ undefined); + function createProgram(rootNames, options, host, oldProgram) { + var program; + var files = []; + var commonSourceDirectory; + var diagnosticsProducingTypeChecker; + var noDiagnosticsTypeChecker; + var classifiableNames; + var resolvedTypeReferenceDirectives = ts.createMap(); + var fileProcessingDiagnostics = ts.createDiagnosticCollection(); + // The below settings are to track if a .js file should be add to the program if loaded via searching under node_modules. + // This works as imported modules are discovered recursively in a depth first manner, specifically: + // - For each root file, findSourceFile is called. + // - This calls processImportedModules for each module imported in the source file. + // - This calls resolveModuleNames, and then calls findSourceFile for each resolved module. + // As all these operations happen - and are nested - within the createProgram call, they close over the below variables. + // The current resolution depth is tracked by incrementing/decrementing as the depth first search progresses. + var maxNodeModulesJsDepth = typeof options.maxNodeModuleJsDepth === "number" ? options.maxNodeModuleJsDepth : 0; + var currentNodeModulesDepth = 0; + // If a module has some of its imports skipped due to being at the depth limit under node_modules, then track + // this, as it may be imported at a shallower depth later, and then it will need its skipped imports processed. + var modulesWithElidedImports = ts.createMap(); + // Track source files that are source files found by searching under node_modules, as these shouldn't be compiled. + var sourceFilesFoundSearchingNodeModules = ts.createMap(); + ts.performance.mark("beforeProgram"); + host = host || createCompilerHost(options); + var skipDefaultLib = options.noLib; + var programDiagnostics = ts.createDiagnosticCollection(); + var currentDirectory = host.getCurrentDirectory(); + var supportedExtensions = ts.getSupportedExtensions(options); + // Map storing if there is emit blocking diagnostics for given input + var hasEmitBlockingDiagnostics = ts.createFileMap(getCanonicalFileName); + var resolveModuleNamesWorker; + if (host.resolveModuleNames) { + resolveModuleNamesWorker = function (moduleNames, containingFile) { return host.resolveModuleNames(moduleNames, containingFile); }; } else { - ts.sys.writeFile(file, JSON.stringify(ts.generateTSConfig(options, fileNames), undefined, 4)); - reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.Successfully_created_a_tsconfig_json_file), /* host */ undefined); + var loader_1 = function (moduleName, containingFile) { return ts.resolveModuleName(moduleName, containingFile, options, host).resolvedModule; }; + resolveModuleNamesWorker = function (moduleNames, containingFile) { return loadWithLocalCache(moduleNames, containingFile, loader_1); }; } - return; - } - var _a; -})(ts || (ts = {})); -ts.executeCommandLine(ts.sys.args); -/* @internal */ -var ts; -(function (ts) { - var OutliningElementsCollector; - (function (OutliningElementsCollector) { - function collectElements(sourceFile) { - var elements = []; - var collapseText = "..."; - function addOutliningSpan(hintSpanNode, startElement, endElement, autoCollapse) { - if (hintSpanNode && startElement && endElement) { - var span = { - textSpan: ts.createTextSpanFromBounds(startElement.pos, endElement.end), - hintSpan: ts.createTextSpanFromBounds(hintSpanNode.getStart(), hintSpanNode.end), - bannerText: collapseText, - autoCollapse: autoCollapse - }; - elements.push(span); + var resolveTypeReferenceDirectiveNamesWorker; + if (host.resolveTypeReferenceDirectives) { + resolveTypeReferenceDirectiveNamesWorker = function (typeDirectiveNames, containingFile) { return host.resolveTypeReferenceDirectives(typeDirectiveNames, containingFile); }; + } + else { + var loader_2 = function (typesRef, containingFile) { return ts.resolveTypeReferenceDirective(typesRef, containingFile, options, host).resolvedTypeReferenceDirective; }; + resolveTypeReferenceDirectiveNamesWorker = function (typeReferenceDirectiveNames, containingFile) { return loadWithLocalCache(typeReferenceDirectiveNames, containingFile, loader_2); }; + } + var filesByName = ts.createFileMap(); + // stores 'filename -> file association' ignoring case + // used to track cases when two file names differ only in casing + var filesByNameIgnoreCase = host.useCaseSensitiveFileNames() ? ts.createFileMap(function (fileName) { return fileName.toLowerCase(); }) : undefined; + if (!tryReuseStructureFromOldProgram()) { + ts.forEach(rootNames, function (name) { return processRootFile(name, /*isDefaultLib*/ false); }); + // load type declarations specified via 'types' argument or implicitly from types/ and node_modules/@types folders + var typeReferences = ts.getAutomaticTypeDirectiveNames(options, host); + if (typeReferences) { + // This containingFilename needs to match with the one used in managed-side + var containingFilename = ts.combinePaths(host.getCurrentDirectory(), "__inferred type names__.ts"); + var resolutions = resolveTypeReferenceDirectiveNamesWorker(typeReferences, containingFilename); + for (var i = 0; i < typeReferences.length; i++) { + processTypeReferenceDirective(typeReferences[i], resolutions[i]); } } - function addOutliningSpanComments(commentSpan, autoCollapse) { - if (commentSpan) { - var span = { - textSpan: ts.createTextSpanFromBounds(commentSpan.pos, commentSpan.end), - hintSpan: ts.createTextSpanFromBounds(commentSpan.pos, commentSpan.end), - bannerText: collapseText, - autoCollapse: autoCollapse - }; - elements.push(span); + // Do not process the default library if: + // - The '--noLib' flag is used. + // - A 'no-default-lib' reference comment is encountered in + // processing the root files. + if (!skipDefaultLib) { + // If '--lib' is not specified, include default library file according to '--target' + // otherwise, using options specified in '--lib' instead of '--target' default library file + if (!options.lib) { + processRootFile(host.getDefaultLibFileName(options), /*isDefaultLib*/ true); + } + else { + var libDirectory_1 = host.getDefaultLibLocation ? host.getDefaultLibLocation() : ts.getDirectoryPath(host.getDefaultLibFileName(options)); + ts.forEach(options.lib, function (libFileName) { + processRootFile(ts.combinePaths(libDirectory_1, libFileName), /*isDefaultLib*/ true); + }); } } - function addOutliningForLeadingCommentsForNode(n) { - var comments = ts.getLeadingCommentRangesOfNode(n, sourceFile); - if (comments) { - var firstSingleLineCommentStart = -1; - var lastSingleLineCommentEnd = -1; - var isFirstSingleLineComment = true; - var singleLineCommentCount = 0; - for (var _i = 0, comments_2 = comments; _i < comments_2.length; _i++) { - var currentComment = comments_2[_i]; - // For single line comments, combine consecutive ones (2 or more) into - // a single span from the start of the first till the end of the last - if (currentComment.kind === 2 /* SingleLineCommentTrivia */) { - if (isFirstSingleLineComment) { - firstSingleLineCommentStart = currentComment.pos; - } - isFirstSingleLineComment = false; - lastSingleLineCommentEnd = currentComment.end; - singleLineCommentCount++; - } - else if (currentComment.kind === 3 /* MultiLineCommentTrivia */) { - combineAndAddMultipleSingleLineComments(singleLineCommentCount, firstSingleLineCommentStart, lastSingleLineCommentEnd); - addOutliningSpanComments(currentComment, /*autoCollapse*/ false); - singleLineCommentCount = 0; - lastSingleLineCommentEnd = -1; - isFirstSingleLineComment = true; - } - } - combineAndAddMultipleSingleLineComments(singleLineCommentCount, firstSingleLineCommentStart, lastSingleLineCommentEnd); + } + // unconditionally set oldProgram to undefined to prevent it from being captured in closure + oldProgram = undefined; + program = { + getRootFileNames: function () { return rootNames; }, + getSourceFile: getSourceFile, + getSourceFileByPath: getSourceFileByPath, + getSourceFiles: function () { return files; }, + getCompilerOptions: function () { return options; }, + getSyntacticDiagnostics: getSyntacticDiagnostics, + getOptionsDiagnostics: getOptionsDiagnostics, + getGlobalDiagnostics: getGlobalDiagnostics, + getSemanticDiagnostics: getSemanticDiagnostics, + getDeclarationDiagnostics: getDeclarationDiagnostics, + getTypeChecker: getTypeChecker, + getClassifiableNames: getClassifiableNames, + getDiagnosticsProducingTypeChecker: getDiagnosticsProducingTypeChecker, + getCommonSourceDirectory: getCommonSourceDirectory, + emit: emit, + getCurrentDirectory: function () { return currentDirectory; }, + getNodeCount: function () { return getDiagnosticsProducingTypeChecker().getNodeCount(); }, + getIdentifierCount: function () { return getDiagnosticsProducingTypeChecker().getIdentifierCount(); }, + getSymbolCount: function () { return getDiagnosticsProducingTypeChecker().getSymbolCount(); }, + getTypeCount: function () { return getDiagnosticsProducingTypeChecker().getTypeCount(); }, + getFileProcessingDiagnostics: function () { return fileProcessingDiagnostics; }, + getResolvedTypeReferenceDirectives: function () { return resolvedTypeReferenceDirectives; }, + dropDiagnosticsProducingTypeChecker: dropDiagnosticsProducingTypeChecker + }; + verifyCompilerOptions(); + ts.performance.mark("afterProgram"); + ts.performance.measure("Program", "beforeProgram", "afterProgram"); + return program; + function getCommonSourceDirectory() { + if (typeof commonSourceDirectory === "undefined") { + if (options.rootDir && checkSourceFilesBelongToPath(files, options.rootDir)) { + // If a rootDir is specified and is valid use it as the commonSourceDirectory + commonSourceDirectory = ts.getNormalizedAbsolutePath(options.rootDir, currentDirectory); + } + else { + commonSourceDirectory = computeCommonSourceDirectory(files); + } + if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== ts.directorySeparator) { + // Make sure directory path ends with directory separator so this string can directly + // used to replace with "" to get the relative path of the source file and the relative path doesn't + // start with / making it rooted path + commonSourceDirectory += ts.directorySeparator; } } - function combineAndAddMultipleSingleLineComments(count, start, end) { - // Only outline spans of two or more consecutive single line comments - if (count > 1) { - var multipleSingleLineComments = { - pos: start, - end: end, - kind: 2 /* SingleLineCommentTrivia */ - }; - addOutliningSpanComments(multipleSingleLineComments, /*autoCollapse*/ false); + return commonSourceDirectory; + } + function getClassifiableNames() { + if (!classifiableNames) { + // Initialize a checker so that all our files are bound. + getTypeChecker(); + classifiableNames = ts.createMap(); + for (var _i = 0, files_2 = files; _i < files_2.length; _i++) { + var sourceFile = files_2[_i]; + ts.copyProperties(sourceFile.classifiableNames, classifiableNames); } } - function autoCollapse(node) { - return ts.isFunctionBlock(node) && node.parent.kind !== 180 /* ArrowFunction */; + return classifiableNames; + } + function tryReuseStructureFromOldProgram() { + if (!oldProgram) { + return false; } - var depth = 0; - var maxDepth = 20; - function walk(n) { - if (depth > maxDepth) { - return; - } - if (ts.isDeclaration(n)) { - addOutliningForLeadingCommentsForNode(n); + // check properties that can affect structure of the program or module resolution strategy + // if any of these properties has changed - structure cannot be reused + var oldOptions = oldProgram.getCompilerOptions(); + if ((oldOptions.module !== options.module) || + (oldOptions.moduleResolution !== options.moduleResolution) || + (oldOptions.noResolve !== options.noResolve) || + (oldOptions.target !== options.target) || + (oldOptions.noLib !== options.noLib) || + (oldOptions.jsx !== options.jsx) || + (oldOptions.allowJs !== options.allowJs) || + (oldOptions.rootDir !== options.rootDir) || + (oldOptions.configFilePath !== options.configFilePath) || + (oldOptions.baseUrl !== options.baseUrl) || + (oldOptions.maxNodeModuleJsDepth !== options.maxNodeModuleJsDepth) || + !ts.arrayIsEqualTo(oldOptions.typeRoots, oldOptions.typeRoots) || + !ts.arrayIsEqualTo(oldOptions.rootDirs, options.rootDirs) || + !ts.equalOwnProperties(oldOptions.paths, options.paths)) { + return false; + } + ts.Debug.assert(!oldProgram.structureIsReused); + // there is an old program, check if we can reuse its structure + var oldRootNames = oldProgram.getRootFileNames(); + if (!ts.arrayIsEqualTo(oldRootNames, rootNames)) { + return false; + } + if (!ts.arrayIsEqualTo(options.types, oldOptions.types)) { + return false; + } + // check if program source files has changed in the way that can affect structure of the program + var newSourceFiles = []; + var filePaths = []; + var modifiedSourceFiles = []; + for (var _i = 0, _a = oldProgram.getSourceFiles(); _i < _a.length; _i++) { + var oldSourceFile = _a[_i]; + var newSourceFile = host.getSourceFileByPath + ? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.path, options.target) + : host.getSourceFile(oldSourceFile.fileName, options.target); + if (!newSourceFile) { + return false; } - switch (n.kind) { - case 199 /* Block */: - if (!ts.isFunctionBlock(n)) { - var parent_16 = n.parent; - var openBrace = ts.findChildOfKind(n, 15 /* OpenBraceToken */, sourceFile); - var closeBrace = ts.findChildOfKind(n, 16 /* CloseBraceToken */, sourceFile); - // Check if the block is standalone, or 'attached' to some parent statement. - // If the latter, we want to collapse the block, but consider its hint span - // to be the entire span of the parent. - if (parent_16.kind === 204 /* DoStatement */ || - parent_16.kind === 207 /* ForInStatement */ || - parent_16.kind === 208 /* ForOfStatement */ || - parent_16.kind === 206 /* ForStatement */ || - parent_16.kind === 203 /* IfStatement */ || - parent_16.kind === 205 /* WhileStatement */ || - parent_16.kind === 212 /* WithStatement */ || - parent_16.kind === 252 /* CatchClause */) { - addOutliningSpan(parent_16, openBrace, closeBrace, autoCollapse(n)); - break; - } - if (parent_16.kind === 216 /* TryStatement */) { - // Could be the try-block, or the finally-block. - var tryStatement = parent_16; - if (tryStatement.tryBlock === n) { - addOutliningSpan(parent_16, openBrace, closeBrace, autoCollapse(n)); - break; - } - else if (tryStatement.finallyBlock === n) { - var finallyKeyword = ts.findChildOfKind(tryStatement, 85 /* FinallyKeyword */, sourceFile); - if (finallyKeyword) { - addOutliningSpan(finallyKeyword, openBrace, closeBrace, autoCollapse(n)); - break; - } - } - } - // Block was a standalone block. In this case we want to only collapse - // the span of the block, independent of any parent span. - var span = ts.createTextSpanFromBounds(n.getStart(), n.end); - elements.push({ - textSpan: span, - hintSpan: span, - bannerText: collapseText, - autoCollapse: autoCollapse(n) - }); - break; + newSourceFile.path = oldSourceFile.path; + filePaths.push(newSourceFile.path); + if (oldSourceFile !== newSourceFile) { + if (oldSourceFile.hasNoDefaultLib !== newSourceFile.hasNoDefaultLib) { + // value of no-default-lib has changed + // this will affect if default library is injected into the list of files + return false; + } + // check tripleslash references + if (!ts.arrayIsEqualTo(oldSourceFile.referencedFiles, newSourceFile.referencedFiles, fileReferenceIsEqualTo)) { + // tripleslash references has changed + return false; + } + // check imports and module augmentations + collectExternalModuleReferences(newSourceFile); + if (!ts.arrayIsEqualTo(oldSourceFile.imports, newSourceFile.imports, moduleNameIsEqualTo)) { + // imports has changed + return false; + } + if (!ts.arrayIsEqualTo(oldSourceFile.moduleAugmentations, newSourceFile.moduleAugmentations, moduleNameIsEqualTo)) { + // moduleAugmentations has changed + return false; + } + if (!ts.arrayIsEqualTo(oldSourceFile.typeReferenceDirectives, newSourceFile.typeReferenceDirectives, fileReferenceIsEqualTo)) { + // 'types' references has changed + return false; + } + var newSourceFilePath = ts.getNormalizedAbsolutePath(newSourceFile.fileName, currentDirectory); + if (resolveModuleNamesWorker) { + var moduleNames = ts.map(ts.concatenate(newSourceFile.imports, newSourceFile.moduleAugmentations), getTextOfLiteral); + var resolutions = resolveModuleNamesWorker(moduleNames, newSourceFilePath); + // ensure that module resolution results are still correct + var resolutionsChanged = ts.hasChangesInResolutions(moduleNames, resolutions, oldSourceFile.resolvedModules, ts.moduleResolutionIsEqualTo); + if (resolutionsChanged) { + return false; } - // Fallthrough. - case 226 /* ModuleBlock */: { - var openBrace = ts.findChildOfKind(n, 15 /* OpenBraceToken */, sourceFile); - var closeBrace = ts.findChildOfKind(n, 16 /* CloseBraceToken */, sourceFile); - addOutliningSpan(n.parent, openBrace, closeBrace, autoCollapse(n)); - break; } - case 221 /* ClassDeclaration */: - case 222 /* InterfaceDeclaration */: - case 224 /* EnumDeclaration */: - case 171 /* ObjectLiteralExpression */: - case 227 /* CaseBlock */: { - var openBrace = ts.findChildOfKind(n, 15 /* OpenBraceToken */, sourceFile); - var closeBrace = ts.findChildOfKind(n, 16 /* CloseBraceToken */, sourceFile); - addOutliningSpan(n, openBrace, closeBrace, autoCollapse(n)); - break; + if (resolveTypeReferenceDirectiveNamesWorker) { + var typesReferenceDirectives = ts.map(newSourceFile.typeReferenceDirectives, function (x) { return x.fileName; }); + var resolutions = resolveTypeReferenceDirectiveNamesWorker(typesReferenceDirectives, newSourceFilePath); + // ensure that types resolutions are still correct + var resolutionsChanged = ts.hasChangesInResolutions(typesReferenceDirectives, resolutions, oldSourceFile.resolvedTypeReferenceDirectiveNames, ts.typeDirectiveIsEqualTo); + if (resolutionsChanged) { + return false; + } } - case 170 /* ArrayLiteralExpression */: - var openBracket = ts.findChildOfKind(n, 19 /* OpenBracketToken */, sourceFile); - var closeBracket = ts.findChildOfKind(n, 20 /* CloseBracketToken */, sourceFile); - addOutliningSpan(n, openBracket, closeBracket, autoCollapse(n)); - break; + // pass the cache of module/types resolutions from the old source file + newSourceFile.resolvedModules = oldSourceFile.resolvedModules; + newSourceFile.resolvedTypeReferenceDirectiveNames = oldSourceFile.resolvedTypeReferenceDirectiveNames; + modifiedSourceFiles.push(newSourceFile); } - depth++; - ts.forEachChild(n, walk); - depth--; + else { + // file has no changes - use it as is + newSourceFile = oldSourceFile; + } + // if file has passed all checks it should be safe to reuse it + newSourceFiles.push(newSourceFile); } - walk(sourceFile); - return elements; + // update fileName -> file mapping + for (var i = 0, len = newSourceFiles.length; i < len; i++) { + filesByName.set(filePaths[i], newSourceFiles[i]); + } + files = newSourceFiles; + fileProcessingDiagnostics = oldProgram.getFileProcessingDiagnostics(); + for (var _b = 0, modifiedSourceFiles_1 = modifiedSourceFiles; _b < modifiedSourceFiles_1.length; _b++) { + var modifiedFile = modifiedSourceFiles_1[_b]; + fileProcessingDiagnostics.reattachFileDiagnostics(modifiedFile); + } + resolvedTypeReferenceDirectives = oldProgram.getResolvedTypeReferenceDirectives(); + oldProgram.structureIsReused = true; + return true; } - OutliningElementsCollector.collectElements = collectElements; - })(OutliningElementsCollector = ts.OutliningElementsCollector || (ts.OutliningElementsCollector = {})); -})(ts || (ts = {})); -/* @internal */ -var ts; -(function (ts) { - var NavigateTo; - (function (NavigateTo) { - function getNavigateToItems(program, checker, cancellationToken, searchValue, maxResultCount) { - var patternMatcher = ts.createPatternMatcher(searchValue); - var rawItems = []; - // This means "compare in a case insensitive manner." - var baseSensitivity = { sensitivity: "base" }; - // Search the declarations in all files and output matched NavigateToItem into array of NavigateToItem[] - ts.forEach(program.getSourceFiles(), function (sourceFile) { - cancellationToken.throwIfCancellationRequested(); - var nameToDeclarations = sourceFile.getNamedDeclarations(); - for (var name_37 in nameToDeclarations) { - var declarations = nameToDeclarations[name_37]; - if (declarations) { - // First do a quick check to see if the name of the declaration matches the - // last portion of the (possibly) dotted name they're searching for. - var matches = patternMatcher.getMatchesForLastSegmentOfPattern(name_37); - if (!matches) { - continue; - } - for (var _i = 0, declarations_7 = declarations; _i < declarations_7.length; _i++) { - var declaration = declarations_7[_i]; - // It was a match! If the pattern has dots in it, then also see if the - // declaration container matches as well. - if (patternMatcher.patternContainsDots) { - var containers = getContainers(declaration); - if (!containers) { - return undefined; - } - matches = patternMatcher.getMatches(containers, name_37); - if (!matches) { - continue; - } - } - var fileName = sourceFile.fileName; - var matchKind = bestMatchKind(matches); - rawItems.push({ name: name_37, fileName: fileName, matchKind: matchKind, isCaseSensitive: allMatchesAreCaseSensitive(matches), declaration: declaration }); - } - } + function getEmitHost(writeFileCallback) { + return { + getCanonicalFileName: getCanonicalFileName, + getCommonSourceDirectory: program.getCommonSourceDirectory, + getCompilerOptions: program.getCompilerOptions, + getCurrentDirectory: function () { return currentDirectory; }, + getNewLine: function () { return host.getNewLine(); }, + getSourceFile: program.getSourceFile, + getSourceFileByPath: program.getSourceFileByPath, + getSourceFiles: program.getSourceFiles, + isSourceFileFromExternalLibrary: function (file) { return !!sourceFilesFoundSearchingNodeModules[file.path]; }, + writeFile: writeFileCallback || (function (fileName, data, writeByteOrderMark, onError, sourceFiles) { return host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles); }), + isEmitBlocked: isEmitBlocked, + }; + } + function getDiagnosticsProducingTypeChecker() { + return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = ts.createTypeChecker(program, /*produceDiagnostics:*/ true)); + } + function dropDiagnosticsProducingTypeChecker() { + diagnosticsProducingTypeChecker = undefined; + } + function getTypeChecker() { + return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = ts.createTypeChecker(program, /*produceDiagnostics:*/ false)); + } + function emit(sourceFile, writeFileCallback, cancellationToken, emitOnlyDtsFiles) { + return runWithCancellationToken(function () { return emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnlyDtsFiles); }); + } + function isEmitBlocked(emitFileName) { + return hasEmitBlockingDiagnostics.contains(ts.toPath(emitFileName, currentDirectory, getCanonicalFileName)); + } + function emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnlyDtsFiles) { + var declarationDiagnostics = []; + if (options.noEmit) { + return { diagnostics: declarationDiagnostics, sourceMaps: undefined, emittedFiles: undefined, emitSkipped: true }; + } + // If the noEmitOnError flag is set, then check if we have any errors so far. If so, + // immediately bail out. Note that we pass 'undefined' for 'sourceFile' so that we + // get any preEmit diagnostics, not just the ones + if (options.noEmitOnError) { + var diagnostics = program.getOptionsDiagnostics(cancellationToken).concat(program.getSyntacticDiagnostics(sourceFile, cancellationToken), program.getGlobalDiagnostics(cancellationToken), program.getSemanticDiagnostics(sourceFile, cancellationToken)); + if (diagnostics.length === 0 && program.getCompilerOptions().declaration) { + declarationDiagnostics = program.getDeclarationDiagnostics(/*sourceFile*/ undefined, cancellationToken); } - }); - // Remove imports when the imported declaration is already in the list and has the same name. - rawItems = ts.filter(rawItems, function (item) { - var decl = item.declaration; - if (decl.kind === 231 /* ImportClause */ || decl.kind === 234 /* ImportSpecifier */ || decl.kind === 229 /* ImportEqualsDeclaration */) { - var importer = checker.getSymbolAtLocation(decl.name); - var imported = checker.getAliasedSymbol(importer); - return importer.name !== imported.name; + if (diagnostics.length > 0 || declarationDiagnostics.length > 0) { + return { + diagnostics: ts.concatenate(diagnostics, declarationDiagnostics), + sourceMaps: undefined, + emittedFiles: undefined, + emitSkipped: true + }; } - else { - return true; + } + // Create the emit resolver outside of the "emitTime" tracking code below. That way + // any cost associated with it (like type checking) are appropriate associated with + // the type-checking counter. + // + // If the -out option is specified, we should not pass the source file to getEmitResolver. + // This is because in the -out scenario all files need to be emitted, and therefore all + // files need to be type checked. And the way to specify that all files need to be type + // checked is to not pass the file to getEmitResolver. + var emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver((options.outFile || options.out) ? undefined : sourceFile); + ts.performance.mark("beforeEmit"); + var emitResult = ts.emitFiles(emitResolver, getEmitHost(writeFileCallback), sourceFile, emitOnlyDtsFiles); + ts.performance.mark("afterEmit"); + ts.performance.measure("Emit", "beforeEmit", "afterEmit"); + return emitResult; + } + function getSourceFile(fileName) { + return getSourceFileByPath(ts.toPath(fileName, currentDirectory, getCanonicalFileName)); + } + function getSourceFileByPath(path) { + return filesByName.get(path); + } + function getDiagnosticsHelper(sourceFile, getDiagnostics, cancellationToken) { + if (sourceFile) { + return getDiagnostics(sourceFile, cancellationToken); + } + var allDiagnostics = []; + ts.forEach(program.getSourceFiles(), function (sourceFile) { + if (cancellationToken) { + cancellationToken.throwIfCancellationRequested(); } + ts.addRange(allDiagnostics, getDiagnostics(sourceFile, cancellationToken)); }); - rawItems.sort(compareNavigateToItems); - if (maxResultCount !== undefined) { - rawItems = rawItems.slice(0, maxResultCount); + return ts.sortAndDeduplicateDiagnostics(allDiagnostics); + } + function getSyntacticDiagnostics(sourceFile, cancellationToken) { + return getDiagnosticsHelper(sourceFile, getSyntacticDiagnosticsForFile, cancellationToken); + } + function getSemanticDiagnostics(sourceFile, cancellationToken) { + return getDiagnosticsHelper(sourceFile, getSemanticDiagnosticsForFile, cancellationToken); + } + function getDeclarationDiagnostics(sourceFile, cancellationToken) { + var options = program.getCompilerOptions(); + // collect diagnostics from the program only once if either no source file was specified or out/outFile is set (bundled emit) + if (!sourceFile || options.out || options.outFile) { + return getDeclarationDiagnosticsWorker(sourceFile, cancellationToken); } - var items = ts.map(rawItems, createNavigateToItem); - return items; - function allMatchesAreCaseSensitive(matches) { - ts.Debug.assert(matches.length > 0); - // This is a case sensitive match, only if all the submatches were case sensitive. - for (var _i = 0, matches_1 = matches; _i < matches_1.length; _i++) { - var match = matches_1[_i]; - if (!match.isCaseSensitive) { - return false; - } - } - return true; + else { + return getDiagnosticsHelper(sourceFile, getDeclarationDiagnosticsForFile, cancellationToken); } - function getTextOfIdentifierOrLiteral(node) { - if (node) { - if (node.kind === 69 /* Identifier */ || - node.kind === 9 /* StringLiteral */ || - node.kind === 8 /* NumericLiteral */) { - return node.text; - } - } - return undefined; + } + function getSyntacticDiagnosticsForFile(sourceFile, cancellationToken) { + return sourceFile.parseDiagnostics; + } + function runWithCancellationToken(func) { + try { + return func(); } - function tryAddSingleDeclarationName(declaration, containers) { - if (declaration && declaration.name) { - var text = getTextOfIdentifierOrLiteral(declaration.name); - if (text !== undefined) { - containers.unshift(text); - } - else if (declaration.name.kind === 140 /* ComputedPropertyName */) { - return tryAddComputedPropertyName(declaration.name.expression, containers, /*includeLastPortion*/ true); - } - else { - // Don't know how to add this. - return false; - } + catch (e) { + if (e instanceof ts.OperationCanceledException) { + // We were canceled while performing the operation. Because our type checker + // might be a bad state, we need to throw it away. + // + // Note: we are overly aggressive here. We do not actually *have* to throw away + // the "noDiagnosticsTypeChecker". However, for simplicity, i'd like to keep + // the lifetimes of these two TypeCheckers the same. Also, we generally only + // cancel when the user has made a change anyways. And, in that case, we (the + // program instance) will get thrown away anyways. So trying to keep one of + // these type checkers alive doesn't serve much purpose. + noDiagnosticsTypeChecker = undefined; + diagnosticsProducingTypeChecker = undefined; } - return true; + throw e; } - // Only added the names of computed properties if they're simple dotted expressions, like: - // - // [X.Y.Z]() { } - function tryAddComputedPropertyName(expression, containers, includeLastPortion) { - var text = getTextOfIdentifierOrLiteral(expression); - if (text !== undefined) { - if (includeLastPortion) { - containers.unshift(text); + } + function getSemanticDiagnosticsForFile(sourceFile, cancellationToken) { + return runWithCancellationToken(function () { + var typeChecker = getDiagnosticsProducingTypeChecker(); + ts.Debug.assert(!!sourceFile.bindDiagnostics); + var bindDiagnostics = sourceFile.bindDiagnostics; + // For JavaScript files, we don't want to report the normal typescript semantic errors. + // Instead, we just report errors for using TypeScript-only constructs from within a + // JavaScript file. + var checkDiagnostics = ts.isSourceFileJavaScript(sourceFile) ? + getJavaScriptSemanticDiagnosticsForFile(sourceFile, cancellationToken) : + typeChecker.getDiagnostics(sourceFile, cancellationToken); + var fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName); + var programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName); + return bindDiagnostics.concat(checkDiagnostics).concat(fileProcessingDiagnosticsInFile).concat(programDiagnosticsInFile); + }); + } + function getJavaScriptSemanticDiagnosticsForFile(sourceFile, cancellationToken) { + return runWithCancellationToken(function () { + var diagnostics = []; + walk(sourceFile); + return diagnostics; + function walk(node) { + if (!node) { + return false; } - return true; - } - if (expression.kind === 172 /* PropertyAccessExpression */) { - var propertyAccess = expression; - if (includeLastPortion) { - containers.unshift(propertyAccess.name.text); + switch (node.kind) { + case 229 /* ImportEqualsDeclaration */: + diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.import_can_only_be_used_in_a_ts_file)); + return true; + case 235 /* ExportAssignment */: + if (node.isExportEquals) { + diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.export_can_only_be_used_in_a_ts_file)); + return true; + } + break; + case 221 /* ClassDeclaration */: + var classDeclaration = node; + if (checkModifiers(classDeclaration.modifiers) || + checkTypeParameters(classDeclaration.typeParameters)) { + return true; + } + break; + case 251 /* HeritageClause */: + var heritageClause = node; + if (heritageClause.token === 106 /* ImplementsKeyword */) { + diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.implements_clauses_can_only_be_used_in_a_ts_file)); + return true; + } + break; + case 222 /* InterfaceDeclaration */: + diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.interface_declarations_can_only_be_used_in_a_ts_file)); + return true; + case 225 /* ModuleDeclaration */: + diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.module_declarations_can_only_be_used_in_a_ts_file)); + return true; + case 223 /* TypeAliasDeclaration */: + diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.type_aliases_can_only_be_used_in_a_ts_file)); + return true; + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + case 148 /* Constructor */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 179 /* FunctionExpression */: + case 220 /* FunctionDeclaration */: + case 180 /* ArrowFunction */: + case 220 /* FunctionDeclaration */: + var functionDeclaration = node; + if (checkModifiers(functionDeclaration.modifiers) || + checkTypeParameters(functionDeclaration.typeParameters) || + checkTypeAnnotation(functionDeclaration.type)) { + return true; + } + break; + case 200 /* VariableStatement */: + var variableStatement = node; + if (checkModifiers(variableStatement.modifiers)) { + return true; + } + break; + case 218 /* VariableDeclaration */: + var variableDeclaration = node; + if (checkTypeAnnotation(variableDeclaration.type)) { + return true; + } + break; + case 174 /* CallExpression */: + case 175 /* NewExpression */: + var expression = node; + if (expression.typeArguments && expression.typeArguments.length > 0) { + var start = expression.typeArguments.pos; + diagnostics.push(ts.createFileDiagnostic(sourceFile, start, expression.typeArguments.end - start, ts.Diagnostics.type_arguments_can_only_be_used_in_a_ts_file)); + return true; + } + break; + case 142 /* Parameter */: + var parameter = node; + if (parameter.modifiers) { + var start = parameter.modifiers.pos; + diagnostics.push(ts.createFileDiagnostic(sourceFile, start, parameter.modifiers.end - start, ts.Diagnostics.parameter_modifiers_can_only_be_used_in_a_ts_file)); + return true; + } + if (parameter.questionToken) { + diagnostics.push(ts.createDiagnosticForNode(parameter.questionToken, ts.Diagnostics._0_can_only_be_used_in_a_ts_file, "?")); + return true; + } + if (parameter.type) { + diagnostics.push(ts.createDiagnosticForNode(parameter.type, ts.Diagnostics.types_can_only_be_used_in_a_ts_file)); + return true; + } + break; + case 145 /* PropertyDeclaration */: + var propertyDeclaration = node; + if (propertyDeclaration.modifiers) { + for (var _i = 0, _a = propertyDeclaration.modifiers; _i < _a.length; _i++) { + var modifier = _a[_i]; + if (modifier.kind !== 113 /* StaticKeyword */) { + diagnostics.push(ts.createDiagnosticForNode(modifier, ts.Diagnostics._0_can_only_be_used_in_a_ts_file, ts.tokenToString(modifier.kind))); + return true; + } + } + } + if (checkTypeAnnotation(node.type)) { + return true; + } + break; + case 224 /* EnumDeclaration */: + diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.enum_declarations_can_only_be_used_in_a_ts_file)); + return true; + case 177 /* TypeAssertionExpression */: + var typeAssertionExpression = node; + diagnostics.push(ts.createDiagnosticForNode(typeAssertionExpression.type, ts.Diagnostics.type_assertion_expressions_can_only_be_used_in_a_ts_file)); + return true; + case 143 /* Decorator */: + if (!options.experimentalDecorators) { + diagnostics.push(ts.createDiagnosticForNode(node, ts.Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_to_remove_this_warning)); + } + return true; } - return tryAddComputedPropertyName(propertyAccess.expression, containers, /*includeLastPortion*/ true); + return ts.forEachChild(node, walk); } - return false; - } - function getContainers(declaration) { - var containers = []; - // First, if we started with a computed property name, then add all but the last - // portion into the container array. - if (declaration.name.kind === 140 /* ComputedPropertyName */) { - if (!tryAddComputedPropertyName(declaration.name.expression, containers, /*includeLastPortion*/ false)) { - return undefined; + function checkTypeParameters(typeParameters) { + if (typeParameters) { + var start = typeParameters.pos; + diagnostics.push(ts.createFileDiagnostic(sourceFile, start, typeParameters.end - start, ts.Diagnostics.type_parameter_declarations_can_only_be_used_in_a_ts_file)); + return true; } + return false; } - // Now, walk up our containers, adding all their names to the container array. - declaration = ts.getContainerNode(declaration); - while (declaration) { - if (!tryAddSingleDeclarationName(declaration, containers)) { - return undefined; + function checkTypeAnnotation(type) { + if (type) { + diagnostics.push(ts.createDiagnosticForNode(type, ts.Diagnostics.types_can_only_be_used_in_a_ts_file)); + return true; } - declaration = ts.getContainerNode(declaration); + return false; } - return containers; - } - function bestMatchKind(matches) { - ts.Debug.assert(matches.length > 0); - var bestMatchKind = ts.PatternMatchKind.camelCase; - for (var _i = 0, matches_2 = matches; _i < matches_2.length; _i++) { - var match = matches_2[_i]; - var kind = match.kind; - if (kind < bestMatchKind) { - bestMatchKind = kind; + function checkModifiers(modifiers) { + if (modifiers) { + for (var _i = 0, modifiers_1 = modifiers; _i < modifiers_1.length; _i++) { + var modifier = modifiers_1[_i]; + switch (modifier.kind) { + case 112 /* PublicKeyword */: + case 110 /* PrivateKeyword */: + case 111 /* ProtectedKeyword */: + case 128 /* ReadonlyKeyword */: + case 122 /* DeclareKeyword */: + diagnostics.push(ts.createDiagnosticForNode(modifier, ts.Diagnostics._0_can_only_be_used_in_a_ts_file, ts.tokenToString(modifier.kind))); + return true; + // These are all legal modifiers. + case 113 /* StaticKeyword */: + case 82 /* ExportKeyword */: + case 74 /* ConstKeyword */: + case 77 /* DefaultKeyword */: + case 115 /* AbstractKeyword */: + } + } } + return false; } - return bestMatchKind; - } - function compareNavigateToItems(i1, i2) { - // TODO(cyrusn): get the gamut of comparisons that VS already uses here. - // Right now we just sort by kind first, and then by name of the item. - // We first sort case insensitively. So "Aaa" will come before "bar". - // Then we sort case sensitively, so "aaa" will come before "Aaa". - return i1.matchKind - i2.matchKind || - i1.name.localeCompare(i2.name, undefined, baseSensitivity) || - i1.name.localeCompare(i2.name); - } - function createNavigateToItem(rawItem) { - var declaration = rawItem.declaration; - var container = ts.getContainerNode(declaration); - return { - name: rawItem.name, - kind: ts.getNodeKind(declaration), - kindModifiers: ts.getNodeModifiers(declaration), - matchKind: ts.PatternMatchKind[rawItem.matchKind], - isCaseSensitive: rawItem.isCaseSensitive, - fileName: rawItem.fileName, - textSpan: ts.createTextSpanFromBounds(declaration.getStart(), declaration.getEnd()), - // TODO(jfreeman): What should be the containerName when the container has a computed name? - containerName: container && container.name ? container.name.text : "", - containerKind: container && container.name ? ts.getNodeKind(container) : "" - }; - } - } - NavigateTo.getNavigateToItems = getNavigateToItems; - })(NavigateTo = ts.NavigateTo || (ts.NavigateTo = {})); -})(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - var NavigationBar; - (function (NavigationBar) { - function getNavigationBarItems(sourceFile) { - curSourceFile = sourceFile; - var result = ts.map(topLevelItems(rootNavigationBarNode(sourceFile)), convertToTopLevelItem); - curSourceFile = undefined; - return result; + }); } - NavigationBar.getNavigationBarItems = getNavigationBarItems; - // Keep sourceFile handy so we don't have to search for it every time we need to call `getText`. - var curSourceFile; - function nodeText(node) { - return node.getText(curSourceFile); + function getDeclarationDiagnosticsWorker(sourceFile, cancellationToken) { + return runWithCancellationToken(function () { + var resolver = getDiagnosticsProducingTypeChecker().getEmitResolver(sourceFile, cancellationToken); + // Don't actually write any files since we're just getting diagnostics. + var writeFile = function () { }; + return ts.getDeclarationDiagnostics(getEmitHost(writeFile), resolver, sourceFile); + }); } - function navigationBarNodeKind(n) { - return n.node.kind; + function getDeclarationDiagnosticsForFile(sourceFile, cancellationToken) { + return ts.isDeclarationFile(sourceFile) ? [] : getDeclarationDiagnosticsWorker(sourceFile, cancellationToken); } - function pushChild(parent, child) { - if (parent.children) { - parent.children.push(child); - } - else { - parent.children = [child]; - } + function getOptionsDiagnostics() { + var allDiagnostics = []; + ts.addRange(allDiagnostics, fileProcessingDiagnostics.getGlobalDiagnostics()); + ts.addRange(allDiagnostics, programDiagnostics.getGlobalDiagnostics()); + return ts.sortAndDeduplicateDiagnostics(allDiagnostics); } - /* - For performance, we keep navigation bar parents on a stack rather than passing them through each recursion. - `parent` is the current parent and is *not* stored in parentsStack. - `startNode` sets a new parent and `endNode` returns to the previous parent. - */ - var parentsStack = []; - var parent; - function rootNavigationBarNode(sourceFile) { - ts.Debug.assert(!parentsStack.length); - var root = { node: sourceFile, additionalNodes: undefined, parent: undefined, children: undefined, indent: 0 }; - parent = root; - for (var _i = 0, _a = sourceFile.statements; _i < _a.length; _i++) { - var statement = _a[_i]; - addChildrenRecursively(statement); - } - endNode(); - ts.Debug.assert(!parent && !parentsStack.length); - return root; + function getGlobalDiagnostics() { + var allDiagnostics = []; + ts.addRange(allDiagnostics, getDiagnosticsProducingTypeChecker().getGlobalDiagnostics()); + return ts.sortAndDeduplicateDiagnostics(allDiagnostics); } - function addLeafNode(node) { - pushChild(parent, emptyNavigationBarNode(node)); + function hasExtension(fileName) { + return ts.getBaseFileName(fileName).indexOf(".") >= 0; } - function emptyNavigationBarNode(node) { - return { - node: node, - additionalNodes: undefined, - parent: parent, - children: undefined, - indent: parent.indent + 1 - }; + function processRootFile(fileName, isDefaultLib) { + processSourceFile(ts.normalizePath(fileName), isDefaultLib, /*isReference*/ true); } - /** - * Add a new level of NavigationBarNodes. - * This pushes to the stack, so you must call `endNode` when you are done adding to this node. - */ - function startNode(node) { - var navNode = emptyNavigationBarNode(node); - pushChild(parent, navNode); - // Save the old parent - parentsStack.push(parent); - parent = navNode; + function fileReferenceIsEqualTo(a, b) { + return a.fileName === b.fileName; } - /** Call after calling `startNode` and adding children to it. */ - function endNode() { - if (parent.children) { - mergeChildren(parent.children); - sortChildren(parent.children); - } - parent = parentsStack.pop(); + function moduleNameIsEqualTo(a, b) { + return a.text === b.text; } - function addNodeWithRecursiveChild(node, child) { - startNode(node); - addChildrenRecursively(child); - endNode(); + function getTextOfLiteral(literal) { + return literal.text; } - /** Look for navigation bar items in node's subtree, adding them to the current `parent`. */ - function addChildrenRecursively(node) { - if (!node || ts.isToken(node)) { + function collectExternalModuleReferences(file) { + if (file.imports) { return; } - switch (node.kind) { - case 148 /* Constructor */: - // Get parameter properties, and treat them as being on the *same* level as the constructor, not under it. - var ctr = node; - addNodeWithRecursiveChild(ctr, ctr.body); - // Parameter properties are children of the class, not the constructor. - for (var _i = 0, _a = ctr.parameters; _i < _a.length; _i++) { - var param = _a[_i]; - if (ts.isParameterPropertyDeclaration(param)) { - addLeafNode(param); - } - } - break; - case 147 /* MethodDeclaration */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 146 /* MethodSignature */: - if (!ts.hasDynamicName(node)) { - addNodeWithRecursiveChild(node, node.body); - } - break; - case 145 /* PropertyDeclaration */: - case 144 /* PropertySignature */: - if (!ts.hasDynamicName(node)) { - addLeafNode(node); - } - break; - case 231 /* ImportClause */: - var importClause = node; - // Handle default import case e.g.: - // import d from "mod"; - if (importClause.name) { - addLeafNode(importClause); - } - // Handle named bindings in imports e.g.: - // import * as NS from "mod"; - // import {a, b as B} from "mod"; - var namedBindings = importClause.namedBindings; - if (namedBindings) { - if (namedBindings.kind === 232 /* NamespaceImport */) { - addLeafNode(namedBindings); + var isJavaScriptFile = ts.isSourceFileJavaScript(file); + var isExternalModuleFile = ts.isExternalModule(file); + var imports; + var moduleAugmentations; + // If we are importing helpers, we need to add a synthetic reference to resolve the + // helpers library. + if (options.importHelpers + && (options.isolatedModules || isExternalModuleFile) + && !file.isDeclarationFile) { + var externalHelpersModuleReference = ts.createNode(9 /* StringLiteral */); + externalHelpersModuleReference.text = ts.externalHelpersModuleNameText; + externalHelpersModuleReference.parent = file; + imports = [externalHelpersModuleReference]; + } + for (var _i = 0, _a = file.statements; _i < _a.length; _i++) { + var node = _a[_i]; + collectModuleReferences(node, /*inAmbientModule*/ false); + if (isJavaScriptFile) { + collectRequireCalls(node); + } + } + file.imports = imports || emptyArray; + file.moduleAugmentations = moduleAugmentations || emptyArray; + return; + function collectModuleReferences(node, inAmbientModule) { + switch (node.kind) { + case 230 /* ImportDeclaration */: + case 229 /* ImportEqualsDeclaration */: + case 236 /* ExportDeclaration */: + var moduleNameExpr = ts.getExternalModuleName(node); + if (!moduleNameExpr || moduleNameExpr.kind !== 9 /* StringLiteral */) { + break; } - else { - for (var _b = 0, _c = namedBindings.elements; _b < _c.length; _b++) { - var element = _c[_b]; - addLeafNode(element); - } + if (!moduleNameExpr.text) { + break; } - } - break; - case 169 /* BindingElement */: - case 218 /* VariableDeclaration */: - var decl = node; - var name_38 = decl.name; - if (ts.isBindingPattern(name_38)) { - addChildrenRecursively(name_38); - } - else if (decl.initializer && isFunctionOrClassExpression(decl.initializer)) { - // For `const x = function() {}`, just use the function node, not the const. - addChildrenRecursively(decl.initializer); - } - else { - addNodeWithRecursiveChild(decl, decl.initializer); - } - break; - case 180 /* ArrowFunction */: - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - addNodeWithRecursiveChild(node, node.body); - break; - case 224 /* EnumDeclaration */: - startNode(node); - for (var _d = 0, _e = node.members; _d < _e.length; _d++) { - var member = _e[_d]; - if (!isComputedProperty(member)) { - addLeafNode(member); + // TypeScript 1.0 spec (April 2014): 12.1.6 + // An ExternalImportDeclaration in an AmbientExternalModuleDeclaration may reference other external modules + // only through top - level external module names. Relative external module names are not permitted. + if (!inAmbientModule || !ts.isExternalModuleNameRelative(moduleNameExpr.text)) { + (imports || (imports = [])).push(moduleNameExpr); } - } - endNode(); - break; - case 221 /* ClassDeclaration */: - case 192 /* ClassExpression */: - case 222 /* InterfaceDeclaration */: - startNode(node); - for (var _f = 0, _g = node.members; _f < _g.length; _f++) { - var member = _g[_f]; - addChildrenRecursively(member); - } - endNode(); - break; - case 225 /* ModuleDeclaration */: - addNodeWithRecursiveChild(node, getInteriorModule(node).body); - break; - case 238 /* ExportSpecifier */: - case 229 /* ImportEqualsDeclaration */: - case 153 /* IndexSignature */: - case 151 /* CallSignature */: - case 152 /* ConstructSignature */: - case 223 /* TypeAliasDeclaration */: - addLeafNode(node); - break; - default: - if (node.jsDocComments) { - for (var _h = 0, _j = node.jsDocComments; _h < _j.length; _h++) { - var jsDocComment = _j[_h]; - for (var _k = 0, _l = jsDocComment.tags; _k < _l.length; _k++) { - var tag = _l[_k]; - if (tag.kind === 279 /* JSDocTypedefTag */) { - addLeafNode(tag); + break; + case 225 /* ModuleDeclaration */: + if (ts.isAmbientModule(node) && (inAmbientModule || ts.hasModifier(node, 2 /* Ambient */) || ts.isDeclarationFile(file))) { + var moduleName = node.name; + // Ambient module declarations can be interpreted as augmentations for some existing external modules. + // This will happen in two cases: + // - if current file is external module then module augmentation is a ambient module declaration defined in the top level scope + // - if current file is not external module then module augmentation is an ambient module declaration with non-relative module name + // immediately nested in top level ambient module declaration . + if (isExternalModuleFile || (inAmbientModule && !ts.isExternalModuleNameRelative(moduleName.text))) { + (moduleAugmentations || (moduleAugmentations = [])).push(moduleName); + } + else if (!inAmbientModule) { + // An AmbientExternalModuleDeclaration declares an external module. + // This type of declaration is permitted only in the global module. + // The StringLiteral must specify a top - level external module name. + // Relative external module names are not permitted + // NOTE: body of ambient module is always a module block, if it exists + var body = node.body; + if (body) { + for (var _i = 0, _a = body.statements; _i < _a.length; _i++) { + var statement = _a[_i]; + collectModuleReferences(statement, /*inAmbientModule*/ true); + } } } } - } - ts.forEachChild(node, addChildrenRecursively); + } } - } - /** Merge declarations of the same kind. */ - function mergeChildren(children) { - var nameToItems = ts.createMap(); - ts.filterMutate(children, function (child) { - var decl = child.node; - var name = decl.name && nodeText(decl.name); - if (!name) { - // Anonymous items are never merged. - return true; + function collectRequireCalls(node) { + if (ts.isRequireCall(node, /*checkArgumentIsStringLiteral*/ true)) { + (imports || (imports = [])).push(node.arguments[0]); } - var itemsWithSameName = nameToItems[name]; - if (!itemsWithSameName) { - nameToItems[name] = child; - return true; + else { + ts.forEachChild(node, collectRequireCalls); } - if (itemsWithSameName instanceof Array) { - for (var _i = 0, itemsWithSameName_1 = itemsWithSameName; _i < itemsWithSameName_1.length; _i++) { - var itemWithSameName = itemsWithSameName_1[_i]; - if (tryMerge(itemWithSameName, child)) { - return false; - } - } - itemsWithSameName.push(child); - return true; + } + } + /** + * 'isReference' indicates whether the file was brought in via a reference directive (rather than an import declaration) + */ + function processSourceFile(fileName, isDefaultLib, isReference, refFile, refPos, refEnd) { + var diagnosticArgument; + var diagnostic; + if (hasExtension(fileName)) { + if (!options.allowNonTsExtensions && !ts.forEach(supportedExtensions, function (extension) { return ts.fileExtensionIs(host.getCanonicalFileName(fileName), extension); })) { + diagnostic = ts.Diagnostics.File_0_has_unsupported_extension_The_only_supported_extensions_are_1; + diagnosticArgument = [fileName, "'" + supportedExtensions.join("', '") + "'"]; } - else { - var itemWithSameName = itemsWithSameName; - if (tryMerge(itemWithSameName, child)) { - return false; - } - nameToItems[name] = [itemWithSameName, child]; - return true; + else if (!findSourceFile(fileName, ts.toPath(fileName, currentDirectory, getCanonicalFileName), isDefaultLib, isReference, refFile, refPos, refEnd)) { + diagnostic = ts.Diagnostics.File_0_not_found; + diagnosticArgument = [fileName]; } - function tryMerge(a, b) { - if (shouldReallyMerge(a.node, b.node)) { - merge(a, b); - return true; - } - return false; + else if (refFile && host.getCanonicalFileName(fileName) === host.getCanonicalFileName(refFile.fileName)) { + diagnostic = ts.Diagnostics.A_file_cannot_have_a_reference_to_itself; + diagnosticArgument = [fileName]; } - }); - /** a and b have the same name, but they may not be mergeable. */ - function shouldReallyMerge(a, b) { - return a.kind === b.kind && (a.kind !== 225 /* ModuleDeclaration */ || areSameModule(a, b)); - // We use 1 NavNode to represent 'A.B.C', but there are multiple source nodes. - // Only merge module nodes that have the same chain. Don't merge 'A.B.C' with 'A'! - function areSameModule(a, b) { - if (a.body.kind !== b.body.kind) { - return false; + } + else { + var nonTsFile = options.allowNonTsExtensions && findSourceFile(fileName, ts.toPath(fileName, currentDirectory, getCanonicalFileName), isDefaultLib, isReference, refFile, refPos, refEnd); + if (!nonTsFile) { + if (options.allowNonTsExtensions) { + diagnostic = ts.Diagnostics.File_0_not_found; + diagnosticArgument = [fileName]; } - if (a.body.kind !== 225 /* ModuleDeclaration */) { - return true; + else if (!ts.forEach(supportedExtensions, function (extension) { return findSourceFile(fileName + extension, ts.toPath(fileName + extension, currentDirectory, getCanonicalFileName), isDefaultLib, isReference, refFile, refPos, refEnd); })) { + diagnostic = ts.Diagnostics.File_0_not_found; + fileName += ".ts"; + diagnosticArgument = [fileName]; } - return areSameModule(a.body, b.body); } } - /** Merge source into target. Source should be thrown away after this is called. */ - function merge(target, source) { - target.additionalNodes = target.additionalNodes || []; - target.additionalNodes.push(source.node); - if (source.additionalNodes) { - (_a = target.additionalNodes).push.apply(_a, source.additionalNodes); + if (diagnostic) { + if (refFile !== undefined && refEnd !== undefined && refPos !== undefined) { + fileProcessingDiagnostics.add(ts.createFileDiagnostic.apply(void 0, [refFile, refPos, refEnd - refPos, diagnostic].concat(diagnosticArgument))); } - target.children = ts.concatenate(target.children, source.children); - if (target.children) { - mergeChildren(target.children); - sortChildren(target.children); + else { + fileProcessingDiagnostics.add(ts.createCompilerDiagnostic.apply(void 0, [diagnostic].concat(diagnosticArgument))); } - var _a; } } - /** Recursively ensure that each NavNode's children are in sorted order. */ - function sortChildren(children) { - children.sort(compareChildren); - } - function compareChildren(child1, child2) { - var name1 = tryGetName(child1.node), name2 = tryGetName(child2.node); - if (name1 && name2) { - var cmp = localeCompareFix(name1, name2); - return cmp !== 0 ? cmp : navigationBarNodeKind(child1) - navigationBarNodeKind(child2); + function reportFileNamesDifferOnlyInCasingError(fileName, existingFileName, refFile, refPos, refEnd) { + if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) { + fileProcessingDiagnostics.add(ts.createFileDiagnostic(refFile, refPos, refEnd - refPos, ts.Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, fileName, existingFileName)); } else { - return name1 ? 1 : name2 ? -1 : navigationBarNodeKind(child1) - navigationBarNodeKind(child2); - } - } - // More efficient to create a collator once and use its `compare` than to call `a.localeCompare(b)` many times. - var collator = typeof Intl === "undefined" ? undefined : new Intl.Collator(); - // Intl is missing in Safari, and node 0.10 treats "a" as greater than "B". - var localeCompareIsCorrect = collator && collator.compare("a", "B") < 0; - var localeCompareFix = localeCompareIsCorrect ? collator.compare : function (a, b) { - // This isn't perfect, but it passes all of our tests. - for (var i = 0; i < Math.min(a.length, b.length); i++) { - var chA = a.charAt(i), chB = b.charAt(i); - if (chA === "\"" && chB === "'") { - return 1; - } - if (chA === "'" && chB === "\"") { - return -1; - } - var cmp = chA.toLocaleLowerCase().localeCompare(chB.toLocaleLowerCase()); - if (cmp !== 0) { - return cmp; - } - } - return a.length - b.length; - }; - /** - * This differs from getItemName because this is just used for sorting. - * We only sort nodes by name that have a more-or-less "direct" name, as opposed to `new()` and the like. - * So `new()` can still come before an `aardvark` method. - */ - function tryGetName(node) { - if (node.kind === 225 /* ModuleDeclaration */) { - return getModuleName(node); - } - var decl = node; - if (decl.name) { - return ts.getPropertyNameForPropertyNameNode(decl.name); - } - switch (node.kind) { - case 179 /* FunctionExpression */: - case 180 /* ArrowFunction */: - case 192 /* ClassExpression */: - return getFunctionOrClassName(node); - case 279 /* JSDocTypedefTag */: - return getJSDocTypedefTagName(node); - default: - return undefined; + fileProcessingDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, fileName, existingFileName)); } } - function getItemName(node) { - if (node.kind === 225 /* ModuleDeclaration */) { - return getModuleName(node); - } - var name = node.name; - if (name) { - var text = nodeText(name); - if (text.length > 0) { - return text; + // Get source file from normalized fileName + function findSourceFile(fileName, path, isDefaultLib, isReference, refFile, refPos, refEnd) { + if (filesByName.contains(path)) { + var file_1 = filesByName.get(path); + // try to check if we've already seen this file but with a different casing in path + // NOTE: this only makes sense for case-insensitive file systems + if (file_1 && options.forceConsistentCasingInFileNames && ts.getNormalizedAbsolutePath(file_1.fileName, currentDirectory) !== ts.getNormalizedAbsolutePath(fileName, currentDirectory)) { + reportFileNamesDifferOnlyInCasingError(fileName, file_1.fileName, refFile, refPos, refEnd); } - } - switch (node.kind) { - case 256 /* SourceFile */: - var sourceFile = node; - return ts.isExternalModule(sourceFile) - ? "\"" + ts.escapeString(ts.getBaseFileName(ts.removeFileExtension(ts.normalizePath(sourceFile.fileName)))) + "\"" - : ""; - case 180 /* ArrowFunction */: - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - case 221 /* ClassDeclaration */: - case 192 /* ClassExpression */: - if (node.flags & 512 /* Default */) { - return "default"; - } - return getFunctionOrClassName(node); - case 148 /* Constructor */: - return "constructor"; - case 152 /* ConstructSignature */: - return "new()"; - case 151 /* CallSignature */: - return "()"; - case 153 /* IndexSignature */: - return "[]"; - case 279 /* JSDocTypedefTag */: - return getJSDocTypedefTagName(node); - default: - return ""; - } - } - function getJSDocTypedefTagName(node) { - if (node.name) { - return node.name.text; - } - else { - var parentNode = node.parent && node.parent.parent; - if (parentNode && parentNode.kind === 200 /* VariableStatement */) { - if (parentNode.declarationList.declarations.length > 0) { - var nameIdentifier = parentNode.declarationList.declarations[0].name; - if (nameIdentifier.kind === 69 /* Identifier */) { - return nameIdentifier.text; - } + // If the file was previously found via a node_modules search, but is now being processed as a root file, + // then everything it sucks in may also be marked incorrectly, and needs to be checked again. + if (file_1 && sourceFilesFoundSearchingNodeModules[file_1.path] && currentNodeModulesDepth == 0) { + sourceFilesFoundSearchingNodeModules[file_1.path] = false; + if (!options.noResolve) { + processReferencedFiles(file_1, ts.getDirectoryPath(fileName), isDefaultLib); + processTypeReferenceDirectives(file_1); } + modulesWithElidedImports[file_1.path] = false; + processImportedModules(file_1, ts.getDirectoryPath(fileName)); } - return ""; - } - } - /** Flattens the NavNode tree to a list, keeping only the top-level items. */ - function topLevelItems(root) { - var topLevel = []; - function recur(item) { - if (isTopLevel(item)) { - topLevel.push(item); - if (item.children) { - for (var _i = 0, _a = item.children; _i < _a.length; _i++) { - var child = _a[_i]; - recur(child); - } + else if (file_1 && modulesWithElidedImports[file_1.path]) { + if (currentNodeModulesDepth < maxNodeModulesJsDepth) { + modulesWithElidedImports[file_1.path] = false; + processImportedModules(file_1, ts.getDirectoryPath(fileName)); } } + return file_1; } - recur(root); - return topLevel; - function isTopLevel(item) { - switch (navigationBarNodeKind(item)) { - case 221 /* ClassDeclaration */: - case 192 /* ClassExpression */: - case 224 /* EnumDeclaration */: - case 222 /* InterfaceDeclaration */: - case 225 /* ModuleDeclaration */: - case 256 /* SourceFile */: - case 223 /* TypeAliasDeclaration */: - case 279 /* JSDocTypedefTag */: - return true; - case 148 /* Constructor */: - case 147 /* MethodDeclaration */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 218 /* VariableDeclaration */: - return hasSomeImportantChild(item); - case 180 /* ArrowFunction */: - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - return isTopLevelFunctionDeclaration(item); - default: - return false; + // We haven't looked for this file, do so now and cache result + var file = host.getSourceFile(fileName, options.target, function (hostErrorMessage) { + if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) { + fileProcessingDiagnostics.add(ts.createFileDiagnostic(refFile, refPos, refEnd - refPos, ts.Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage)); } - function isTopLevelFunctionDeclaration(item) { - if (!item.node.body) { - return false; + else { + fileProcessingDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage)); + } + }); + filesByName.set(path, file); + if (file) { + sourceFilesFoundSearchingNodeModules[path] = (currentNodeModulesDepth > 0); + file.path = path; + if (host.useCaseSensitiveFileNames()) { + // for case-sensitive file systems check if we've already seen some file with similar filename ignoring case + var existingFile = filesByNameIgnoreCase.get(path); + if (existingFile) { + reportFileNamesDifferOnlyInCasingError(fileName, existingFile.fileName, refFile, refPos, refEnd); } - switch (navigationBarNodeKind(item.parent)) { - case 226 /* ModuleBlock */: - case 256 /* SourceFile */: - case 147 /* MethodDeclaration */: - case 148 /* Constructor */: - return true; - default: - return hasSomeImportantChild(item); + else { + filesByNameIgnoreCase.set(path, file); } } - function hasSomeImportantChild(item) { - return ts.forEach(item.children, function (child) { - var childKind = navigationBarNodeKind(child); - return childKind !== 218 /* VariableDeclaration */ && childKind !== 169 /* BindingElement */; - }); + skipDefaultLib = skipDefaultLib || file.hasNoDefaultLib; + var basePath = ts.getDirectoryPath(fileName); + if (!options.noResolve) { + processReferencedFiles(file, basePath, isDefaultLib); + processTypeReferenceDirectives(file); } - } - } - // NavigationBarItem requires an array, but will not mutate it, so just give it this for performance. - var emptyChildItemArray = []; - function convertToTopLevelItem(n) { - return { - text: getItemName(n.node), - kind: ts.getNodeKind(n.node), - kindModifiers: ts.getNodeModifiers(n.node), - spans: getSpans(n), - childItems: ts.map(n.children, convertToChildItem) || emptyChildItemArray, - indent: n.indent, - bolded: false, - grayed: false - }; - function convertToChildItem(n) { - return { - text: getItemName(n.node), - kind: ts.getNodeKind(n.node), - kindModifiers: ts.getNodeModifiers(n.node), - spans: getSpans(n), - childItems: emptyChildItemArray, - indent: 0, - bolded: false, - grayed: false - }; - } - function getSpans(n) { - var spans = [getNodeSpan(n.node)]; - if (n.additionalNodes) { - for (var _i = 0, _a = n.additionalNodes; _i < _a.length; _i++) { - var node = _a[_i]; - spans.push(getNodeSpan(node)); - } + // always process imported modules to record module name resolutions + processImportedModules(file, basePath); + if (isDefaultLib) { + files.unshift(file); + } + else { + files.push(file); } - return spans; - } - } - function getModuleName(moduleDeclaration) { - // We want to maintain quotation marks. - if (ts.isAmbientModule(moduleDeclaration)) { - return ts.getTextOfNode(moduleDeclaration.name); - } - // Otherwise, we need to aggregate each identifier to build up the qualified name. - var result = []; - result.push(moduleDeclaration.name.text); - while (moduleDeclaration.body && moduleDeclaration.body.kind === 225 /* ModuleDeclaration */) { - moduleDeclaration = moduleDeclaration.body; - result.push(moduleDeclaration.name.text); } - return result.join("."); - } - /** - * For 'module A.B.C', we want to get the node for 'C'. - * We store 'A' as associated with a NavNode, and use getModuleName to traverse down again. - */ - function getInteriorModule(decl) { - return decl.body.kind === 225 /* ModuleDeclaration */ ? getInteriorModule(decl.body) : decl; + return file; } - function isComputedProperty(member) { - return !member.name || member.name.kind === 140 /* ComputedPropertyName */; + function processReferencedFiles(file, basePath, isDefaultLib) { + ts.forEach(file.referencedFiles, function (ref) { + var referencedFileName = resolveTripleslashReference(ref.fileName, file.fileName); + processSourceFile(referencedFileName, isDefaultLib, /*isReference*/ true, file, ref.pos, ref.end); + }); } - function getNodeSpan(node) { - return node.kind === 256 /* SourceFile */ - ? ts.createTextSpanFromBounds(node.getFullStart(), node.getEnd()) - : ts.createTextSpanFromBounds(node.getStart(curSourceFile), node.getEnd()); + function processTypeReferenceDirectives(file) { + // We lower-case all type references because npm automatically lowercases all packages. See GH#9824. + var typeDirectives = ts.map(file.typeReferenceDirectives, function (ref) { return ref.fileName.toLocaleLowerCase(); }); + var resolutions = resolveTypeReferenceDirectiveNamesWorker(typeDirectives, file.fileName); + for (var i = 0; i < typeDirectives.length; i++) { + var ref = file.typeReferenceDirectives[i]; + var resolvedTypeReferenceDirective = resolutions[i]; + // store resolved type directive on the file + var fileName = ref.fileName.toLocaleLowerCase(); + ts.setResolvedTypeReferenceDirective(file, fileName, resolvedTypeReferenceDirective); + processTypeReferenceDirective(fileName, resolvedTypeReferenceDirective, file, ref.pos, ref.end); + } } - function getFunctionOrClassName(node) { - if (node.name && ts.getFullWidth(node.name) > 0) { - return ts.declarationNameToString(node.name); + function processTypeReferenceDirective(typeReferenceDirective, resolvedTypeReferenceDirective, refFile, refPos, refEnd) { + // If we already found this library as a primary reference - nothing to do + var previousResolution = resolvedTypeReferenceDirectives[typeReferenceDirective]; + if (previousResolution && previousResolution.primary) { + return; + } + var saveResolution = true; + if (resolvedTypeReferenceDirective) { + if (resolvedTypeReferenceDirective.primary) { + // resolved from the primary path + processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, /*isDefaultLib*/ false, /*isReference*/ true, refFile, refPos, refEnd); + } + else { + // If we already resolved to this file, it must have been a secondary reference. Check file contents + // for sameness and possibly issue an error + if (previousResolution) { + var otherFileText = host.readFile(resolvedTypeReferenceDirective.resolvedFileName); + if (otherFileText !== getSourceFile(previousResolution.resolvedFileName).text) { + fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd, ts.Diagnostics.Conflicting_definitions_for_0_found_at_1_and_2_Consider_installing_a_specific_version_of_this_library_to_resolve_the_conflict, typeReferenceDirective, resolvedTypeReferenceDirective.resolvedFileName, previousResolution.resolvedFileName)); + } + // don't overwrite previous resolution result + saveResolution = false; + } + else { + // First resolution of this library + processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, /*isDefaultLib*/ false, /*isReference*/ true, refFile, refPos, refEnd); + } + } } - else if (node.parent.kind === 218 /* VariableDeclaration */) { - return ts.declarationNameToString(node.parent.name); + else { + fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd, ts.Diagnostics.Cannot_find_type_definition_file_for_0, typeReferenceDirective)); } - else if (node.parent.kind === 187 /* BinaryExpression */ && - node.parent.operatorToken.kind === 56 /* EqualsToken */) { - return nodeText(node.parent.left); + if (saveResolution) { + resolvedTypeReferenceDirectives[typeReferenceDirective] = resolvedTypeReferenceDirective; } - else if (node.parent.kind === 253 /* PropertyAssignment */ && node.parent.name) { - return nodeText(node.parent.name); + } + function createDiagnostic(refFile, refPos, refEnd, message) { + var args = []; + for (var _i = 4; _i < arguments.length; _i++) { + args[_i - 4] = arguments[_i]; } - else if (node.flags & 512 /* Default */) { - return "default"; + if (refFile === undefined || refPos === undefined || refEnd === undefined) { + return ts.createCompilerDiagnostic.apply(void 0, [message].concat(args)); } else { - return ts.isClassLike(node) ? "" : ""; + return ts.createFileDiagnostic.apply(void 0, [refFile, refPos, refEnd - refPos, message].concat(args)); } } - function isFunctionOrClassExpression(node) { - return node.kind === 179 /* FunctionExpression */ || node.kind === 180 /* ArrowFunction */ || node.kind === 192 /* ClassExpression */; - } - })(NavigationBar = ts.NavigationBar || (ts.NavigationBar = {})); -})(ts || (ts = {})); -/* @internal */ -var ts; -(function (ts) { - // Note(cyrusn): this enum is ordered from strongest match type to weakest match type. - (function (PatternMatchKind) { - PatternMatchKind[PatternMatchKind["exact"] = 0] = "exact"; - PatternMatchKind[PatternMatchKind["prefix"] = 1] = "prefix"; - PatternMatchKind[PatternMatchKind["substring"] = 2] = "substring"; - PatternMatchKind[PatternMatchKind["camelCase"] = 3] = "camelCase"; - })(ts.PatternMatchKind || (ts.PatternMatchKind = {})); - var PatternMatchKind = ts.PatternMatchKind; - function createPatternMatch(kind, punctuationStripped, isCaseSensitive, camelCaseWeight) { - return { - kind: kind, - punctuationStripped: punctuationStripped, - isCaseSensitive: isCaseSensitive, - camelCaseWeight: camelCaseWeight - }; - } - function createPatternMatcher(pattern) { - // We'll often see the same candidate string many times when searching (For example, when - // we see the name of a module that is used everywhere, or the name of an overload). As - // such, we cache the information we compute about the candidate for the life of this - // pattern matcher so we don't have to compute it multiple times. - var stringToWordSpans = ts.createMap(); - pattern = pattern.trim(); - var dotSeparatedSegments = pattern.split(".").map(function (p) { return createSegment(p.trim()); }); - var invalidPattern = dotSeparatedSegments.length === 0 || ts.forEach(dotSeparatedSegments, segmentIsInvalid); - return { - getMatches: getMatches, - getMatchesForLastSegmentOfPattern: getMatchesForLastSegmentOfPattern, - patternContainsDots: dotSeparatedSegments.length > 1 - }; - // Quick checks so we can bail out when asked to match a candidate. - function skipMatch(candidate) { - return invalidPattern || !candidate; - } - function getMatchesForLastSegmentOfPattern(candidate) { - if (skipMatch(candidate)) { - return undefined; - } - return matchSegment(candidate, ts.lastOrUndefined(dotSeparatedSegments)); + function getCanonicalFileName(fileName) { + return host.getCanonicalFileName(fileName); } - function getMatches(candidateContainers, candidate) { - if (skipMatch(candidate)) { - return undefined; - } - // First, check that the last part of the dot separated pattern matches the name of the - // candidate. If not, then there's no point in proceeding and doing the more - // expensive work. - var candidateMatch = matchSegment(candidate, ts.lastOrUndefined(dotSeparatedSegments)); - if (!candidateMatch) { - return undefined; + function processImportedModules(file, basePath) { + collectExternalModuleReferences(file); + if (file.imports.length || file.moduleAugmentations.length) { + file.resolvedModules = ts.createMap(); + var moduleNames = ts.map(ts.concatenate(file.imports, file.moduleAugmentations), getTextOfLiteral); + var resolutions = resolveModuleNamesWorker(moduleNames, ts.getNormalizedAbsolutePath(file.fileName, currentDirectory)); + for (var i = 0; i < moduleNames.length; i++) { + var resolution = resolutions[i]; + ts.setResolvedModule(file, moduleNames[i], resolution); + var resolvedPath = resolution ? ts.toPath(resolution.resolvedFileName, currentDirectory, getCanonicalFileName) : undefined; + // add file to program only if: + // - resolution was successful + // - noResolve is falsy + // - module name comes from the list of imports + // - it's not a top level JavaScript module that exceeded the search max + var isFromNodeModulesSearch = resolution && resolution.isExternalLibraryImport; + var isJsFileFromNodeModules = isFromNodeModulesSearch && ts.hasJavaScriptFileExtension(resolution.resolvedFileName); + if (isFromNodeModulesSearch) { + currentNodeModulesDepth++; + } + var elideImport = isJsFileFromNodeModules && currentNodeModulesDepth > maxNodeModulesJsDepth; + var shouldAddFile = resolution && !options.noResolve && i < file.imports.length && !elideImport; + if (elideImport) { + modulesWithElidedImports[file.path] = true; + } + else if (shouldAddFile) { + findSourceFile(resolution.resolvedFileName, resolvedPath, + /*isDefaultLib*/ false, /*isReference*/ false, file, ts.skipTrivia(file.text, file.imports[i].pos), file.imports[i].end); + } + if (isFromNodeModulesSearch) { + currentNodeModulesDepth--; + } + } } - candidateContainers = candidateContainers || []; - // -1 because the last part was checked against the name, and only the rest - // of the parts are checked against the container. - if (dotSeparatedSegments.length - 1 > candidateContainers.length) { - // There weren't enough container parts to match against the pattern parts. - // So this definitely doesn't match. - return undefined; + else { + // no imports - drop cached module resolutions + file.resolvedModules = undefined; } - // So far so good. Now break up the container for the candidate and check if all - // the dotted parts match up correctly. - var totalMatch = candidateMatch; - for (var i = dotSeparatedSegments.length - 2, j = candidateContainers.length - 1; i >= 0; i -= 1, j -= 1) { - var segment = dotSeparatedSegments[i]; - var containerName = candidateContainers[j]; - var containerMatch = matchSegment(containerName, segment); - if (!containerMatch) { - // This container didn't match the pattern piece. So there's no match at all. - return undefined; + return; + } + function computeCommonSourceDirectory(sourceFiles) { + var fileNames = []; + for (var _i = 0, sourceFiles_6 = sourceFiles; _i < sourceFiles_6.length; _i++) { + var file = sourceFiles_6[_i]; + if (!file.isDeclarationFile) { + fileNames.push(file.fileName); } - ts.addRange(totalMatch, containerMatch); } - // Success, this symbol's full name matched against the dotted name the user was asking - // about. - return totalMatch; + return computeCommonSourceDirectoryOfFilenames(fileNames, currentDirectory, getCanonicalFileName); } - function getWordSpans(word) { - if (!(word in stringToWordSpans)) { - stringToWordSpans[word] = breakIntoWordSpans(word); + function checkSourceFilesBelongToPath(sourceFiles, rootDirectory) { + var allFilesBelongToPath = true; + if (sourceFiles) { + var absoluteRootDirectoryPath = host.getCanonicalFileName(ts.getNormalizedAbsolutePath(rootDirectory, currentDirectory)); + for (var _i = 0, sourceFiles_7 = sourceFiles; _i < sourceFiles_7.length; _i++) { + var sourceFile = sourceFiles_7[_i]; + if (!ts.isDeclarationFile(sourceFile)) { + var absoluteSourceFilePath = host.getCanonicalFileName(ts.getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory)); + if (absoluteSourceFilePath.indexOf(absoluteRootDirectoryPath) !== 0) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, sourceFile.fileName, options.rootDir)); + allFilesBelongToPath = false; + } + } + } } - return stringToWordSpans[word]; + return allFilesBelongToPath; } - function matchTextChunk(candidate, chunk, punctuationStripped) { - var index = indexOfIgnoringCase(candidate, chunk.textLowerCase); - if (index === 0) { - if (chunk.text.length === candidate.length) { - // a) Check if the part matches the candidate entirely, in an case insensitive or - // sensitive manner. If it does, return that there was an exact match. - return createPatternMatch(PatternMatchKind.exact, punctuationStripped, /*isCaseSensitive:*/ candidate === chunk.text); + function verifyCompilerOptions() { + if (options.isolatedModules) { + if (options.declaration) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "declaration", "isolatedModules")); } - else { - // b) Check if the part is a prefix of the candidate, in a case insensitive or sensitive - // manner. If it does, return that there was a prefix match. - return createPatternMatch(PatternMatchKind.prefix, punctuationStripped, /*isCaseSensitive:*/ ts.startsWith(candidate, chunk.text)); + if (options.noEmitOnError) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "noEmitOnError", "isolatedModules")); } - } - var isLowercase = chunk.isLowerCase; - if (isLowercase) { - if (index > 0) { - // c) If the part is entirely lowercase, then check if it is contained anywhere in the - // candidate in a case insensitive manner. If so, return that there was a substring - // match. - // - // Note: We only have a substring match if the lowercase part is prefix match of some - // word part. That way we don't match something like 'Class' when the user types 'a'. - // But we would match 'FooAttribute' (since 'Attribute' starts with 'a'). - var wordSpans = getWordSpans(candidate); - for (var _i = 0, wordSpans_1 = wordSpans; _i < wordSpans_1.length; _i++) { - var span = wordSpans_1[_i]; - if (partStartsWith(candidate, span, chunk.text, /*ignoreCase:*/ true)) { - return createPatternMatch(PatternMatchKind.substring, punctuationStripped, - /*isCaseSensitive:*/ partStartsWith(candidate, span, chunk.text, /*ignoreCase:*/ false)); - } - } + if (options.out) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "out", "isolatedModules")); + } + if (options.outFile) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "outFile", "isolatedModules")); } } - else { - // d) If the part was not entirely lowercase, then check if it is contained in the - // candidate in a case *sensitive* manner. If so, return that there was a substring - // match. - if (candidate.indexOf(chunk.text) > 0) { - return createPatternMatch(PatternMatchKind.substring, punctuationStripped, /*isCaseSensitive:*/ true); + if (options.inlineSourceMap) { + if (options.sourceMap) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "sourceMap", "inlineSourceMap")); + } + if (options.mapRoot) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "mapRoot", "inlineSourceMap")); } } - if (!isLowercase) { - // e) If the part was not entirely lowercase, then attempt a camel cased match as well. - if (chunk.characterSpans.length > 0) { - var candidateParts = getWordSpans(candidate); - var camelCaseWeight = tryCamelCaseMatch(candidate, candidateParts, chunk, /*ignoreCase:*/ false); - if (camelCaseWeight !== undefined) { - return createPatternMatch(PatternMatchKind.camelCase, punctuationStripped, /*isCaseSensitive:*/ true, /*camelCaseWeight:*/ camelCaseWeight); + if (options.paths && options.baseUrl === undefined) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_paths_cannot_be_used_without_specifying_baseUrl_option)); + } + if (options.paths) { + for (var key in options.paths) { + if (!ts.hasProperty(options.paths, key)) { + continue; } - camelCaseWeight = tryCamelCaseMatch(candidate, candidateParts, chunk, /*ignoreCase:*/ true); - if (camelCaseWeight !== undefined) { - return createPatternMatch(PatternMatchKind.camelCase, punctuationStripped, /*isCaseSensitive:*/ false, /*camelCaseWeight:*/ camelCaseWeight); + if (!ts.hasZeroOrOneAsteriskCharacter(key)) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, key)); } - } - } - if (isLowercase) { - // f) Is the pattern a substring of the candidate starting on one of the candidate's word boundaries? - // We could check every character boundary start of the candidate for the pattern. However, that's - // an m * n operation in the wost case. Instead, find the first instance of the pattern - // substring, and see if it starts on a capital letter. It seems unlikely that the user will try to - // filter the list based on a substring that starts on a capital letter and also with a lowercase one. - // (Pattern: fogbar, Candidate: quuxfogbarFogBar). - if (chunk.text.length < candidate.length) { - if (index > 0 && isUpperCaseLetter(candidate.charCodeAt(index))) { - return createPatternMatch(PatternMatchKind.substring, punctuationStripped, /*isCaseSensitive:*/ false); + if (ts.isArray(options.paths[key])) { + if (options.paths[key].length === 0) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Substitutions_for_pattern_0_shouldn_t_be_an_empty_array, key)); + } + for (var _i = 0, _a = options.paths[key]; _i < _a.length; _i++) { + var subst = _a[_i]; + var typeOfSubst = typeof subst; + if (typeOfSubst === "string") { + if (!ts.hasZeroOrOneAsteriskCharacter(subst)) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Substitution_0_in_pattern_1_in_can_have_at_most_one_Asterisk_character, subst, key)); + } + } + else { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Substitution_0_for_pattern_1_has_incorrect_type_expected_string_got_2, subst, key, typeOfSubst)); + } + } + } + else { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Substitutions_for_pattern_0_should_be_an_array, key)); } } } - return undefined; - } - function containsSpaceOrAsterisk(text) { - for (var i = 0; i < text.length; i++) { - var ch = text.charCodeAt(i); - if (ch === 32 /* space */ || ch === 42 /* asterisk */) { - return true; + if (!options.sourceMap && !options.inlineSourceMap) { + if (options.inlineSources) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided, "inlineSources")); + } + if (options.sourceRoot) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided, "sourceRoot")); } } - return false; - } - function matchSegment(candidate, segment) { - // First check if the segment matches as is. This is also useful if the segment contains - // characters we would normally strip when splitting into parts that we also may want to - // match in the candidate. For example if the segment is "@int" and the candidate is - // "@int", then that will show up as an exact match here. - // - // Note: if the segment contains a space or an asterisk then we must assume that it's a - // multi-word segment. - if (!containsSpaceOrAsterisk(segment.totalTextChunk.text)) { - var match = matchTextChunk(candidate, segment.totalTextChunk, /*punctuationStripped:*/ false); - if (match) { - return [match]; + if (options.out && options.outFile) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "out", "outFile")); + } + if (options.mapRoot && !options.sourceMap) { + // Error to specify --mapRoot without --sourcemap + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "mapRoot", "sourceMap")); + } + if (options.declarationDir) { + if (!options.declaration) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "declarationDir", "declaration")); + } + if (options.out || options.outFile) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "declarationDir", options.out ? "out" : "outFile")); } } - // The logic for pattern matching is now as follows: - // - // 1) Break the segment passed in into words. Breaking is rather simple and a - // good way to think about it that if gives you all the individual alphanumeric words - // of the pattern. - // - // 2) For each word try to match the word against the candidate value. - // - // 3) Matching is as follows: - // - // a) Check if the word matches the candidate entirely, in an case insensitive or - // sensitive manner. If it does, return that there was an exact match. - // - // b) Check if the word is a prefix of the candidate, in a case insensitive or - // sensitive manner. If it does, return that there was a prefix match. - // - // c) If the word is entirely lowercase, then check if it is contained anywhere in the - // candidate in a case insensitive manner. If so, return that there was a substring - // match. - // - // Note: We only have a substring match if the lowercase part is prefix match of - // some word part. That way we don't match something like 'Class' when the user - // types 'a'. But we would match 'FooAttribute' (since 'Attribute' starts with - // 'a'). - // - // d) If the word was not entirely lowercase, then check if it is contained in the - // candidate in a case *sensitive* manner. If so, return that there was a substring - // match. - // - // e) If the word was not entirely lowercase, then attempt a camel cased match as - // well. - // - // f) The word is all lower case. Is it a case insensitive substring of the candidate starting - // on a part boundary of the candidate? - // - // Only if all words have some sort of match is the pattern considered matched. - var subWordTextChunks = segment.subWordTextChunks; - var matches = undefined; - for (var _i = 0, subWordTextChunks_1 = subWordTextChunks; _i < subWordTextChunks_1.length; _i++) { - var subWordTextChunk = subWordTextChunks_1[_i]; - // Try to match the candidate with this word - var result = matchTextChunk(candidate, subWordTextChunk, /*punctuationStripped:*/ true); - if (!result) { - return undefined; + if (options.lib && options.noLib) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "lib", "noLib")); + } + var languageVersion = options.target || 0 /* ES3 */; + var outFile = options.outFile || options.out; + var firstNonAmbientExternalModuleSourceFile = ts.forEach(files, function (f) { return ts.isExternalModule(f) && !ts.isDeclarationFile(f) ? f : undefined; }); + if (options.isolatedModules) { + if (options.module === ts.ModuleKind.None && languageVersion < 2 /* ES6 */) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_isolatedModules_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES2015_or_higher)); + } + var firstNonExternalModuleSourceFile = ts.forEach(files, function (f) { return !ts.isExternalModule(f) && !ts.isDeclarationFile(f) ? f : undefined; }); + if (firstNonExternalModuleSourceFile) { + var span_7 = ts.getErrorSpanForNode(firstNonExternalModuleSourceFile, firstNonExternalModuleSourceFile); + programDiagnostics.add(ts.createFileDiagnostic(firstNonExternalModuleSourceFile, span_7.start, span_7.length, ts.Diagnostics.Cannot_compile_namespaces_when_the_isolatedModules_flag_is_provided)); } - matches = matches || []; - matches.push(result); } - return matches; - } - function partStartsWith(candidate, candidateSpan, pattern, ignoreCase, patternSpan) { - var patternPartStart = patternSpan ? patternSpan.start : 0; - var patternPartLength = patternSpan ? patternSpan.length : pattern.length; - if (patternPartLength > candidateSpan.length) { - // Pattern part is longer than the candidate part. There can never be a match. - return false; + else if (firstNonAmbientExternalModuleSourceFile && languageVersion < 2 /* ES6 */ && options.module === ts.ModuleKind.None) { + // We cannot use createDiagnosticFromNode because nodes do not have parents yet + var span_8 = ts.getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, firstNonAmbientExternalModuleSourceFile.externalModuleIndicator); + programDiagnostics.add(ts.createFileDiagnostic(firstNonAmbientExternalModuleSourceFile, span_8.start, span_8.length, ts.Diagnostics.Cannot_use_imports_exports_or_module_augmentations_when_module_is_none)); } - if (ignoreCase) { - for (var i = 0; i < patternPartLength; i++) { - var ch1 = pattern.charCodeAt(patternPartStart + i); - var ch2 = candidate.charCodeAt(candidateSpan.start + i); - if (toLowerCase(ch1) !== toLowerCase(ch2)) { - return false; - } + // Cannot specify module gen that isn't amd or system with --out + if (outFile) { + if (options.module && !(options.module === ts.ModuleKind.AMD || options.module === ts.ModuleKind.System)) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Only_amd_and_system_modules_are_supported_alongside_0, options.out ? "out" : "outFile")); + } + else if (options.module === undefined && firstNonAmbientExternalModuleSourceFile) { + var span_9 = ts.getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, firstNonAmbientExternalModuleSourceFile.externalModuleIndicator); + programDiagnostics.add(ts.createFileDiagnostic(firstNonAmbientExternalModuleSourceFile, span_9.start, span_9.length, ts.Diagnostics.Cannot_compile_modules_using_option_0_unless_the_module_flag_is_amd_or_system, options.out ? "out" : "outFile")); } } - else { - for (var i = 0; i < patternPartLength; i++) { - var ch1 = pattern.charCodeAt(patternPartStart + i); - var ch2 = candidate.charCodeAt(candidateSpan.start + i); - if (ch1 !== ch2) { - return false; - } + // there has to be common source directory if user specified --outdir || --sourceRoot + // if user specified --mapRoot, there needs to be common source directory if there would be multiple files being emitted + if (options.outDir || + options.sourceRoot || + options.mapRoot) { + // Precalculate and cache the common source directory + var dir = getCommonSourceDirectory(); + // If we failed to find a good common directory, but outDir is specified and at least one of our files is on a windows drive/URL/other resource, add a failure + if (options.outDir && dir === "" && ts.forEach(files, function (file) { return ts.getRootLength(file.fileName) > 1; })) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files)); } } - return true; - } - function tryCamelCaseMatch(candidate, candidateParts, chunk, ignoreCase) { - var chunkCharacterSpans = chunk.characterSpans; - // Note: we may have more pattern parts than candidate parts. This is because multiple - // pattern parts may match a candidate part. For example "SiUI" against "SimpleUI". - // We'll have 3 pattern parts Si/U/I against two candidate parts Simple/UI. However, U - // and I will both match in UI. - var currentCandidate = 0; - var currentChunkSpan = 0; - var firstMatch = undefined; - var contiguous = undefined; - while (true) { - // Let's consider our termination cases - if (currentChunkSpan === chunkCharacterSpans.length) { - // We did match! We shall assign a weight to this - var weight = 0; - // Was this contiguous? - if (contiguous) { - weight += 1; - } - // Did we start at the beginning of the candidate? - if (firstMatch === 0) { - weight += 2; + if (!options.noEmit && options.allowJs && options.declaration) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration")); + } + if (options.emitDecoratorMetadata && + !options.experimentalDecorators) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDecoratorMetadata", "experimentalDecorators")); + } + if (options.reactNamespace && !ts.isIdentifierText(options.reactNamespace, languageVersion)) { + programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Invalid_value_for_reactNamespace_0_is_not_a_valid_identifier, options.reactNamespace)); + } + // If the emit is enabled make sure that every output file is unique and not overwriting any of the input files + if (!options.noEmit && !options.suppressOutputPathCheck) { + var emitHost = getEmitHost(); + var emitFilesSeen_1 = ts.createFileMap(!host.useCaseSensitiveFileNames() ? function (key) { return key.toLocaleLowerCase(); } : undefined); + ts.forEachExpectedEmitFile(emitHost, function (emitFileNames, sourceFiles, isBundledEmit) { + verifyEmitFilePath(emitFileNames.jsFilePath, emitFilesSeen_1); + verifyEmitFilePath(emitFileNames.declarationFilePath, emitFilesSeen_1); + }); + } + // Verify that all the emit files are unique and don't overwrite input files + function verifyEmitFilePath(emitFileName, emitFilesSeen) { + if (emitFileName) { + var emitFilePath = ts.toPath(emitFileName, currentDirectory, getCanonicalFileName); + // Report error if the output overwrites input file + if (filesByName.contains(emitFilePath)) { + createEmitBlockingDiagnostics(emitFileName, emitFilePath, ts.Diagnostics.Cannot_write_file_0_because_it_would_overwrite_input_file); } - return weight; - } - else if (currentCandidate === candidateParts.length) { - // No match, since we still have more of the pattern to hit - return undefined; - } - var candidatePart = candidateParts[currentCandidate]; - var gotOneMatchThisCandidate = false; - // Consider the case of matching SiUI against SimpleUIElement. The candidate parts - // will be Simple/UI/Element, and the pattern parts will be Si/U/I. We'll match 'Si' - // against 'Simple' first. Then we'll match 'U' against 'UI'. However, we want to - // still keep matching pattern parts against that candidate part. - for (; currentChunkSpan < chunkCharacterSpans.length; currentChunkSpan++) { - var chunkCharacterSpan = chunkCharacterSpans[currentChunkSpan]; - if (gotOneMatchThisCandidate) { - // We've already gotten one pattern part match in this candidate. We will - // only continue trying to consumer pattern parts if the last part and this - // part are both upper case. - if (!isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan - 1].start)) || - !isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan].start))) { - break; - } + // Report error if multiple files write into same file + if (emitFilesSeen.contains(emitFilePath)) { + // Already seen the same emit file - report error + createEmitBlockingDiagnostics(emitFileName, emitFilePath, ts.Diagnostics.Cannot_write_file_0_because_it_would_be_overwritten_by_multiple_input_files); } - if (!partStartsWith(candidate, candidatePart, chunk.text, ignoreCase, chunkCharacterSpan)) { - break; + else { + emitFilesSeen.set(emitFilePath, true); } - gotOneMatchThisCandidate = true; - firstMatch = firstMatch === undefined ? currentCandidate : firstMatch; - // If we were contiguous, then keep that value. If we weren't, then keep that - // value. If we don't know, then set the value to 'true' as an initial match is - // obviously contiguous. - contiguous = contiguous === undefined ? true : contiguous; - candidatePart = ts.createTextSpan(candidatePart.start + chunkCharacterSpan.length, candidatePart.length - chunkCharacterSpan.length); - } - // Check if we matched anything at all. If we didn't, then we need to unset the - // contiguous bit if we currently had it set. - // If we haven't set the bit yet, then that means we haven't matched anything so - // far, and we don't want to change that. - if (!gotOneMatchThisCandidate && contiguous !== undefined) { - contiguous = false; } - // Move onto the next candidate. - currentCandidate++; } } + function createEmitBlockingDiagnostics(emitFileName, emitFilePath, message) { + hasEmitBlockingDiagnostics.set(ts.toPath(emitFileName, currentDirectory, getCanonicalFileName), true); + programDiagnostics.add(ts.createCompilerDiagnostic(message, emitFileName)); + } + } + ts.createProgram = createProgram; +})(ts || (ts = {})); +/// +/// +var ts; +(function (ts) { + var defaultFormatDiagnosticsHost = { + getCurrentDirectory: function () { return ts.sys.getCurrentDirectory(); }, + getNewLine: function () { return ts.sys.newLine; }, + getCanonicalFileName: ts.createGetCanonicalFileName(ts.sys.useCaseSensitiveFileNames) + }; + var reportDiagnosticWorker = reportDiagnosticSimply; + function reportDiagnostic(diagnostic, host) { + reportDiagnosticWorker(diagnostic, host || defaultFormatDiagnosticsHost); + } + function reportDiagnostics(diagnostics, host) { + for (var _i = 0, diagnostics_2 = diagnostics; _i < diagnostics_2.length; _i++) { + var diagnostic = diagnostics_2[_i]; + reportDiagnostic(diagnostic, host); + } } - ts.createPatternMatcher = createPatternMatcher; - function createSegment(text) { - return { - totalTextChunk: createTextChunk(text), - subWordTextChunks: breakPatternIntoTextChunks(text) - }; + function reportEmittedFiles(files, host) { + if (!files || files.length == 0) { + return; + } + var currentDir = ts.sys.getCurrentDirectory(); + for (var _i = 0, files_3 = files; _i < files_3.length; _i++) { + var file = files_3[_i]; + var filepath = ts.getNormalizedAbsolutePath(file, currentDir); + ts.sys.write("TSFILE: " + filepath + ts.sys.newLine); + } } - // A segment is considered invalid if we couldn't find any words in it. - function segmentIsInvalid(segment) { - return segment.subWordTextChunks.length === 0; + /** + * Checks to see if the locale is in the appropriate format, + * and if it is, attempts to set the appropriate language. + */ + function validateLocaleAndSetLanguage(locale, errors) { + var matchResult = /^([a-z]+)([_\-]([a-z]+))?$/.exec(locale.toLowerCase()); + if (!matchResult) { + errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Locale_must_be_of_the_form_language_or_language_territory_For_example_0_or_1, "en", "ja-jp")); + return false; + } + var language = matchResult[1]; + var territory = matchResult[3]; + // First try the entire locale, then fall back to just language if that's all we have. + // Either ways do not fail, and fallback to the English diagnostic strings. + if (!trySetLanguageAndTerritory(language, territory, errors)) { + trySetLanguageAndTerritory(language, undefined, errors); + } + return true; } - function isUpperCaseLetter(ch) { - // Fast check for the ascii range. - if (ch >= 65 /* A */ && ch <= 90 /* Z */) { - return true; + function trySetLanguageAndTerritory(language, territory, errors) { + var compilerFilePath = ts.normalizePath(ts.sys.getExecutingFilePath()); + var containingDirectoryPath = ts.getDirectoryPath(compilerFilePath); + var filePath = ts.combinePaths(containingDirectoryPath, language); + if (territory) { + filePath = filePath + "-" + territory; } - if (ch < 127 /* maxAsciiCharacter */ || !ts.isUnicodeIdentifierStart(ch, 2 /* Latest */)) { + filePath = ts.sys.resolvePath(ts.combinePaths(filePath, "diagnosticMessages.generated.json")); + if (!ts.sys.fileExists(filePath)) { return false; } - // TODO: find a way to determine this for any unicode characters in a - // non-allocating manner. - var str = String.fromCharCode(ch); - return str === str.toUpperCase(); - } - function isLowerCaseLetter(ch) { - // Fast check for the ascii range. - if (ch >= 97 /* a */ && ch <= 122 /* z */) { - return true; + // TODO: Add codePage support for readFile? + var fileContents = ""; + try { + fileContents = ts.sys.readFile(filePath); } - if (ch < 127 /* maxAsciiCharacter */ || !ts.isUnicodeIdentifierStart(ch, 2 /* Latest */)) { + catch (e) { + errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unable_to_open_file_0, filePath)); return false; } - // TODO: find a way to determine this for any unicode characters in a - // non-allocating manner. - var str = String.fromCharCode(ch); - return str === str.toLowerCase(); - } - // Assumes 'value' is already lowercase. - function indexOfIgnoringCase(string, value) { - for (var i = 0, n = string.length - value.length; i <= n; i++) { - if (startsWithIgnoringCase(string, value, i)) { - return i; - } + try { + ts.localizedDiagnosticMessages = JSON.parse(fileContents); } - return -1; - } - // Assumes 'value' is already lowercase. - function startsWithIgnoringCase(string, value, start) { - for (var i = 0, n = value.length; i < n; i++) { - var ch1 = toLowerCase(string.charCodeAt(i + start)); - var ch2 = value.charCodeAt(i); - if (ch1 !== ch2) { - return false; - } + catch (e) { + errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Corrupted_locale_file_0, filePath)); + return false; } return true; } - function toLowerCase(ch) { - // Fast convert for the ascii range. - if (ch >= 65 /* A */ && ch <= 90 /* Z */) { - return 97 /* a */ + (ch - 65 /* A */); - } - if (ch < 127 /* maxAsciiCharacter */) { - return ch; + function countLines(program) { + var count = 0; + ts.forEach(program.getSourceFiles(), function (file) { + count += ts.getLineStarts(file).length; + }); + return count; + } + function getDiagnosticText(message) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; } - // TODO: find a way to compute this for any unicode characters in a - // non-allocating manner. - return String.fromCharCode(ch).toLowerCase().charCodeAt(0); + var diagnostic = ts.createCompilerDiagnostic.apply(undefined, arguments); + return diagnostic.messageText; } - function isDigit(ch) { - // TODO(cyrusn): Find a way to support this for unicode digits. - return ch >= 48 /* _0 */ && ch <= 57 /* _9 */; + function reportDiagnosticSimply(diagnostic, host) { + ts.sys.write(ts.formatDiagnostics([diagnostic], host)); } - function isWordChar(ch) { - return isUpperCaseLetter(ch) || isLowerCaseLetter(ch) || isDigit(ch) || ch === 95 /* _ */ || ch === 36 /* $ */; + var redForegroundEscapeSequence = "\u001b[91m"; + var yellowForegroundEscapeSequence = "\u001b[93m"; + var blueForegroundEscapeSequence = "\u001b[93m"; + var gutterStyleSequence = "\u001b[100;30m"; + var gutterSeparator = " "; + var resetEscapeSequence = "\u001b[0m"; + var ellipsis = "..."; + var categoryFormatMap = ts.createMap((_a = {}, + _a[ts.DiagnosticCategory.Warning] = yellowForegroundEscapeSequence, + _a[ts.DiagnosticCategory.Error] = redForegroundEscapeSequence, + _a[ts.DiagnosticCategory.Message] = blueForegroundEscapeSequence, + _a)); + function formatAndReset(text, formatStyle) { + return formatStyle + text + resetEscapeSequence; } - function breakPatternIntoTextChunks(pattern) { - var result = []; - var wordStart = 0; - var wordLength = 0; - for (var i = 0; i < pattern.length; i++) { - var ch = pattern.charCodeAt(i); - if (isWordChar(ch)) { - if (wordLength === 0) { - wordStart = i; - } - wordLength++; + function reportDiagnosticWithColorAndContext(diagnostic, host) { + var output = ""; + if (diagnostic.file) { + var start = diagnostic.start, length_4 = diagnostic.length, file = diagnostic.file; + var _a = ts.getLineAndCharacterOfPosition(file, start), firstLine = _a.line, firstLineChar = _a.character; + var _b = ts.getLineAndCharacterOfPosition(file, start + length_4), lastLine = _b.line, lastLineChar = _b.character; + var lastLineInFile = ts.getLineAndCharacterOfPosition(file, file.text.length).line; + var relativeFileName = host ? ts.convertToRelativePath(file.fileName, host.getCurrentDirectory(), function (fileName) { return host.getCanonicalFileName(fileName); }) : file.fileName; + var hasMoreThanFiveLines = (lastLine - firstLine) >= 4; + var gutterWidth = (lastLine + 1 + "").length; + if (hasMoreThanFiveLines) { + gutterWidth = Math.max(ellipsis.length, gutterWidth); } - else { - if (wordLength > 0) { - result.push(createTextChunk(pattern.substr(wordStart, wordLength))); - wordLength = 0; + output += ts.sys.newLine; + for (var i = firstLine; i <= lastLine; i++) { + // If the error spans over 5 lines, we'll only show the first 2 and last 2 lines, + // so we'll skip ahead to the second-to-last line. + if (hasMoreThanFiveLines && firstLine + 1 < i && i < lastLine - 1) { + output += formatAndReset(padLeft(ellipsis, gutterWidth), gutterStyleSequence) + gutterSeparator + ts.sys.newLine; + i = lastLine - 1; } - } - } - if (wordLength > 0) { - result.push(createTextChunk(pattern.substr(wordStart, wordLength))); - } - return result; - } - function createTextChunk(text) { - var textLowerCase = text.toLowerCase(); - return { - text: text, - textLowerCase: textLowerCase, - isLowerCase: text === textLowerCase, - characterSpans: breakIntoCharacterSpans(text) - }; - } - /* @internal */ function breakIntoCharacterSpans(identifier) { - return breakIntoSpans(identifier, /*word:*/ false); - } - ts.breakIntoCharacterSpans = breakIntoCharacterSpans; - /* @internal */ function breakIntoWordSpans(identifier) { - return breakIntoSpans(identifier, /*word:*/ true); - } - ts.breakIntoWordSpans = breakIntoWordSpans; - function breakIntoSpans(identifier, word) { - var result = []; - var wordStart = 0; - for (var i = 1, n = identifier.length; i < n; i++) { - var lastIsDigit = isDigit(identifier.charCodeAt(i - 1)); - var currentIsDigit = isDigit(identifier.charCodeAt(i)); - var hasTransitionFromLowerToUpper = transitionFromLowerToUpper(identifier, word, i); - var hasTransitionFromUpperToLower = transitionFromUpperToLower(identifier, word, i, wordStart); - if (charIsPunctuation(identifier.charCodeAt(i - 1)) || - charIsPunctuation(identifier.charCodeAt(i)) || - lastIsDigit !== currentIsDigit || - hasTransitionFromLowerToUpper || - hasTransitionFromUpperToLower) { - if (!isAllPunctuation(identifier, wordStart, i)) { - result.push(ts.createTextSpan(wordStart, i - wordStart)); + var lineStart = ts.getPositionOfLineAndCharacter(file, i, 0); + var lineEnd = i < lastLineInFile ? ts.getPositionOfLineAndCharacter(file, i + 1, 0) : file.text.length; + var lineContent = file.text.slice(lineStart, lineEnd); + lineContent = lineContent.replace(/\s+$/g, ""); // trim from end + lineContent = lineContent.replace("\t", " "); // convert tabs to single spaces + // Output the gutter and the actual contents of the line. + output += formatAndReset(padLeft(i + 1 + "", gutterWidth), gutterStyleSequence) + gutterSeparator; + output += lineContent + ts.sys.newLine; + // Output the gutter and the error span for the line using tildes. + output += formatAndReset(padLeft("", gutterWidth), gutterStyleSequence) + gutterSeparator; + output += redForegroundEscapeSequence; + if (i === firstLine) { + // If we're on the last line, then limit it to the last character of the last line. + // Otherwise, we'll just squiggle the rest of the line, giving 'slice' no end position. + var lastCharForLine = i === lastLine ? lastLineChar : undefined; + output += lineContent.slice(0, firstLineChar).replace(/\S/g, " "); + output += lineContent.slice(firstLineChar, lastCharForLine).replace(/./g, "~"); } - wordStart = i; + else if (i === lastLine) { + output += lineContent.slice(0, lastLineChar).replace(/./g, "~"); + } + else { + // Squiggle the entire line. + output += lineContent.replace(/./g, "~"); + } + output += resetEscapeSequence; + output += ts.sys.newLine; } + output += ts.sys.newLine; + output += relativeFileName + "(" + (firstLine + 1) + "," + (firstLineChar + 1) + "): "; } - if (!isAllPunctuation(identifier, wordStart, identifier.length)) { - result.push(ts.createTextSpan(wordStart, identifier.length - wordStart)); - } - return result; + var categoryColor = categoryFormatMap[diagnostic.category]; + var category = ts.DiagnosticCategory[diagnostic.category].toLowerCase(); + output += formatAndReset(category, categoryColor) + " TS" + diagnostic.code + ": " + ts.flattenDiagnosticMessageText(diagnostic.messageText, ts.sys.newLine); + output += ts.sys.newLine + ts.sys.newLine; + ts.sys.write(output); } - function charIsPunctuation(ch) { - switch (ch) { - case 33 /* exclamation */: - case 34 /* doubleQuote */: - case 35 /* hash */: - case 37 /* percent */: - case 38 /* ampersand */: - case 39 /* singleQuote */: - case 40 /* openParen */: - case 41 /* closeParen */: - case 42 /* asterisk */: - case 44 /* comma */: - case 45 /* minus */: - case 46 /* dot */: - case 47 /* slash */: - case 58 /* colon */: - case 59 /* semicolon */: - case 63 /* question */: - case 64 /* at */: - case 91 /* openBracket */: - case 92 /* backslash */: - case 93 /* closeBracket */: - case 95 /* _ */: - case 123 /* openBrace */: - case 125 /* closeBrace */: - return true; + function reportWatchDiagnostic(diagnostic) { + var output = new Date().toLocaleTimeString() + " - "; + if (diagnostic.file) { + var loc = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start); + output += diagnostic.file.fileName + "(" + (loc.line + 1) + "," + (loc.character + 1) + "): "; } - return false; + output += "" + ts.flattenDiagnosticMessageText(diagnostic.messageText, ts.sys.newLine) + ts.sys.newLine; + ts.sys.write(output); } - function isAllPunctuation(identifier, start, end) { - for (var i = start; i < end; i++) { - var ch = identifier.charCodeAt(i); - // We don't consider _ or $ as punctuation as there may be things with that name. - if (!charIsPunctuation(ch) || ch === 95 /* _ */ || ch === 36 /* $ */) { - return false; - } + function padLeft(s, length) { + while (s.length < length) { + s = " " + s; } - return true; + return s; } - function transitionFromUpperToLower(identifier, word, index, wordStart) { - if (word) { - // Cases this supports: - // 1) IDisposable -> I, Disposable - // 2) UIElement -> UI, Element - // 3) HTMLDocument -> HTML, Document - // - // etc. - if (index !== wordStart && - index + 1 < identifier.length) { - var currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index)); - var nextIsLower = isLowerCaseLetter(identifier.charCodeAt(index + 1)); - if (currentIsUpper && nextIsLower) { - // We have a transition from an upper to a lower letter here. But we only - // want to break if all the letters that preceded are uppercase. i.e. if we - // have "Foo" we don't want to break that into "F, oo". But if we have - // "IFoo" or "UIFoo", then we want to break that into "I, Foo" and "UI, - // Foo". i.e. the last uppercase letter belongs to the lowercase letters - // that follows. Note: this will make the following not split properly: - // "HELLOthere". However, these sorts of names do not show up in .Net - // programs. - for (var i = wordStart; i < index; i++) { - if (!isUpperCaseLetter(identifier.charCodeAt(i))) { - return false; - } - } - return true; - } - } + function padRight(s, length) { + while (s.length < length) { + s = s + " "; } - return false; + return s; } - function transitionFromLowerToUpper(identifier, word, index) { - var lastIsUpper = isUpperCaseLetter(identifier.charCodeAt(index - 1)); - var currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index)); - // See if the casing indicates we're starting a new word. Note: if we're breaking on - // words, then just seeing an upper case character isn't enough. Instead, it has to - // be uppercase and the previous character can't be uppercase. - // - // For example, breaking "AddMetadata" on words would make: Add Metadata - // - // on characters would be: A dd M etadata - // - // Break "AM" on words would be: AM - // - // on characters would be: A M - // - // We break the search string on characters. But we break the symbol name on words. - var transition = word - ? (currentIsUpper && !lastIsUpper) - : currentIsUpper; - return transition; + function isJSONSupported() { + return typeof JSON === "object" && typeof JSON.parse === "function"; } -})(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - var SignatureHelp; - (function (SignatureHelp) { - // A partially written generic type expression is not guaranteed to have the correct syntax tree. the expression could be parsed as less than/greater than expression or a comma expression - // or some other combination depending on what the user has typed so far. For the purposes of signature help we need to consider any location after "<" as a possible generic type reference. - // To do this, the method will back parse the expression starting at the position required. it will try to parse the current expression as a generic type expression, if it did succeed it - // will return the generic identifier that started the expression (e.g. "foo" in "foo 0) { + reportDiagnostics(commandLine.errors, compilerHost); + return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + } + if (commandLine.options.init) { + writeConfigFile(commandLine.options, commandLine.fileNames); + return ts.sys.exit(ts.ExitStatus.Success); + } + if (commandLine.options.version) { + printVersion(); + return ts.sys.exit(ts.ExitStatus.Success); + } + if (commandLine.options.help) { + printVersion(); + printHelp(); + return ts.sys.exit(ts.ExitStatus.Success); + } + if (commandLine.options.project) { + if (!isJSONSupported()) { + reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.The_current_host_does_not_support_the_0_option, "--project"), /* host */ undefined); + return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); } - var call = argumentInfo.invocation; - var candidates = []; - var resolvedSignature = typeChecker.getResolvedSignature(call, candidates); - cancellationToken.throwIfCancellationRequested(); - if (!candidates.length) { - // We didn't have any sig help items produced by the TS compiler. If this is a JS - // file, then see if we can figure out anything better. - if (ts.isSourceFileJavaScript(sourceFile)) { - return createJavaScriptSignatureHelpItems(argumentInfo, program); + if (commandLine.fileNames.length !== 0) { + reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line), /* host */ undefined); + return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + } + var fileOrDirectory = ts.normalizePath(commandLine.options.project); + if (!fileOrDirectory /* current directory "." */ || ts.sys.directoryExists(fileOrDirectory)) { + configFileName = ts.combinePaths(fileOrDirectory, "tsconfig.json"); + if (!ts.sys.fileExists(configFileName)) { + reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_find_a_tsconfig_json_file_at_the_specified_directory_Colon_0, commandLine.options.project), /* host */ undefined); + return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + } + } + else { + configFileName = fileOrDirectory; + if (!ts.sys.fileExists(configFileName)) { + reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.The_specified_path_does_not_exist_Colon_0, commandLine.options.project), /* host */ undefined); + return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); } - return undefined; } - return createSignatureHelpItems(candidates, resolvedSignature, argumentInfo, typeChecker); } - SignatureHelp.getSignatureHelpItems = getSignatureHelpItems; - function createJavaScriptSignatureHelpItems(argumentInfo, program) { - if (argumentInfo.invocation.kind !== 174 /* CallExpression */) { - return undefined; + else if (commandLine.fileNames.length === 0 && isJSONSupported()) { + var searchPath = ts.normalizePath(ts.sys.getCurrentDirectory()); + configFileName = ts.findConfigFile(searchPath, ts.sys.fileExists); + } + if (commandLine.fileNames.length === 0 && !configFileName) { + printVersion(); + printHelp(); + return ts.sys.exit(ts.ExitStatus.Success); + } + if (ts.isWatchSet(commandLine.options)) { + if (!ts.sys.watchFile) { + reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), /* host */ undefined); + return ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); } - // See if we can find some symbol with the call expression name that has call signatures. - var callExpression = argumentInfo.invocation; - var expression = callExpression.expression; - var name = expression.kind === 69 /* Identifier */ - ? expression - : expression.kind === 172 /* PropertyAccessExpression */ - ? expression.name - : undefined; - if (!name || !name.text) { - return undefined; + if (configFileName) { + configFileWatcher = ts.sys.watchFile(configFileName, configFileChanged); } - var typeChecker = program.getTypeChecker(); - for (var _i = 0, _a = program.getSourceFiles(); _i < _a.length; _i++) { - var sourceFile = _a[_i]; - var nameToDeclarations = sourceFile.getNamedDeclarations(); - var declarations = nameToDeclarations[name.text]; - if (declarations) { - for (var _b = 0, declarations_8 = declarations; _b < declarations_8.length; _b++) { - var declaration = declarations_8[_b]; - var symbol = declaration.symbol; - if (symbol) { - var type = typeChecker.getTypeOfSymbolAtLocation(symbol, declaration); - if (type) { - var callSignatures = type.getCallSignatures(); - if (callSignatures && callSignatures.length) { - return createSignatureHelpItems(callSignatures, callSignatures[0], argumentInfo, typeChecker); - } - } - } - } - } + if (ts.sys.watchDirectory && configFileName) { + var directory = ts.getDirectoryPath(configFileName); + directoryWatcher = ts.sys.watchDirectory( + // When the configFileName is just "tsconfig.json", the watched directory should be + // the current directory; if there is a given "project" parameter, then the configFileName + // is an absolute file name. + directory == "" ? "." : directory, watchedDirectoryChanged, /*recursive*/ true); } } - /** - * Returns relevant information for the argument list and the current argument if we are - * in the argument of an invocation; returns undefined otherwise. - */ - function getImmediatelyContainingArgumentInfo(node, position, sourceFile) { - if (node.parent.kind === 174 /* CallExpression */ || node.parent.kind === 175 /* NewExpression */) { - var callExpression = node.parent; - // There are 3 cases to handle: - // 1. The token introduces a list, and should begin a sig help session - // 2. The token is either not associated with a list, or ends a list, so the session should end - // 3. The token is buried inside a list, and should give sig help - // - // The following are examples of each: - // - // Case 1: - // foo<#T, U>(#a, b) -> The token introduces a list, and should begin a sig help session - // Case 2: - // fo#o#(a, b)# -> The token is either not associated with a list, or ends a list, so the session should end - // Case 3: - // foo(a#, #b#) -> The token is buried inside a list, and should give sig help - // Find out if 'node' is an argument, a type argument, or neither - if (node.kind === 25 /* LessThanToken */ || - node.kind === 17 /* OpenParenToken */) { - // Find the list that starts right *after* the < or ( token. - // If the user has just opened a list, consider this item 0. - var list = getChildListThatStartsWithOpenerToken(callExpression, node, sourceFile); - var isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos; - ts.Debug.assert(list !== undefined); - return { - kind: isTypeArgList ? 0 /* TypeArguments */ : 1 /* CallArguments */, - invocation: callExpression, - argumentsSpan: getApplicableSpanForArguments(list, sourceFile), - argumentIndex: 0, - argumentCount: getArgumentCount(list) - }; + performCompilation(); + function parseConfigFile() { + if (!cachedConfigFileText) { + try { + cachedConfigFileText = ts.sys.readFile(configFileName); } - // findListItemInfo can return undefined if we are not in parent's argument list - // or type argument list. This includes cases where the cursor is: - // - To the right of the closing paren, non-substitution template, or template tail. - // - Between the type arguments and the arguments (greater than token) - // - On the target of the call (parent.func) - // - On the 'new' keyword in a 'new' expression - var listItemInfo = ts.findListItemInfo(node); - if (listItemInfo) { - var list = listItemInfo.list; - var isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos; - var argumentIndex = getArgumentIndex(list, node); - var argumentCount = getArgumentCount(list); - ts.Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, "argumentCount < argumentIndex, " + argumentCount + " < " + argumentIndex); - return { - kind: isTypeArgList ? 0 /* TypeArguments */ : 1 /* CallArguments */, - invocation: callExpression, - argumentsSpan: getApplicableSpanForArguments(list, sourceFile), - argumentIndex: argumentIndex, - argumentCount: argumentCount - }; + catch (e) { + var error = ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_read_file_0_Colon_1, configFileName, e.message); + reportWatchDiagnostic(error); + ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + return; } - return undefined; } - else if (node.kind === 11 /* NoSubstitutionTemplateLiteral */ && node.parent.kind === 176 /* TaggedTemplateExpression */) { - // Check if we're actually inside the template; - // otherwise we'll fall out and return undefined. - if (ts.isInsideTemplateLiteral(node, position)) { - return getArgumentListInfoForTemplate(node.parent, /*argumentIndex*/ 0, sourceFile); - } + if (!cachedConfigFileText) { + var error = ts.createCompilerDiagnostic(ts.Diagnostics.File_0_not_found, configFileName); + reportDiagnostics([error], /* compilerHost */ undefined); + ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + return; } - else if (node.kind === 12 /* TemplateHead */ && node.parent.parent.kind === 176 /* TaggedTemplateExpression */) { - var templateExpression = node.parent; - var tagExpression = templateExpression.parent; - ts.Debug.assert(templateExpression.kind === 189 /* TemplateExpression */); - var argumentIndex = ts.isInsideTemplateLiteral(node, position) ? 0 : 1; - return getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile); + var result = ts.parseConfigFileTextToJson(configFileName, cachedConfigFileText); + var configObject = result.config; + if (!configObject) { + reportDiagnostics([result.error], /* compilerHost */ undefined); + ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + return; } - else if (node.parent.kind === 197 /* TemplateSpan */ && node.parent.parent.parent.kind === 176 /* TaggedTemplateExpression */) { - var templateSpan = node.parent; - var templateExpression = templateSpan.parent; - var tagExpression = templateExpression.parent; - ts.Debug.assert(templateExpression.kind === 189 /* TemplateExpression */); - // If we're just after a template tail, don't show signature help. - if (node.kind === 14 /* TemplateTail */ && !ts.isInsideTemplateLiteral(node, position)) { - return undefined; + var cwd = ts.sys.getCurrentDirectory(); + var configParseResult = ts.parseJsonConfigFileContent(configObject, ts.sys, ts.getNormalizedAbsolutePath(ts.getDirectoryPath(configFileName), cwd), commandLine.options, ts.getNormalizedAbsolutePath(configFileName, cwd)); + if (configParseResult.errors.length > 0) { + reportDiagnostics(configParseResult.errors, /* compilerHost */ undefined); + ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); + return; + } + if (ts.isWatchSet(configParseResult.options)) { + if (!ts.sys.watchFile) { + reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), /* host */ undefined); + ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); } - var spanIndex = templateExpression.templateSpans.indexOf(templateSpan); - var argumentIndex = getArgumentIndexForTemplatePiece(spanIndex, node, position); - return getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile); + if (!directoryWatcher && ts.sys.watchDirectory && configFileName) { + var directory = ts.getDirectoryPath(configFileName); + directoryWatcher = ts.sys.watchDirectory( + // When the configFileName is just "tsconfig.json", the watched directory should be + // the current directory; if there is a given "project" parameter, then the configFileName + // is an absolute file name. + directory == "" ? "." : directory, watchedDirectoryChanged, /*recursive*/ true); + } + ; } - return undefined; + return configParseResult; } - function getArgumentIndex(argumentsList, node) { - // The list we got back can include commas. In the presence of errors it may - // also just have nodes without commas. For example "Foo(a b c)" will have 3 - // args without commas. We want to find what index we're at. So we count - // forward until we hit ourselves, only incrementing the index if it isn't a - // comma. - // - // Note: the subtlety around trailing commas (in getArgumentCount) does not apply - // here. That's because we're only walking forward until we hit the node we're - // on. In that case, even if we're after the trailing comma, we'll still see - // that trailing comma in the list, and we'll have generated the appropriate - // arg index. - var argumentIndex = 0; - var listChildren = argumentsList.getChildren(); - for (var _i = 0, listChildren_1 = listChildren; _i < listChildren_1.length; _i++) { - var child = listChildren_1[_i]; - if (child === node) { - break; + // Invoked to perform initial compilation or re-compilation in watch mode + function performCompilation() { + if (!cachedProgram) { + if (configFileName) { + var configParseResult = parseConfigFile(); + rootFileNames = configParseResult.fileNames; + compilerOptions = configParseResult.options; } - if (child.kind !== 24 /* CommaToken */) { - argumentIndex++; + else { + rootFileNames = commandLine.fileNames; + compilerOptions = commandLine.options; } + compilerHost = ts.createCompilerHost(compilerOptions); + hostGetSourceFile = compilerHost.getSourceFile; + compilerHost.getSourceFile = getSourceFile; + hostFileExists = compilerHost.fileExists; + compilerHost.fileExists = cachedFileExists; } - return argumentIndex; - } - function getArgumentCount(argumentsList) { - // The argument count for a list is normally the number of non-comma children it has. - // For example, if you have "Foo(a,b)" then there will be three children of the arg - // list 'a' '' 'b'. So, in this case the arg count will be 2. However, there - // is a small subtlety. If you have "Foo(a,)", then the child list will just have - // 'a' ''. So, in the case where the last child is a comma, we increase the - // arg count by one to compensate. - // - // Note: this subtlety only applies to the last comma. If you had "Foo(a,," then - // we'll have: 'a' '' '' - // That will give us 2 non-commas. We then add one for the last comma, givin us an - // arg count of 3. - var listChildren = argumentsList.getChildren(); - var argumentCount = ts.countWhere(listChildren, function (arg) { return arg.kind !== 24 /* CommaToken */; }); - if (listChildren.length > 0 && ts.lastOrUndefined(listChildren).kind === 24 /* CommaToken */) { - argumentCount++; + if (compilerOptions.pretty) { + reportDiagnosticWorker = reportDiagnosticWithColorAndContext; } - return argumentCount; + // reset the cache of existing files + cachedExistingFiles = ts.createMap(); + var compileResult = compile(rootFileNames, compilerOptions, compilerHost); + if (!ts.isWatchSet(compilerOptions)) { + return ts.sys.exit(compileResult.exitStatus); + } + setCachedProgram(compileResult.program); + reportWatchDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.Compilation_complete_Watching_for_file_changes)); } - // spanIndex is either the index for a given template span. - // This does not give appropriate results for a NoSubstitutionTemplateLiteral - function getArgumentIndexForTemplatePiece(spanIndex, node, position) { - // Because the TemplateStringsArray is the first argument, we have to offset each substitution expression by 1. - // There are three cases we can encounter: - // 1. We are precisely in the template literal (argIndex = 0). - // 2. We are in or to the right of the substitution expression (argIndex = spanIndex + 1). - // 3. We are directly to the right of the template literal, but because we look for the token on the left, - // not enough to put us in the substitution expression; we should consider ourselves part of - // the *next* span's expression by offsetting the index (argIndex = (spanIndex + 1) + 1). - // - // Example: f `# abcd $#{# 1 + 1# }# efghi ${ #"#hello"# } # ` - // ^ ^ ^ ^ ^ ^ ^ ^ ^ - // Case: 1 1 3 2 1 3 2 2 1 - ts.Debug.assert(position >= node.getStart(), "Assumed 'position' could not occur before node."); - if (ts.isTemplateLiteralKind(node.kind)) { - if (ts.isInsideTemplateLiteral(node, position)) { - return 0; + function cachedFileExists(fileName) { + return fileName in cachedExistingFiles + ? cachedExistingFiles[fileName] + : cachedExistingFiles[fileName] = hostFileExists(fileName); + } + function getSourceFile(fileName, languageVersion, onError) { + // Return existing SourceFile object if one is available + if (cachedProgram) { + var sourceFile_1 = cachedProgram.getSourceFile(fileName); + // A modified source file has no watcher and should not be reused + if (sourceFile_1 && sourceFile_1.fileWatcher) { + return sourceFile_1; } - return spanIndex + 2; } - return spanIndex + 1; + // Use default host function + var sourceFile = hostGetSourceFile(fileName, languageVersion, onError); + if (sourceFile && ts.isWatchSet(compilerOptions) && ts.sys.watchFile) { + // Attach a file watcher + sourceFile.fileWatcher = ts.sys.watchFile(sourceFile.fileName, function (fileName, removed) { return sourceFileChanged(sourceFile, removed); }); + } + return sourceFile; } - function getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile) { - // argumentCount is either 1 or (numSpans + 1) to account for the template strings array argument. - var argumentCount = tagExpression.template.kind === 11 /* NoSubstitutionTemplateLiteral */ - ? 1 - : tagExpression.template.templateSpans.length + 1; - ts.Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, "argumentCount < argumentIndex, " + argumentCount + " < " + argumentIndex); - return { - kind: 2 /* TaggedTemplateArguments */, - invocation: tagExpression, - argumentsSpan: getApplicableSpanForTaggedTemplate(tagExpression, sourceFile), - argumentIndex: argumentIndex, - argumentCount: argumentCount - }; + // Change cached program to the given program + function setCachedProgram(program) { + if (cachedProgram) { + var newSourceFiles_1 = program ? program.getSourceFiles() : undefined; + ts.forEach(cachedProgram.getSourceFiles(), function (sourceFile) { + if (!(newSourceFiles_1 && ts.contains(newSourceFiles_1, sourceFile))) { + if (sourceFile.fileWatcher) { + sourceFile.fileWatcher.close(); + sourceFile.fileWatcher = undefined; + } + } + }); + } + cachedProgram = program; } - function getApplicableSpanForArguments(argumentsList, sourceFile) { - // We use full start and skip trivia on the end because we want to include trivia on - // both sides. For example, - // - // foo( /*comment */ a, b, c /*comment*/ ) - // | | - // - // The applicable span is from the first bar to the second bar (inclusive, - // but not including parentheses) - var applicableSpanStart = argumentsList.getFullStart(); - var applicableSpanEnd = ts.skipTrivia(sourceFile.text, argumentsList.getEnd(), /*stopAfterLineBreak*/ false); - return ts.createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart); + // If a source file changes, mark it as unwatched and start the recompilation timer + function sourceFileChanged(sourceFile, removed) { + sourceFile.fileWatcher.close(); + sourceFile.fileWatcher = undefined; + if (removed) { + ts.unorderedRemoveItem(rootFileNames, sourceFile.fileName); + } + startTimerForRecompilation(); } - function getApplicableSpanForTaggedTemplate(taggedTemplate, sourceFile) { - var template = taggedTemplate.template; - var applicableSpanStart = template.getStart(); - var applicableSpanEnd = template.getEnd(); - // We need to adjust the end position for the case where the template does not have a tail. - // Otherwise, we will not show signature help past the expression. - // For example, - // - // ` ${ 1 + 1 foo(10) - // | | - // - // This is because a Missing node has no width. However, what we actually want is to include trivia - // leading up to the next token in case the user is about to type in a TemplateMiddle or TemplateTail. - if (template.kind === 189 /* TemplateExpression */) { - var lastSpan = ts.lastOrUndefined(template.templateSpans); - if (lastSpan.literal.getFullWidth() === 0) { - applicableSpanEnd = ts.skipTrivia(sourceFile.text, applicableSpanEnd, /*stopAfterLineBreak*/ false); + // If the configuration file changes, forget cached program and start the recompilation timer + function configFileChanged() { + setCachedProgram(undefined); + cachedConfigFileText = undefined; + startTimerForRecompilation(); + } + function watchedDirectoryChanged(fileName) { + if (fileName && !ts.isSupportedSourceFileName(fileName, compilerOptions)) { + return; + } + startTimerForHandlingDirectoryChanges(); + } + function startTimerForHandlingDirectoryChanges() { + if (timerHandleForDirectoryChanges) { + clearTimeout(timerHandleForDirectoryChanges); + } + timerHandleForDirectoryChanges = setTimeout(directoryChangeHandler, 250); + } + function directoryChangeHandler() { + var parsedCommandLine = parseConfigFile(); + var newFileNames = ts.map(parsedCommandLine.fileNames, compilerHost.getCanonicalFileName); + var canonicalRootFileNames = ts.map(rootFileNames, compilerHost.getCanonicalFileName); + // We check if the project file list has changed. If so, we just throw away the old program and start fresh. + if (!ts.arrayIsEqualTo(newFileNames && newFileNames.sort(), canonicalRootFileNames && canonicalRootFileNames.sort())) { + setCachedProgram(undefined); + startTimerForRecompilation(); + } + } + // Upon detecting a file change, wait for 250ms and then perform a recompilation. This gives batch + // operations (such as saving all modified files in an editor) a chance to complete before we kick + // off a new compilation. + function startTimerForRecompilation() { + if (timerHandleForRecompilation) { + clearTimeout(timerHandleForRecompilation); + } + timerHandleForRecompilation = setTimeout(recompile, 250); + } + function recompile() { + timerHandleForRecompilation = undefined; + reportWatchDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.File_change_detected_Starting_incremental_compilation)); + performCompilation(); + } + } + ts.executeCommandLine = executeCommandLine; + function compile(fileNames, compilerOptions, compilerHost) { + var hasDiagnostics = compilerOptions.diagnostics || compilerOptions.extendedDiagnostics; + var statistics; + if (hasDiagnostics) { + ts.performance.enable(); + statistics = []; + } + var program = ts.createProgram(fileNames, compilerOptions, compilerHost); + var exitStatus = compileProgram(); + if (compilerOptions.listFiles) { + ts.forEach(program.getSourceFiles(), function (file) { + ts.sys.write(file.fileName + ts.sys.newLine); + }); + } + if (hasDiagnostics) { + var memoryUsed = ts.sys.getMemoryUsage ? ts.sys.getMemoryUsage() : -1; + reportCountStatistic("Files", program.getSourceFiles().length); + reportCountStatistic("Lines", countLines(program)); + reportCountStatistic("Nodes", program.getNodeCount()); + reportCountStatistic("Identifiers", program.getIdentifierCount()); + reportCountStatistic("Symbols", program.getSymbolCount()); + reportCountStatistic("Types", program.getTypeCount()); + if (memoryUsed >= 0) { + reportStatisticalValue("Memory used", Math.round(memoryUsed / 1000) + "K"); + } + var programTime = ts.performance.getDuration("Program"); + var bindTime = ts.performance.getDuration("Bind"); + var checkTime = ts.performance.getDuration("Check"); + var emitTime = ts.performance.getDuration("Emit"); + if (compilerOptions.extendedDiagnostics) { + ts.performance.forEachMeasure(function (name, duration) { return reportTimeStatistic(name + " time", duration); }); + } + else { + // Individual component times. + // Note: To match the behavior of previous versions of the compiler, the reported parse time includes + // I/O read time and processing time for triple-slash references and module imports, and the reported + // emit time includes I/O write time. We preserve this behavior so we can accurately compare times. + reportTimeStatistic("I/O read", ts.performance.getDuration("I/O Read")); + reportTimeStatistic("I/O write", ts.performance.getDuration("I/O Write")); + reportTimeStatistic("Parse time", programTime); + reportTimeStatistic("Bind time", bindTime); + reportTimeStatistic("Check time", checkTime); + reportTimeStatistic("Emit time", emitTime); + } + reportTimeStatistic("Total time", programTime + bindTime + checkTime + emitTime); + reportStatistics(); + ts.performance.disable(); + } + return { program: program, exitStatus: exitStatus }; + function compileProgram() { + var diagnostics; + // First get and report any syntactic errors. + diagnostics = program.getSyntacticDiagnostics(); + // If we didn't have any syntactic errors, then also try getting the global and + // semantic errors. + if (diagnostics.length === 0) { + diagnostics = program.getOptionsDiagnostics().concat(program.getGlobalDiagnostics()); + if (diagnostics.length === 0) { + diagnostics = program.getSemanticDiagnostics(); } } - return ts.createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart); + // Otherwise, emit and report any errors we ran into. + var emitOutput = program.emit(); + diagnostics = diagnostics.concat(emitOutput.diagnostics); + reportDiagnostics(ts.sortAndDeduplicateDiagnostics(diagnostics), compilerHost); + reportEmittedFiles(emitOutput.emittedFiles, compilerHost); + if (emitOutput.emitSkipped && diagnostics.length > 0) { + // If the emitter didn't emit anything, then pass that value along. + return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped; + } + else if (diagnostics.length > 0) { + // The emitter emitted something, inform the caller if that happened in the presence + // of diagnostics or not. + return ts.ExitStatus.DiagnosticsPresent_OutputsGenerated; + } + return ts.ExitStatus.Success; } - function getContainingArgumentInfo(node, position, sourceFile) { - for (var n = node; n.kind !== 256 /* SourceFile */; n = n.parent) { - if (ts.isFunctionBlock(n)) { - return undefined; - } - // If the node is not a subspan of its parent, this is a big problem. - // There have been crashes that might be caused by this violation. - if (n.pos < n.parent.pos || n.end > n.parent.end) { - ts.Debug.fail("Node of kind " + n.kind + " is not a subspan of its parent of kind " + n.parent.kind); + function reportStatistics() { + var nameSize = 0; + var valueSize = 0; + for (var _i = 0, statistics_1 = statistics; _i < statistics_1.length; _i++) { + var _a = statistics_1[_i], name_47 = _a.name, value = _a.value; + if (name_47.length > nameSize) { + nameSize = name_47.length; } - var argumentInfo = getImmediatelyContainingArgumentInfo(n, position, sourceFile); - if (argumentInfo) { - return argumentInfo; + if (value.length > valueSize) { + valueSize = value.length; } } - return undefined; + for (var _b = 0, statistics_2 = statistics; _b < statistics_2.length; _b++) { + var _c = statistics_2[_b], name_48 = _c.name, value = _c.value; + ts.sys.write(padRight(name_48 + ":", nameSize + 2) + padLeft(value.toString(), valueSize) + ts.sys.newLine); + } } - SignatureHelp.getContainingArgumentInfo = getContainingArgumentInfo; - function getChildListThatStartsWithOpenerToken(parent, openerToken, sourceFile) { - var children = parent.getChildren(sourceFile); - var indexOfOpenerToken = children.indexOf(openerToken); - ts.Debug.assert(indexOfOpenerToken >= 0 && children.length > indexOfOpenerToken + 1); - return children[indexOfOpenerToken + 1]; + function reportStatisticalValue(name, value) { + statistics.push({ name: name, value: value }); } - /** - * The selectedItemIndex could be negative for several reasons. - * 1. There are too many arguments for all of the overloads - * 2. None of the overloads were type compatible - * The solution here is to try to pick the best overload by picking - * either the first one that has an appropriate number of parameters, - * or the one with the most parameters. - */ - function selectBestInvalidOverloadIndex(candidates, argumentCount) { - var maxParamsSignatureIndex = -1; - var maxParams = -1; - for (var i = 0; i < candidates.length; i++) { - var candidate = candidates[i]; - if (candidate.hasRestParameter || candidate.parameters.length >= argumentCount) { - return i; - } - if (candidate.parameters.length > maxParams) { - maxParams = candidate.parameters.length; - maxParamsSignatureIndex = i; + function reportCountStatistic(name, count) { + reportStatisticalValue(name, "" + count); + } + function reportTimeStatistic(name, time) { + reportStatisticalValue(name, (time / 1000).toFixed(2) + "s"); + } + } + function printVersion() { + ts.sys.write(getDiagnosticText(ts.Diagnostics.Version_0, ts.version) + ts.sys.newLine); + } + function printHelp() { + var output = []; + // We want to align our "syntax" and "examples" commands to a certain margin. + var syntaxLength = getDiagnosticText(ts.Diagnostics.Syntax_Colon_0, "").length; + var examplesLength = getDiagnosticText(ts.Diagnostics.Examples_Colon_0, "").length; + var marginLength = Math.max(syntaxLength, examplesLength); + // Build up the syntactic skeleton. + var syntax = makePadding(marginLength - syntaxLength); + syntax += "tsc [" + getDiagnosticText(ts.Diagnostics.options) + "] [" + getDiagnosticText(ts.Diagnostics.file) + " ...]"; + output.push(getDiagnosticText(ts.Diagnostics.Syntax_Colon_0, syntax)); + output.push(ts.sys.newLine + ts.sys.newLine); + // Build up the list of examples. + var padding = makePadding(marginLength); + output.push(getDiagnosticText(ts.Diagnostics.Examples_Colon_0, makePadding(marginLength - examplesLength) + "tsc hello.ts") + ts.sys.newLine); + output.push(padding + "tsc --outFile file.js file.ts" + ts.sys.newLine); + output.push(padding + "tsc @args.txt" + ts.sys.newLine); + output.push(ts.sys.newLine); + output.push(getDiagnosticText(ts.Diagnostics.Options_Colon) + ts.sys.newLine); + // Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch") + var optsList = ts.filter(ts.optionDeclarations.slice(), function (v) { return !v.experimental; }); + optsList.sort(function (a, b) { return ts.compareValues(a.name.toLowerCase(), b.name.toLowerCase()); }); + // We want our descriptions to align at the same column in our output, + // so we keep track of the longest option usage string. + marginLength = 0; + var usageColumn = []; // Things like "-d, --declaration" go in here. + var descriptionColumn = []; + var optionsDescriptionMap = ts.createMap(); // Map between option.description and list of option.type if it is a kind + for (var i = 0; i < optsList.length; i++) { + var option = optsList[i]; + // If an option lacks a description, + // it is not officially supported. + if (!option.description) { + continue; + } + var usageText_1 = " "; + if (option.shortName) { + usageText_1 += "-" + option.shortName; + usageText_1 += getParamType(option); + usageText_1 += ", "; + } + usageText_1 += "--" + option.name; + usageText_1 += getParamType(option); + usageColumn.push(usageText_1); + var description = void 0; + if (option.name === "lib") { + description = getDiagnosticText(option.description); + var options = []; + var element = option.element; + var typeMap = element.type; + for (var key in typeMap) { + options.push("'" + key + "'"); } + optionsDescriptionMap[description] = options; } - return maxParamsSignatureIndex; + else { + description = getDiagnosticText(option.description); + } + descriptionColumn.push(description); + // Set the new margin for the description column if necessary. + marginLength = Math.max(usageText_1.length, marginLength); } - function createSignatureHelpItems(candidates, bestSignature, argumentListInfo, typeChecker) { - var applicableSpan = argumentListInfo.argumentsSpan; - var isTypeParameterList = argumentListInfo.kind === 0 /* TypeArguments */; - var invocation = argumentListInfo.invocation; - var callTarget = ts.getInvokedExpression(invocation); - var callTargetSymbol = typeChecker.getSymbolAtLocation(callTarget); - var callTargetDisplayParts = callTargetSymbol && ts.symbolToDisplayParts(typeChecker, callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined); - var items = ts.map(candidates, function (candidateSignature) { - var signatureHelpParameters; - var prefixDisplayParts = []; - var suffixDisplayParts = []; - if (callTargetDisplayParts) { - ts.addRange(prefixDisplayParts, callTargetDisplayParts); - } - if (isTypeParameterList) { - prefixDisplayParts.push(ts.punctuationPart(25 /* LessThanToken */)); - var typeParameters = candidateSignature.typeParameters; - signatureHelpParameters = typeParameters && typeParameters.length > 0 ? ts.map(typeParameters, createSignatureHelpParameterForTypeParameter) : emptyArray; - suffixDisplayParts.push(ts.punctuationPart(27 /* GreaterThanToken */)); - var parameterParts = ts.mapToDisplayParts(function (writer) { - return typeChecker.getSymbolDisplayBuilder().buildDisplayForParametersAndDelimiters(candidateSignature.thisParameter, candidateSignature.parameters, writer, invocation); - }); - ts.addRange(suffixDisplayParts, parameterParts); - } - else { - var typeParameterParts = ts.mapToDisplayParts(function (writer) { - return typeChecker.getSymbolDisplayBuilder().buildDisplayForTypeParametersAndDelimiters(candidateSignature.typeParameters, writer, invocation); - }); - ts.addRange(prefixDisplayParts, typeParameterParts); - prefixDisplayParts.push(ts.punctuationPart(17 /* OpenParenToken */)); - var parameters = candidateSignature.parameters; - signatureHelpParameters = parameters.length > 0 ? ts.map(parameters, createSignatureHelpParameterForParameter) : emptyArray; - suffixDisplayParts.push(ts.punctuationPart(18 /* CloseParenToken */)); + // Special case that can't fit in the loop. + var usageText = " @<" + getDiagnosticText(ts.Diagnostics.file) + ">"; + usageColumn.push(usageText); + descriptionColumn.push(getDiagnosticText(ts.Diagnostics.Insert_command_line_options_and_files_from_a_file)); + marginLength = Math.max(usageText.length, marginLength); + // Print out each row, aligning all the descriptions on the same column. + for (var i = 0; i < usageColumn.length; i++) { + var usage = usageColumn[i]; + var description = descriptionColumn[i]; + var kindsList = optionsDescriptionMap[description]; + output.push(usage + makePadding(marginLength - usage.length + 2) + description + ts.sys.newLine); + if (kindsList) { + output.push(makePadding(marginLength + 4)); + for (var _i = 0, kindsList_1 = kindsList; _i < kindsList_1.length; _i++) { + var kind = kindsList_1[_i]; + output.push(kind + " "); } - var returnTypeParts = ts.mapToDisplayParts(function (writer) { - return typeChecker.getSymbolDisplayBuilder().buildReturnTypeDisplay(candidateSignature, writer, invocation); - }); - ts.addRange(suffixDisplayParts, returnTypeParts); - return { - isVariadic: candidateSignature.hasRestParameter, - prefixDisplayParts: prefixDisplayParts, - suffixDisplayParts: suffixDisplayParts, - separatorDisplayParts: [ts.punctuationPart(24 /* CommaToken */), ts.spacePart()], - parameters: signatureHelpParameters, - documentation: candidateSignature.getDocumentationComment() - }; - }); - var argumentIndex = argumentListInfo.argumentIndex; - // argumentCount is the *apparent* number of arguments. - var argumentCount = argumentListInfo.argumentCount; - var selectedItemIndex = candidates.indexOf(bestSignature); - if (selectedItemIndex < 0) { - selectedItemIndex = selectBestInvalidOverloadIndex(candidates, argumentCount); - } - ts.Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, "argumentCount < argumentIndex, " + argumentCount + " < " + argumentIndex); - return { - items: items, - applicableSpan: applicableSpan, - selectedItemIndex: selectedItemIndex, - argumentIndex: argumentIndex, - argumentCount: argumentCount - }; - function createSignatureHelpParameterForParameter(parameter) { - var displayParts = ts.mapToDisplayParts(function (writer) { - return typeChecker.getSymbolDisplayBuilder().buildParameterDisplay(parameter, writer, invocation); - }); - return { - name: parameter.name, - documentation: parameter.getDocumentationComment(), - displayParts: displayParts, - isOptional: typeChecker.isOptionalParameter(parameter.valueDeclaration) - }; + output.push(ts.sys.newLine); } - function createSignatureHelpParameterForTypeParameter(typeParameter) { - var displayParts = ts.mapToDisplayParts(function (writer) { - return typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(typeParameter, writer, invocation); - }); - return { - name: typeParameter.symbol.name, - documentation: emptyArray, - displayParts: displayParts, - isOptional: false - }; + } + for (var _a = 0, output_1 = output; _a < output_1.length; _a++) { + var line = output_1[_a]; + ts.sys.write(line); + } + return; + function getParamType(option) { + if (option.paramType !== undefined) { + return " " + getDiagnosticText(option.paramType); } + return ""; } - })(SignatureHelp = ts.SignatureHelp || (ts.SignatureHelp = {})); + function makePadding(paddingLength) { + return Array(paddingLength + 1).join(" "); + } + } + function writeConfigFile(options, fileNames) { + var currentDirectory = ts.sys.getCurrentDirectory(); + var file = ts.normalizePath(ts.combinePaths(currentDirectory, "tsconfig.json")); + if (ts.sys.fileExists(file)) { + reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file), /* host */ undefined); + } + else { + ts.sys.writeFile(file, JSON.stringify(ts.generateTSConfig(options, fileNames), undefined, 4)); + reportDiagnostic(ts.createCompilerDiagnostic(ts.Diagnostics.Successfully_created_a_tsconfig_json_file), /* host */ undefined); + } + return; + } + var _a; })(ts || (ts = {})); +if (ts.sys.tryEnableSourceMapsForHost && /^development$/i.test(ts.sys.getEnvironmentVariable("NODE_ENV"))) { + ts.sys.tryEnableSourceMapsForHost(); +} +ts.executeCommandLine(ts.sys.args); var ts; (function (ts) { var ScriptSnapshot; @@ -50069,6 +61160,8 @@ var ts; ScriptElementKind.alias = "alias"; ScriptElementKind.constElement = "const"; ScriptElementKind.letElement = "let"; + ScriptElementKind.directory = "directory"; + ScriptElementKind.externalModuleName = "external module name"; })(ScriptElementKind = ts.ScriptElementKind || (ts.ScriptElementKind = {})); var ScriptElementKindModifier; (function (ScriptElementKindModifier) { @@ -50084,64 +61177,421 @@ var ts; var ClassificationTypeNames = (function () { function ClassificationTypeNames() { } - ClassificationTypeNames.comment = "comment"; - ClassificationTypeNames.identifier = "identifier"; - ClassificationTypeNames.keyword = "keyword"; - ClassificationTypeNames.numericLiteral = "number"; - ClassificationTypeNames.operator = "operator"; - ClassificationTypeNames.stringLiteral = "string"; - ClassificationTypeNames.whiteSpace = "whitespace"; - ClassificationTypeNames.text = "text"; - ClassificationTypeNames.punctuation = "punctuation"; - ClassificationTypeNames.className = "class name"; - ClassificationTypeNames.enumName = "enum name"; - ClassificationTypeNames.interfaceName = "interface name"; - ClassificationTypeNames.moduleName = "module name"; - ClassificationTypeNames.typeParameterName = "type parameter name"; - ClassificationTypeNames.typeAliasName = "type alias name"; - ClassificationTypeNames.parameterName = "parameter name"; - ClassificationTypeNames.docCommentTagName = "doc comment tag name"; - ClassificationTypeNames.jsxOpenTagName = "jsx open tag name"; - ClassificationTypeNames.jsxCloseTagName = "jsx close tag name"; - ClassificationTypeNames.jsxSelfClosingTagName = "jsx self closing tag name"; - ClassificationTypeNames.jsxAttribute = "jsx attribute"; - ClassificationTypeNames.jsxText = "jsx text"; - ClassificationTypeNames.jsxAttributeStringLiteralValue = "jsx attribute string literal value"; - return ClassificationTypeNames; - }()); - ts.ClassificationTypeNames = ClassificationTypeNames; - (function (ClassificationType) { - ClassificationType[ClassificationType["comment"] = 1] = "comment"; - ClassificationType[ClassificationType["identifier"] = 2] = "identifier"; - ClassificationType[ClassificationType["keyword"] = 3] = "keyword"; - ClassificationType[ClassificationType["numericLiteral"] = 4] = "numericLiteral"; - ClassificationType[ClassificationType["operator"] = 5] = "operator"; - ClassificationType[ClassificationType["stringLiteral"] = 6] = "stringLiteral"; - ClassificationType[ClassificationType["regularExpressionLiteral"] = 7] = "regularExpressionLiteral"; - ClassificationType[ClassificationType["whiteSpace"] = 8] = "whiteSpace"; - ClassificationType[ClassificationType["text"] = 9] = "text"; - ClassificationType[ClassificationType["punctuation"] = 10] = "punctuation"; - ClassificationType[ClassificationType["className"] = 11] = "className"; - ClassificationType[ClassificationType["enumName"] = 12] = "enumName"; - ClassificationType[ClassificationType["interfaceName"] = 13] = "interfaceName"; - ClassificationType[ClassificationType["moduleName"] = 14] = "moduleName"; - ClassificationType[ClassificationType["typeParameterName"] = 15] = "typeParameterName"; - ClassificationType[ClassificationType["typeAliasName"] = 16] = "typeAliasName"; - ClassificationType[ClassificationType["parameterName"] = 17] = "parameterName"; - ClassificationType[ClassificationType["docCommentTagName"] = 18] = "docCommentTagName"; - ClassificationType[ClassificationType["jsxOpenTagName"] = 19] = "jsxOpenTagName"; - ClassificationType[ClassificationType["jsxCloseTagName"] = 20] = "jsxCloseTagName"; - ClassificationType[ClassificationType["jsxSelfClosingTagName"] = 21] = "jsxSelfClosingTagName"; - ClassificationType[ClassificationType["jsxAttribute"] = 22] = "jsxAttribute"; - ClassificationType[ClassificationType["jsxText"] = 23] = "jsxText"; - ClassificationType[ClassificationType["jsxAttributeStringLiteralValue"] = 24] = "jsxAttributeStringLiteralValue"; - })(ts.ClassificationType || (ts.ClassificationType = {})); - var ClassificationType = ts.ClassificationType; -})(ts || (ts = {})); -// These utilities are common to multiple language service features. -/* @internal */ -var ts; -(function (ts) { + return ClassificationTypeNames; + }()); + ClassificationTypeNames.comment = "comment"; + ClassificationTypeNames.identifier = "identifier"; + ClassificationTypeNames.keyword = "keyword"; + ClassificationTypeNames.numericLiteral = "number"; + ClassificationTypeNames.operator = "operator"; + ClassificationTypeNames.stringLiteral = "string"; + ClassificationTypeNames.whiteSpace = "whitespace"; + ClassificationTypeNames.text = "text"; + ClassificationTypeNames.punctuation = "punctuation"; + ClassificationTypeNames.className = "class name"; + ClassificationTypeNames.enumName = "enum name"; + ClassificationTypeNames.interfaceName = "interface name"; + ClassificationTypeNames.moduleName = "module name"; + ClassificationTypeNames.typeParameterName = "type parameter name"; + ClassificationTypeNames.typeAliasName = "type alias name"; + ClassificationTypeNames.parameterName = "parameter name"; + ClassificationTypeNames.docCommentTagName = "doc comment tag name"; + ClassificationTypeNames.jsxOpenTagName = "jsx open tag name"; + ClassificationTypeNames.jsxCloseTagName = "jsx close tag name"; + ClassificationTypeNames.jsxSelfClosingTagName = "jsx self closing tag name"; + ClassificationTypeNames.jsxAttribute = "jsx attribute"; + ClassificationTypeNames.jsxText = "jsx text"; + ClassificationTypeNames.jsxAttributeStringLiteralValue = "jsx attribute string literal value"; + ts.ClassificationTypeNames = ClassificationTypeNames; + (function (ClassificationType) { + ClassificationType[ClassificationType["comment"] = 1] = "comment"; + ClassificationType[ClassificationType["identifier"] = 2] = "identifier"; + ClassificationType[ClassificationType["keyword"] = 3] = "keyword"; + ClassificationType[ClassificationType["numericLiteral"] = 4] = "numericLiteral"; + ClassificationType[ClassificationType["operator"] = 5] = "operator"; + ClassificationType[ClassificationType["stringLiteral"] = 6] = "stringLiteral"; + ClassificationType[ClassificationType["regularExpressionLiteral"] = 7] = "regularExpressionLiteral"; + ClassificationType[ClassificationType["whiteSpace"] = 8] = "whiteSpace"; + ClassificationType[ClassificationType["text"] = 9] = "text"; + ClassificationType[ClassificationType["punctuation"] = 10] = "punctuation"; + ClassificationType[ClassificationType["className"] = 11] = "className"; + ClassificationType[ClassificationType["enumName"] = 12] = "enumName"; + ClassificationType[ClassificationType["interfaceName"] = 13] = "interfaceName"; + ClassificationType[ClassificationType["moduleName"] = 14] = "moduleName"; + ClassificationType[ClassificationType["typeParameterName"] = 15] = "typeParameterName"; + ClassificationType[ClassificationType["typeAliasName"] = 16] = "typeAliasName"; + ClassificationType[ClassificationType["parameterName"] = 17] = "parameterName"; + ClassificationType[ClassificationType["docCommentTagName"] = 18] = "docCommentTagName"; + ClassificationType[ClassificationType["jsxOpenTagName"] = 19] = "jsxOpenTagName"; + ClassificationType[ClassificationType["jsxCloseTagName"] = 20] = "jsxCloseTagName"; + ClassificationType[ClassificationType["jsxSelfClosingTagName"] = 21] = "jsxSelfClosingTagName"; + ClassificationType[ClassificationType["jsxAttribute"] = 22] = "jsxAttribute"; + ClassificationType[ClassificationType["jsxText"] = 23] = "jsxText"; + ClassificationType[ClassificationType["jsxAttributeStringLiteralValue"] = 24] = "jsxAttributeStringLiteralValue"; + })(ts.ClassificationType || (ts.ClassificationType = {})); + var ClassificationType = ts.ClassificationType; +})(ts || (ts = {})); +// These utilities are common to multiple language service features. +/* @internal */ +var ts; +(function (ts) { + ts.scanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ true); + ts.emptyArray = []; + (function (SemanticMeaning) { + SemanticMeaning[SemanticMeaning["None"] = 0] = "None"; + SemanticMeaning[SemanticMeaning["Value"] = 1] = "Value"; + SemanticMeaning[SemanticMeaning["Type"] = 2] = "Type"; + SemanticMeaning[SemanticMeaning["Namespace"] = 4] = "Namespace"; + SemanticMeaning[SemanticMeaning["All"] = 7] = "All"; + })(ts.SemanticMeaning || (ts.SemanticMeaning = {})); + var SemanticMeaning = ts.SemanticMeaning; + function getMeaningFromDeclaration(node) { + switch (node.kind) { + case 142 /* Parameter */: + case 218 /* VariableDeclaration */: + case 169 /* BindingElement */: + case 145 /* PropertyDeclaration */: + case 144 /* PropertySignature */: + case 253 /* PropertyAssignment */: + case 254 /* ShorthandPropertyAssignment */: + case 255 /* EnumMember */: + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + case 148 /* Constructor */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + case 180 /* ArrowFunction */: + case 252 /* CatchClause */: + return 1 /* Value */; + case 141 /* TypeParameter */: + case 222 /* InterfaceDeclaration */: + case 223 /* TypeAliasDeclaration */: + case 159 /* TypeLiteral */: + return 2 /* Type */; + case 221 /* ClassDeclaration */: + case 224 /* EnumDeclaration */: + return 1 /* Value */ | 2 /* Type */; + case 225 /* ModuleDeclaration */: + if (ts.isAmbientModule(node)) { + return 4 /* Namespace */ | 1 /* Value */; + } + else if (ts.getModuleInstanceState(node) === 1 /* Instantiated */) { + return 4 /* Namespace */ | 1 /* Value */; + } + else { + return 4 /* Namespace */; + } + case 233 /* NamedImports */: + case 234 /* ImportSpecifier */: + case 229 /* ImportEqualsDeclaration */: + case 230 /* ImportDeclaration */: + case 235 /* ExportAssignment */: + case 236 /* ExportDeclaration */: + return 1 /* Value */ | 2 /* Type */ | 4 /* Namespace */; + // An external module can be a Value + case 256 /* SourceFile */: + return 4 /* Namespace */ | 1 /* Value */; + } + return 1 /* Value */ | 2 /* Type */ | 4 /* Namespace */; + } + ts.getMeaningFromDeclaration = getMeaningFromDeclaration; + function getMeaningFromLocation(node) { + if (node.parent.kind === 235 /* ExportAssignment */) { + return 1 /* Value */ | 2 /* Type */ | 4 /* Namespace */; + } + else if (isInRightSideOfImport(node)) { + return getMeaningFromRightHandSideOfImportEquals(node); + } + else if (ts.isDeclarationName(node)) { + return getMeaningFromDeclaration(node.parent); + } + else if (isTypeReference(node)) { + return 2 /* Type */; + } + else if (isNamespaceReference(node)) { + return 4 /* Namespace */; + } + else { + return 1 /* Value */; + } + } + ts.getMeaningFromLocation = getMeaningFromLocation; + function getMeaningFromRightHandSideOfImportEquals(node) { + ts.Debug.assert(node.kind === 69 /* Identifier */); + // import a = |b|; // Namespace + // import a = |b.c|; // Value, type, namespace + // import a = |b.c|.d; // Namespace + if (node.parent.kind === 139 /* QualifiedName */ && + node.parent.right === node && + node.parent.parent.kind === 229 /* ImportEqualsDeclaration */) { + return 1 /* Value */ | 2 /* Type */ | 4 /* Namespace */; + } + return 4 /* Namespace */; + } + function isInRightSideOfImport(node) { + while (node.parent.kind === 139 /* QualifiedName */) { + node = node.parent; + } + return ts.isInternalModuleImportEqualsDeclaration(node.parent) && node.parent.moduleReference === node; + } + function isNamespaceReference(node) { + return isQualifiedNameNamespaceReference(node) || isPropertyAccessNamespaceReference(node); + } + function isQualifiedNameNamespaceReference(node) { + var root = node; + var isLastClause = true; + if (root.parent.kind === 139 /* QualifiedName */) { + while (root.parent && root.parent.kind === 139 /* QualifiedName */) { + root = root.parent; + } + isLastClause = root.right === node; + } + return root.parent.kind === 155 /* TypeReference */ && !isLastClause; + } + function isPropertyAccessNamespaceReference(node) { + var root = node; + var isLastClause = true; + if (root.parent.kind === 172 /* PropertyAccessExpression */) { + while (root.parent && root.parent.kind === 172 /* PropertyAccessExpression */) { + root = root.parent; + } + isLastClause = root.name === node; + } + if (!isLastClause && root.parent.kind === 194 /* ExpressionWithTypeArguments */ && root.parent.parent.kind === 251 /* HeritageClause */) { + var decl = root.parent.parent.parent; + return (decl.kind === 221 /* ClassDeclaration */ && root.parent.parent.token === 106 /* ImplementsKeyword */) || + (decl.kind === 222 /* InterfaceDeclaration */ && root.parent.parent.token === 83 /* ExtendsKeyword */); + } + return false; + } + function isTypeReference(node) { + if (ts.isRightSideOfQualifiedNameOrPropertyAccess(node)) { + node = node.parent; + } + return node.parent.kind === 155 /* TypeReference */ || + (node.parent.kind === 194 /* ExpressionWithTypeArguments */ && !ts.isExpressionWithTypeArgumentsInClassExtendsClause(node.parent)) || + (node.kind === 97 /* ThisKeyword */ && !ts.isPartOfExpression(node)) || + node.kind === 165 /* ThisType */; + } + function isCallExpressionTarget(node) { + return isCallOrNewExpressionTarget(node, 174 /* CallExpression */); + } + ts.isCallExpressionTarget = isCallExpressionTarget; + function isNewExpressionTarget(node) { + return isCallOrNewExpressionTarget(node, 175 /* NewExpression */); + } + ts.isNewExpressionTarget = isNewExpressionTarget; + function isCallOrNewExpressionTarget(node, kind) { + var target = climbPastPropertyAccess(node); + return target && target.parent && target.parent.kind === kind && target.parent.expression === target; + } + function climbPastPropertyAccess(node) { + return isRightSideOfPropertyAccess(node) ? node.parent : node; + } + ts.climbPastPropertyAccess = climbPastPropertyAccess; + function getTargetLabel(referenceNode, labelName) { + while (referenceNode) { + if (referenceNode.kind === 214 /* LabeledStatement */ && referenceNode.label.text === labelName) { + return referenceNode.label; + } + referenceNode = referenceNode.parent; + } + return undefined; + } + ts.getTargetLabel = getTargetLabel; + function isJumpStatementTarget(node) { + return node.kind === 69 /* Identifier */ && + (node.parent.kind === 210 /* BreakStatement */ || node.parent.kind === 209 /* ContinueStatement */) && + node.parent.label === node; + } + ts.isJumpStatementTarget = isJumpStatementTarget; + function isLabelOfLabeledStatement(node) { + return node.kind === 69 /* Identifier */ && + node.parent.kind === 214 /* LabeledStatement */ && + node.parent.label === node; + } + function isLabelName(node) { + return isLabelOfLabeledStatement(node) || isJumpStatementTarget(node); + } + ts.isLabelName = isLabelName; + function isRightSideOfQualifiedName(node) { + return node.parent.kind === 139 /* QualifiedName */ && node.parent.right === node; + } + ts.isRightSideOfQualifiedName = isRightSideOfQualifiedName; + function isRightSideOfPropertyAccess(node) { + return node && node.parent && node.parent.kind === 172 /* PropertyAccessExpression */ && node.parent.name === node; + } + ts.isRightSideOfPropertyAccess = isRightSideOfPropertyAccess; + function isNameOfModuleDeclaration(node) { + return node.parent.kind === 225 /* ModuleDeclaration */ && node.parent.name === node; + } + ts.isNameOfModuleDeclaration = isNameOfModuleDeclaration; + function isNameOfFunctionDeclaration(node) { + return node.kind === 69 /* Identifier */ && + ts.isFunctionLike(node.parent) && node.parent.name === node; + } + ts.isNameOfFunctionDeclaration = isNameOfFunctionDeclaration; + function isLiteralNameOfPropertyDeclarationOrIndexAccess(node) { + if (node.kind === 9 /* StringLiteral */ || node.kind === 8 /* NumericLiteral */) { + switch (node.parent.kind) { + case 145 /* PropertyDeclaration */: + case 144 /* PropertySignature */: + case 253 /* PropertyAssignment */: + case 255 /* EnumMember */: + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 225 /* ModuleDeclaration */: + return node.parent.name === node; + case 173 /* ElementAccessExpression */: + return node.parent.argumentExpression === node; + case 140 /* ComputedPropertyName */: + return true; + } + } + return false; + } + ts.isLiteralNameOfPropertyDeclarationOrIndexAccess = isLiteralNameOfPropertyDeclarationOrIndexAccess; + function isExpressionOfExternalModuleImportEqualsDeclaration(node) { + return ts.isExternalModuleImportEqualsDeclaration(node.parent.parent) && + ts.getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node; + } + ts.isExpressionOfExternalModuleImportEqualsDeclaration = isExpressionOfExternalModuleImportEqualsDeclaration; + /** Returns true if the position is within a comment */ + function isInsideComment(sourceFile, token, position) { + // The position has to be: 1. in the leading trivia (before token.getStart()), and 2. within a comment + return position <= token.getStart(sourceFile) && + (isInsideCommentRange(ts.getTrailingCommentRanges(sourceFile.text, token.getFullStart())) || + isInsideCommentRange(ts.getLeadingCommentRanges(sourceFile.text, token.getFullStart()))); + function isInsideCommentRange(comments) { + return ts.forEach(comments, function (comment) { + // either we are 1. completely inside the comment, or 2. at the end of the comment + if (comment.pos < position && position < comment.end) { + return true; + } + else if (position === comment.end) { + var text = sourceFile.text; + var width = comment.end - comment.pos; + // is single line comment or just /* + if (width <= 2 || text.charCodeAt(comment.pos + 1) === 47 /* slash */) { + return true; + } + else { + // is unterminated multi-line comment + return !(text.charCodeAt(comment.end - 1) === 47 /* slash */ && + text.charCodeAt(comment.end - 2) === 42 /* asterisk */); + } + } + return false; + }); + } + } + ts.isInsideComment = isInsideComment; + function getContainerNode(node) { + while (true) { + node = node.parent; + if (!node) { + return undefined; + } + switch (node.kind) { + case 256 /* SourceFile */: + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 221 /* ClassDeclaration */: + case 222 /* InterfaceDeclaration */: + case 224 /* EnumDeclaration */: + case 225 /* ModuleDeclaration */: + return node; + } + } + } + ts.getContainerNode = getContainerNode; + function getNodeKind(node) { + switch (node.kind) { + case 256 /* SourceFile */: + return ts.isExternalModule(node) ? ts.ScriptElementKind.moduleElement : ts.ScriptElementKind.scriptElement; + case 225 /* ModuleDeclaration */: + return ts.ScriptElementKind.moduleElement; + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + return ts.ScriptElementKind.classElement; + case 222 /* InterfaceDeclaration */: return ts.ScriptElementKind.interfaceElement; + case 223 /* TypeAliasDeclaration */: return ts.ScriptElementKind.typeElement; + case 224 /* EnumDeclaration */: return ts.ScriptElementKind.enumElement; + case 218 /* VariableDeclaration */: + return getKindOfVariableDeclaration(node); + case 169 /* BindingElement */: + return getKindOfVariableDeclaration(ts.getRootDeclaration(node)); + case 180 /* ArrowFunction */: + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + return ts.ScriptElementKind.functionElement; + case 149 /* GetAccessor */: return ts.ScriptElementKind.memberGetAccessorElement; + case 150 /* SetAccessor */: return ts.ScriptElementKind.memberSetAccessorElement; + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + return ts.ScriptElementKind.memberFunctionElement; + case 145 /* PropertyDeclaration */: + case 144 /* PropertySignature */: + return ts.ScriptElementKind.memberVariableElement; + case 153 /* IndexSignature */: return ts.ScriptElementKind.indexSignatureElement; + case 152 /* ConstructSignature */: return ts.ScriptElementKind.constructSignatureElement; + case 151 /* CallSignature */: return ts.ScriptElementKind.callSignatureElement; + case 148 /* Constructor */: return ts.ScriptElementKind.constructorImplementationElement; + case 141 /* TypeParameter */: return ts.ScriptElementKind.typeParameterElement; + case 255 /* EnumMember */: return ts.ScriptElementKind.enumMemberElement; + case 142 /* Parameter */: return ts.hasModifier(node, 92 /* ParameterPropertyModifier */) ? ts.ScriptElementKind.memberVariableElement : ts.ScriptElementKind.parameterElement; + case 229 /* ImportEqualsDeclaration */: + case 234 /* ImportSpecifier */: + case 231 /* ImportClause */: + case 238 /* ExportSpecifier */: + case 232 /* NamespaceImport */: + return ts.ScriptElementKind.alias; + case 279 /* JSDocTypedefTag */: + return ts.ScriptElementKind.typeElement; + default: + return ts.ScriptElementKind.unknown; + } + function getKindOfVariableDeclaration(v) { + return ts.isConst(v) + ? ts.ScriptElementKind.constElement + : ts.isLet(v) + ? ts.ScriptElementKind.letElement + : ts.ScriptElementKind.variableElement; + } + } + ts.getNodeKind = getNodeKind; + function getStringLiteralTypeForNode(node, typeChecker) { + var searchNode = node.parent.kind === 166 /* LiteralType */ ? node.parent : node; + var type = typeChecker.getTypeAtLocation(searchNode); + if (type && type.flags & 32 /* StringLiteral */) { + return type; + } + return undefined; + } + ts.getStringLiteralTypeForNode = getStringLiteralTypeForNode; + function isThis(node) { + switch (node.kind) { + case 97 /* ThisKeyword */: + // case SyntaxKind.ThisType: TODO: GH#9267 + return true; + case 69 /* Identifier */: + // 'this' as a parameter + return node.originalKeywordKind === 97 /* ThisKeyword */ && node.parent.kind === 142 /* Parameter */; + default: + return false; + } + } + ts.isThis = isThis; + // Matches the beginning of a triple slash directive + var tripleSlashDirectivePrefixRegex = /^\/\/\/\s*= node.end) { + return c; + } + }); + // Either we didn't find an appropriate list, or the list must contain us. + ts.Debug.assert(!syntaxList || ts.contains(syntaxList.getChildren(), node)); + return syntaxList; + } + ts.findContainingList = findContainingList; + /* Gets the token whose text has range [start, end) and + * position >= start and (position < end or (position === end && token is keyword or identifier)) + */ + function getTouchingWord(sourceFile, position, includeJsDocComment) { + if (includeJsDocComment === void 0) { includeJsDocComment = false; } + return getTouchingToken(sourceFile, position, function (n) { return isWord(n.kind); }, includeJsDocComment); + } + ts.getTouchingWord = getTouchingWord; + /* Gets the token whose text has range [start, end) and position >= start + * and (position < end or (position === end && token is keyword or identifier or numeric/string literal)) + */ + function getTouchingPropertyName(sourceFile, position, includeJsDocComment) { + if (includeJsDocComment === void 0) { includeJsDocComment = false; } + return getTouchingToken(sourceFile, position, function (n) { return isPropertyName(n.kind); }, includeJsDocComment); + } + ts.getTouchingPropertyName = getTouchingPropertyName; + /** Returns the token if position is in [start, end) or if position === end and includeItemAtEndPosition(token) === true */ + function getTouchingToken(sourceFile, position, includeItemAtEndPosition, includeJsDocComment) { + if (includeJsDocComment === void 0) { includeJsDocComment = false; } + return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ false, includeItemAtEndPosition, includeJsDocComment); + } + ts.getTouchingToken = getTouchingToken; + /** Returns a token if position is in [start-of-leading-trivia, end) */ + function getTokenAtPosition(sourceFile, position, includeJsDocComment) { + if (includeJsDocComment === void 0) { includeJsDocComment = false; } + return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ true, /*includeItemAtEndPosition*/ undefined, includeJsDocComment); + } + ts.getTokenAtPosition = getTokenAtPosition; + /** Get the token whose text contains the position */ + function getTokenAtPositionWorker(sourceFile, position, allowPositionInLeadingTrivia, includeItemAtEndPosition, includeJsDocComment) { + if (includeJsDocComment === void 0) { includeJsDocComment = false; } + var current = sourceFile; + outer: while (true) { + if (isToken(current)) { + // exit early + return current; + } + if (includeJsDocComment) { + var jsDocChildren = ts.filter(current.getChildren(), ts.isJSDocNode); + for (var _i = 0, jsDocChildren_1 = jsDocChildren; _i < jsDocChildren_1.length; _i++) { + var jsDocChild = jsDocChildren_1[_i]; + var start = allowPositionInLeadingTrivia ? jsDocChild.getFullStart() : jsDocChild.getStart(sourceFile, includeJsDocComment); + if (start <= position) { + var end = jsDocChild.getEnd(); + if (position < end || (position === end && jsDocChild.kind === 1 /* EndOfFileToken */)) { + current = jsDocChild; + continue outer; + } + else if (includeItemAtEndPosition && end === position) { + var previousToken = findPrecedingToken(position, sourceFile, jsDocChild); + if (previousToken && includeItemAtEndPosition(previousToken)) { + return previousToken; + } + } + } + } + } + // find the child that contains 'position' + for (var i = 0, n = current.getChildCount(sourceFile); i < n; i++) { + var child = current.getChildAt(i); + // all jsDocComment nodes were already visited + if (ts.isJSDocNode(child)) { + continue; + } + var start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile, includeJsDocComment); + if (start <= position) { + var end = child.getEnd(); + if (position < end || (position === end && child.kind === 1 /* EndOfFileToken */)) { + current = child; + continue outer; + } + else if (includeItemAtEndPosition && end === position) { + var previousToken = findPrecedingToken(position, sourceFile, child); + if (previousToken && includeItemAtEndPosition(previousToken)) { + return previousToken; + } + } + } + } + return current; + } + } + /** + * The token on the left of the position is the token that strictly includes the position + * or sits to the left of the cursor if it is on a boundary. For example + * + * fo|o -> will return foo + * foo |bar -> will return foo + * + */ + function findTokenOnLeftOfPosition(file, position) { + // Ideally, getTokenAtPosition should return a token. However, it is currently + // broken, so we do a check to make sure the result was indeed a token. + var tokenAtPosition = getTokenAtPosition(file, position); + if (isToken(tokenAtPosition) && position > tokenAtPosition.getStart(file) && position < tokenAtPosition.getEnd()) { + return tokenAtPosition; + } + return findPrecedingToken(position, file); + } + ts.findTokenOnLeftOfPosition = findTokenOnLeftOfPosition; + function findNextToken(previousToken, parent) { + return find(parent); + function find(n) { + if (isToken(n) && n.pos === previousToken.end) { + // this is token that starts at the end of previous token - return it + return n; + } + var children = n.getChildren(); + for (var _i = 0, children_2 = children; _i < children_2.length; _i++) { + var child = children_2[_i]; + var shouldDiveInChildNode = + // previous token is enclosed somewhere in the child + (child.pos <= previousToken.pos && child.end > previousToken.end) || + // previous token ends exactly at the beginning of child + (child.pos === previousToken.end); + if (shouldDiveInChildNode && nodeHasTokens(child)) { + return find(child); + } + } + return undefined; + } + } + ts.findNextToken = findNextToken; + function findPrecedingToken(position, sourceFile, startNode) { + return find(startNode || sourceFile); + function findRightmostToken(n) { + if (isToken(n) || n.kind === 244 /* JsxText */) { + return n; + } + var children = n.getChildren(); + var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length); + return candidate && findRightmostToken(candidate); + } + function find(n) { + if (isToken(n) || n.kind === 244 /* JsxText */) { + return n; + } + var children = n.getChildren(); + for (var i = 0, len = children.length; i < len; i++) { + var child = children[i]; + // condition 'position < child.end' checks if child node end after the position + // in the example below this condition will be false for 'aaaa' and 'bbbb' and true for 'ccc' + // aaaa___bbbb___$__ccc + // after we found child node with end after the position we check if start of the node is after the position. + // if yes - then position is in the trivia and we need to look into the previous child to find the token in question. + // if no - position is in the node itself so we should recurse in it. + // NOTE: JsxText is a weird kind of node that can contain only whitespaces (since they are not counted as trivia). + // if this is the case - then we should assume that token in question is located in previous child. + if (position < child.end && (nodeHasTokens(child) || child.kind === 244 /* JsxText */)) { + var start = child.getStart(sourceFile); + var lookInPreviousChild = (start >= position) || + (child.kind === 244 /* JsxText */ && start === child.end); // whitespace only JsxText + if (lookInPreviousChild) { + // actual start of the node is past the position - previous token should be at the end of previous child + var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ i); + return candidate && findRightmostToken(candidate); + } + else { + // candidate should be in this node + return find(child); + } + } + } + ts.Debug.assert(startNode !== undefined || n.kind === 256 /* SourceFile */); + // Here we know that none of child token nodes embrace the position, + // the only known case is when position is at the end of the file. + // Try to find the rightmost token in the file without filtering. + // Namely we are skipping the check: 'position < node.end' + if (children.length) { + var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length); + return candidate && findRightmostToken(candidate); + } + } + /// finds last node that is considered as candidate for search (isCandidate(node) === true) starting from 'exclusiveStartPosition' + function findRightmostChildNodeWithTokens(children, exclusiveStartPosition) { + for (var i = exclusiveStartPosition - 1; i >= 0; i--) { + if (nodeHasTokens(children[i])) { + return children[i]; + } + } + } + } + ts.findPrecedingToken = findPrecedingToken; + function isInString(sourceFile, position) { + var previousToken = findPrecedingToken(position, sourceFile); + if (previousToken && previousToken.kind === 9 /* StringLiteral */) { + var start = previousToken.getStart(); + var end = previousToken.getEnd(); + // To be "in" one of these literals, the position has to be: + // 1. entirely within the token text. + // 2. at the end position of an unterminated token. + // 3. at the end of a regular expression (due to trailing flags like '/foo/g'). + if (start < position && position < end) { + return true; + } + if (position === end) { + return !!previousToken.isUnterminated; + } + } + return false; + } + ts.isInString = isInString; + function isInComment(sourceFile, position) { + return isInCommentHelper(sourceFile, position, /*predicate*/ undefined); + } + ts.isInComment = isInComment; + /** + * returns true if the position is in between the open and close elements of an JSX expression. + */ + function isInsideJsxElementOrAttribute(sourceFile, position) { + var token = getTokenAtPosition(sourceFile, position); + if (!token) { + return false; + } + if (token.kind === 244 /* JsxText */) { + return true; + } + //
Hello |
+ if (token.kind === 25 /* LessThanToken */ && token.parent.kind === 244 /* JsxText */) { + return true; + } + //
{ |
or
+ if (token.kind === 25 /* LessThanToken */ && token.parent.kind === 248 /* JsxExpression */) { + return true; + } + //
{ + // | + // } < /div> + if (token && token.kind === 16 /* CloseBraceToken */ && token.parent.kind === 248 /* JsxExpression */) { + return true; + } + //
|
+ if (token.kind === 25 /* LessThanToken */ && token.parent.kind === 245 /* JsxClosingElement */) { + return true; + } + return false; + } + ts.isInsideJsxElementOrAttribute = isInsideJsxElementOrAttribute; + function isInTemplateString(sourceFile, position) { + var token = getTokenAtPosition(sourceFile, position); + return ts.isTemplateLiteralKind(token.kind) && position > token.getStart(sourceFile); + } + ts.isInTemplateString = isInTemplateString; + /** + * Returns true if the cursor at position in sourceFile is within a comment that additionally + * satisfies predicate, and false otherwise. + */ + function isInCommentHelper(sourceFile, position, predicate) { + var token = getTokenAtPosition(sourceFile, position); + if (token && position <= token.getStart(sourceFile)) { + var commentRanges = ts.getLeadingCommentRanges(sourceFile.text, token.pos); + // The end marker of a single-line comment does not include the newline character. + // In the following case, we are inside a comment (^ denotes the cursor position): + // + // // asdf ^\n + // + // But for multi-line comments, we don't want to be inside the comment in the following case: + // + // /* asdf */^ + // + // Internally, we represent the end of the comment at the newline and closing '/', respectively. + return predicate ? + ts.forEach(commentRanges, function (c) { return c.pos < position && + (c.kind == 2 /* SingleLineCommentTrivia */ ? position <= c.end : position < c.end) && + predicate(c); }) : + ts.forEach(commentRanges, function (c) { return c.pos < position && + (c.kind == 2 /* SingleLineCommentTrivia */ ? position <= c.end : position < c.end); }); + } + return false; + } + ts.isInCommentHelper = isInCommentHelper; + function hasDocComment(sourceFile, position) { + var token = getTokenAtPosition(sourceFile, position); + // First, we have to see if this position actually landed in a comment. + var commentRanges = ts.getLeadingCommentRanges(sourceFile.text, token.pos); + return ts.forEach(commentRanges, jsDocPrefix); + function jsDocPrefix(c) { + var text = sourceFile.text; + return text.length >= c.pos + 3 && text[c.pos] === "/" && text[c.pos + 1] === "*" && text[c.pos + 2] === "*"; + } + } + ts.hasDocComment = hasDocComment; + /** + * Get the corresponding JSDocTag node if the position is in a jsDoc comment + */ + function getJsDocTagAtPosition(sourceFile, position) { + var node = ts.getTokenAtPosition(sourceFile, position); + if (isToken(node)) { + switch (node.kind) { + case 102 /* VarKeyword */: + case 108 /* LetKeyword */: + case 74 /* ConstKeyword */: + // if the current token is var, let or const, skip the VariableDeclarationList + node = node.parent === undefined ? undefined : node.parent.parent; + break; + default: + node = node.parent; + break; + } + } + if (node) { + if (node.jsDocComments) { + for (var _i = 0, _a = node.jsDocComments; _i < _a.length; _i++) { + var jsDocComment = _a[_i]; + if (jsDocComment.tags) { + for (var _b = 0, _c = jsDocComment.tags; _b < _c.length; _b++) { + var tag = _c[_b]; + if (tag.pos <= position && position <= tag.end) { + return tag; + } + } + } + } + } + } + return undefined; + } + ts.getJsDocTagAtPosition = getJsDocTagAtPosition; + function nodeHasTokens(n) { + // If we have a token or node that has a non-zero width, it must have tokens. + // Note, that getWidth() does not take trivia into account. + return n.getWidth() !== 0; + } + function getNodeModifiers(node) { + var flags = ts.getCombinedModifierFlags(node); + var result = []; + if (flags & 8 /* Private */) + result.push(ts.ScriptElementKindModifier.privateMemberModifier); + if (flags & 16 /* Protected */) + result.push(ts.ScriptElementKindModifier.protectedMemberModifier); + if (flags & 4 /* Public */) + result.push(ts.ScriptElementKindModifier.publicMemberModifier); + if (flags & 32 /* Static */) + result.push(ts.ScriptElementKindModifier.staticModifier); + if (flags & 128 /* Abstract */) + result.push(ts.ScriptElementKindModifier.abstractModifier); + if (flags & 1 /* Export */) + result.push(ts.ScriptElementKindModifier.exportedModifier); + if (ts.isInAmbientContext(node)) + result.push(ts.ScriptElementKindModifier.ambientModifier); + return result.length > 0 ? result.join(",") : ts.ScriptElementKindModifier.none; + } + ts.getNodeModifiers = getNodeModifiers; + function getTypeArgumentOrTypeParameterList(node) { + if (node.kind === 155 /* TypeReference */ || node.kind === 174 /* CallExpression */) { + return node.typeArguments; + } + if (ts.isFunctionLike(node) || node.kind === 221 /* ClassDeclaration */ || node.kind === 222 /* InterfaceDeclaration */) { + return node.typeParameters; + } + return undefined; + } + ts.getTypeArgumentOrTypeParameterList = getTypeArgumentOrTypeParameterList; + function isToken(n) { + return n.kind >= 0 /* FirstToken */ && n.kind <= 138 /* LastToken */; + } + ts.isToken = isToken; + function isWord(kind) { + return kind === 69 /* Identifier */ || ts.isKeyword(kind); + } + ts.isWord = isWord; + function isPropertyName(kind) { + return kind === 9 /* StringLiteral */ || kind === 8 /* NumericLiteral */ || isWord(kind); + } + function isComment(kind) { + return kind === 2 /* SingleLineCommentTrivia */ || kind === 3 /* MultiLineCommentTrivia */; + } + ts.isComment = isComment; + function isStringOrRegularExpressionOrTemplateLiteral(kind) { + if (kind === 9 /* StringLiteral */ + || kind === 10 /* RegularExpressionLiteral */ + || ts.isTemplateLiteralKind(kind)) { + return true; + } + return false; + } + ts.isStringOrRegularExpressionOrTemplateLiteral = isStringOrRegularExpressionOrTemplateLiteral; + function isPunctuation(kind) { + return 15 /* FirstPunctuation */ <= kind && kind <= 68 /* LastPunctuation */; + } + ts.isPunctuation = isPunctuation; + function isInsideTemplateLiteral(node, position) { + return ts.isTemplateLiteralKind(node.kind) + && (node.getStart() < position && position < node.getEnd()) || (!!node.isUnterminated && position === node.getEnd()); + } + ts.isInsideTemplateLiteral = isInsideTemplateLiteral; + function isAccessibilityModifier(kind) { + switch (kind) { + case 112 /* PublicKeyword */: + case 110 /* PrivateKeyword */: + case 111 /* ProtectedKeyword */: + return true; + } + return false; + } + ts.isAccessibilityModifier = isAccessibilityModifier; + function compareDataObjects(dst, src) { + for (var e in dst) { + if (typeof dst[e] === "object") { + if (!compareDataObjects(dst[e], src[e])) { + return false; + } + } + else if (typeof dst[e] !== "function") { + if (dst[e] !== src[e]) { + return false; } - return isCompletedNode(n.statement, sourceFile); - case 158 /* TypeQuery */: - return isCompletedNode(n.exprName, sourceFile); - case 182 /* TypeOfExpression */: - case 181 /* DeleteExpression */: - case 183 /* VoidExpression */: - case 190 /* YieldExpression */: - case 191 /* SpreadElementExpression */: - var unaryWordExpression = n; - return isCompletedNode(unaryWordExpression.expression, sourceFile); - case 176 /* TaggedTemplateExpression */: - return isCompletedNode(n.template, sourceFile); - case 189 /* TemplateExpression */: - var lastSpan = ts.lastOrUndefined(n.templateSpans); - return isCompletedNode(lastSpan, sourceFile); - case 197 /* TemplateSpan */: - return ts.nodeIsPresent(n.literal); - case 236 /* ExportDeclaration */: - case 230 /* ImportDeclaration */: - return ts.nodeIsPresent(n.moduleSpecifier); - case 185 /* PrefixUnaryExpression */: - return isCompletedNode(n.operand, sourceFile); - case 187 /* BinaryExpression */: - return isCompletedNode(n.right, sourceFile); - case 188 /* ConditionalExpression */: - return isCompletedNode(n.whenFalse, sourceFile); - default: - return true; + } } + return true; } - ts.isCompletedNode = isCompletedNode; - /* - * Checks if node ends with 'expectedLastToken'. - * If child at position 'length - 1' is 'SemicolonToken' it is skipped and 'expectedLastToken' is compared with child at position 'length - 2'. - */ - function nodeEndsWith(n, expectedLastToken, sourceFile) { - var children = n.getChildren(sourceFile); - if (children.length) { - var last = ts.lastOrUndefined(children); - if (last.kind === expectedLastToken) { + ts.compareDataObjects = compareDataObjects; + function isArrayLiteralOrObjectLiteralDestructuringPattern(node) { + if (node.kind === 170 /* ArrayLiteralExpression */ || + node.kind === 171 /* ObjectLiteralExpression */) { + // [a,b,c] from: + // [a, b, c] = someExpression; + if (node.parent.kind === 187 /* BinaryExpression */ && + node.parent.left === node && + node.parent.operatorToken.kind === 56 /* EqualsToken */) { return true; } - else if (last.kind === 23 /* SemicolonToken */ && children.length !== 1) { - return children[children.length - 2].kind === expectedLastToken; + // [a, b, c] from: + // for([a, b, c] of expression) + if (node.parent.kind === 208 /* ForOfStatement */ && + node.parent.initializer === node) { + return true; + } + // [a, b, c] of + // [x, [a, b, c] ] = someExpression + // or + // {x, a: {a, b, c} } = someExpression + if (isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent.kind === 253 /* PropertyAssignment */ ? node.parent.parent : node.parent)) { + return true; } } return false; } - function findListItemInfo(node) { - var list = findContainingList(node); - // It is possible at this point for syntaxList to be undefined, either if - // node.parent had no list child, or if none of its list children contained - // the span of node. If this happens, return undefined. The caller should - // handle this case. - if (!list) { - return undefined; + ts.isArrayLiteralOrObjectLiteralDestructuringPattern = isArrayLiteralOrObjectLiteralDestructuringPattern; + function hasTrailingDirectorySeparator(path) { + var lastCharacter = path.charAt(path.length - 1); + return lastCharacter === "/" || lastCharacter === "\\"; + } + ts.hasTrailingDirectorySeparator = hasTrailingDirectorySeparator; + function isInReferenceComment(sourceFile, position) { + return isInCommentHelper(sourceFile, position, isReferenceComment); + function isReferenceComment(c) { + var commentText = sourceFile.text.substring(c.pos, c.end); + return tripleSlashDirectivePrefixRegex.test(commentText); } - var children = list.getChildren(); - var listItemIndex = ts.indexOf(children, node); + } + ts.isInReferenceComment = isInReferenceComment; + function isInNonReferenceComment(sourceFile, position) { + return isInCommentHelper(sourceFile, position, isNonReferenceComment); + function isNonReferenceComment(c) { + var commentText = sourceFile.text.substring(c.pos, c.end); + return !tripleSlashDirectivePrefixRegex.test(commentText); + } + } + ts.isInNonReferenceComment = isInNonReferenceComment; +})(ts || (ts = {})); +// Display-part writer helpers +/* @internal */ +var ts; +(function (ts) { + function isFirstDeclarationOfSymbolParameter(symbol) { + return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === 142 /* Parameter */; + } + ts.isFirstDeclarationOfSymbolParameter = isFirstDeclarationOfSymbolParameter; + var displayPartWriter = getDisplayPartWriter(); + function getDisplayPartWriter() { + var displayParts; + var lineStart; + var indent; + resetWriter(); return { - listItemIndex: listItemIndex, - list: list + displayParts: function () { return displayParts; }, + writeKeyword: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.keyword); }, + writeOperator: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.operator); }, + writePunctuation: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.punctuation); }, + writeSpace: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.space); }, + writeStringLiteral: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.stringLiteral); }, + writeParameter: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.parameterName); }, + writeSymbol: writeSymbol, + writeLine: writeLine, + increaseIndent: function () { indent++; }, + decreaseIndent: function () { indent--; }, + clear: resetWriter, + trackSymbol: function () { }, + reportInaccessibleThisError: function () { } }; + function writeIndent() { + if (lineStart) { + var indentString = ts.getIndentString(indent); + if (indentString) { + displayParts.push(displayPart(indentString, ts.SymbolDisplayPartKind.space)); + } + lineStart = false; + } + } + function writeKind(text, kind) { + writeIndent(); + displayParts.push(displayPart(text, kind)); + } + function writeSymbol(text, symbol) { + writeIndent(); + displayParts.push(symbolPart(text, symbol)); + } + function writeLine() { + displayParts.push(lineBreakPart()); + lineStart = true; + } + function resetWriter() { + displayParts = []; + lineStart = true; + indent = 0; + } } - ts.findListItemInfo = findListItemInfo; - function hasChildOfKind(n, kind, sourceFile) { - return !!findChildOfKind(n, kind, sourceFile); + function symbolPart(text, symbol) { + return displayPart(text, displayPartKind(symbol), symbol); + function displayPartKind(symbol) { + var flags = symbol.flags; + if (flags & 3 /* Variable */) { + return isFirstDeclarationOfSymbolParameter(symbol) ? ts.SymbolDisplayPartKind.parameterName : ts.SymbolDisplayPartKind.localName; + } + else if (flags & 4 /* Property */) { + return ts.SymbolDisplayPartKind.propertyName; + } + else if (flags & 32768 /* GetAccessor */) { + return ts.SymbolDisplayPartKind.propertyName; + } + else if (flags & 65536 /* SetAccessor */) { + return ts.SymbolDisplayPartKind.propertyName; + } + else if (flags & 8 /* EnumMember */) { + return ts.SymbolDisplayPartKind.enumMemberName; + } + else if (flags & 16 /* Function */) { + return ts.SymbolDisplayPartKind.functionName; + } + else if (flags & 32 /* Class */) { + return ts.SymbolDisplayPartKind.className; + } + else if (flags & 64 /* Interface */) { + return ts.SymbolDisplayPartKind.interfaceName; + } + else if (flags & 384 /* Enum */) { + return ts.SymbolDisplayPartKind.enumName; + } + else if (flags & 1536 /* Module */) { + return ts.SymbolDisplayPartKind.moduleName; + } + else if (flags & 8192 /* Method */) { + return ts.SymbolDisplayPartKind.methodName; + } + else if (flags & 262144 /* TypeParameter */) { + return ts.SymbolDisplayPartKind.typeParameterName; + } + else if (flags & 524288 /* TypeAlias */) { + return ts.SymbolDisplayPartKind.aliasName; + } + else if (flags & 8388608 /* Alias */) { + return ts.SymbolDisplayPartKind.aliasName; + } + return ts.SymbolDisplayPartKind.text; + } } - ts.hasChildOfKind = hasChildOfKind; - function findChildOfKind(n, kind, sourceFile) { - return ts.forEach(n.getChildren(sourceFile), function (c) { return c.kind === kind && c; }); + ts.symbolPart = symbolPart; + function displayPart(text, kind, symbol) { + return { + text: text, + kind: ts.SymbolDisplayPartKind[kind] + }; } - ts.findChildOfKind = findChildOfKind; - function findContainingList(node) { - // The node might be a list element (nonsynthetic) or a comma (synthetic). Either way, it will - // be parented by the container of the SyntaxList, not the SyntaxList itself. - // In order to find the list item index, we first need to locate SyntaxList itself and then search - // for the position of the relevant node (or comma). - var syntaxList = ts.forEach(node.parent.getChildren(), function (c) { - // find syntax list that covers the span of the node - if (c.kind === 286 /* SyntaxList */ && c.pos <= node.pos && c.end >= node.end) { - return c; - } - }); - // Either we didn't find an appropriate list, or the list must contain us. - ts.Debug.assert(!syntaxList || ts.contains(syntaxList.getChildren(), node)); - return syntaxList; + ts.displayPart = displayPart; + function spacePart() { + return displayPart(" ", ts.SymbolDisplayPartKind.space); } - ts.findContainingList = findContainingList; - /* Gets the token whose text has range [start, end) and - * position >= start and (position < end or (position === end && token is keyword or identifier)) + ts.spacePart = spacePart; + function keywordPart(kind) { + return displayPart(ts.tokenToString(kind), ts.SymbolDisplayPartKind.keyword); + } + ts.keywordPart = keywordPart; + function punctuationPart(kind) { + return displayPart(ts.tokenToString(kind), ts.SymbolDisplayPartKind.punctuation); + } + ts.punctuationPart = punctuationPart; + function operatorPart(kind) { + return displayPart(ts.tokenToString(kind), ts.SymbolDisplayPartKind.operator); + } + ts.operatorPart = operatorPart; + function textOrKeywordPart(text) { + var kind = ts.stringToToken(text); + return kind === undefined + ? textPart(text) + : keywordPart(kind); + } + ts.textOrKeywordPart = textOrKeywordPart; + function textPart(text) { + return displayPart(text, ts.SymbolDisplayPartKind.text); + } + ts.textPart = textPart; + var carriageReturnLineFeed = "\r\n"; + /** + * The default is CRLF. */ - function getTouchingWord(sourceFile, position, includeJsDocComment) { - if (includeJsDocComment === void 0) { includeJsDocComment = false; } - return getTouchingToken(sourceFile, position, function (n) { return isWord(n.kind); }, includeJsDocComment); + function getNewLineOrDefaultFromHost(host) { + return host.getNewLine ? host.getNewLine() : carriageReturnLineFeed; } - ts.getTouchingWord = getTouchingWord; - /* Gets the token whose text has range [start, end) and position >= start - * and (position < end or (position === end && token is keyword or identifier or numeric/string literal)) + ts.getNewLineOrDefaultFromHost = getNewLineOrDefaultFromHost; + function lineBreakPart() { + return displayPart("\n", ts.SymbolDisplayPartKind.lineBreak); + } + ts.lineBreakPart = lineBreakPart; + function mapToDisplayParts(writeDisplayParts) { + writeDisplayParts(displayPartWriter); + var result = displayPartWriter.displayParts(); + displayPartWriter.clear(); + return result; + } + ts.mapToDisplayParts = mapToDisplayParts; + function typeToDisplayParts(typechecker, type, enclosingDeclaration, flags) { + return mapToDisplayParts(function (writer) { + typechecker.getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags); + }); + } + ts.typeToDisplayParts = typeToDisplayParts; + function symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration, meaning, flags) { + return mapToDisplayParts(function (writer) { + typeChecker.getSymbolDisplayBuilder().buildSymbolDisplay(symbol, writer, enclosingDeclaration, meaning, flags); + }); + } + ts.symbolToDisplayParts = symbolToDisplayParts; + function signatureToDisplayParts(typechecker, signature, enclosingDeclaration, flags) { + return mapToDisplayParts(function (writer) { + typechecker.getSymbolDisplayBuilder().buildSignatureDisplay(signature, writer, enclosingDeclaration, flags); + }); + } + ts.signatureToDisplayParts = signatureToDisplayParts; + function getDeclaredName(typeChecker, symbol, location) { + // If this is an export or import specifier it could have been renamed using the 'as' syntax. + // If so we want to search for whatever is under the cursor. + if (isImportOrExportSpecifierName(location)) { + return location.getText(); + } + else if (ts.isStringOrNumericLiteral(location.kind) && + location.parent.kind === 140 /* ComputedPropertyName */) { + return location.text; + } + // Try to get the local symbol if we're dealing with an 'export default' + // since that symbol has the "true" name. + var localExportDefaultSymbol = ts.getLocalSymbolForExportDefault(symbol); + var name = typeChecker.symbolToString(localExportDefaultSymbol || symbol); + return name; + } + ts.getDeclaredName = getDeclaredName; + function isImportOrExportSpecifierName(location) { + return location.parent && + (location.parent.kind === 234 /* ImportSpecifier */ || location.parent.kind === 238 /* ExportSpecifier */) && + location.parent.propertyName === location; + } + ts.isImportOrExportSpecifierName = isImportOrExportSpecifierName; + /** + * Strip off existed single quotes or double quotes from a given string + * + * @return non-quoted string */ - function getTouchingPropertyName(sourceFile, position, includeJsDocComment) { - if (includeJsDocComment === void 0) { includeJsDocComment = false; } - return getTouchingToken(sourceFile, position, function (n) { return isPropertyName(n.kind); }, includeJsDocComment); + function stripQuotes(name) { + var length = name.length; + if (length >= 2 && + name.charCodeAt(0) === name.charCodeAt(length - 1) && + (name.charCodeAt(0) === 34 /* doubleQuote */ || name.charCodeAt(0) === 39 /* singleQuote */)) { + return name.substring(1, length - 1); + } + ; + return name; } - ts.getTouchingPropertyName = getTouchingPropertyName; - /** Returns the token if position is in [start, end) or if position === end and includeItemAtEndPosition(token) === true */ - function getTouchingToken(sourceFile, position, includeItemAtEndPosition, includeJsDocComment) { - if (includeJsDocComment === void 0) { includeJsDocComment = false; } - return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ false, includeItemAtEndPosition, includeJsDocComment); + ts.stripQuotes = stripQuotes; + function scriptKindIs(fileName, host) { + var scriptKinds = []; + for (var _i = 2; _i < arguments.length; _i++) { + scriptKinds[_i - 2] = arguments[_i]; + } + var scriptKind = getScriptKind(fileName, host); + return ts.forEach(scriptKinds, function (k) { return k === scriptKind; }); } - ts.getTouchingToken = getTouchingToken; - /** Returns a token if position is in [start-of-leading-trivia, end) */ - function getTokenAtPosition(sourceFile, position, includeJsDocComment) { - if (includeJsDocComment === void 0) { includeJsDocComment = false; } - return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ true, /*includeItemAtEndPosition*/ undefined, includeJsDocComment); + ts.scriptKindIs = scriptKindIs; + function getScriptKind(fileName, host) { + // First check to see if the script kind was specified by the host. Chances are the host + // may override the default script kind for the file extension. + var scriptKind; + if (host && host.getScriptKind) { + scriptKind = host.getScriptKind(fileName); + } + if (!scriptKind) { + scriptKind = ts.getScriptKindFromFileName(fileName); + } + return ts.ensureScriptKind(fileName, scriptKind); } - ts.getTokenAtPosition = getTokenAtPosition; - /** Get the token whose text contains the position */ - function getTokenAtPositionWorker(sourceFile, position, allowPositionInLeadingTrivia, includeItemAtEndPosition, includeJsDocComment) { - if (includeJsDocComment === void 0) { includeJsDocComment = false; } - var current = sourceFile; - outer: while (true) { - if (isToken(current)) { - // exit early - return current; - } - if (includeJsDocComment) { - var jsDocChildren = ts.filter(current.getChildren(), ts.isJSDocNode); - for (var _i = 0, jsDocChildren_1 = jsDocChildren; _i < jsDocChildren_1.length; _i++) { - var jsDocChild = jsDocChildren_1[_i]; - var start = allowPositionInLeadingTrivia ? jsDocChild.getFullStart() : jsDocChild.getStart(sourceFile, includeJsDocComment); - if (start <= position) { - var end = jsDocChild.getEnd(); - if (position < end || (position === end && jsDocChild.kind === 1 /* EndOfFileToken */)) { - current = jsDocChild; - continue outer; - } - else if (includeItemAtEndPosition && end === position) { - var previousToken = findPrecedingToken(position, sourceFile, jsDocChild); - if (previousToken && includeItemAtEndPosition(previousToken)) { - return previousToken; - } - } - } + ts.getScriptKind = getScriptKind; + function sanitizeConfigFile(configFileName, content) { + var options = { + fileName: "config.js", + compilerOptions: { + target: 2 /* ES6 */, + removeComments: true + }, + reportDiagnostics: true + }; + var _a = ts.transpileModule("(" + content + ")", options), outputText = _a.outputText, diagnostics = _a.diagnostics; + // Becasue the content was wrapped in "()", the start position of diagnostics needs to be subtract by 1 + // also, the emitted result will have "(" in the beginning and ");" in the end. We need to strip these + // as well + var trimmedOutput = outputText.trim(); + for (var _i = 0, diagnostics_3 = diagnostics; _i < diagnostics_3.length; _i++) { + var diagnostic = diagnostics_3[_i]; + diagnostic.start = diagnostic.start - 1; + } + var _b = ts.parseConfigFileTextToJson(configFileName, trimmedOutput.substring(1, trimmedOutput.length - 2), /*stripComments*/ false), config = _b.config, error = _b.error; + return { + configJsonObject: config || {}, + diagnostics: error ? ts.concatenate(diagnostics, [error]) : diagnostics + }; + } + ts.sanitizeConfigFile = sanitizeConfigFile; +})(ts || (ts = {})); +var ts; +(function (ts) { + /// Classifier + function createClassifier() { + var scanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ false); + /// We do not have a full parser support to know when we should parse a regex or not + /// If we consider every slash token to be a regex, we could be missing cases like "1/2/3", where + /// we have a series of divide operator. this list allows us to be more accurate by ruling out + /// locations where a regexp cannot exist. + var noRegexTable = []; + noRegexTable[69 /* Identifier */] = true; + noRegexTable[9 /* StringLiteral */] = true; + noRegexTable[8 /* NumericLiteral */] = true; + noRegexTable[10 /* RegularExpressionLiteral */] = true; + noRegexTable[97 /* ThisKeyword */] = true; + noRegexTable[41 /* PlusPlusToken */] = true; + noRegexTable[42 /* MinusMinusToken */] = true; + noRegexTable[18 /* CloseParenToken */] = true; + noRegexTable[20 /* CloseBracketToken */] = true; + noRegexTable[16 /* CloseBraceToken */] = true; + noRegexTable[99 /* TrueKeyword */] = true; + noRegexTable[84 /* FalseKeyword */] = true; + // Just a stack of TemplateHeads and OpenCurlyBraces, used to perform rudimentary (inexact) + // classification on template strings. Because of the context free nature of templates, + // the only precise way to classify a template portion would be by propagating the stack across + // lines, just as we do with the end-of-line state. However, this is a burden for implementers, + // and the behavior is entirely subsumed by the syntactic classifier anyway, so we instead + // flatten any nesting when the template stack is non-empty and encode it in the end-of-line state. + // Situations in which this fails are + // 1) When template strings are nested across different lines: + // `hello ${ `world + // ` }` + // + // Where on the second line, you will get the closing of a template, + // a closing curly, and a new template. + // + // 2) When substitution expressions have curly braces and the curly brace falls on the next line: + // `hello ${ () => { + // return "world" } } ` + // + // Where on the second line, you will get the 'return' keyword, + // a string literal, and a template end consisting of '} } `'. + var templateStack = []; + /** Returns true if 'keyword2' can legally follow 'keyword1' in any language construct. */ + function canFollow(keyword1, keyword2) { + if (ts.isAccessibilityModifier(keyword1)) { + if (keyword2 === 123 /* GetKeyword */ || + keyword2 === 131 /* SetKeyword */ || + keyword2 === 121 /* ConstructorKeyword */ || + keyword2 === 113 /* StaticKeyword */) { + // Allow things like "public get", "public constructor" and "public static". + // These are all legal. + return true; } + // Any other keyword following "public" is actually an identifier an not a real + // keyword. + return false; } - // find the child that contains 'position' - for (var i = 0, n = current.getChildCount(sourceFile); i < n; i++) { - var child = current.getChildAt(i); - // all jsDocComment nodes were already visited - if (ts.isJSDocNode(child)) { - continue; - } - var start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile, includeJsDocComment); - if (start <= position) { - var end = child.getEnd(); - if (position < end || (position === end && child.kind === 1 /* EndOfFileToken */)) { - current = child; - continue outer; - } - else if (includeItemAtEndPosition && end === position) { - var previousToken = findPrecedingToken(position, sourceFile, child); - if (previousToken && includeItemAtEndPosition(previousToken)) { - return previousToken; - } + // Assume any other keyword combination is legal. This can be refined in the future + // if there are more cases we want the classifier to be better at. + return true; + } + function convertClassifications(classifications, text) { + var entries = []; + var dense = classifications.spans; + var lastEnd = 0; + for (var i = 0, n = dense.length; i < n; i += 3) { + var start = dense[i]; + var length_5 = dense[i + 1]; + var type = dense[i + 2]; + // Make a whitespace entry between the last item and this one. + if (lastEnd >= 0) { + var whitespaceLength_1 = start - lastEnd; + if (whitespaceLength_1 > 0) { + entries.push({ length: whitespaceLength_1, classification: ts.TokenClass.Whitespace }); } } + entries.push({ length: length_5, classification: convertClassification(type) }); + lastEnd = start + length_5; } - return current; - } - } - /** - * The token on the left of the position is the token that strictly includes the position - * or sits to the left of the cursor if it is on a boundary. For example - * - * fo|o -> will return foo - * foo |bar -> will return foo - * - */ - function findTokenOnLeftOfPosition(file, position) { - // Ideally, getTokenAtPosition should return a token. However, it is currently - // broken, so we do a check to make sure the result was indeed a token. - var tokenAtPosition = getTokenAtPosition(file, position); - if (isToken(tokenAtPosition) && position > tokenAtPosition.getStart(file) && position < tokenAtPosition.getEnd()) { - return tokenAtPosition; - } - return findPrecedingToken(position, file); - } - ts.findTokenOnLeftOfPosition = findTokenOnLeftOfPosition; - function findNextToken(previousToken, parent) { - return find(parent); - function find(n) { - if (isToken(n) && n.pos === previousToken.end) { - // this is token that starts at the end of previous token - return it - return n; - } - var children = n.getChildren(); - for (var _i = 0, children_1 = children; _i < children_1.length; _i++) { - var child = children_1[_i]; - var shouldDiveInChildNode = - // previous token is enclosed somewhere in the child - (child.pos <= previousToken.pos && child.end > previousToken.end) || - // previous token ends exactly at the beginning of child - (child.pos === previousToken.end); - if (shouldDiveInChildNode && nodeHasTokens(child)) { - return find(child); - } + var whitespaceLength = text.length - lastEnd; + if (whitespaceLength > 0) { + entries.push({ length: whitespaceLength, classification: ts.TokenClass.Whitespace }); } - return undefined; + return { entries: entries, finalLexState: classifications.endOfLineState }; } - } - ts.findNextToken = findNextToken; - function findPrecedingToken(position, sourceFile, startNode) { - return find(startNode || sourceFile); - function findRightmostToken(n) { - if (isToken(n) || n.kind === 244 /* JsxText */) { - return n; + function convertClassification(type) { + switch (type) { + case 1 /* comment */: return ts.TokenClass.Comment; + case 3 /* keyword */: return ts.TokenClass.Keyword; + case 4 /* numericLiteral */: return ts.TokenClass.NumberLiteral; + case 5 /* operator */: return ts.TokenClass.Operator; + case 6 /* stringLiteral */: return ts.TokenClass.StringLiteral; + case 8 /* whiteSpace */: return ts.TokenClass.Whitespace; + case 10 /* punctuation */: return ts.TokenClass.Punctuation; + case 2 /* identifier */: + case 11 /* className */: + case 12 /* enumName */: + case 13 /* interfaceName */: + case 14 /* moduleName */: + case 15 /* typeParameterName */: + case 16 /* typeAliasName */: + case 9 /* text */: + case 17 /* parameterName */: + default: + return ts.TokenClass.Identifier; } - var children = n.getChildren(); - var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length); - return candidate && findRightmostToken(candidate); } - function find(n) { - if (isToken(n) || n.kind === 244 /* JsxText */) { - return n; + function getClassificationsForLine(text, lexState, syntacticClassifierAbsent) { + return convertClassifications(getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent), text); + } + // If there is a syntactic classifier ('syntacticClassifierAbsent' is false), + // we will be more conservative in order to avoid conflicting with the syntactic classifier. + function getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent) { + var offset = 0; + var token = 0 /* Unknown */; + var lastNonTriviaToken = 0 /* Unknown */; + // Empty out the template stack for reuse. + while (templateStack.length > 0) { + templateStack.pop(); } - var children = n.getChildren(); - for (var i = 0, len = children.length; i < len; i++) { - var child = children[i]; - // condition 'position < child.end' checks if child node end after the position - // in the example below this condition will be false for 'aaaa' and 'bbbb' and true for 'ccc' - // aaaa___bbbb___$__ccc - // after we found child node with end after the position we check if start of the node is after the position. - // if yes - then position is in the trivia and we need to look into the previous child to find the token in question. - // if no - position is in the node itself so we should recurse in it. - // NOTE: JsxText is a weird kind of node that can contain only whitespaces (since they are not counted as trivia). - // if this is the case - then we should assume that token in question is located in previous child. - if (position < child.end && (nodeHasTokens(child) || child.kind === 244 /* JsxText */)) { - var start = child.getStart(sourceFile); - var lookInPreviousChild = (start >= position) || - (child.kind === 244 /* JsxText */ && start === child.end); // whitespace only JsxText - if (lookInPreviousChild) { - // actual start of the node is past the position - previous token should be at the end of previous child - var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ i); - return candidate && findRightmostToken(candidate); + // If we're in a string literal, then prepend: "\ + // (and a newline). That way when we lex we'll think we're still in a string literal. + // + // If we're in a multiline comment, then prepend: /* + // (and a newline). That way when we lex we'll think we're still in a multiline comment. + switch (lexState) { + case 3 /* InDoubleQuoteStringLiteral */: + text = "\"\\\n" + text; + offset = 3; + break; + case 2 /* InSingleQuoteStringLiteral */: + text = "'\\\n" + text; + offset = 3; + break; + case 1 /* InMultiLineCommentTrivia */: + text = "/*\n" + text; + offset = 3; + break; + case 4 /* InTemplateHeadOrNoSubstitutionTemplate */: + text = "`\n" + text; + offset = 2; + break; + case 5 /* InTemplateMiddleOrTail */: + text = "}\n" + text; + offset = 2; + // fallthrough + case 6 /* InTemplateSubstitutionPosition */: + templateStack.push(12 /* TemplateHead */); + break; + } + scanner.setText(text); + var result = { + endOfLineState: 0 /* None */, + spans: [] + }; + // We can run into an unfortunate interaction between the lexical and syntactic classifier + // when the user is typing something generic. Consider the case where the user types: + // + // Foo tokens. It's a weak heuristic, but should + // work well enough in practice. + var angleBracketStack = 0; + do { + token = scanner.scan(); + if (!ts.isTrivia(token)) { + if ((token === 39 /* SlashToken */ || token === 61 /* SlashEqualsToken */) && !noRegexTable[lastNonTriviaToken]) { + if (scanner.reScanSlashToken() === 10 /* RegularExpressionLiteral */) { + token = 10 /* RegularExpressionLiteral */; + } } - else { - // candidate should be in this node - return find(child); + else if (lastNonTriviaToken === 21 /* DotToken */ && isKeyword(token)) { + token = 69 /* Identifier */; + } + else if (isKeyword(lastNonTriviaToken) && isKeyword(token) && !canFollow(lastNonTriviaToken, token)) { + // We have two keywords in a row. Only treat the second as a keyword if + // it's a sequence that could legally occur in the language. Otherwise + // treat it as an identifier. This way, if someone writes "private var" + // we recognize that 'var' is actually an identifier here. + token = 69 /* Identifier */; + } + else if (lastNonTriviaToken === 69 /* Identifier */ && + token === 25 /* LessThanToken */) { + // Could be the start of something generic. Keep track of that by bumping + // up the current count of generic contexts we may be in. + angleBracketStack++; + } + else if (token === 27 /* GreaterThanToken */ && angleBracketStack > 0) { + // If we think we're currently in something generic, then mark that that + // generic entity is complete. + angleBracketStack--; + } + else if (token === 117 /* AnyKeyword */ || + token === 132 /* StringKeyword */ || + token === 130 /* NumberKeyword */ || + token === 120 /* BooleanKeyword */ || + token === 133 /* SymbolKeyword */) { + if (angleBracketStack > 0 && !syntacticClassifierAbsent) { + // If it looks like we're could be in something generic, don't classify this + // as a keyword. We may just get overwritten by the syntactic classifier, + // causing a noisy experience for the user. + token = 69 /* Identifier */; + } + } + else if (token === 12 /* TemplateHead */) { + templateStack.push(token); + } + else if (token === 15 /* OpenBraceToken */) { + // If we don't have anything on the template stack, + // then we aren't trying to keep track of a previously scanned template head. + if (templateStack.length > 0) { + templateStack.push(token); + } + } + else if (token === 16 /* CloseBraceToken */) { + // If we don't have anything on the template stack, + // then we aren't trying to keep track of a previously scanned template head. + if (templateStack.length > 0) { + var lastTemplateStackToken = ts.lastOrUndefined(templateStack); + if (lastTemplateStackToken === 12 /* TemplateHead */) { + token = scanner.reScanTemplateToken(); + // Only pop on a TemplateTail; a TemplateMiddle indicates there is more for us. + if (token === 14 /* TemplateTail */) { + templateStack.pop(); + } + else { + ts.Debug.assert(token === 13 /* TemplateMiddle */, "Should have been a template middle. Was " + token); + } + } + else { + ts.Debug.assert(lastTemplateStackToken === 15 /* OpenBraceToken */, "Should have been an open brace. Was: " + token); + templateStack.pop(); + } + } + } + lastNonTriviaToken = token; + } + processToken(); + } while (token !== 1 /* EndOfFileToken */); + return result; + function processToken() { + var start = scanner.getTokenPos(); + var end = scanner.getTextPos(); + addResult(start, end, classFromKind(token)); + if (end >= text.length) { + if (token === 9 /* StringLiteral */) { + // Check to see if we finished up on a multiline string literal. + var tokenText = scanner.getTokenText(); + if (scanner.isUnterminated()) { + var lastCharIndex = tokenText.length - 1; + var numBackslashes = 0; + while (tokenText.charCodeAt(lastCharIndex - numBackslashes) === 92 /* backslash */) { + numBackslashes++; + } + // If we have an odd number of backslashes, then the multiline string is unclosed + if (numBackslashes & 1) { + var quoteChar = tokenText.charCodeAt(0); + result.endOfLineState = quoteChar === 34 /* doubleQuote */ + ? 3 /* InDoubleQuoteStringLiteral */ + : 2 /* InSingleQuoteStringLiteral */; + } + } + } + else if (token === 3 /* MultiLineCommentTrivia */) { + // Check to see if the multiline comment was unclosed. + if (scanner.isUnterminated()) { + result.endOfLineState = 1 /* InMultiLineCommentTrivia */; + } + } + else if (ts.isTemplateLiteralKind(token)) { + if (scanner.isUnterminated()) { + if (token === 14 /* TemplateTail */) { + result.endOfLineState = 5 /* InTemplateMiddleOrTail */; + } + else if (token === 11 /* NoSubstitutionTemplateLiteral */) { + result.endOfLineState = 4 /* InTemplateHeadOrNoSubstitutionTemplate */; + } + else { + ts.Debug.fail("Only 'NoSubstitutionTemplateLiteral's and 'TemplateTail's can be unterminated; got SyntaxKind #" + token); + } + } + } + else if (templateStack.length > 0 && ts.lastOrUndefined(templateStack) === 12 /* TemplateHead */) { + result.endOfLineState = 6 /* InTemplateSubstitutionPosition */; } } } - ts.Debug.assert(startNode !== undefined || n.kind === 256 /* SourceFile */); - // Here we know that none of child token nodes embrace the position, - // the only known case is when position is at the end of the file. - // Try to find the rightmost token in the file without filtering. - // Namely we are skipping the check: 'position < node.end' - if (children.length) { - var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length); - return candidate && findRightmostToken(candidate); - } - } - /// finds last node that is considered as candidate for search (isCandidate(node) === true) starting from 'exclusiveStartPosition' - function findRightmostChildNodeWithTokens(children, exclusiveStartPosition) { - for (var i = exclusiveStartPosition - 1; i >= 0; i--) { - if (nodeHasTokens(children[i])) { - return children[i]; + function addResult(start, end, classification) { + if (classification === 8 /* whiteSpace */) { + // Don't bother with whitespace classifications. They're not needed. + return; + } + if (start === 0 && offset > 0) { + // We're classifying the first token, and this was a case where we prepended + // text. We should consider the start of this token to be at the start of + // the original text. + start += offset; + } + // All our tokens are in relation to the augmented text. Move them back to be + // relative to the original text. + start -= offset; + end -= offset; + var length = end - start; + if (length > 0) { + result.spans.push(start); + result.spans.push(length); + result.spans.push(classification); } } } - } - ts.findPrecedingToken = findPrecedingToken; - function isInString(sourceFile, position) { - var previousToken = findPrecedingToken(position, sourceFile); - if (previousToken && previousToken.kind === 9 /* StringLiteral */) { - var start = previousToken.getStart(); - var end = previousToken.getEnd(); - // To be "in" one of these literals, the position has to be: - // 1. entirely within the token text. - // 2. at the end position of an unterminated token. - // 3. at the end of a regular expression (due to trailing flags like '/foo/g'). - if (start < position && position < end) { - return true; - } - if (position === end) { - return !!previousToken.isUnterminated; + function isBinaryExpressionOperatorToken(token) { + switch (token) { + case 37 /* AsteriskToken */: + case 39 /* SlashToken */: + case 40 /* PercentToken */: + case 35 /* PlusToken */: + case 36 /* MinusToken */: + case 43 /* LessThanLessThanToken */: + case 44 /* GreaterThanGreaterThanToken */: + case 45 /* GreaterThanGreaterThanGreaterThanToken */: + case 25 /* LessThanToken */: + case 27 /* GreaterThanToken */: + case 28 /* LessThanEqualsToken */: + case 29 /* GreaterThanEqualsToken */: + case 91 /* InstanceOfKeyword */: + case 90 /* InKeyword */: + case 116 /* AsKeyword */: + case 30 /* EqualsEqualsToken */: + case 31 /* ExclamationEqualsToken */: + case 32 /* EqualsEqualsEqualsToken */: + case 33 /* ExclamationEqualsEqualsToken */: + case 46 /* AmpersandToken */: + case 48 /* CaretToken */: + case 47 /* BarToken */: + case 51 /* AmpersandAmpersandToken */: + case 52 /* BarBarToken */: + case 67 /* BarEqualsToken */: + case 66 /* AmpersandEqualsToken */: + case 68 /* CaretEqualsToken */: + case 63 /* LessThanLessThanEqualsToken */: + case 64 /* GreaterThanGreaterThanEqualsToken */: + case 65 /* GreaterThanGreaterThanGreaterThanEqualsToken */: + case 57 /* PlusEqualsToken */: + case 58 /* MinusEqualsToken */: + case 59 /* AsteriskEqualsToken */: + case 61 /* SlashEqualsToken */: + case 62 /* PercentEqualsToken */: + case 56 /* EqualsToken */: + case 24 /* CommaToken */: + return true; + default: + return false; } } - return false; - } - ts.isInString = isInString; - function isInComment(sourceFile, position) { - return isInCommentHelper(sourceFile, position, /*predicate*/ undefined); - } - ts.isInComment = isInComment; - /** - * returns true if the position is in between the open and close elements of an JSX expression. - */ - function isInsideJsxElementOrAttribute(sourceFile, position) { - var token = getTokenAtPosition(sourceFile, position); - if (!token) { - return false; - } - if (token.kind === 244 /* JsxText */) { - return true; - } - //
Hello |
- if (token.kind === 25 /* LessThanToken */ && token.parent.kind === 244 /* JsxText */) { - return true; - } - //
{ |
or
- if (token.kind === 25 /* LessThanToken */ && token.parent.kind === 248 /* JsxExpression */) { - return true; - } - //
{ - // | - // } < /div> - if (token && token.kind === 16 /* CloseBraceToken */ && token.parent.kind === 248 /* JsxExpression */) { - return true; + function isPrefixUnaryExpressionOperatorToken(token) { + switch (token) { + case 35 /* PlusToken */: + case 36 /* MinusToken */: + case 50 /* TildeToken */: + case 49 /* ExclamationToken */: + case 41 /* PlusPlusToken */: + case 42 /* MinusMinusToken */: + return true; + default: + return false; + } } - //
|
- if (token.kind === 25 /* LessThanToken */ && token.parent.kind === 245 /* JsxClosingElement */) { - return true; + function isKeyword(token) { + return token >= 70 /* FirstKeyword */ && token <= 138 /* LastKeyword */; } - return false; - } - ts.isInsideJsxElementOrAttribute = isInsideJsxElementOrAttribute; - function isInTemplateString(sourceFile, position) { - var token = getTokenAtPosition(sourceFile, position); - return ts.isTemplateLiteralKind(token.kind) && position > token.getStart(sourceFile); - } - ts.isInTemplateString = isInTemplateString; - /** - * Returns true if the cursor at position in sourceFile is within a comment that additionally - * satisfies predicate, and false otherwise. - */ - function isInCommentHelper(sourceFile, position, predicate) { - var token = getTokenAtPosition(sourceFile, position); - if (token && position <= token.getStart(sourceFile)) { - var commentRanges = ts.getLeadingCommentRanges(sourceFile.text, token.pos); - // The end marker of a single-line comment does not include the newline character. - // In the following case, we are inside a comment (^ denotes the cursor position): - // - // // asdf ^\n - // - // But for multi-line comments, we don't want to be inside the comment in the following case: - // - // /* asdf */^ - // - // Internally, we represent the end of the comment at the newline and closing '/', respectively. - return predicate ? - ts.forEach(commentRanges, function (c) { return c.pos < position && - (c.kind == 2 /* SingleLineCommentTrivia */ ? position <= c.end : position < c.end) && - predicate(c); }) : - ts.forEach(commentRanges, function (c) { return c.pos < position && - (c.kind == 2 /* SingleLineCommentTrivia */ ? position <= c.end : position < c.end); }); + function classFromKind(token) { + if (isKeyword(token)) { + return 3 /* keyword */; + } + else if (isBinaryExpressionOperatorToken(token) || isPrefixUnaryExpressionOperatorToken(token)) { + return 5 /* operator */; + } + else if (token >= 15 /* FirstPunctuation */ && token <= 68 /* LastPunctuation */) { + return 10 /* punctuation */; + } + switch (token) { + case 8 /* NumericLiteral */: + return 4 /* numericLiteral */; + case 9 /* StringLiteral */: + return 6 /* stringLiteral */; + case 10 /* RegularExpressionLiteral */: + return 7 /* regularExpressionLiteral */; + case 7 /* ConflictMarkerTrivia */: + case 3 /* MultiLineCommentTrivia */: + case 2 /* SingleLineCommentTrivia */: + return 1 /* comment */; + case 5 /* WhitespaceTrivia */: + case 4 /* NewLineTrivia */: + return 8 /* whiteSpace */; + case 69 /* Identifier */: + default: + if (ts.isTemplateLiteralKind(token)) { + return 6 /* stringLiteral */; + } + return 2 /* identifier */; + } } - return false; + return { + getClassificationsForLine: getClassificationsForLine, + getEncodedLexicalClassifications: getEncodedLexicalClassifications + }; } - ts.isInCommentHelper = isInCommentHelper; - function hasDocComment(sourceFile, position) { - var token = getTokenAtPosition(sourceFile, position); - // First, we have to see if this position actually landed in a comment. - var commentRanges = ts.getLeadingCommentRanges(sourceFile.text, token.pos); - return ts.forEach(commentRanges, jsDocPrefix); - function jsDocPrefix(c) { - var text = sourceFile.text; - return text.length >= c.pos + 3 && text[c.pos] === "/" && text[c.pos + 1] === "*" && text[c.pos + 2] === "*"; + ts.createClassifier = createClassifier; + /* @internal */ + function getSemanticClassifications(typeChecker, cancellationToken, sourceFile, classifiableNames, span) { + return convertClassifications(getEncodedSemanticClassifications(typeChecker, cancellationToken, sourceFile, classifiableNames, span)); + } + ts.getSemanticClassifications = getSemanticClassifications; + function checkForClassificationCancellation(cancellationToken, kind) { + // We don't want to actually call back into our host on every node to find out if we've + // been canceled. That would be an enormous amount of chattyness, along with the all + // the overhead of marshalling the data to/from the host. So instead we pick a few + // reasonable node kinds to bother checking on. These node kinds represent high level + // constructs that we would expect to see commonly, but just at a far less frequent + // interval. + // + // For example, in checker.ts (around 750k) we only have around 600 of these constructs. + // That means we're calling back into the host around every 1.2k of the file we process. + // Lib.d.ts has similar numbers. + switch (kind) { + case 225 /* ModuleDeclaration */: + case 221 /* ClassDeclaration */: + case 222 /* InterfaceDeclaration */: + case 220 /* FunctionDeclaration */: + cancellationToken.throwIfCancellationRequested(); } } - ts.hasDocComment = hasDocComment; - /** - * Get the corresponding JSDocTag node if the position is in a jsDoc comment - */ - function getJsDocTagAtPosition(sourceFile, position) { - var node = ts.getTokenAtPosition(sourceFile, position); - if (isToken(node)) { - switch (node.kind) { - case 102 /* VarKeyword */: - case 108 /* LetKeyword */: - case 74 /* ConstKeyword */: - // if the current token is var, let or const, skip the VariableDeclarationList - node = node.parent === undefined ? undefined : node.parent.parent; - break; - default: - node = node.parent; - break; + /* @internal */ + function getEncodedSemanticClassifications(typeChecker, cancellationToken, sourceFile, classifiableNames, span) { + var result = []; + processNode(sourceFile); + return { spans: result, endOfLineState: 0 /* None */ }; + function pushClassification(start, length, type) { + result.push(start); + result.push(length); + result.push(type); + } + function classifySymbol(symbol, meaningAtPosition) { + var flags = symbol.getFlags(); + if ((flags & 788448 /* Classifiable */) === 0 /* None */) { + return; + } + if (flags & 32 /* Class */) { + return 11 /* className */; + } + else if (flags & 384 /* Enum */) { + return 12 /* enumName */; + } + else if (flags & 524288 /* TypeAlias */) { + return 16 /* typeAliasName */; + } + else if (meaningAtPosition & 2 /* Type */) { + if (flags & 64 /* Interface */) { + return 13 /* interfaceName */; + } + else if (flags & 262144 /* TypeParameter */) { + return 15 /* typeParameterName */; + } + } + else if (flags & 1536 /* Module */) { + // Only classify a module as such if + // - It appears in a namespace context. + // - There exists a module declaration which actually impacts the value side. + if (meaningAtPosition & 4 /* Namespace */ || + (meaningAtPosition & 1 /* Value */ && hasValueSideModule(symbol))) { + return 14 /* moduleName */; + } + } + return undefined; + /** + * Returns true if there exists a module that introduces entities on the value side. + */ + function hasValueSideModule(symbol) { + return ts.forEach(symbol.declarations, function (declaration) { + return declaration.kind === 225 /* ModuleDeclaration */ && + ts.getModuleInstanceState(declaration) === 1 /* Instantiated */; + }); } } - if (node) { - if (node.jsDocComments) { - for (var _i = 0, _a = node.jsDocComments; _i < _a.length; _i++) { - var jsDocComment = _a[_i]; - for (var _b = 0, _c = jsDocComment.tags; _b < _c.length; _b++) { - var tag = _c[_b]; - if (tag.pos <= position && position <= tag.end) { - return tag; + function processNode(node) { + // Only walk into nodes that intersect the requested span. + if (node && ts.textSpanIntersectsWith(span, node.getFullStart(), node.getFullWidth())) { + var kind = node.kind; + checkForClassificationCancellation(cancellationToken, kind); + if (kind === 69 /* Identifier */ && !ts.nodeIsMissing(node)) { + var identifier = node; + // Only bother calling into the typechecker if this is an identifier that + // could possibly resolve to a type name. This makes classification run + // in a third of the time it would normally take. + if (classifiableNames[identifier.text]) { + var symbol = typeChecker.getSymbolAtLocation(node); + if (symbol) { + var type = classifySymbol(symbol, ts.getMeaningFromLocation(node)); + if (type) { + pushClassification(node.getStart(), node.getWidth(), type); + } } } } + ts.forEachChild(node, processNode); } } - return undefined; } - ts.getJsDocTagAtPosition = getJsDocTagAtPosition; - function nodeHasTokens(n) { - // If we have a token or node that has a non-zero width, it must have tokens. - // Note, that getWidth() does not take trivia into account. - return n.getWidth() !== 0; + ts.getEncodedSemanticClassifications = getEncodedSemanticClassifications; + function getClassificationTypeName(type) { + switch (type) { + case 1 /* comment */: return ts.ClassificationTypeNames.comment; + case 2 /* identifier */: return ts.ClassificationTypeNames.identifier; + case 3 /* keyword */: return ts.ClassificationTypeNames.keyword; + case 4 /* numericLiteral */: return ts.ClassificationTypeNames.numericLiteral; + case 5 /* operator */: return ts.ClassificationTypeNames.operator; + case 6 /* stringLiteral */: return ts.ClassificationTypeNames.stringLiteral; + case 8 /* whiteSpace */: return ts.ClassificationTypeNames.whiteSpace; + case 9 /* text */: return ts.ClassificationTypeNames.text; + case 10 /* punctuation */: return ts.ClassificationTypeNames.punctuation; + case 11 /* className */: return ts.ClassificationTypeNames.className; + case 12 /* enumName */: return ts.ClassificationTypeNames.enumName; + case 13 /* interfaceName */: return ts.ClassificationTypeNames.interfaceName; + case 14 /* moduleName */: return ts.ClassificationTypeNames.moduleName; + case 15 /* typeParameterName */: return ts.ClassificationTypeNames.typeParameterName; + case 16 /* typeAliasName */: return ts.ClassificationTypeNames.typeAliasName; + case 17 /* parameterName */: return ts.ClassificationTypeNames.parameterName; + case 18 /* docCommentTagName */: return ts.ClassificationTypeNames.docCommentTagName; + case 19 /* jsxOpenTagName */: return ts.ClassificationTypeNames.jsxOpenTagName; + case 20 /* jsxCloseTagName */: return ts.ClassificationTypeNames.jsxCloseTagName; + case 21 /* jsxSelfClosingTagName */: return ts.ClassificationTypeNames.jsxSelfClosingTagName; + case 22 /* jsxAttribute */: return ts.ClassificationTypeNames.jsxAttribute; + case 23 /* jsxText */: return ts.ClassificationTypeNames.jsxText; + case 24 /* jsxAttributeStringLiteralValue */: return ts.ClassificationTypeNames.jsxAttributeStringLiteralValue; + } } - function getNodeModifiers(node) { - var flags = ts.getCombinedNodeFlags(node); + function convertClassifications(classifications) { + ts.Debug.assert(classifications.spans.length % 3 === 0); + var dense = classifications.spans; var result = []; - if (flags & 8 /* Private */) - result.push(ts.ScriptElementKindModifier.privateMemberModifier); - if (flags & 16 /* Protected */) - result.push(ts.ScriptElementKindModifier.protectedMemberModifier); - if (flags & 4 /* Public */) - result.push(ts.ScriptElementKindModifier.publicMemberModifier); - if (flags & 32 /* Static */) - result.push(ts.ScriptElementKindModifier.staticModifier); - if (flags & 128 /* Abstract */) - result.push(ts.ScriptElementKindModifier.abstractModifier); - if (flags & 1 /* Export */) - result.push(ts.ScriptElementKindModifier.exportedModifier); - if (ts.isInAmbientContext(node)) - result.push(ts.ScriptElementKindModifier.ambientModifier); - return result.length > 0 ? result.join(",") : ts.ScriptElementKindModifier.none; - } - ts.getNodeModifiers = getNodeModifiers; - function getTypeArgumentOrTypeParameterList(node) { - if (node.kind === 155 /* TypeReference */ || node.kind === 174 /* CallExpression */) { - return node.typeArguments; - } - if (ts.isFunctionLike(node) || node.kind === 221 /* ClassDeclaration */ || node.kind === 222 /* InterfaceDeclaration */) { - return node.typeParameters; + for (var i = 0, n = dense.length; i < n; i += 3) { + result.push({ + textSpan: ts.createTextSpan(dense[i], dense[i + 1]), + classificationType: getClassificationTypeName(dense[i + 2]) + }); } - return undefined; - } - ts.getTypeArgumentOrTypeParameterList = getTypeArgumentOrTypeParameterList; - function isToken(n) { - return n.kind >= 0 /* FirstToken */ && n.kind <= 138 /* LastToken */; - } - ts.isToken = isToken; - function isWord(kind) { - return kind === 69 /* Identifier */ || ts.isKeyword(kind); - } - ts.isWord = isWord; - function isPropertyName(kind) { - return kind === 9 /* StringLiteral */ || kind === 8 /* NumericLiteral */ || isWord(kind); + return result; } - function isComment(kind) { - return kind === 2 /* SingleLineCommentTrivia */ || kind === 3 /* MultiLineCommentTrivia */; + /* @internal */ + function getSyntacticClassifications(cancellationToken, sourceFile, span) { + return convertClassifications(getEncodedSyntacticClassifications(cancellationToken, sourceFile, span)); } - ts.isComment = isComment; - function isStringOrRegularExpressionOrTemplateLiteral(kind) { - if (kind === 9 /* StringLiteral */ - || kind === 10 /* RegularExpressionLiteral */ - || ts.isTemplateLiteralKind(kind)) { - return true; + ts.getSyntacticClassifications = getSyntacticClassifications; + /* @internal */ + function getEncodedSyntacticClassifications(cancellationToken, sourceFile, span) { + var spanStart = span.start; + var spanLength = span.length; + // Make a scanner we can get trivia from. + var triviaScanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text); + var mergeConflictScanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text); + var result = []; + processElement(sourceFile); + return { spans: result, endOfLineState: 0 /* None */ }; + function pushClassification(start, length, type) { + result.push(start); + result.push(length); + result.push(type); + } + function classifyLeadingTriviaAndGetTokenStart(token) { + triviaScanner.setTextPos(token.pos); + while (true) { + var start = triviaScanner.getTextPos(); + // only bother scanning if we have something that could be trivia. + if (!ts.couldStartTrivia(sourceFile.text, start)) { + return start; + } + var kind = triviaScanner.scan(); + var end = triviaScanner.getTextPos(); + var width = end - start; + // The moment we get something that isn't trivia, then stop processing. + if (!ts.isTrivia(kind)) { + return start; + } + // Don't bother with newlines/whitespace. + if (kind === 4 /* NewLineTrivia */ || kind === 5 /* WhitespaceTrivia */) { + continue; + } + // Only bother with the trivia if it at least intersects the span of interest. + if (ts.isComment(kind)) { + classifyComment(token, kind, start, width); + // Classifying a comment might cause us to reuse the trivia scanner + // (because of jsdoc comments). So after we classify the comment make + // sure we set the scanner position back to where it needs to be. + triviaScanner.setTextPos(end); + continue; + } + if (kind === 7 /* ConflictMarkerTrivia */) { + var text = sourceFile.text; + var ch = text.charCodeAt(start); + // for the <<<<<<< and >>>>>>> markers, we just add them in as comments + // in the classification stream. + if (ch === 60 /* lessThan */ || ch === 62 /* greaterThan */) { + pushClassification(start, width, 1 /* comment */); + continue; + } + // for the ======== add a comment for the first line, and then lex all + // subsequent lines up until the end of the conflict marker. + ts.Debug.assert(ch === 61 /* equals */); + classifyDisabledMergeCode(text, start, end); + } + } } - return false; - } - ts.isStringOrRegularExpressionOrTemplateLiteral = isStringOrRegularExpressionOrTemplateLiteral; - function isPunctuation(kind) { - return 15 /* FirstPunctuation */ <= kind && kind <= 68 /* LastPunctuation */; - } - ts.isPunctuation = isPunctuation; - function isInsideTemplateLiteral(node, position) { - return ts.isTemplateLiteralKind(node.kind) - && (node.getStart() < position && position < node.getEnd()) || (!!node.isUnterminated && position === node.getEnd()); - } - ts.isInsideTemplateLiteral = isInsideTemplateLiteral; - function isAccessibilityModifier(kind) { - switch (kind) { - case 112 /* PublicKeyword */: - case 110 /* PrivateKeyword */: - case 111 /* ProtectedKeyword */: - return true; + function classifyComment(token, kind, start, width) { + if (kind === 3 /* MultiLineCommentTrivia */) { + // See if this is a doc comment. If so, we'll classify certain portions of it + // specially. + var docCommentAndDiagnostics = ts.parseIsolatedJSDocComment(sourceFile.text, start, width); + if (docCommentAndDiagnostics && docCommentAndDiagnostics.jsDoc) { + docCommentAndDiagnostics.jsDoc.parent = token; + classifyJSDocComment(docCommentAndDiagnostics.jsDoc); + return; + } + } + // Simple comment. Just add as is. + pushCommentRange(start, width); } - return false; - } - ts.isAccessibilityModifier = isAccessibilityModifier; - function compareDataObjects(dst, src) { - for (var e in dst) { - if (typeof dst[e] === "object") { - if (!compareDataObjects(dst[e], src[e])) { - return false; + function pushCommentRange(start, width) { + pushClassification(start, width, 1 /* comment */); + } + function classifyJSDocComment(docComment) { + var pos = docComment.pos; + if (docComment.tags) { + for (var _i = 0, _a = docComment.tags; _i < _a.length; _i++) { + var tag = _a[_i]; + // As we walk through each tag, classify the portion of text from the end of + // the last tag (or the start of the entire doc comment) as 'comment'. + if (tag.pos !== pos) { + pushCommentRange(pos, tag.pos - pos); + } + pushClassification(tag.atToken.pos, tag.atToken.end - tag.atToken.pos, 10 /* punctuation */); + pushClassification(tag.tagName.pos, tag.tagName.end - tag.tagName.pos, 18 /* docCommentTagName */); + pos = tag.tagName.end; + switch (tag.kind) { + case 275 /* JSDocParameterTag */: + processJSDocParameterTag(tag); + break; + case 278 /* JSDocTemplateTag */: + processJSDocTemplateTag(tag); + break; + case 277 /* JSDocTypeTag */: + processElement(tag.typeExpression); + break; + case 276 /* JSDocReturnTag */: + processElement(tag.typeExpression); + break; + } + pos = tag.end; } } - else if (typeof dst[e] !== "function") { - if (dst[e] !== src[e]) { - return false; + if (pos !== docComment.end) { + pushCommentRange(pos, docComment.end - pos); + } + return; + function processJSDocParameterTag(tag) { + if (tag.preParameterName) { + pushCommentRange(pos, tag.preParameterName.pos - pos); + pushClassification(tag.preParameterName.pos, tag.preParameterName.end - tag.preParameterName.pos, 17 /* parameterName */); + pos = tag.preParameterName.end; + } + if (tag.typeExpression) { + pushCommentRange(pos, tag.typeExpression.pos - pos); + processElement(tag.typeExpression); + pos = tag.typeExpression.end; + } + if (tag.postParameterName) { + pushCommentRange(pos, tag.postParameterName.pos - pos); + pushClassification(tag.postParameterName.pos, tag.postParameterName.end - tag.postParameterName.pos, 17 /* parameterName */); + pos = tag.postParameterName.end; } } } - return true; - } - ts.compareDataObjects = compareDataObjects; - function isArrayLiteralOrObjectLiteralDestructuringPattern(node) { - if (node.kind === 170 /* ArrayLiteralExpression */ || - node.kind === 171 /* ObjectLiteralExpression */) { - // [a,b,c] from: - // [a, b, c] = someExpression; - if (node.parent.kind === 187 /* BinaryExpression */ && - node.parent.left === node && - node.parent.operatorToken.kind === 56 /* EqualsToken */) { - return true; + function processJSDocTemplateTag(tag) { + for (var _i = 0, _a = tag.getChildren(); _i < _a.length; _i++) { + var child = _a[_i]; + processElement(child); } - // [a, b, c] from: - // for([a, b, c] of expression) - if (node.parent.kind === 208 /* ForOfStatement */ && - node.parent.initializer === node) { + } + function classifyDisabledMergeCode(text, start, end) { + // Classify the line that the ======= marker is on as a comment. Then just lex + // all further tokens and add them to the result. + var i; + for (i = start; i < end; i++) { + if (ts.isLineBreak(text.charCodeAt(i))) { + break; + } + } + pushClassification(start, i - start, 1 /* comment */); + mergeConflictScanner.setTextPos(i); + while (mergeConflictScanner.getTextPos() < end) { + classifyDisabledCodeToken(); + } + } + function classifyDisabledCodeToken() { + var start = mergeConflictScanner.getTextPos(); + var tokenKind = mergeConflictScanner.scan(); + var end = mergeConflictScanner.getTextPos(); + var type = classifyTokenType(tokenKind); + if (type) { + pushClassification(start, end - start, type); + } + } + /** + * Returns true if node should be treated as classified and no further processing is required. + * False will mean that node is not classified and traverse routine should recurse into node contents. + */ + function tryClassifyNode(node) { + if (ts.isJSDocTag(node)) { return true; } - // [a, b, c] of - // [x, [a, b, c] ] = someExpression - // or - // {x, a: {a, b, c} } = someExpression - if (isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent.kind === 253 /* PropertyAssignment */ ? node.parent.parent : node.parent)) { + if (ts.nodeIsMissing(node)) { return true; } + var classifiedElementName = tryClassifyJsxElementName(node); + if (!ts.isToken(node) && node.kind !== 244 /* JsxText */ && classifiedElementName === undefined) { + return false; + } + var tokenStart = node.kind === 244 /* JsxText */ ? node.pos : classifyLeadingTriviaAndGetTokenStart(node); + var tokenWidth = node.end - tokenStart; + ts.Debug.assert(tokenWidth >= 0); + if (tokenWidth > 0) { + var type = classifiedElementName || classifyTokenType(node.kind, node); + if (type) { + pushClassification(tokenStart, tokenWidth, type); + } + } + return true; + } + function tryClassifyJsxElementName(token) { + switch (token.parent && token.parent.kind) { + case 243 /* JsxOpeningElement */: + if (token.parent.tagName === token) { + return 19 /* jsxOpenTagName */; + } + break; + case 245 /* JsxClosingElement */: + if (token.parent.tagName === token) { + return 20 /* jsxCloseTagName */; + } + break; + case 242 /* JsxSelfClosingElement */: + if (token.parent.tagName === token) { + return 21 /* jsxSelfClosingTagName */; + } + break; + case 246 /* JsxAttribute */: + if (token.parent.name === token) { + return 22 /* jsxAttribute */; + } + break; + } + return undefined; + } + // for accurate classification, the actual token should be passed in. however, for + // cases like 'disabled merge code' classification, we just get the token kind and + // classify based on that instead. + function classifyTokenType(tokenKind, token) { + if (ts.isKeyword(tokenKind)) { + return 3 /* keyword */; + } + // Special case < and > If they appear in a generic context they are punctuation, + // not operators. + if (tokenKind === 25 /* LessThanToken */ || tokenKind === 27 /* GreaterThanToken */) { + // If the node owning the token has a type argument list or type parameter list, then + // we can effectively assume that a '<' and '>' belong to those lists. + if (token && ts.getTypeArgumentOrTypeParameterList(token.parent)) { + return 10 /* punctuation */; + } + } + if (ts.isPunctuation(tokenKind)) { + if (token) { + if (tokenKind === 56 /* EqualsToken */) { + // the '=' in a variable declaration is special cased here. + if (token.parent.kind === 218 /* VariableDeclaration */ || + token.parent.kind === 145 /* PropertyDeclaration */ || + token.parent.kind === 142 /* Parameter */ || + token.parent.kind === 246 /* JsxAttribute */) { + return 5 /* operator */; + } + } + if (token.parent.kind === 187 /* BinaryExpression */ || + token.parent.kind === 185 /* PrefixUnaryExpression */ || + token.parent.kind === 186 /* PostfixUnaryExpression */ || + token.parent.kind === 188 /* ConditionalExpression */) { + return 5 /* operator */; + } + } + return 10 /* punctuation */; + } + else if (tokenKind === 8 /* NumericLiteral */) { + return 4 /* numericLiteral */; + } + else if (tokenKind === 9 /* StringLiteral */) { + return token.parent.kind === 246 /* JsxAttribute */ ? 24 /* jsxAttributeStringLiteralValue */ : 6 /* stringLiteral */; + } + else if (tokenKind === 10 /* RegularExpressionLiteral */) { + // TODO: we should get another classification type for these literals. + return 6 /* stringLiteral */; + } + else if (ts.isTemplateLiteralKind(tokenKind)) { + // TODO (drosen): we should *also* get another classification type for these literals. + return 6 /* stringLiteral */; + } + else if (tokenKind === 244 /* JsxText */) { + return 23 /* jsxText */; + } + else if (tokenKind === 69 /* Identifier */) { + if (token) { + switch (token.parent.kind) { + case 221 /* ClassDeclaration */: + if (token.parent.name === token) { + return 11 /* className */; + } + return; + case 141 /* TypeParameter */: + if (token.parent.name === token) { + return 15 /* typeParameterName */; + } + return; + case 222 /* InterfaceDeclaration */: + if (token.parent.name === token) { + return 13 /* interfaceName */; + } + return; + case 224 /* EnumDeclaration */: + if (token.parent.name === token) { + return 12 /* enumName */; + } + return; + case 225 /* ModuleDeclaration */: + if (token.parent.name === token) { + return 14 /* moduleName */; + } + return; + case 142 /* Parameter */: + if (token.parent.name === token) { + var isThis_1 = token.kind === 69 /* Identifier */ && token.originalKeywordKind === 97 /* ThisKeyword */; + return isThis_1 ? 3 /* keyword */ : 17 /* parameterName */; + } + return; + } + } + return 2 /* identifier */; + } + } + function processElement(element) { + if (!element) { + return; + } + // Ignore nodes that don't intersect the original span to classify. + if (ts.decodedTextSpanIntersectsWith(spanStart, spanLength, element.pos, element.getFullWidth())) { + checkForClassificationCancellation(cancellationToken, element.kind); + var children = element.getChildren(sourceFile); + for (var i = 0, n = children.length; i < n; i++) { + var child = children[i]; + if (!tryClassifyNode(child)) { + // Recurse into our child nodes. + processElement(child); + } + } + } } - return false; } - ts.isArrayLiteralOrObjectLiteralDestructuringPattern = isArrayLiteralOrObjectLiteralDestructuringPattern; + ts.getEncodedSyntacticClassifications = getEncodedSyntacticClassifications; })(ts || (ts = {})); -// Display-part writer helpers /* @internal */ var ts; (function (ts) { - function isFirstDeclarationOfSymbolParameter(symbol) { - return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === 142 /* Parameter */; - } - ts.isFirstDeclarationOfSymbolParameter = isFirstDeclarationOfSymbolParameter; - var displayPartWriter = getDisplayPartWriter(); - function getDisplayPartWriter() { - var displayParts; - var lineStart; - var indent; - resetWriter(); - return { - displayParts: function () { return displayParts; }, - writeKeyword: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.keyword); }, - writeOperator: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.operator); }, - writePunctuation: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.punctuation); }, - writeSpace: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.space); }, - writeStringLiteral: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.stringLiteral); }, - writeParameter: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.parameterName); }, - writeSymbol: writeSymbol, - writeLine: writeLine, - increaseIndent: function () { indent++; }, - decreaseIndent: function () { indent--; }, - clear: resetWriter, - trackSymbol: function () { }, - reportInaccessibleThisError: function () { } - }; - function writeIndent() { - if (lineStart) { - var indentString = ts.getIndentString(indent); - if (indentString) { - displayParts.push(displayPart(indentString, ts.SymbolDisplayPartKind.space)); + var Completions; + (function (Completions) { + function getCompletionsAtPosition(host, typeChecker, log, compilerOptions, sourceFile, position) { + if (ts.isInReferenceComment(sourceFile, position)) { + return getTripleSlashReferenceCompletion(sourceFile, position); + } + if (ts.isInString(sourceFile, position)) { + return getStringLiteralCompletionEntries(sourceFile, position); + } + var completionData = getCompletionData(typeChecker, log, sourceFile, position); + if (!completionData) { + return undefined; + } + var symbols = completionData.symbols, isMemberCompletion = completionData.isMemberCompletion, isNewIdentifierLocation = completionData.isNewIdentifierLocation, location = completionData.location, isJsDocTagName = completionData.isJsDocTagName; + if (isJsDocTagName) { + // If the current position is a jsDoc tag name, only tag names should be provided for completion + return { isMemberCompletion: false, isNewIdentifierLocation: false, entries: ts.JsDoc.getAllJsDocCompletionEntries() }; + } + var entries = []; + if (ts.isSourceFileJavaScript(sourceFile)) { + var uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, /*performCharacterChecks*/ false); + ts.addRange(entries, getJavaScriptCompletionEntries(sourceFile, location.pos, uniqueNames)); + } + else { + if (!symbols || symbols.length === 0) { + if (sourceFile.languageVariant === 1 /* JSX */ && + location.parent && location.parent.kind === 245 /* JsxClosingElement */) { + // In the TypeScript JSX element, if such element is not defined. When users query for completion at closing tag, + // instead of simply giving unknown value, the completion will return the tag-name of an associated opening-element. + // For example: + // var x =
completion list at "1" will contain "div" with type any + var tagName = location.parent.parent.openingElement.tagName; + entries.push({ + name: tagName.text, + kind: undefined, + kindModifiers: undefined, + sortText: "0", + }); + } + else { + return undefined; + } + } + getCompletionEntriesFromSymbols(symbols, entries, location, /*performCharacterChecks*/ true); + } + // Add keywords if this is not a member completion list + if (!isMemberCompletion && !isJsDocTagName) { + ts.addRange(entries, keywordCompletions); + } + return { isMemberCompletion: isMemberCompletion, isNewIdentifierLocation: isNewIdentifierLocation, entries: entries }; + function getJavaScriptCompletionEntries(sourceFile, position, uniqueNames) { + var entries = []; + var nameTable = ts.getNameTable(sourceFile); + for (var name_49 in nameTable) { + // Skip identifiers produced only from the current location + if (nameTable[name_49] === position) { + continue; + } + if (!uniqueNames[name_49]) { + uniqueNames[name_49] = name_49; + var displayName = getCompletionEntryDisplayName(ts.unescapeIdentifier(name_49), compilerOptions.target, /*performCharacterChecks*/ true); + if (displayName) { + var entry = { + name: displayName, + kind: ts.ScriptElementKind.warning, + kindModifiers: "", + sortText: "1" + }; + entries.push(entry); + } + } + } + return entries; + } + function createCompletionEntry(symbol, location, performCharacterChecks) { + // Try to get a valid display name for this symbol, if we could not find one, then ignore it. + // We would like to only show things that can be added after a dot, so for instance numeric properties can + // not be accessed with a dot (a.1 <- invalid) + var displayName = getCompletionEntryDisplayNameForSymbol(typeChecker, symbol, compilerOptions.target, performCharacterChecks, location); + if (!displayName) { + return undefined; + } + // TODO(drosen): Right now we just permit *all* semantic meanings when calling + // 'getSymbolKind' which is permissible given that it is backwards compatible; but + // really we should consider passing the meaning for the node so that we don't report + // that a suggestion for a value is an interface. We COULD also just do what + // 'getSymbolModifiers' does, which is to use the first declaration. + // Use a 'sortText' of 0' so that all symbol completion entries come before any other + // entries (like JavaScript identifier entries). + return { + name: displayName, + kind: ts.SymbolDisplay.getSymbolKind(typeChecker, symbol, location), + kindModifiers: ts.SymbolDisplay.getSymbolModifiers(symbol), + sortText: "0", + }; + } + function getCompletionEntriesFromSymbols(symbols, entries, location, performCharacterChecks) { + var start = ts.timestamp(); + var uniqueNames = ts.createMap(); + if (symbols) { + for (var _i = 0, symbols_4 = symbols; _i < symbols_4.length; _i++) { + var symbol = symbols_4[_i]; + var entry = createCompletionEntry(symbol, location, performCharacterChecks); + if (entry) { + var id = ts.escapeIdentifier(entry.name); + if (!uniqueNames[id]) { + entries.push(entry); + uniqueNames[id] = id; + } + } + } + } + log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (ts.timestamp() - start)); + return uniqueNames; + } + function getStringLiteralCompletionEntries(sourceFile, position) { + var node = ts.findPrecedingToken(position, sourceFile); + if (!node || node.kind !== 9 /* StringLiteral */) { + return undefined; + } + if (node.parent.kind === 253 /* PropertyAssignment */ && node.parent.parent.kind === 171 /* ObjectLiteralExpression */) { + // Get quoted name of properties of the object literal expression + // i.e. interface ConfigFiles { + // 'jspm:dev': string + // } + // let files: ConfigFiles = { + // '/*completion position*/' + // } + // + // function foo(c: ConfigFiles) {} + // foo({ + // '/*completion position*/' + // }); + return getStringLiteralCompletionEntriesFromPropertyAssignment(node.parent); + } + else if (ts.isElementAccessExpression(node.parent) && node.parent.argumentExpression === node) { + // Get all names of properties on the expression + // i.e. interface A { + // 'prop1': string + // } + // let a: A; + // a['/*completion position*/'] + return getStringLiteralCompletionEntriesFromElementAccess(node.parent); + } + else if (node.parent.kind === 230 /* ImportDeclaration */ || ts.isExpressionOfExternalModuleImportEqualsDeclaration(node) || ts.isRequireCall(node.parent, false)) { + // Get all known external module names or complete a path to a module + // i.e. import * as ns from "/*completion position*/"; + // import x = require("/*completion position*/"); + // var y = require("/*completion position*/"); + return getStringLiteralCompletionEntriesFromModuleNames(node); + } + else { + var argumentInfo = ts.SignatureHelp.getContainingArgumentInfo(node, position, sourceFile); + if (argumentInfo) { + // Get string literal completions from specialized signatures of the target + // i.e. declare function f(a: 'A'); + // f("/*completion position*/") + return getStringLiteralCompletionEntriesFromCallExpression(argumentInfo, node); + } + // Get completion for string literal from string literal type + // i.e. var x: "hi" | "hello" = "/*completion position*/" + return getStringLiteralCompletionEntriesFromContextualType(node); + } + } + function getStringLiteralCompletionEntriesFromPropertyAssignment(element) { + var type = typeChecker.getContextualType(element.parent); + var entries = []; + if (type) { + getCompletionEntriesFromSymbols(type.getApparentProperties(), entries, element, /*performCharacterChecks*/ false); + if (entries.length) { + return { isMemberCompletion: true, isNewIdentifierLocation: true, entries: entries }; + } + } + } + function getStringLiteralCompletionEntriesFromCallExpression(argumentInfo, location) { + var candidates = []; + var entries = []; + typeChecker.getResolvedSignature(argumentInfo.invocation, candidates); + for (var _i = 0, candidates_3 = candidates; _i < candidates_3.length; _i++) { + var candidate = candidates_3[_i]; + if (candidate.parameters.length > argumentInfo.argumentIndex) { + var parameter = candidate.parameters[argumentInfo.argumentIndex]; + addStringLiteralCompletionsFromType(typeChecker.getTypeAtLocation(parameter.valueDeclaration), entries); + } } - lineStart = false; + if (entries.length) { + return { isMemberCompletion: false, isNewIdentifierLocation: true, entries: entries }; + } + return undefined; } - } - function writeKind(text, kind) { - writeIndent(); - displayParts.push(displayPart(text, kind)); - } - function writeSymbol(text, symbol) { - writeIndent(); - displayParts.push(symbolPart(text, symbol)); - } - function writeLine() { - displayParts.push(lineBreakPart()); - lineStart = true; - } - function resetWriter() { - displayParts = []; - lineStart = true; - indent = 0; - } - } - function symbolPart(text, symbol) { - return displayPart(text, displayPartKind(symbol), symbol); - function displayPartKind(symbol) { - var flags = symbol.flags; - if (flags & 3 /* Variable */) { - return isFirstDeclarationOfSymbolParameter(symbol) ? ts.SymbolDisplayPartKind.parameterName : ts.SymbolDisplayPartKind.localName; + function getStringLiteralCompletionEntriesFromElementAccess(node) { + var type = typeChecker.getTypeAtLocation(node.expression); + var entries = []; + if (type) { + getCompletionEntriesFromSymbols(type.getApparentProperties(), entries, node, /*performCharacterChecks*/ false); + if (entries.length) { + return { isMemberCompletion: true, isNewIdentifierLocation: true, entries: entries }; + } + } + return undefined; } - else if (flags & 4 /* Property */) { - return ts.SymbolDisplayPartKind.propertyName; + function getStringLiteralCompletionEntriesFromContextualType(node) { + var type = typeChecker.getContextualType(node); + if (type) { + var entries_2 = []; + addStringLiteralCompletionsFromType(type, entries_2); + if (entries_2.length) { + return { isMemberCompletion: false, isNewIdentifierLocation: false, entries: entries_2 }; + } + } + return undefined; } - else if (flags & 32768 /* GetAccessor */) { - return ts.SymbolDisplayPartKind.propertyName; + function addStringLiteralCompletionsFromType(type, result) { + if (!type) { + return; + } + if (type.flags & 524288 /* Union */) { + ts.forEach(type.types, function (t) { return addStringLiteralCompletionsFromType(t, result); }); + } + else { + if (type.flags & 32 /* StringLiteral */) { + result.push({ + name: type.text, + kindModifiers: ts.ScriptElementKindModifier.none, + kind: ts.ScriptElementKind.variableElement, + sortText: "0" + }); + } + } } - else if (flags & 65536 /* SetAccessor */) { - return ts.SymbolDisplayPartKind.propertyName; + function getStringLiteralCompletionEntriesFromModuleNames(node) { + var literalValue = ts.normalizeSlashes(node.text); + var scriptPath = node.getSourceFile().path; + var scriptDirectory = ts.getDirectoryPath(scriptPath); + var span = getDirectoryFragmentTextSpan(node.text, node.getStart() + 1); + var entries; + if (isPathRelativeToScript(literalValue) || ts.isRootedDiskPath(literalValue)) { + if (compilerOptions.rootDirs) { + entries = getCompletionEntriesForDirectoryFragmentWithRootDirs(compilerOptions.rootDirs, literalValue, scriptDirectory, ts.getSupportedExtensions(compilerOptions), /*includeExtensions*/ false, span, scriptPath); + } + else { + entries = getCompletionEntriesForDirectoryFragment(literalValue, scriptDirectory, ts.getSupportedExtensions(compilerOptions), /*includeExtensions*/ false, span, scriptPath); + } + } + else { + // Check for node modules + entries = getCompletionEntriesForNonRelativeModules(literalValue, scriptDirectory, span); + } + return { + isMemberCompletion: false, + isNewIdentifierLocation: true, + entries: entries + }; } - else if (flags & 8 /* EnumMember */) { - return ts.SymbolDisplayPartKind.enumMemberName; + /** + * Takes a script path and returns paths for all potential folders that could be merged with its + * containing folder via the "rootDirs" compiler option + */ + function getBaseDirectoriesFromRootDirs(rootDirs, basePath, scriptPath, ignoreCase) { + // Make all paths absolute/normalized if they are not already + rootDirs = ts.map(rootDirs, function (rootDirectory) { return ts.normalizePath(ts.isRootedDiskPath(rootDirectory) ? rootDirectory : ts.combinePaths(basePath, rootDirectory)); }); + // Determine the path to the directory containing the script relative to the root directory it is contained within + var relativeDirectory; + for (var _i = 0, rootDirs_1 = rootDirs; _i < rootDirs_1.length; _i++) { + var rootDirectory = rootDirs_1[_i]; + if (ts.containsPath(rootDirectory, scriptPath, basePath, ignoreCase)) { + relativeDirectory = scriptPath.substr(rootDirectory.length); + break; + } + } + // Now find a path for each potential directory that is to be merged with the one containing the script + return ts.deduplicate(ts.map(rootDirs, function (rootDirectory) { return ts.combinePaths(rootDirectory, relativeDirectory); })); } - else if (flags & 16 /* Function */) { - return ts.SymbolDisplayPartKind.functionName; + function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs, fragment, scriptPath, extensions, includeExtensions, span, exclude) { + var basePath = compilerOptions.project || host.getCurrentDirectory(); + var ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames()); + var baseDirectories = getBaseDirectoriesFromRootDirs(rootDirs, basePath, scriptPath, ignoreCase); + var result = []; + for (var _i = 0, baseDirectories_1 = baseDirectories; _i < baseDirectories_1.length; _i++) { + var baseDirectory = baseDirectories_1[_i]; + getCompletionEntriesForDirectoryFragment(fragment, baseDirectory, extensions, includeExtensions, span, exclude, result); + } + return result; } - else if (flags & 32 /* Class */) { - return ts.SymbolDisplayPartKind.className; + function getCompletionEntriesForDirectoryFragment(fragment, scriptPath, extensions, includeExtensions, span, exclude, result) { + if (result === void 0) { result = []; } + fragment = ts.getDirectoryPath(fragment); + if (!fragment) { + fragment = "./"; + } + else { + fragment = ts.ensureTrailingDirectorySeparator(fragment); + } + var absolutePath = normalizeAndPreserveTrailingSlash(ts.isRootedDiskPath(fragment) ? fragment : ts.combinePaths(scriptPath, fragment)); + var baseDirectory = ts.getDirectoryPath(absolutePath); + var ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames()); + if (tryDirectoryExists(host, baseDirectory)) { + // Enumerate the available files if possible + var files = tryReadDirectory(host, baseDirectory, extensions, /*exclude*/ undefined, /*include*/ ["./*"]); + if (files) { + var foundFiles = ts.createMap(); + for (var _i = 0, files_4 = files; _i < files_4.length; _i++) { + var filePath = files_4[_i]; + filePath = ts.normalizePath(filePath); + if (exclude && ts.comparePaths(filePath, exclude, scriptPath, ignoreCase) === 0 /* EqualTo */) { + continue; + } + var foundFileName = includeExtensions ? ts.getBaseFileName(filePath) : ts.removeFileExtension(ts.getBaseFileName(filePath)); + if (!foundFiles[foundFileName]) { + foundFiles[foundFileName] = true; + } + } + for (var foundFile in foundFiles) { + result.push(createCompletionEntryForModule(foundFile, ts.ScriptElementKind.scriptElement, span)); + } + } + // If possible, get folder completion as well + var directories = tryGetDirectories(host, baseDirectory); + if (directories) { + for (var _a = 0, directories_2 = directories; _a < directories_2.length; _a++) { + var directory = directories_2[_a]; + var directoryName = ts.getBaseFileName(ts.normalizePath(directory)); + result.push(createCompletionEntryForModule(directoryName, ts.ScriptElementKind.directory, span)); + } + } + } + return result; } - else if (flags & 64 /* Interface */) { - return ts.SymbolDisplayPartKind.interfaceName; + /** + * Check all of the declared modules and those in node modules. Possible sources of modules: + * Modules that are found by the type checker + * Modules found relative to "baseUrl" compliler options (including patterns from "paths" compiler option) + * Modules from node_modules (i.e. those listed in package.json) + * This includes all files that are found in node_modules/moduleName/ with acceptable file extensions + */ + function getCompletionEntriesForNonRelativeModules(fragment, scriptPath, span) { + var baseUrl = compilerOptions.baseUrl, paths = compilerOptions.paths; + var result; + if (baseUrl) { + var fileExtensions = ts.getSupportedExtensions(compilerOptions); + var projectDir = compilerOptions.project || host.getCurrentDirectory(); + var absolute = ts.isRootedDiskPath(baseUrl) ? baseUrl : ts.combinePaths(projectDir, baseUrl); + result = getCompletionEntriesForDirectoryFragment(fragment, ts.normalizePath(absolute), fileExtensions, /*includeExtensions*/ false, span); + if (paths) { + for (var path in paths) { + if (paths.hasOwnProperty(path)) { + if (path === "*") { + if (paths[path]) { + for (var _i = 0, _a = paths[path]; _i < _a.length; _i++) { + var pattern = _a[_i]; + for (var _b = 0, _c = getModulesForPathsPattern(fragment, baseUrl, pattern, fileExtensions); _b < _c.length; _b++) { + var match = _c[_b]; + result.push(createCompletionEntryForModule(match, ts.ScriptElementKind.externalModuleName, span)); + } + } + } + } + else if (ts.startsWith(path, fragment)) { + var entry = paths[path] && paths[path].length === 1 && paths[path][0]; + if (entry) { + result.push(createCompletionEntryForModule(path, ts.ScriptElementKind.externalModuleName, span)); + } + } + } + } + } + } + else { + result = []; + } + getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, span, result); + for (var _d = 0, _e = enumeratePotentialNonRelativeModules(fragment, scriptPath, compilerOptions); _d < _e.length; _d++) { + var moduleName = _e[_d]; + result.push(createCompletionEntryForModule(moduleName, ts.ScriptElementKind.externalModuleName, span)); + } + return result; } - else if (flags & 384 /* Enum */) { - return ts.SymbolDisplayPartKind.enumName; + function getModulesForPathsPattern(fragment, baseUrl, pattern, fileExtensions) { + if (host.readDirectory) { + var parsed = ts.hasZeroOrOneAsteriskCharacter(pattern) ? ts.tryParsePattern(pattern) : undefined; + if (parsed) { + // The prefix has two effective parts: the directory path and the base component after the filepath that is not a + // full directory component. For example: directory/path/of/prefix/base* + var normalizedPrefix = normalizeAndPreserveTrailingSlash(parsed.prefix); + var normalizedPrefixDirectory = ts.getDirectoryPath(normalizedPrefix); + var normalizedPrefixBase = ts.getBaseFileName(normalizedPrefix); + var fragmentHasPath = fragment.indexOf(ts.directorySeparator) !== -1; + // Try and expand the prefix to include any path from the fragment so that we can limit the readDirectory call + var expandedPrefixDirectory = fragmentHasPath ? ts.combinePaths(normalizedPrefixDirectory, normalizedPrefixBase + ts.getDirectoryPath(fragment)) : normalizedPrefixDirectory; + var normalizedSuffix = ts.normalizePath(parsed.suffix); + var baseDirectory = ts.combinePaths(baseUrl, expandedPrefixDirectory); + var completePrefix = fragmentHasPath ? baseDirectory : ts.ensureTrailingDirectorySeparator(baseDirectory) + normalizedPrefixBase; + // If we have a suffix, then we need to read the directory all the way down. We could create a glob + // that encodes the suffix, but we would have to escape the character "?" which readDirectory + // doesn't support. For now, this is safer but slower + var includeGlob = normalizedSuffix ? "**/*" : "./*"; + var matches = tryReadDirectory(host, baseDirectory, fileExtensions, undefined, [includeGlob]); + if (matches) { + var result = []; + // Trim away prefix and suffix + for (var _i = 0, matches_1 = matches; _i < matches_1.length; _i++) { + var match = matches_1[_i]; + var normalizedMatch = ts.normalizePath(match); + if (!ts.endsWith(normalizedMatch, normalizedSuffix) || !ts.startsWith(normalizedMatch, completePrefix)) { + continue; + } + var start = completePrefix.length; + var length_6 = normalizedMatch.length - start - normalizedSuffix.length; + result.push(ts.removeFileExtension(normalizedMatch.substr(start, length_6))); + } + return result; + } + } + } + return undefined; } - else if (flags & 1536 /* Module */) { - return ts.SymbolDisplayPartKind.moduleName; + function enumeratePotentialNonRelativeModules(fragment, scriptPath, options) { + // Check If this is a nested module + var isNestedModule = fragment.indexOf(ts.directorySeparator) !== -1; + var moduleNameFragment = isNestedModule ? fragment.substr(0, fragment.lastIndexOf(ts.directorySeparator)) : undefined; + // Get modules that the type checker picked up + var ambientModules = ts.map(typeChecker.getAmbientModules(), function (sym) { return ts.stripQuotes(sym.name); }); + var nonRelativeModules = ts.filter(ambientModules, function (moduleName) { return ts.startsWith(moduleName, fragment); }); + // Nested modules of the form "module-name/sub" need to be adjusted to only return the string + // after the last '/' that appears in the fragment because that's where the replacement span + // starts + if (isNestedModule) { + var moduleNameWithSeperator_1 = ts.ensureTrailingDirectorySeparator(moduleNameFragment); + nonRelativeModules = ts.map(nonRelativeModules, function (moduleName) { + if (ts.startsWith(fragment, moduleNameWithSeperator_1)) { + return moduleName.substr(moduleNameWithSeperator_1.length); + } + return moduleName; + }); + } + if (!options.moduleResolution || options.moduleResolution === ts.ModuleResolutionKind.NodeJs) { + for (var _i = 0, _a = enumerateNodeModulesVisibleToScript(host, scriptPath); _i < _a.length; _i++) { + var visibleModule = _a[_i]; + if (!isNestedModule) { + nonRelativeModules.push(visibleModule.moduleName); + } + else if (ts.startsWith(visibleModule.moduleName, moduleNameFragment)) { + var nestedFiles = tryReadDirectory(host, visibleModule.moduleDir, ts.supportedTypeScriptExtensions, /*exclude*/ undefined, /*include*/ ["./*"]); + if (nestedFiles) { + for (var _b = 0, nestedFiles_1 = nestedFiles; _b < nestedFiles_1.length; _b++) { + var f = nestedFiles_1[_b]; + f = ts.normalizePath(f); + var nestedModule = ts.removeFileExtension(ts.getBaseFileName(f)); + nonRelativeModules.push(nestedModule); + } + } + } + } + } + return ts.deduplicate(nonRelativeModules); } - else if (flags & 8192 /* Method */) { - return ts.SymbolDisplayPartKind.methodName; + function getTripleSlashReferenceCompletion(sourceFile, position) { + var token = ts.getTokenAtPosition(sourceFile, position); + if (!token) { + return undefined; + } + var commentRanges = ts.getLeadingCommentRanges(sourceFile.text, token.pos); + if (!commentRanges || !commentRanges.length) { + return undefined; + } + var range = ts.forEach(commentRanges, function (commentRange) { return position >= commentRange.pos && position <= commentRange.end && commentRange; }); + if (!range) { + return undefined; + } + var text = sourceFile.text.substr(range.pos, position - range.pos); + var match = tripleSlashDirectiveFragmentRegex.exec(text); + if (match) { + var prefix = match[1]; + var kind = match[2]; + var toComplete = match[3]; + var scriptPath = ts.getDirectoryPath(sourceFile.path); + var entries_3; + if (kind === "path") { + // Give completions for a relative path + var span_10 = getDirectoryFragmentTextSpan(toComplete, range.pos + prefix.length); + entries_3 = getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, ts.getSupportedExtensions(compilerOptions), /*includeExtensions*/ true, span_10, sourceFile.path); + } + else { + // Give completions based on the typings available + var span_11 = { start: range.pos + prefix.length, length: match[0].length - prefix.length }; + entries_3 = getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, span_11); + } + return { + isMemberCompletion: false, + isNewIdentifierLocation: true, + entries: entries_3 + }; + } + return undefined; } - else if (flags & 262144 /* TypeParameter */) { - return ts.SymbolDisplayPartKind.typeParameterName; + function getCompletionEntriesFromTypings(host, options, scriptPath, span, result) { + if (result === void 0) { result = []; } + // Check for typings specified in compiler options + if (options.types) { + for (var _i = 0, _a = options.types; _i < _a.length; _i++) { + var moduleName = _a[_i]; + result.push(createCompletionEntryForModule(moduleName, ts.ScriptElementKind.externalModuleName, span)); + } + } + else if (host.getDirectories) { + var typeRoots = void 0; + try { + // Wrap in try catch because getEffectiveTypeRoots touches the filesystem + typeRoots = ts.getEffectiveTypeRoots(options, host); + } + catch (e) { } + if (typeRoots) { + for (var _b = 0, typeRoots_2 = typeRoots; _b < typeRoots_2.length; _b++) { + var root = typeRoots_2[_b]; + getCompletionEntriesFromDirectories(host, options, root, span, result); + } + } + } + if (host.getDirectories) { + // Also get all @types typings installed in visible node_modules directories + for (var _c = 0, _d = findPackageJsons(scriptPath); _c < _d.length; _c++) { + var packageJson = _d[_c]; + var typesDir = ts.combinePaths(ts.getDirectoryPath(packageJson), "node_modules/@types"); + getCompletionEntriesFromDirectories(host, options, typesDir, span, result); + } + } + return result; } - else if (flags & 524288 /* TypeAlias */) { - return ts.SymbolDisplayPartKind.aliasName; + function getCompletionEntriesFromDirectories(host, options, directory, span, result) { + if (host.getDirectories && tryDirectoryExists(host, directory)) { + var directories = tryGetDirectories(host, directory); + if (directories) { + for (var _i = 0, directories_3 = directories; _i < directories_3.length; _i++) { + var typeDirectory = directories_3[_i]; + typeDirectory = ts.normalizePath(typeDirectory); + result.push(createCompletionEntryForModule(ts.getBaseFileName(typeDirectory), ts.ScriptElementKind.externalModuleName, span)); + } + } + } } - else if (flags & 8388608 /* Alias */) { - return ts.SymbolDisplayPartKind.aliasName; + function findPackageJsons(currentDir) { + var paths = []; + var currentConfigPath; + while (true) { + currentConfigPath = ts.findConfigFile(currentDir, function (f) { return tryFileExists(host, f); }, "package.json"); + if (currentConfigPath) { + paths.push(currentConfigPath); + currentDir = ts.getDirectoryPath(currentConfigPath); + var parent_16 = ts.getDirectoryPath(currentDir); + if (currentDir === parent_16) { + break; + } + currentDir = parent_16; + } + else { + break; + } + } + return paths; } - return ts.SymbolDisplayPartKind.text; - } - } - ts.symbolPart = symbolPart; - function displayPart(text, kind, symbol) { - return { - text: text, - kind: ts.SymbolDisplayPartKind[kind] - }; - } - ts.displayPart = displayPart; - function spacePart() { - return displayPart(" ", ts.SymbolDisplayPartKind.space); - } - ts.spacePart = spacePart; - function keywordPart(kind) { - return displayPart(ts.tokenToString(kind), ts.SymbolDisplayPartKind.keyword); - } - ts.keywordPart = keywordPart; - function punctuationPart(kind) { - return displayPart(ts.tokenToString(kind), ts.SymbolDisplayPartKind.punctuation); - } - ts.punctuationPart = punctuationPart; - function operatorPart(kind) { - return displayPart(ts.tokenToString(kind), ts.SymbolDisplayPartKind.operator); - } - ts.operatorPart = operatorPart; - function textOrKeywordPart(text) { - var kind = ts.stringToToken(text); - return kind === undefined - ? textPart(text) - : keywordPart(kind); - } - ts.textOrKeywordPart = textOrKeywordPart; - function textPart(text) { - return displayPart(text, ts.SymbolDisplayPartKind.text); - } - ts.textPart = textPart; - var carriageReturnLineFeed = "\r\n"; - /** - * The default is CRLF. - */ - function getNewLineOrDefaultFromHost(host) { - return host.getNewLine ? host.getNewLine() : carriageReturnLineFeed; - } - ts.getNewLineOrDefaultFromHost = getNewLineOrDefaultFromHost; - function lineBreakPart() { - return displayPart("\n", ts.SymbolDisplayPartKind.lineBreak); - } - ts.lineBreakPart = lineBreakPart; - function mapToDisplayParts(writeDisplayParts) { - writeDisplayParts(displayPartWriter); - var result = displayPartWriter.displayParts(); - displayPartWriter.clear(); - return result; - } - ts.mapToDisplayParts = mapToDisplayParts; - function typeToDisplayParts(typechecker, type, enclosingDeclaration, flags) { - return mapToDisplayParts(function (writer) { - typechecker.getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags); - }); - } - ts.typeToDisplayParts = typeToDisplayParts; - function symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration, meaning, flags) { - return mapToDisplayParts(function (writer) { - typeChecker.getSymbolDisplayBuilder().buildSymbolDisplay(symbol, writer, enclosingDeclaration, meaning, flags); - }); - } - ts.symbolToDisplayParts = symbolToDisplayParts; - function signatureToDisplayParts(typechecker, signature, enclosingDeclaration, flags) { - return mapToDisplayParts(function (writer) { - typechecker.getSymbolDisplayBuilder().buildSignatureDisplay(signature, writer, enclosingDeclaration, flags); - }); - } - ts.signatureToDisplayParts = signatureToDisplayParts; - function getDeclaredName(typeChecker, symbol, location) { - // If this is an export or import specifier it could have been renamed using the 'as' syntax. - // If so we want to search for whatever is under the cursor. - if (isImportOrExportSpecifierName(location)) { - return location.getText(); - } - else if (ts.isStringOrNumericLiteral(location.kind) && - location.parent.kind === 140 /* ComputedPropertyName */) { - return location.text; - } - // Try to get the local symbol if we're dealing with an 'export default' - // since that symbol has the "true" name. - var localExportDefaultSymbol = ts.getLocalSymbolForExportDefault(symbol); - var name = typeChecker.symbolToString(localExportDefaultSymbol || symbol); - return name; - } - ts.getDeclaredName = getDeclaredName; - function isImportOrExportSpecifierName(location) { - return location.parent && - (location.parent.kind === 234 /* ImportSpecifier */ || location.parent.kind === 238 /* ExportSpecifier */) && - location.parent.propertyName === location; - } - ts.isImportOrExportSpecifierName = isImportOrExportSpecifierName; - /** - * Strip off existed single quotes or double quotes from a given string - * - * @return non-quoted string - */ - function stripQuotes(name) { - var length = name.length; - if (length >= 2 && - name.charCodeAt(0) === name.charCodeAt(length - 1) && - (name.charCodeAt(0) === 34 /* doubleQuote */ || name.charCodeAt(0) === 39 /* singleQuote */)) { - return name.substring(1, length - 1); - } - ; - return name; - } - ts.stripQuotes = stripQuotes; - function scriptKindIs(fileName, host) { - var scriptKinds = []; - for (var _i = 2; _i < arguments.length; _i++) { - scriptKinds[_i - 2] = arguments[_i]; - } - var scriptKind = getScriptKind(fileName, host); - return ts.forEach(scriptKinds, function (k) { return k === scriptKind; }); - } - ts.scriptKindIs = scriptKindIs; - function getScriptKind(fileName, host) { - // First check to see if the script kind was specified by the host. Chances are the host - // may override the default script kind for the file extension. - var scriptKind; - if (host && host.getScriptKind) { - scriptKind = host.getScriptKind(fileName); - } - if (!scriptKind) { - scriptKind = ts.getScriptKindFromFileName(fileName); - } - return ts.ensureScriptKind(fileName, scriptKind); - } - ts.getScriptKind = getScriptKind; - function parseAndReEmitConfigJSONFile(content) { - var options = { - fileName: "config.js", - compilerOptions: { - target: 2 /* ES6 */, - removeComments: true - }, - reportDiagnostics: true - }; - var _a = ts.transpileModule("(" + content + ")", options), outputText = _a.outputText, diagnostics = _a.diagnostics; - // Becasue the content was wrapped in "()", the start position of diagnostics needs to be subtract by 1 - // also, the emitted result will have "(" in the beginning and ");" in the end. We need to strip these - // as well - var trimmedOutput = outputText.trim(); - var configJsonObject = JSON.parse(trimmedOutput.substring(1, trimmedOutput.length - 2)); - for (var _i = 0, diagnostics_4 = diagnostics; _i < diagnostics_4.length; _i++) { - var diagnostic = diagnostics_4[_i]; - diagnostic.start = diagnostic.start - 1; - } - return { configJsonObject: configJsonObject, diagnostics: diagnostics }; - } - ts.parseAndReEmitConfigJSONFile = parseAndReEmitConfigJSONFile; -})(ts || (ts = {})); -// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0. -// See LICENSE.txt in the project root for complete license information. -/// -/* @internal */ -var ts; -(function (ts) { - var JsTyping; - (function (JsTyping) { - ; - ; - // A map of loose file names to library names - // that we are confident require typings - var safeList; - /** - * @param host is the object providing I/O related operations. - * @param fileNames are the file names that belong to the same project - * @param projectRootPath is the path to the project root directory - * @param safeListPath is the path used to retrieve the safe list - * @param packageNameToTypingLocation is the map of package names to their cached typing locations - * @param typingOptions are used to customize the typing inference process - * @param compilerOptions are used as a source for typing inference - */ - function discoverTypings(host, fileNames, projectRootPath, safeListPath, packageNameToTypingLocation, typingOptions, compilerOptions) { - // A typing name to typing file path mapping - var inferredTypings = ts.createMap(); - if (!typingOptions || !typingOptions.enableAutoDiscovery) { - return { cachedTypingPaths: [], newTypingNames: [], filesToWatch: [] }; + function enumerateNodeModulesVisibleToScript(host, scriptPath) { + var result = []; + if (host.readFile && host.fileExists) { + for (var _i = 0, _a = findPackageJsons(scriptPath); _i < _a.length; _i++) { + var packageJson = _a[_i]; + var contents = tryReadingPackageJson(packageJson); + if (!contents) { + return; + } + var nodeModulesDir = ts.combinePaths(ts.getDirectoryPath(packageJson), "node_modules"); + var foundModuleNames = []; + // Provide completions for all non @types dependencies + for (var _b = 0, nodeModulesDependencyKeys_1 = nodeModulesDependencyKeys; _b < nodeModulesDependencyKeys_1.length; _b++) { + var key = nodeModulesDependencyKeys_1[_b]; + addPotentialPackageNames(contents[key], foundModuleNames); + } + for (var _c = 0, foundModuleNames_1 = foundModuleNames; _c < foundModuleNames_1.length; _c++) { + var moduleName = foundModuleNames_1[_c]; + var moduleDir = ts.combinePaths(nodeModulesDir, moduleName); + result.push({ + moduleName: moduleName, + moduleDir: moduleDir + }); + } + } + } + return result; + function tryReadingPackageJson(filePath) { + try { + var fileText = tryReadFile(host, filePath); + return fileText ? JSON.parse(fileText) : undefined; + } + catch (e) { + return undefined; + } + } + function addPotentialPackageNames(dependencies, result) { + if (dependencies) { + for (var dep in dependencies) { + if (dependencies.hasOwnProperty(dep) && !ts.startsWith(dep, "@types/")) { + result.push(dep); + } + } + } + } } - // Only infer typings for .js and .jsx files - fileNames = ts.filter(ts.map(fileNames, ts.normalizePath), function (f) { return ts.scriptKindIs(f, /*LanguageServiceHost*/ undefined, 1 /* JS */, 2 /* JSX */); }); - if (!safeList) { - var result = ts.readConfigFile(safeListPath, function (path) { return host.readFile(path); }); - safeList = ts.createMap(result.config); + function createCompletionEntryForModule(name, kind, replacementSpan) { + return { name: name, kind: kind, kindModifiers: ts.ScriptElementKindModifier.none, sortText: name, replacementSpan: replacementSpan }; } - var filesToWatch = []; - // Directories to search for package.json, bower.json and other typing information - var searchDirs = []; - var exclude = []; - mergeTypings(typingOptions.include); - exclude = typingOptions.exclude || []; - var possibleSearchDirs = ts.map(fileNames, ts.getDirectoryPath); - if (projectRootPath !== undefined) { - possibleSearchDirs.push(projectRootPath); + // Replace everything after the last directory seperator that appears + function getDirectoryFragmentTextSpan(text, textStart) { + var index = text.lastIndexOf(ts.directorySeparator); + var offset = index !== -1 ? index + 1 : 0; + return { start: textStart + offset, length: text.length - offset }; } - searchDirs = ts.deduplicate(possibleSearchDirs); - for (var _i = 0, searchDirs_1 = searchDirs; _i < searchDirs_1.length; _i++) { - var searchDir = searchDirs_1[_i]; - var packageJsonPath = ts.combinePaths(searchDir, "package.json"); - getTypingNamesFromJson(packageJsonPath, filesToWatch); - var bowerJsonPath = ts.combinePaths(searchDir, "bower.json"); - getTypingNamesFromJson(bowerJsonPath, filesToWatch); - var nodeModulesPath = ts.combinePaths(searchDir, "node_modules"); - getTypingNamesFromNodeModuleFolder(nodeModulesPath); + // Returns true if the path is explicitly relative to the script (i.e. relative to . or ..) + function isPathRelativeToScript(path) { + if (path && path.length >= 2 && path.charCodeAt(0) === 46 /* dot */) { + var slashIndex = path.length >= 3 && path.charCodeAt(1) === 46 /* dot */ ? 2 : 1; + var slashCharCode = path.charCodeAt(slashIndex); + return slashCharCode === 47 /* slash */ || slashCharCode === 92 /* backslash */; + } + return false; } - getTypingNamesFromSourceFileNames(fileNames); - // Add the cached typing locations for inferred typings that are already installed - for (var name_39 in packageNameToTypingLocation) { - if (name_39 in inferredTypings && !inferredTypings[name_39]) { - inferredTypings[name_39] = packageNameToTypingLocation[name_39]; + function normalizeAndPreserveTrailingSlash(path) { + return ts.hasTrailingDirectorySeparator(path) ? ts.ensureTrailingDirectorySeparator(ts.normalizePath(path)) : ts.normalizePath(path); + } + } + Completions.getCompletionsAtPosition = getCompletionsAtPosition; + function getCompletionEntryDetails(typeChecker, log, compilerOptions, sourceFile, position, entryName) { + // Compute all the completion symbols again. + var completionData = getCompletionData(typeChecker, log, sourceFile, position); + if (completionData) { + var symbols = completionData.symbols, location_2 = completionData.location; + // Find the symbol with the matching entry name. + // We don't need to perform character checks here because we're only comparing the + // name against 'entryName' (which is known to be good), not building a new + // completion entry. + var symbol = ts.forEach(symbols, function (s) { return getCompletionEntryDisplayNameForSymbol(typeChecker, s, compilerOptions.target, /*performCharacterChecks*/ false, location_2) === entryName ? s : undefined; }); + if (symbol) { + var _a = ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, sourceFile, location_2, location_2, 7 /* All */), displayParts = _a.displayParts, documentation = _a.documentation, symbolKind = _a.symbolKind; + return { + name: entryName, + kindModifiers: ts.SymbolDisplay.getSymbolModifiers(symbol), + kind: symbolKind, + displayParts: displayParts, + documentation: documentation + }; } } - // Remove typings that the user has added to the exclude list - for (var _a = 0, exclude_1 = exclude; _a < exclude_1.length; _a++) { - var excludeTypingName = exclude_1[_a]; - delete inferredTypings[excludeTypingName]; + // Didn't find a symbol with this name. See if we can find a keyword instead. + var keywordCompletion = ts.forEach(keywordCompletions, function (c) { return c.name === entryName; }); + if (keywordCompletion) { + return { + name: entryName, + kind: ts.ScriptElementKind.keyword, + kindModifiers: ts.ScriptElementKindModifier.none, + displayParts: [ts.displayPart(entryName, ts.SymbolDisplayPartKind.keyword)], + documentation: undefined + }; } - var newTypingNames = []; - var cachedTypingPaths = []; - for (var typing in inferredTypings) { - if (inferredTypings[typing] !== undefined) { - cachedTypingPaths.push(inferredTypings[typing]); + return undefined; + } + Completions.getCompletionEntryDetails = getCompletionEntryDetails; + function getCompletionEntrySymbol(typeChecker, log, compilerOptions, sourceFile, position, entryName) { + // Compute all the completion symbols again. + var completionData = getCompletionData(typeChecker, log, sourceFile, position); + if (completionData) { + var symbols = completionData.symbols, location_3 = completionData.location; + // Find the symbol with the matching entry name. + // We don't need to perform character checks here because we're only comparing the + // name against 'entryName' (which is known to be good), not building a new + // completion entry. + return ts.forEach(symbols, function (s) { return getCompletionEntryDisplayNameForSymbol(typeChecker, s, compilerOptions.target, /*performCharacterChecks*/ false, location_3) === entryName ? s : undefined; }); + } + return undefined; + } + Completions.getCompletionEntrySymbol = getCompletionEntrySymbol; + function getCompletionData(typeChecker, log, sourceFile, position) { + var isJavaScriptFile = ts.isSourceFileJavaScript(sourceFile); + var isJsDocTagName = false; + var start = ts.timestamp(); + var currentToken = ts.getTokenAtPosition(sourceFile, position); + log("getCompletionData: Get current token: " + (ts.timestamp() - start)); + start = ts.timestamp(); + // Completion not allowed inside comments, bail out if this is the case + var insideComment = ts.isInsideComment(sourceFile, currentToken, position); + log("getCompletionData: Is inside comment: " + (ts.timestamp() - start)); + if (insideComment) { + // The current position is next to the '@' sign, when no tag name being provided yet. + // Provide a full list of tag names + if (ts.hasDocComment(sourceFile, position) && sourceFile.text.charCodeAt(position - 1) === 64 /* at */) { + isJsDocTagName = true; } - else { - newTypingNames.push(typing); + // Completion should work inside certain JsDoc tags. For example: + // /** @type {number | string} */ + // Completion should work in the brackets + var insideJsDocTagExpression = false; + var tag = ts.getJsDocTagAtPosition(sourceFile, position); + if (tag) { + if (tag.tagName.pos <= position && position <= tag.tagName.end) { + isJsDocTagName = true; + } + switch (tag.kind) { + case 277 /* JSDocTypeTag */: + case 275 /* JSDocParameterTag */: + case 276 /* JSDocReturnTag */: + var tagWithExpression = tag; + if (tagWithExpression.typeExpression) { + insideJsDocTagExpression = tagWithExpression.typeExpression.pos < position && position < tagWithExpression.typeExpression.end; + } + break; + } } + if (isJsDocTagName) { + return { symbols: undefined, isMemberCompletion: false, isNewIdentifierLocation: false, location: undefined, isRightOfDot: false, isJsDocTagName: isJsDocTagName }; + } + if (!insideJsDocTagExpression) { + // Proceed if the current position is in jsDoc tag expression; otherwise it is a normal + // comment or the plain text part of a jsDoc comment, so no completion should be available + log("Returning an empty list because completion was inside a regular comment or plain text part of a JsDoc comment."); + return undefined; + } + } + start = ts.timestamp(); + var previousToken = ts.findPrecedingToken(position, sourceFile); + log("getCompletionData: Get previous token 1: " + (ts.timestamp() - start)); + // The decision to provide completion depends on the contextToken, which is determined through the previousToken. + // Note: 'previousToken' (and thus 'contextToken') can be undefined if we are the beginning of the file + var contextToken = previousToken; + // Check if the caret is at the end of an identifier; this is a partial identifier that we want to complete: e.g. a.toS| + // Skip this partial identifier and adjust the contextToken to the token that precedes it. + if (contextToken && position <= contextToken.end && ts.isWord(contextToken.kind)) { + var start_2 = ts.timestamp(); + contextToken = ts.findPrecedingToken(contextToken.getFullStart(), sourceFile); + log("getCompletionData: Get previous token 2: " + (ts.timestamp() - start_2)); } - return { cachedTypingPaths: cachedTypingPaths, newTypingNames: newTypingNames, filesToWatch: filesToWatch }; - /** - * Merge a given list of typingNames to the inferredTypings map - */ - function mergeTypings(typingNames) { - if (!typingNames) { - return; + // Find the node where completion is requested on. + // Also determine whether we are trying to complete with members of that node + // or attributes of a JSX tag. + var node = currentToken; + var isRightOfDot = false; + var isRightOfOpenTag = false; + var isStartingCloseTag = false; + var location = ts.getTouchingPropertyName(sourceFile, position); + if (contextToken) { + // Bail out if this is a known invalid completion location + if (isCompletionListBlocker(contextToken)) { + log("Returning an empty list because completion was requested in an invalid position."); + return undefined; } - for (var _i = 0, typingNames_1 = typingNames; _i < typingNames_1.length; _i++) { - var typing = typingNames_1[_i]; - if (!(typing in inferredTypings)) { - inferredTypings[typing] = undefined; + var parent_17 = contextToken.parent, kind = contextToken.kind; + if (kind === 21 /* DotToken */) { + if (parent_17.kind === 172 /* PropertyAccessExpression */) { + node = contextToken.parent.expression; + isRightOfDot = true; } - } - } - /** - * Get the typing info from common package manager json files like package.json or bower.json - */ - function getTypingNamesFromJson(jsonPath, filesToWatch) { - var result = ts.readConfigFile(jsonPath, function (path) { return host.readFile(path); }); - if (result.config) { - var jsonConfig = result.config; - filesToWatch.push(jsonPath); - if (jsonConfig.dependencies) { - mergeTypings(ts.getOwnKeys(jsonConfig.dependencies)); + else if (parent_17.kind === 139 /* QualifiedName */) { + node = contextToken.parent.left; + isRightOfDot = true; } - if (jsonConfig.devDependencies) { - mergeTypings(ts.getOwnKeys(jsonConfig.devDependencies)); + else { + // There is nothing that precedes the dot, so this likely just a stray character + // or leading into a '...' token. Just bail out instead. + return undefined; } - if (jsonConfig.optionalDependencies) { - mergeTypings(ts.getOwnKeys(jsonConfig.optionalDependencies)); + } + else if (sourceFile.languageVariant === 1 /* JSX */) { + if (kind === 25 /* LessThanToken */) { + isRightOfOpenTag = true; + location = contextToken; } - if (jsonConfig.peerDependencies) { - mergeTypings(ts.getOwnKeys(jsonConfig.peerDependencies)); + else if (kind === 39 /* SlashToken */ && contextToken.parent.kind === 245 /* JsxClosingElement */) { + isStartingCloseTag = true; + location = contextToken; } } } - /** - * Infer typing names from given file names. For example, the file name "jquery-min.2.3.4.js" - * should be inferred to the 'jquery' typing name; and "angular-route.1.2.3.js" should be inferred - * to the 'angular-route' typing name. - * @param fileNames are the names for source files in the project - */ - function getTypingNamesFromSourceFileNames(fileNames) { - var jsFileNames = ts.filter(fileNames, ts.hasJavaScriptFileExtension); - var inferredTypingNames = ts.map(jsFileNames, function (f) { return ts.removeFileExtension(ts.getBaseFileName(f.toLowerCase())); }); - var cleanedTypingNames = ts.map(inferredTypingNames, function (f) { return f.replace(/((?:\.|-)min(?=\.|$))|((?:-|\.)\d+)/g, ""); }); - if (safeList === undefined) { - mergeTypings(cleanedTypingNames); + var semanticStart = ts.timestamp(); + var isMemberCompletion; + var isNewIdentifierLocation; + var symbols = []; + if (isRightOfDot) { + getTypeScriptMemberSymbols(); + } + else if (isRightOfOpenTag) { + var tagSymbols = typeChecker.getJsxIntrinsicTagNames(); + if (tryGetGlobalSymbols()) { + symbols = tagSymbols.concat(symbols.filter(function (s) { return !!(s.flags & (107455 /* Value */ | 8388608 /* Alias */)); })); } else { - mergeTypings(ts.filter(cleanedTypingNames, function (f) { return f in safeList; })); + symbols = tagSymbols; } - var hasJsxFile = ts.forEach(fileNames, function (f) { return ts.scriptKindIs(f, /*LanguageServiceHost*/ undefined, 2 /* JSX */); }); - if (hasJsxFile) { - mergeTypings(["react"]); + isMemberCompletion = true; + isNewIdentifierLocation = false; + } + else if (isStartingCloseTag) { + var tagName = contextToken.parent.parent.openingElement.tagName; + var tagSymbol = typeChecker.getSymbolAtLocation(tagName); + if (!typeChecker.isUnknownSymbol(tagSymbol)) { + symbols = [tagSymbol]; } + isMemberCompletion = true; + isNewIdentifierLocation = false; } - /** - * Infer typing names from node_module folder - * @param nodeModulesPath is the path to the "node_modules" folder - */ - function getTypingNamesFromNodeModuleFolder(nodeModulesPath) { - // Todo: add support for ModuleResolutionHost too - if (!host.directoryExists(nodeModulesPath)) { - return; + else { + // For JavaScript or TypeScript, if we're not after a dot, then just try to get the + // global symbols in scope. These results should be valid for either language as + // the set of symbols that can be referenced from this location. + if (!tryGetGlobalSymbols()) { + return undefined; } - var typingNames = []; - var fileNames = host.readDirectory(nodeModulesPath, ["*.json"], /*excludes*/ undefined, /*includes*/ undefined, /*depth*/ 2); - for (var _i = 0, fileNames_2 = fileNames; _i < fileNames_2.length; _i++) { - var fileName = fileNames_2[_i]; - var normalizedFileName = ts.normalizePath(fileName); - if (ts.getBaseFileName(normalizedFileName) !== "package.json") { - continue; - } - var result = ts.readConfigFile(normalizedFileName, function (path) { return host.readFile(path); }); - if (!result.config) { - continue; - } - var packageJson = result.config; - // npm 3's package.json contains a "_requiredBy" field - // we should include all the top level module names for npm 2, and only module names whose - // "_requiredBy" field starts with "#" or equals "/" for npm 3. - if (packageJson._requiredBy && - ts.filter(packageJson._requiredBy, function (r) { return r[0] === "#" || r === "/"; }).length === 0) { - continue; + } + log("getCompletionData: Semantic work: " + (ts.timestamp() - semanticStart)); + return { symbols: symbols, isMemberCompletion: isMemberCompletion, isNewIdentifierLocation: isNewIdentifierLocation, location: location, isRightOfDot: (isRightOfDot || isRightOfOpenTag), isJsDocTagName: isJsDocTagName }; + function getTypeScriptMemberSymbols() { + // Right of dot member completion list + isMemberCompletion = true; + isNewIdentifierLocation = false; + if (node.kind === 69 /* Identifier */ || node.kind === 139 /* QualifiedName */ || node.kind === 172 /* PropertyAccessExpression */) { + var symbol = typeChecker.getSymbolAtLocation(node); + // This is an alias, follow what it aliases + if (symbol && symbol.flags & 8388608 /* Alias */) { + symbol = typeChecker.getAliasedSymbol(symbol); } - // If the package has its own d.ts typings, those will take precedence. Otherwise the package name will be used - // to download d.ts files from DefinitelyTyped - if (!packageJson.name) { - continue; + if (symbol && symbol.flags & 1952 /* HasExports */) { + // Extract module or enum members + var exportedSymbols = typeChecker.getExportsOfModule(symbol); + ts.forEach(exportedSymbols, function (symbol) { + if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) { + symbols.push(symbol); + } + }); } - if (packageJson.typings) { - var absolutePath = ts.getNormalizedAbsolutePath(packageJson.typings, ts.getDirectoryPath(normalizedFileName)); - inferredTypings[packageJson.name] = absolutePath; + } + var type = typeChecker.getTypeAtLocation(node); + addTypeProperties(type); + } + function addTypeProperties(type) { + if (type) { + // Filter private properties + for (var _i = 0, _a = type.getApparentProperties(); _i < _a.length; _i++) { + var symbol = _a[_i]; + if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) { + symbols.push(symbol); + } } - else { - typingNames.push(packageJson.name); + if (isJavaScriptFile && type.flags & 524288 /* Union */) { + // In javascript files, for union types, we don't just get the members that + // the individual types have in common, we also include all the members that + // each individual type has. This is because we're going to add all identifiers + // anyways. So we might as well elevate the members that were at least part + // of the individual types to a higher status since we know what they are. + var unionType = type; + for (var _b = 0, _c = unionType.types; _b < _c.length; _b++) { + var elementType = _c[_b]; + addTypeProperties(elementType); + } } } - mergeTypings(typingNames); } - } - JsTyping.discoverTypings = discoverTypings; - })(JsTyping = ts.JsTyping || (ts.JsTyping = {})); -})(ts || (ts = {})); -/// -/// -/* @internal */ -var ts; -(function (ts) { - var formatting; - (function (formatting) { - var standardScanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ false, 0 /* Standard */); - var jsxScanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ false, 1 /* JSX */); - /** - * Scanner that is currently used for formatting - */ - var scanner; - var ScanAction; - (function (ScanAction) { - ScanAction[ScanAction["Scan"] = 0] = "Scan"; - ScanAction[ScanAction["RescanGreaterThanToken"] = 1] = "RescanGreaterThanToken"; - ScanAction[ScanAction["RescanSlashToken"] = 2] = "RescanSlashToken"; - ScanAction[ScanAction["RescanTemplateToken"] = 3] = "RescanTemplateToken"; - ScanAction[ScanAction["RescanJsxIdentifier"] = 4] = "RescanJsxIdentifier"; - ScanAction[ScanAction["RescanJsxText"] = 5] = "RescanJsxText"; - })(ScanAction || (ScanAction = {})); - function getFormattingScanner(sourceFile, startPos, endPos) { - ts.Debug.assert(scanner === undefined); - scanner = sourceFile.languageVariant === 1 /* JSX */ ? jsxScanner : standardScanner; - scanner.setText(sourceFile.text); - scanner.setTextPos(startPos); - var wasNewLine = true; - var leadingTrivia; - var trailingTrivia; - var savedPos; - var lastScanAction; - var lastTokenInfo; - return { - advance: advance, - readTokenInfo: readTokenInfo, - isOnToken: isOnToken, - getCurrentLeadingTrivia: function () { return leadingTrivia; }, - lastTrailingTriviaWasNewLine: function () { return wasNewLine; }, - skipToEndOf: skipToEndOf, - close: function () { - ts.Debug.assert(scanner !== undefined); - lastTokenInfo = undefined; - scanner.setText(undefined); - scanner = undefined; + function tryGetGlobalSymbols() { + var objectLikeContainer; + var namedImportsOrExports; + var jsxContainer; + if (objectLikeContainer = tryGetObjectLikeCompletionContainer(contextToken)) { + return tryGetObjectLikeCompletionSymbols(objectLikeContainer); } - }; - function advance() { - ts.Debug.assert(scanner !== undefined); - lastTokenInfo = undefined; - var isStarted = scanner.getStartPos() !== startPos; - if (isStarted) { - if (trailingTrivia) { - ts.Debug.assert(trailingTrivia.length !== 0); - wasNewLine = ts.lastOrUndefined(trailingTrivia).kind === 4 /* NewLineTrivia */; - } - else { - wasNewLine = false; + if (namedImportsOrExports = tryGetNamedImportsOrExportsForCompletion(contextToken)) { + // cursor is in an import clause + // try to show exported member for imported module + return tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports); + } + if (jsxContainer = tryGetContainingJsxElement(contextToken)) { + var attrsType = void 0; + if ((jsxContainer.kind === 242 /* JsxSelfClosingElement */) || (jsxContainer.kind === 243 /* JsxOpeningElement */)) { + // Cursor is inside a JSX self-closing element or opening element + attrsType = typeChecker.getJsxElementAttributesType(jsxContainer); + if (attrsType) { + symbols = filterJsxAttributes(typeChecker.getPropertiesOfType(attrsType), jsxContainer.attributes); + isMemberCompletion = true; + isNewIdentifierLocation = false; + return true; + } } } - leadingTrivia = undefined; - trailingTrivia = undefined; - if (!isStarted) { - scanner.scan(); + // Get all entities in the current scope. + isMemberCompletion = false; + isNewIdentifierLocation = isNewIdentifierDefinitionLocation(contextToken); + if (previousToken !== contextToken) { + ts.Debug.assert(!!previousToken, "Expected 'contextToken' to be defined when different from 'previousToken'."); } - var pos = scanner.getStartPos(); - // Read leading trivia and token - while (pos < endPos) { - var t = scanner.getToken(); - if (!ts.isTrivia(t)) { - break; + // We need to find the node that will give us an appropriate scope to begin + // aggregating completion candidates. This is achieved in 'getScopeNode' + // by finding the first node that encompasses a position, accounting for whether a node + // is "complete" to decide whether a position belongs to the node. + // + // However, at the end of an identifier, we are interested in the scope of the identifier + // itself, but fall outside of the identifier. For instance: + // + // xyz => x$ + // + // the cursor is outside of both the 'x' and the arrow function 'xyz => x', + // so 'xyz' is not returned in our results. + // + // We define 'adjustedPosition' so that we may appropriately account for + // being at the end of an identifier. The intention is that if requesting completion + // at the end of an identifier, it should be effectively equivalent to requesting completion + // anywhere inside/at the beginning of the identifier. So in the previous case, the + // 'adjustedPosition' will work as if requesting completion in the following: + // + // xyz => $x + // + // If previousToken !== contextToken, then + // - 'contextToken' was adjusted to the token prior to 'previousToken' + // because we were at the end of an identifier. + // - 'previousToken' is defined. + var adjustedPosition = previousToken !== contextToken ? + previousToken.getStart() : + position; + var scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile; + /// TODO filter meaning based on the current context + var symbolMeanings = 793064 /* Type */ | 107455 /* Value */ | 1920 /* Namespace */ | 8388608 /* Alias */; + symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings); + return true; + } + /** + * Finds the first node that "embraces" the position, so that one may + * accurately aggregate locals from the closest containing scope. + */ + function getScopeNode(initialToken, position, sourceFile) { + var scope = initialToken; + while (scope && !ts.positionBelongsToNode(scope, position, sourceFile)) { + scope = scope.parent; + } + return scope; + } + function isCompletionListBlocker(contextToken) { + var start = ts.timestamp(); + var result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) || + isSolelyIdentifierDefinitionLocation(contextToken) || + isDotOfNumericLiteral(contextToken) || + isInJsxText(contextToken); + log("getCompletionsAtPosition: isCompletionListBlocker: " + (ts.timestamp() - start)); + return result; + } + function isInJsxText(contextToken) { + if (contextToken.kind === 244 /* JsxText */) { + return true; + } + if (contextToken.kind === 27 /* GreaterThanToken */ && contextToken.parent) { + if (contextToken.parent.kind === 243 /* JsxOpeningElement */) { + return true; } - // consume leading trivia - scanner.scan(); - var item = { - pos: pos, - end: scanner.getStartPos(), - kind: t - }; - pos = scanner.getStartPos(); - if (!leadingTrivia) { - leadingTrivia = []; + if (contextToken.parent.kind === 245 /* JsxClosingElement */ || contextToken.parent.kind === 242 /* JsxSelfClosingElement */) { + return contextToken.parent.parent && contextToken.parent.parent.kind === 241 /* JsxElement */; } - leadingTrivia.push(item); } - savedPos = scanner.getStartPos(); + return false; } - function shouldRescanGreaterThanToken(node) { - if (node) { - switch (node.kind) { - case 29 /* GreaterThanEqualsToken */: - case 64 /* GreaterThanGreaterThanEqualsToken */: - case 65 /* GreaterThanGreaterThanGreaterThanEqualsToken */: - case 45 /* GreaterThanGreaterThanGreaterThanToken */: - case 44 /* GreaterThanGreaterThanToken */: + function isNewIdentifierDefinitionLocation(previousToken) { + if (previousToken) { + var containingNodeKind = previousToken.parent.kind; + switch (previousToken.kind) { + case 24 /* CommaToken */: + return containingNodeKind === 174 /* CallExpression */ // func( a, | + || containingNodeKind === 148 /* Constructor */ // constructor( a, | /* public, protected, private keywords are allowed here, so show completion */ + || containingNodeKind === 175 /* NewExpression */ // new C(a, | + || containingNodeKind === 170 /* ArrayLiteralExpression */ // [a, | + || containingNodeKind === 187 /* BinaryExpression */ // const x = (a, | + || containingNodeKind === 156 /* FunctionType */; // var x: (s: string, list| + case 17 /* OpenParenToken */: + return containingNodeKind === 174 /* CallExpression */ // func( | + || containingNodeKind === 148 /* Constructor */ // constructor( | + || containingNodeKind === 175 /* NewExpression */ // new C(a| + || containingNodeKind === 178 /* ParenthesizedExpression */ // const x = (a| + || containingNodeKind === 164 /* ParenthesizedType */; // function F(pred: (a| /* this can become an arrow function, where 'a' is the argument */ + case 19 /* OpenBracketToken */: + return containingNodeKind === 170 /* ArrayLiteralExpression */ // [ | + || containingNodeKind === 153 /* IndexSignature */ // [ | : string ] + || containingNodeKind === 140 /* ComputedPropertyName */; // [ | /* this can become an index signature */ + case 125 /* ModuleKeyword */: // module | + case 126 /* NamespaceKeyword */: + return true; + case 21 /* DotToken */: + return containingNodeKind === 225 /* ModuleDeclaration */; // module A.| + case 15 /* OpenBraceToken */: + return containingNodeKind === 221 /* ClassDeclaration */; // class A{ | + case 56 /* EqualsToken */: + return containingNodeKind === 218 /* VariableDeclaration */ // const x = a| + || containingNodeKind === 187 /* BinaryExpression */; // x = a| + case 12 /* TemplateHead */: + return containingNodeKind === 189 /* TemplateExpression */; // `aa ${| + case 13 /* TemplateMiddle */: + return containingNodeKind === 197 /* TemplateSpan */; // `aa ${10} dd ${| + case 112 /* PublicKeyword */: + case 110 /* PrivateKeyword */: + case 111 /* ProtectedKeyword */: + return containingNodeKind === 145 /* PropertyDeclaration */; // class A{ public | + } + // Previous token may have been a keyword that was converted to an identifier. + switch (previousToken.getText()) { + case "public": + case "protected": + case "private": return true; } } return false; } - function shouldRescanJsxIdentifier(node) { - if (node.parent) { - switch (node.parent.kind) { - case 246 /* JsxAttribute */: - case 243 /* JsxOpeningElement */: - case 245 /* JsxClosingElement */: - case 242 /* JsxSelfClosingElement */: - return node.kind === 69 /* Identifier */; + function isInStringOrRegularExpressionOrTemplateLiteral(contextToken) { + if (contextToken.kind === 9 /* StringLiteral */ + || contextToken.kind === 10 /* RegularExpressionLiteral */ + || ts.isTemplateLiteralKind(contextToken.kind)) { + var start_3 = contextToken.getStart(); + var end = contextToken.getEnd(); + // To be "in" one of these literals, the position has to be: + // 1. entirely within the token text. + // 2. at the end position of an unterminated token. + // 3. at the end of a regular expression (due to trailing flags like '/foo/g'). + if (start_3 < position && position < end) { + return true; + } + if (position === end) { + return !!contextToken.isUnterminated + || contextToken.kind === 10 /* RegularExpressionLiteral */; } } return false; } - function shouldRescanJsxText(node) { - return node && node.kind === 244 /* JsxText */; - } - function shouldRescanSlashToken(container) { - return container.kind === 10 /* RegularExpressionLiteral */; - } - function shouldRescanTemplateToken(container) { - return container.kind === 13 /* TemplateMiddle */ || - container.kind === 14 /* TemplateTail */; - } - function startsWithSlashToken(t) { - return t === 39 /* SlashToken */ || t === 61 /* SlashEqualsToken */; - } - function readTokenInfo(n) { - ts.Debug.assert(scanner !== undefined); - if (!isOnToken()) { - // scanner is not on the token (either advance was not called yet or scanner is already past the end position) - return { - leadingTrivia: leadingTrivia, - trailingTrivia: undefined, - token: undefined - }; - } - // normally scanner returns the smallest available token - // check the kind of context node to determine if scanner should have more greedy behavior and consume more text. - var expectedScanAction = shouldRescanGreaterThanToken(n) - ? 1 /* RescanGreaterThanToken */ - : shouldRescanSlashToken(n) - ? 2 /* RescanSlashToken */ - : shouldRescanTemplateToken(n) - ? 3 /* RescanTemplateToken */ - : shouldRescanJsxIdentifier(n) - ? 4 /* RescanJsxIdentifier */ - : shouldRescanJsxText(n) - ? 5 /* RescanJsxText */ - : 0 /* Scan */; - if (lastTokenInfo && expectedScanAction === lastScanAction) { - // readTokenInfo was called before with the same expected scan action. - // No need to re-scan text, return existing 'lastTokenInfo' - // it is ok to call fixTokenKind here since it does not affect - // what portion of text is consumed. In contrast rescanning can change it, - // i.e. for '>=' when originally scanner eats just one character - // and rescanning forces it to consume more. - return fixTokenKind(lastTokenInfo, n); - } - if (scanner.getStartPos() !== savedPos) { - ts.Debug.assert(lastTokenInfo !== undefined); - // readTokenInfo was called before but scan action differs - rescan text - scanner.setTextPos(savedPos); - scanner.scan(); - } - var currentToken = scanner.getToken(); - if (expectedScanAction === 1 /* RescanGreaterThanToken */ && currentToken === 27 /* GreaterThanToken */) { - currentToken = scanner.reScanGreaterToken(); - ts.Debug.assert(n.kind === currentToken); - lastScanAction = 1 /* RescanGreaterThanToken */; + /** + * Aggregates relevant symbols for completion in object literals and object binding patterns. + * Relevant symbols are stored in the captured 'symbols' variable. + * + * @returns true if 'symbols' was successfully populated; false otherwise. + */ + function tryGetObjectLikeCompletionSymbols(objectLikeContainer) { + // We're looking up possible property names from contextual/inferred/declared type. + isMemberCompletion = true; + var typeForObject; + var existingMembers; + if (objectLikeContainer.kind === 171 /* ObjectLiteralExpression */) { + // We are completing on contextual types, but may also include properties + // other than those within the declared type. + isNewIdentifierLocation = true; + // If the object literal is being assigned to something of type 'null | { hello: string }', + // it clearly isn't trying to satisfy the 'null' type. So we grab the non-nullable type if possible. + typeForObject = typeChecker.getContextualType(objectLikeContainer); + typeForObject = typeForObject && typeForObject.getNonNullableType(); + existingMembers = objectLikeContainer.properties; } - else if (expectedScanAction === 2 /* RescanSlashToken */ && startsWithSlashToken(currentToken)) { - currentToken = scanner.reScanSlashToken(); - ts.Debug.assert(n.kind === currentToken); - lastScanAction = 2 /* RescanSlashToken */; + else if (objectLikeContainer.kind === 167 /* ObjectBindingPattern */) { + // We are *only* completing on properties from the type being destructured. + isNewIdentifierLocation = false; + var rootDeclaration = ts.getRootDeclaration(objectLikeContainer.parent); + if (ts.isVariableLike(rootDeclaration)) { + // We don't want to complete using the type acquired by the shape + // of the binding pattern; we are only interested in types acquired + // through type declaration or inference. + // Also proceed if rootDeclaration is a parameter and if its containing function expression/arrow function is contextually typed - + // type of parameter will flow in from the contextual type of the function + var canGetType = !!(rootDeclaration.initializer || rootDeclaration.type); + if (!canGetType && rootDeclaration.kind === 142 /* Parameter */) { + if (ts.isExpression(rootDeclaration.parent)) { + canGetType = !!typeChecker.getContextualType(rootDeclaration.parent); + } + else if (rootDeclaration.parent.kind === 147 /* MethodDeclaration */ || rootDeclaration.parent.kind === 150 /* SetAccessor */) { + canGetType = ts.isExpression(rootDeclaration.parent.parent) && !!typeChecker.getContextualType(rootDeclaration.parent.parent); + } + } + if (canGetType) { + typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer); + existingMembers = objectLikeContainer.elements; + } + } + else { + ts.Debug.fail("Root declaration is not variable-like."); + } } - else if (expectedScanAction === 3 /* RescanTemplateToken */ && currentToken === 16 /* CloseBraceToken */) { - currentToken = scanner.reScanTemplateToken(); - lastScanAction = 3 /* RescanTemplateToken */; + else { + ts.Debug.fail("Expected object literal or binding pattern, got " + objectLikeContainer.kind); } - else if (expectedScanAction === 4 /* RescanJsxIdentifier */ && currentToken === 69 /* Identifier */) { - currentToken = scanner.scanJsxIdentifier(); - lastScanAction = 4 /* RescanJsxIdentifier */; + if (!typeForObject) { + return false; } - else if (expectedScanAction === 5 /* RescanJsxText */) { - currentToken = scanner.reScanJsxToken(); - lastScanAction = 5 /* RescanJsxText */; + var typeMembers = typeChecker.getPropertiesOfType(typeForObject); + if (typeMembers && typeMembers.length > 0) { + // Add filtered items to the completion list + symbols = filterObjectMembersList(typeMembers, existingMembers); } - else { - lastScanAction = 0 /* Scan */; + return true; + } + /** + * Aggregates relevant symbols for completion in import clauses and export clauses + * whose declarations have a module specifier; for instance, symbols will be aggregated for + * + * import { | } from "moduleName"; + * export { a as foo, | } from "moduleName"; + * + * but not for + * + * export { | }; + * + * Relevant symbols are stored in the captured 'symbols' variable. + * + * @returns true if 'symbols' was successfully populated; false otherwise. + */ + function tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports) { + var declarationKind = namedImportsOrExports.kind === 233 /* NamedImports */ ? + 230 /* ImportDeclaration */ : + 236 /* ExportDeclaration */; + var importOrExportDeclaration = ts.getAncestor(namedImportsOrExports, declarationKind); + var moduleSpecifier = importOrExportDeclaration.moduleSpecifier; + if (!moduleSpecifier) { + return false; } - var token = { - pos: scanner.getStartPos(), - end: scanner.getTextPos(), - kind: currentToken - }; - // consume trailing trivia - if (trailingTrivia) { - trailingTrivia = undefined; + isMemberCompletion = true; + isNewIdentifierLocation = false; + var exports; + var moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importOrExportDeclaration.moduleSpecifier); + if (moduleSpecifierSymbol) { + exports = typeChecker.getExportsOfModule(moduleSpecifierSymbol); } - while (scanner.getStartPos() < endPos) { - currentToken = scanner.scan(); - if (!ts.isTrivia(currentToken)) { - break; - } - var trivia = { - pos: scanner.getStartPos(), - end: scanner.getTextPos(), - kind: currentToken - }; - if (!trailingTrivia) { - trailingTrivia = []; - } - trailingTrivia.push(trivia); - if (currentToken === 4 /* NewLineTrivia */) { - // move past new line - scanner.scan(); - break; + symbols = exports ? filterNamedImportOrExportCompletionItems(exports, namedImportsOrExports.elements) : ts.emptyArray; + return true; + } + /** + * Returns the immediate owning object literal or binding pattern of a context token, + * on the condition that one exists and that the context implies completion should be given. + */ + function tryGetObjectLikeCompletionContainer(contextToken) { + if (contextToken) { + switch (contextToken.kind) { + case 15 /* OpenBraceToken */: // const x = { | + case 24 /* CommaToken */: + var parent_18 = contextToken.parent; + if (parent_18 && (parent_18.kind === 171 /* ObjectLiteralExpression */ || parent_18.kind === 167 /* ObjectBindingPattern */)) { + return parent_18; + } + break; } } - lastTokenInfo = { - leadingTrivia: leadingTrivia, - trailingTrivia: trailingTrivia, - token: token - }; - return fixTokenKind(lastTokenInfo, n); - } - function isOnToken() { - ts.Debug.assert(scanner !== undefined); - var current = (lastTokenInfo && lastTokenInfo.token.kind) || scanner.getToken(); - var startPos = (lastTokenInfo && lastTokenInfo.token.pos) || scanner.getStartPos(); - return startPos < endPos && current !== 1 /* EndOfFileToken */ && !ts.isTrivia(current); + return undefined; } - // when containing node in the tree is token - // but its kind differs from the kind that was returned by the scanner, - // then kind needs to be fixed. This might happen in cases - // when parser interprets token differently, i.e keyword treated as identifier - function fixTokenKind(tokenInfo, container) { - if (ts.isToken(container) && tokenInfo.token.kind !== container.kind) { - tokenInfo.token.kind = container.kind; + /** + * Returns the containing list of named imports or exports of a context token, + * on the condition that one exists and that the context implies completion should be given. + */ + function tryGetNamedImportsOrExportsForCompletion(contextToken) { + if (contextToken) { + switch (contextToken.kind) { + case 15 /* OpenBraceToken */: // import { | + case 24 /* CommaToken */: + switch (contextToken.parent.kind) { + case 233 /* NamedImports */: + case 237 /* NamedExports */: + return contextToken.parent; + } + } } - return tokenInfo; - } - function skipToEndOf(node) { - scanner.setTextPos(node.end); - savedPos = scanner.getStartPos(); - lastScanAction = undefined; - lastTokenInfo = undefined; - wasNewLine = false; - leadingTrivia = undefined; - trailingTrivia = undefined; - } - } - formatting.getFormattingScanner = getFormattingScanner; - })(formatting = ts.formatting || (ts.formatting = {})); -})(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - var formatting; - (function (formatting) { - var FormattingContext = (function () { - function FormattingContext(sourceFile, formattingRequestKind) { - this.sourceFile = sourceFile; - this.formattingRequestKind = formattingRequestKind; + return undefined; } - FormattingContext.prototype.updateContext = function (currentRange, currentTokenParent, nextRange, nextTokenParent, commonParent) { - ts.Debug.assert(currentRange !== undefined, "currentTokenSpan is null"); - ts.Debug.assert(currentTokenParent !== undefined, "currentTokenParent is null"); - ts.Debug.assert(nextRange !== undefined, "nextTokenSpan is null"); - ts.Debug.assert(nextTokenParent !== undefined, "nextTokenParent is null"); - ts.Debug.assert(commonParent !== undefined, "commonParent is null"); - this.currentTokenSpan = currentRange; - this.currentTokenParent = currentTokenParent; - this.nextTokenSpan = nextRange; - this.nextTokenParent = nextTokenParent; - this.contextNode = commonParent; - // drop cached results - this.contextNodeAllOnSameLine = undefined; - this.nextNodeAllOnSameLine = undefined; - this.tokensAreOnSameLine = undefined; - this.contextNodeBlockIsOnOneLine = undefined; - this.nextNodeBlockIsOnOneLine = undefined; - }; - FormattingContext.prototype.ContextNodeAllOnSameLine = function () { - if (this.contextNodeAllOnSameLine === undefined) { - this.contextNodeAllOnSameLine = this.NodeIsOnOneLine(this.contextNode); - } - return this.contextNodeAllOnSameLine; - }; - FormattingContext.prototype.NextNodeAllOnSameLine = function () { - if (this.nextNodeAllOnSameLine === undefined) { - this.nextNodeAllOnSameLine = this.NodeIsOnOneLine(this.nextTokenParent); - } - return this.nextNodeAllOnSameLine; - }; - FormattingContext.prototype.TokensAreOnSameLine = function () { - if (this.tokensAreOnSameLine === undefined) { - var startLine = this.sourceFile.getLineAndCharacterOfPosition(this.currentTokenSpan.pos).line; - var endLine = this.sourceFile.getLineAndCharacterOfPosition(this.nextTokenSpan.pos).line; - this.tokensAreOnSameLine = (startLine === endLine); + function tryGetContainingJsxElement(contextToken) { + if (contextToken) { + var parent_19 = contextToken.parent; + switch (contextToken.kind) { + case 26 /* LessThanSlashToken */: + case 39 /* SlashToken */: + case 69 /* Identifier */: + case 246 /* JsxAttribute */: + case 247 /* JsxSpreadAttribute */: + if (parent_19 && (parent_19.kind === 242 /* JsxSelfClosingElement */ || parent_19.kind === 243 /* JsxOpeningElement */)) { + return parent_19; + } + else if (parent_19.kind === 246 /* JsxAttribute */) { + return parent_19.parent; + } + break; + // The context token is the closing } or " of an attribute, which means + // its parent is a JsxExpression, whose parent is a JsxAttribute, + // whose parent is a JsxOpeningLikeElement + case 9 /* StringLiteral */: + if (parent_19 && ((parent_19.kind === 246 /* JsxAttribute */) || (parent_19.kind === 247 /* JsxSpreadAttribute */))) { + return parent_19.parent; + } + break; + case 16 /* CloseBraceToken */: + if (parent_19 && + parent_19.kind === 248 /* JsxExpression */ && + parent_19.parent && + (parent_19.parent.kind === 246 /* JsxAttribute */)) { + return parent_19.parent.parent; + } + if (parent_19 && parent_19.kind === 247 /* JsxSpreadAttribute */) { + return parent_19.parent; + } + break; + } } - return this.tokensAreOnSameLine; - }; - FormattingContext.prototype.ContextNodeBlockIsOnOneLine = function () { - if (this.contextNodeBlockIsOnOneLine === undefined) { - this.contextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.contextNode); + return undefined; + } + function isFunction(kind) { + switch (kind) { + case 179 /* FunctionExpression */: + case 180 /* ArrowFunction */: + case 220 /* FunctionDeclaration */: + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 151 /* CallSignature */: + case 152 /* ConstructSignature */: + case 153 /* IndexSignature */: + return true; } - return this.contextNodeBlockIsOnOneLine; - }; - FormattingContext.prototype.NextNodeBlockIsOnOneLine = function () { - if (this.nextNodeBlockIsOnOneLine === undefined) { - this.nextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.nextTokenParent); + return false; + } + /** + * @returns true if we are certain that the currently edited location must define a new location; false otherwise. + */ + function isSolelyIdentifierDefinitionLocation(contextToken) { + var containingNodeKind = contextToken.parent.kind; + switch (contextToken.kind) { + case 24 /* CommaToken */: + return containingNodeKind === 218 /* VariableDeclaration */ || + containingNodeKind === 219 /* VariableDeclarationList */ || + containingNodeKind === 200 /* VariableStatement */ || + containingNodeKind === 224 /* EnumDeclaration */ || + isFunction(containingNodeKind) || + containingNodeKind === 221 /* ClassDeclaration */ || + containingNodeKind === 192 /* ClassExpression */ || + containingNodeKind === 222 /* InterfaceDeclaration */ || + containingNodeKind === 168 /* ArrayBindingPattern */ || + containingNodeKind === 223 /* TypeAliasDeclaration */; // type Map, K, | + case 21 /* DotToken */: + return containingNodeKind === 168 /* ArrayBindingPattern */; // var [.| + case 54 /* ColonToken */: + return containingNodeKind === 169 /* BindingElement */; // var {x :html| + case 19 /* OpenBracketToken */: + return containingNodeKind === 168 /* ArrayBindingPattern */; // var [x| + case 17 /* OpenParenToken */: + return containingNodeKind === 252 /* CatchClause */ || + isFunction(containingNodeKind); + case 15 /* OpenBraceToken */: + return containingNodeKind === 224 /* EnumDeclaration */ || + containingNodeKind === 222 /* InterfaceDeclaration */ || + containingNodeKind === 159 /* TypeLiteral */; // const x : { | + case 23 /* SemicolonToken */: + return containingNodeKind === 144 /* PropertySignature */ && + contextToken.parent && contextToken.parent.parent && + (contextToken.parent.parent.kind === 222 /* InterfaceDeclaration */ || + contextToken.parent.parent.kind === 159 /* TypeLiteral */); // const x : { a; | + case 25 /* LessThanToken */: + return containingNodeKind === 221 /* ClassDeclaration */ || + containingNodeKind === 192 /* ClassExpression */ || + containingNodeKind === 222 /* InterfaceDeclaration */ || + containingNodeKind === 223 /* TypeAliasDeclaration */ || + isFunction(containingNodeKind); + case 113 /* StaticKeyword */: + return containingNodeKind === 145 /* PropertyDeclaration */; + case 22 /* DotDotDotToken */: + return containingNodeKind === 142 /* Parameter */ || + (contextToken.parent && contextToken.parent.parent && + contextToken.parent.parent.kind === 168 /* ArrayBindingPattern */); // var [...z| + case 112 /* PublicKeyword */: + case 110 /* PrivateKeyword */: + case 111 /* ProtectedKeyword */: + return containingNodeKind === 142 /* Parameter */; + case 116 /* AsKeyword */: + return containingNodeKind === 234 /* ImportSpecifier */ || + containingNodeKind === 238 /* ExportSpecifier */ || + containingNodeKind === 232 /* NamespaceImport */; + case 73 /* ClassKeyword */: + case 81 /* EnumKeyword */: + case 107 /* InterfaceKeyword */: + case 87 /* FunctionKeyword */: + case 102 /* VarKeyword */: + case 123 /* GetKeyword */: + case 131 /* SetKeyword */: + case 89 /* ImportKeyword */: + case 108 /* LetKeyword */: + case 74 /* ConstKeyword */: + case 114 /* YieldKeyword */: + case 134 /* TypeKeyword */: + return true; } - return this.nextNodeBlockIsOnOneLine; - }; - FormattingContext.prototype.NodeIsOnOneLine = function (node) { - var startLine = this.sourceFile.getLineAndCharacterOfPosition(node.getStart(this.sourceFile)).line; - var endLine = this.sourceFile.getLineAndCharacterOfPosition(node.getEnd()).line; - return startLine === endLine; - }; - FormattingContext.prototype.BlockIsOnOneLine = function (node) { - var openBrace = ts.findChildOfKind(node, 15 /* OpenBraceToken */, this.sourceFile); - var closeBrace = ts.findChildOfKind(node, 16 /* CloseBraceToken */, this.sourceFile); - if (openBrace && closeBrace) { - var startLine = this.sourceFile.getLineAndCharacterOfPosition(openBrace.getEnd()).line; - var endLine = this.sourceFile.getLineAndCharacterOfPosition(closeBrace.getStart(this.sourceFile)).line; - return startLine === endLine; + // Previous token may have been a keyword that was converted to an identifier. + switch (contextToken.getText()) { + case "abstract": + case "async": + case "class": + case "const": + case "declare": + case "enum": + case "function": + case "interface": + case "let": + case "private": + case "protected": + case "public": + case "static": + case "var": + case "yield": + return true; } return false; - }; - return FormattingContext; - }()); - formatting.FormattingContext = FormattingContext; - })(formatting = ts.formatting || (ts.formatting = {})); -})(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - var formatting; - (function (formatting) { - (function (FormattingRequestKind) { - FormattingRequestKind[FormattingRequestKind["FormatDocument"] = 0] = "FormatDocument"; - FormattingRequestKind[FormattingRequestKind["FormatSelection"] = 1] = "FormatSelection"; - FormattingRequestKind[FormattingRequestKind["FormatOnEnter"] = 2] = "FormatOnEnter"; - FormattingRequestKind[FormattingRequestKind["FormatOnSemicolon"] = 3] = "FormatOnSemicolon"; - FormattingRequestKind[FormattingRequestKind["FormatOnClosingCurlyBrace"] = 4] = "FormatOnClosingCurlyBrace"; - })(formatting.FormattingRequestKind || (formatting.FormattingRequestKind = {})); - var FormattingRequestKind = formatting.FormattingRequestKind; - })(formatting = ts.formatting || (ts.formatting = {})); -})(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - var formatting; - (function (formatting) { - var Rule = (function () { - function Rule(Descriptor, Operation, Flag) { - if (Flag === void 0) { Flag = 0 /* None */; } - this.Descriptor = Descriptor; - this.Operation = Operation; - this.Flag = Flag; - } - Rule.prototype.toString = function () { - return "[desc=" + this.Descriptor + "," + - "operation=" + this.Operation + "," + - "flag=" + this.Flag + "]"; - }; - return Rule; - }()); - formatting.Rule = Rule; - })(formatting = ts.formatting || (ts.formatting = {})); -})(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - var formatting; - (function (formatting) { - (function (RuleAction) { - RuleAction[RuleAction["Ignore"] = 1] = "Ignore"; - RuleAction[RuleAction["Space"] = 2] = "Space"; - RuleAction[RuleAction["NewLine"] = 4] = "NewLine"; - RuleAction[RuleAction["Delete"] = 8] = "Delete"; - })(formatting.RuleAction || (formatting.RuleAction = {})); - var RuleAction = formatting.RuleAction; - })(formatting = ts.formatting || (ts.formatting = {})); -})(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - var formatting; - (function (formatting) { - var RuleDescriptor = (function () { - function RuleDescriptor(LeftTokenRange, RightTokenRange) { - this.LeftTokenRange = LeftTokenRange; - this.RightTokenRange = RightTokenRange; } - RuleDescriptor.prototype.toString = function () { - return "[leftRange=" + this.LeftTokenRange + "," + - "rightRange=" + this.RightTokenRange + "]"; - }; - RuleDescriptor.create1 = function (left, right) { - return RuleDescriptor.create4(formatting.Shared.TokenRange.FromToken(left), formatting.Shared.TokenRange.FromToken(right)); - }; - RuleDescriptor.create2 = function (left, right) { - return RuleDescriptor.create4(left, formatting.Shared.TokenRange.FromToken(right)); - }; - RuleDescriptor.create3 = function (left, right) { - return RuleDescriptor.create4(formatting.Shared.TokenRange.FromToken(left), right); - }; - RuleDescriptor.create4 = function (left, right) { - return new RuleDescriptor(left, right); - }; - return RuleDescriptor; - }()); - formatting.RuleDescriptor = RuleDescriptor; - })(formatting = ts.formatting || (ts.formatting = {})); -})(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - var formatting; - (function (formatting) { - (function (RuleFlags) { - RuleFlags[RuleFlags["None"] = 0] = "None"; - RuleFlags[RuleFlags["CanDeleteNewLines"] = 1] = "CanDeleteNewLines"; - })(formatting.RuleFlags || (formatting.RuleFlags = {})); - var RuleFlags = formatting.RuleFlags; - })(formatting = ts.formatting || (ts.formatting = {})); -})(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - var formatting; - (function (formatting) { - var RuleOperation = (function () { - function RuleOperation(Context, Action) { - this.Context = Context; - this.Action = Action; + function isDotOfNumericLiteral(contextToken) { + if (contextToken.kind === 8 /* NumericLiteral */) { + var text = contextToken.getFullText(); + return text.charAt(text.length - 1) === "."; + } + return false; } - RuleOperation.prototype.toString = function () { - return "[context=" + this.Context + "," + - "action=" + this.Action + "]"; - }; - RuleOperation.create1 = function (action) { - return RuleOperation.create2(formatting.RuleOperationContext.Any, action); - }; - RuleOperation.create2 = function (context, action) { - return new RuleOperation(context, action); - }; - return RuleOperation; - }()); - formatting.RuleOperation = RuleOperation; - })(formatting = ts.formatting || (ts.formatting = {})); -})(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - var formatting; - (function (formatting) { - var RuleOperationContext = (function () { - function RuleOperationContext() { - var funcs = []; - for (var _i = 0; _i < arguments.length; _i++) { - funcs[_i - 0] = arguments[_i]; + /** + * Filters out completion suggestions for named imports or exports. + * + * @param exportsOfModule The list of symbols which a module exposes. + * @param namedImportsOrExports The list of existing import/export specifiers in the import/export clause. + * + * @returns Symbols to be suggested at an import/export clause, barring those whose named imports/exports + * do not occur at the current position and have not otherwise been typed. + */ + function filterNamedImportOrExportCompletionItems(exportsOfModule, namedImportsOrExports) { + var existingImportsOrExports = ts.createMap(); + for (var _i = 0, namedImportsOrExports_1 = namedImportsOrExports; _i < namedImportsOrExports_1.length; _i++) { + var element = namedImportsOrExports_1[_i]; + // If this is the current item we are editing right now, do not filter it out + if (element.getStart() <= position && position <= element.getEnd()) { + continue; + } + var name_50 = element.propertyName || element.name; + existingImportsOrExports[name_50.text] = true; } - this.customContextChecks = funcs; + if (!ts.someProperties(existingImportsOrExports)) { + return ts.filter(exportsOfModule, function (e) { return e.name !== "default"; }); + } + return ts.filter(exportsOfModule, function (e) { return e.name !== "default" && !existingImportsOrExports[e.name]; }); } - RuleOperationContext.prototype.IsAny = function () { - return this === RuleOperationContext.Any; - }; - RuleOperationContext.prototype.InContext = function (context) { - if (this.IsAny()) { - return true; + /** + * Filters out completion suggestions for named imports or exports. + * + * @returns Symbols to be suggested in an object binding pattern or object literal expression, barring those whose declarations + * do not occur at the current position and have not otherwise been typed. + */ + function filterObjectMembersList(contextualMemberSymbols, existingMembers) { + if (!existingMembers || existingMembers.length === 0) { + return contextualMemberSymbols; } - for (var _i = 0, _a = this.customContextChecks; _i < _a.length; _i++) { - var check = _a[_i]; - if (!check(context)) { - return false; + var existingMemberNames = ts.createMap(); + for (var _i = 0, existingMembers_1 = existingMembers; _i < existingMembers_1.length; _i++) { + var m = existingMembers_1[_i]; + // Ignore omitted expressions for missing members + if (m.kind !== 253 /* PropertyAssignment */ && + m.kind !== 254 /* ShorthandPropertyAssignment */ && + m.kind !== 169 /* BindingElement */ && + m.kind !== 147 /* MethodDeclaration */) { + continue; + } + // If this is the current item we are editing right now, do not filter it out + if (m.getStart() <= position && position <= m.getEnd()) { + continue; + } + var existingName = void 0; + if (m.kind === 169 /* BindingElement */ && m.propertyName) { + // include only identifiers in completion list + if (m.propertyName.kind === 69 /* Identifier */) { + existingName = m.propertyName.text; + } + } + else { + // TODO(jfreeman): Account for computed property name + // NOTE: if one only performs this step when m.name is an identifier, + // things like '__proto__' are not filtered out. + existingName = m.name.text; } + existingMemberNames[existingName] = true; } - return true; - }; - RuleOperationContext.Any = new RuleOperationContext(); - return RuleOperationContext; - }()); - formatting.RuleOperationContext = RuleOperationContext; - })(formatting = ts.formatting || (ts.formatting = {})); + return ts.filter(contextualMemberSymbols, function (m) { return !existingMemberNames[m.name]; }); + } + /** + * Filters out completion suggestions from 'symbols' according to existing JSX attributes. + * + * @returns Symbols to be suggested in a JSX element, barring those whose attributes + * do not occur at the current position and have not otherwise been typed. + */ + function filterJsxAttributes(symbols, attributes) { + var seenNames = ts.createMap(); + for (var _i = 0, attributes_1 = attributes; _i < attributes_1.length; _i++) { + var attr = attributes_1[_i]; + // If this is the current item we are editing right now, do not filter it out + if (attr.getStart() <= position && position <= attr.getEnd()) { + continue; + } + if (attr.kind === 246 /* JsxAttribute */) { + seenNames[attr.name.text] = true; + } + } + return ts.filter(symbols, function (a) { return !seenNames[a.name]; }); + } + } + /** + * Get the name to be display in completion from a given symbol. + * + * @return undefined if the name is of external module otherwise a name with striped of any quote + */ + function getCompletionEntryDisplayNameForSymbol(typeChecker, symbol, target, performCharacterChecks, location) { + var displayName = ts.getDeclaredName(typeChecker, symbol, location); + if (displayName) { + var firstCharCode = displayName.charCodeAt(0); + // First check of the displayName is not external module; if it is an external module, it is not valid entry + if ((symbol.flags & 1920 /* Namespace */) && (firstCharCode === 39 /* singleQuote */ || firstCharCode === 34 /* doubleQuote */)) { + // If the symbol is external module, don't show it in the completion list + // (i.e declare module "http" { const x; } | // <= request completion here, "http" should not be there) + return undefined; + } + } + return getCompletionEntryDisplayName(displayName, target, performCharacterChecks); + } + /** + * Get a displayName from a given for completion list, performing any necessary quotes stripping + * and checking whether the name is valid identifier name. + */ + function getCompletionEntryDisplayName(name, target, performCharacterChecks) { + if (!name) { + return undefined; + } + name = ts.stripQuotes(name); + if (!name) { + return undefined; + } + // If the user entered name for the symbol was quoted, removing the quotes is not enough, as the name could be an + // invalid identifier name. We need to check if whatever was inside the quotes is actually a valid identifier name. + // e.g "b a" is valid quoted name but when we strip off the quotes, it is invalid. + // We, thus, need to check if whatever was inside the quotes is actually a valid identifier name. + if (performCharacterChecks) { + if (!ts.isIdentifierText(name, target)) { + return undefined; + } + } + return name; + } + // A cache of completion entries for keywords, these do not change between sessions + var keywordCompletions = []; + for (var i = 70 /* FirstKeyword */; i <= 138 /* LastKeyword */; i++) { + keywordCompletions.push({ + name: ts.tokenToString(i), + kind: ts.ScriptElementKind.keyword, + kindModifiers: ts.ScriptElementKindModifier.none, + sortText: "0" + }); + } + /** + * Matches a triple slash reference directive with an incomplete string literal for its path. Used + * to determine if the caret is currently within the string literal and capture the literal fragment + * for completions. + * For example, this matches /// /* @internal */ var ts; (function (ts) { - var formatting; - (function (formatting) { - var Rules = (function () { - function Rules() { - /// - /// Common Rules - /// - // Leave comments alone - this.IgnoreBeforeComment = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.Comments), formatting.RuleOperation.create1(1 /* Ignore */)); - this.IgnoreAfterLineComment = new formatting.Rule(formatting.RuleDescriptor.create3(2 /* SingleLineCommentTrivia */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create1(1 /* Ignore */)); - // Space after keyword but not before ; or : or ? - this.NoSpaceBeforeSemicolon = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 23 /* SemicolonToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceBeforeColon = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 54 /* ColonToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), 8 /* Delete */)); - this.NoSpaceBeforeQuestionMark = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 53 /* QuestionToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), 8 /* Delete */)); - this.SpaceAfterColon = new formatting.Rule(formatting.RuleDescriptor.create3(54 /* ColonToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), 2 /* Space */)); - this.SpaceAfterQuestionMarkInConditionalOperator = new formatting.Rule(formatting.RuleDescriptor.create3(53 /* QuestionToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsConditionalOperatorContext), 2 /* Space */)); - this.NoSpaceAfterQuestionMark = new formatting.Rule(formatting.RuleDescriptor.create3(53 /* QuestionToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.SpaceAfterSemicolon = new formatting.Rule(formatting.RuleDescriptor.create3(23 /* SemicolonToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - // Space after }. - this.SpaceAfterCloseBrace = new formatting.Rule(formatting.RuleDescriptor.create3(16 /* CloseBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsAfterCodeBlockContext), 2 /* Space */)); - // Special case for (}, else) and (}, while) since else & while tokens are not part of the tree which makes SpaceAfterCloseBrace rule not applied - this.SpaceBetweenCloseBraceAndElse = new formatting.Rule(formatting.RuleDescriptor.create1(16 /* CloseBraceToken */, 80 /* ElseKeyword */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.SpaceBetweenCloseBraceAndWhile = new formatting.Rule(formatting.RuleDescriptor.create1(16 /* CloseBraceToken */, 104 /* WhileKeyword */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.NoSpaceAfterCloseBrace = new formatting.Rule(formatting.RuleDescriptor.create3(16 /* CloseBraceToken */, formatting.Shared.TokenRange.FromTokens([18 /* CloseParenToken */, 20 /* CloseBracketToken */, 24 /* CommaToken */, 23 /* SemicolonToken */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - // No space for dot - this.NoSpaceBeforeDot = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 21 /* DotToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceAfterDot = new formatting.Rule(formatting.RuleDescriptor.create3(21 /* DotToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - // No space before and after indexer - this.NoSpaceBeforeOpenBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 19 /* OpenBracketToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceAfterCloseBracket = new formatting.Rule(formatting.RuleDescriptor.create3(20 /* CloseBracketToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBeforeBlockInFunctionDeclarationContext), 8 /* Delete */)); - // Place a space before open brace in a function declaration - this.FunctionOpenBraceLeftTokenRange = formatting.Shared.TokenRange.AnyIncludingMultilineComments; - this.SpaceBeforeOpenBraceInFunction = new formatting.Rule(formatting.RuleDescriptor.create2(this.FunctionOpenBraceLeftTokenRange, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext, Rules.IsBeforeBlockContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), 2 /* Space */), 1 /* CanDeleteNewLines */); - // Place a space before open brace in a TypeScript declaration that has braces as children (class, module, enum, etc) - this.TypeScriptOpenBraceLeftTokenRange = formatting.Shared.TokenRange.FromTokens([69 /* Identifier */, 3 /* MultiLineCommentTrivia */, 73 /* ClassKeyword */, 82 /* ExportKeyword */, 89 /* ImportKeyword */]); - this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock = new formatting.Rule(formatting.RuleDescriptor.create2(this.TypeScriptOpenBraceLeftTokenRange, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsTypeScriptDeclWithBlockContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), 2 /* Space */), 1 /* CanDeleteNewLines */); - // Place a space before open brace in a control flow construct - this.ControlOpenBraceLeftTokenRange = formatting.Shared.TokenRange.FromTokens([18 /* CloseParenToken */, 3 /* MultiLineCommentTrivia */, 79 /* DoKeyword */, 100 /* TryKeyword */, 85 /* FinallyKeyword */, 80 /* ElseKeyword */]); - this.SpaceBeforeOpenBraceInControl = new formatting.Rule(formatting.RuleDescriptor.create2(this.ControlOpenBraceLeftTokenRange, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), 2 /* Space */), 1 /* CanDeleteNewLines */); - // Insert a space after { and before } in single-line contexts, but remove space from empty object literals {}. - this.SpaceAfterOpenBrace = new formatting.Rule(formatting.RuleDescriptor.create3(15 /* OpenBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSingleLineBlockContext), 2 /* Space */)); - this.SpaceBeforeCloseBrace = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSingleLineBlockContext), 2 /* Space */)); - this.NoSpaceBetweenEmptyBraceBrackets = new formatting.Rule(formatting.RuleDescriptor.create1(15 /* OpenBraceToken */, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsObjectContext), 8 /* Delete */)); - // Insert new line after { and before } in multi-line contexts. - this.NewLineAfterOpenBraceInBlockContext = new formatting.Rule(formatting.RuleDescriptor.create3(15 /* OpenBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsMultilineBlockContext), 4 /* NewLine */)); - // For functions and control block place } on a new line [multi-line rule] - this.NewLineBeforeCloseBraceInBlockContext = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.AnyIncludingMultilineComments, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsMultilineBlockContext), 4 /* NewLine */)); - // Special handling of unary operators. - // Prefix operators generally shouldn't have a space between - // them and their target unary expression. - this.NoSpaceAfterUnaryPrefixOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.UnaryPrefixOperators, formatting.Shared.TokenRange.UnaryPrefixExpressions), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), 8 /* Delete */)); - this.NoSpaceAfterUnaryPreincrementOperator = new formatting.Rule(formatting.RuleDescriptor.create3(41 /* PlusPlusToken */, formatting.Shared.TokenRange.UnaryPreincrementExpressions), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceAfterUnaryPredecrementOperator = new formatting.Rule(formatting.RuleDescriptor.create3(42 /* MinusMinusToken */, formatting.Shared.TokenRange.UnaryPredecrementExpressions), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceBeforeUnaryPostincrementOperator = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.UnaryPostincrementExpressions, 41 /* PlusPlusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceBeforeUnaryPostdecrementOperator = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.UnaryPostdecrementExpressions, 42 /* MinusMinusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - // More unary operator special-casing. - // DevDiv 181814: Be careful when removing leading whitespace - // around unary operators. Examples: - // 1 - -2 --X--> 1--2 - // a + ++b --X--> a+++b - this.SpaceAfterPostincrementWhenFollowedByAdd = new formatting.Rule(formatting.RuleDescriptor.create1(41 /* PlusPlusToken */, 35 /* PlusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); - this.SpaceAfterAddWhenFollowedByUnaryPlus = new formatting.Rule(formatting.RuleDescriptor.create1(35 /* PlusToken */, 35 /* PlusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); - this.SpaceAfterAddWhenFollowedByPreincrement = new formatting.Rule(formatting.RuleDescriptor.create1(35 /* PlusToken */, 41 /* PlusPlusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); - this.SpaceAfterPostdecrementWhenFollowedBySubtract = new formatting.Rule(formatting.RuleDescriptor.create1(42 /* MinusMinusToken */, 36 /* MinusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); - this.SpaceAfterSubtractWhenFollowedByUnaryMinus = new formatting.Rule(formatting.RuleDescriptor.create1(36 /* MinusToken */, 36 /* MinusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); - this.SpaceAfterSubtractWhenFollowedByPredecrement = new formatting.Rule(formatting.RuleDescriptor.create1(36 /* MinusToken */, 42 /* MinusMinusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); - this.NoSpaceBeforeComma = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 24 /* CommaToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.SpaceAfterCertainKeywords = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([102 /* VarKeyword */, 98 /* ThrowKeyword */, 92 /* NewKeyword */, 78 /* DeleteKeyword */, 94 /* ReturnKeyword */, 101 /* TypeOfKeyword */, 119 /* AwaitKeyword */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.SpaceAfterLetConstInVariableDeclaration = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([108 /* LetKeyword */, 74 /* ConstKeyword */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsStartOfVariableDeclarationList), 2 /* Space */)); - this.NoSpaceBeforeOpenParenInFuncCall = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsFunctionCallOrNewContext, Rules.IsPreviousTokenNotComma), 8 /* Delete */)); - this.SpaceAfterFunctionInFuncDecl = new formatting.Rule(formatting.RuleDescriptor.create3(87 /* FunctionKeyword */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 2 /* Space */)); - this.NoSpaceBeforeOpenParenInFuncDecl = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsFunctionDeclContext), 8 /* Delete */)); - this.SpaceAfterVoidOperator = new formatting.Rule(formatting.RuleDescriptor.create3(103 /* VoidKeyword */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsVoidOpContext), 2 /* Space */)); - this.NoSpaceBetweenReturnAndSemicolon = new formatting.Rule(formatting.RuleDescriptor.create1(94 /* ReturnKeyword */, 23 /* SemicolonToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - // Add a space between statements. All keywords except (do,else,case) has open/close parens after them. - // So, we have a rule to add a space for [),Any], [do,Any], [else,Any], and [case,Any] - this.SpaceBetweenStatements = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([18 /* CloseParenToken */, 79 /* DoKeyword */, 80 /* ElseKeyword */, 71 /* CaseKeyword */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNonJsxElementContext, Rules.IsNotForContext), 2 /* Space */)); - // This low-pri rule takes care of "try {" and "finally {" in case the rule SpaceBeforeOpenBraceInControl didn't execute on FormatOnEnter. - this.SpaceAfterTryFinally = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.FromTokens([100 /* TryKeyword */, 85 /* FinallyKeyword */]), 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - // get x() {} - // set x(val) {} - this.SpaceAfterGetSetInMember = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.FromTokens([123 /* GetKeyword */, 131 /* SetKeyword */]), 69 /* Identifier */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 2 /* Space */)); - // Special case for binary operators (that are keywords). For these we have to add a space and shouldn't follow any user options. - this.SpaceBeforeBinaryKeywordOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.BinaryKeywordOperators), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); - this.SpaceAfterBinaryKeywordOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.BinaryKeywordOperators, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); - // TypeScript-specific higher priority rules - // Treat constructor as an identifier in a function declaration, and remove spaces between constructor and following left parentheses - this.NoSpaceAfterConstructor = new formatting.Rule(formatting.RuleDescriptor.create1(121 /* ConstructorKeyword */, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - // Use of module as a function call. e.g.: import m2 = module("m2"); - this.NoSpaceAfterModuleImport = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.FromTokens([125 /* ModuleKeyword */, 129 /* RequireKeyword */]), 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - // Add a space around certain TypeScript keywords - this.SpaceAfterCertainTypeScriptKeywords = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([115 /* AbstractKeyword */, 73 /* ClassKeyword */, 122 /* DeclareKeyword */, 77 /* DefaultKeyword */, 81 /* EnumKeyword */, 82 /* ExportKeyword */, 83 /* ExtendsKeyword */, 123 /* GetKeyword */, 106 /* ImplementsKeyword */, 89 /* ImportKeyword */, 107 /* InterfaceKeyword */, 125 /* ModuleKeyword */, 126 /* NamespaceKeyword */, 110 /* PrivateKeyword */, 112 /* PublicKeyword */, 111 /* ProtectedKeyword */, 131 /* SetKeyword */, 113 /* StaticKeyword */, 134 /* TypeKeyword */, 136 /* FromKeyword */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.SpaceBeforeCertainTypeScriptKeywords = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.FromTokens([83 /* ExtendsKeyword */, 106 /* ImplementsKeyword */, 136 /* FromKeyword */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - // Treat string literals in module names as identifiers, and add a space between the literal and the opening Brace braces, e.g.: module "m2" { - this.SpaceAfterModuleName = new formatting.Rule(formatting.RuleDescriptor.create1(9 /* StringLiteral */, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsModuleDeclContext), 2 /* Space */)); - // Lambda expressions - this.SpaceBeforeArrow = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 34 /* EqualsGreaterThanToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.SpaceAfterArrow = new formatting.Rule(formatting.RuleDescriptor.create3(34 /* EqualsGreaterThanToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - // Optional parameters and let args - this.NoSpaceAfterEllipsis = new formatting.Rule(formatting.RuleDescriptor.create1(22 /* DotDotDotToken */, 69 /* Identifier */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceAfterOptionalParameters = new formatting.Rule(formatting.RuleDescriptor.create3(53 /* QuestionToken */, formatting.Shared.TokenRange.FromTokens([18 /* CloseParenToken */, 24 /* CommaToken */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), 8 /* Delete */)); - // generics and type assertions - this.NoSpaceBeforeOpenAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.TypeNames, 25 /* LessThanToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), 8 /* Delete */)); - this.NoSpaceBetweenCloseParenAndAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create1(18 /* CloseParenToken */, 25 /* LessThanToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), 8 /* Delete */)); - this.NoSpaceAfterOpenAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create3(25 /* LessThanToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), 8 /* Delete */)); - this.NoSpaceBeforeCloseAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 27 /* GreaterThanToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), 8 /* Delete */)); - this.NoSpaceAfterCloseAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create3(27 /* GreaterThanToken */, formatting.Shared.TokenRange.FromTokens([17 /* OpenParenToken */, 19 /* OpenBracketToken */, 27 /* GreaterThanToken */, 24 /* CommaToken */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), 8 /* Delete */)); - this.NoSpaceAfterTypeAssertion = new formatting.Rule(formatting.RuleDescriptor.create3(27 /* GreaterThanToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeAssertionContext), 8 /* Delete */)); - // Remove spaces in empty interface literals. e.g.: x: {} - this.NoSpaceBetweenEmptyInterfaceBraceBrackets = new formatting.Rule(formatting.RuleDescriptor.create1(15 /* OpenBraceToken */, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsObjectTypeContext), 8 /* Delete */)); - // decorators - this.SpaceBeforeAt = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 55 /* AtToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.NoSpaceAfterAt = new formatting.Rule(formatting.RuleDescriptor.create3(55 /* AtToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.SpaceAfterDecorator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.FromTokens([115 /* AbstractKeyword */, 69 /* Identifier */, 82 /* ExportKeyword */, 77 /* DefaultKeyword */, 73 /* ClassKeyword */, 113 /* StaticKeyword */, 112 /* PublicKeyword */, 110 /* PrivateKeyword */, 111 /* ProtectedKeyword */, 123 /* GetKeyword */, 131 /* SetKeyword */, 19 /* OpenBracketToken */, 37 /* AsteriskToken */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsEndOfDecoratorContextOnSameLine), 2 /* Space */)); - this.NoSpaceBetweenFunctionKeywordAndStar = new formatting.Rule(formatting.RuleDescriptor.create1(87 /* FunctionKeyword */, 37 /* AsteriskToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclarationOrFunctionExpressionContext), 8 /* Delete */)); - this.SpaceAfterStarInGeneratorDeclaration = new formatting.Rule(formatting.RuleDescriptor.create3(37 /* AsteriskToken */, formatting.Shared.TokenRange.FromTokens([69 /* Identifier */, 17 /* OpenParenToken */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclarationOrFunctionExpressionContext), 2 /* Space */)); - this.NoSpaceBetweenYieldKeywordAndStar = new formatting.Rule(formatting.RuleDescriptor.create1(114 /* YieldKeyword */, 37 /* AsteriskToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsYieldOrYieldStarWithOperand), 8 /* Delete */)); - this.SpaceBetweenYieldOrYieldStarAndOperand = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([114 /* YieldKeyword */, 37 /* AsteriskToken */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsYieldOrYieldStarWithOperand), 2 /* Space */)); - // Async-await - this.SpaceBetweenAsyncAndOpenParen = new formatting.Rule(formatting.RuleDescriptor.create1(118 /* AsyncKeyword */, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsArrowFunctionContext, Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.SpaceBetweenAsyncAndFunctionKeyword = new formatting.Rule(formatting.RuleDescriptor.create1(118 /* AsyncKeyword */, 87 /* FunctionKeyword */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - // template string - this.NoSpaceBetweenTagAndTemplateString = new formatting.Rule(formatting.RuleDescriptor.create3(69 /* Identifier */, formatting.Shared.TokenRange.FromTokens([11 /* NoSubstitutionTemplateLiteral */, 12 /* TemplateHead */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - // jsx opening element - this.SpaceBeforeJsxAttribute = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 69 /* Identifier */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNextTokenParentJsxAttribute, Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.SpaceBeforeSlashInJsxOpeningElement = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 39 /* SlashToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsJsxSelfClosingElementContext, Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.NoSpaceBeforeGreaterThanTokenInJsxOpeningElement = new formatting.Rule(formatting.RuleDescriptor.create1(39 /* SlashToken */, 27 /* GreaterThanToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsJsxSelfClosingElementContext, Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceBeforeEqualInJsxAttribute = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 56 /* EqualsToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsJsxAttributeContext, Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceAfterEqualInJsxAttribute = new formatting.Rule(formatting.RuleDescriptor.create3(56 /* EqualsToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsJsxAttributeContext, Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - // These rules are higher in priority than user-configurable rules. - this.HighPriorityCommonRules = [ - this.IgnoreBeforeComment, this.IgnoreAfterLineComment, - this.NoSpaceBeforeColon, this.SpaceAfterColon, this.NoSpaceBeforeQuestionMark, this.SpaceAfterQuestionMarkInConditionalOperator, - this.NoSpaceAfterQuestionMark, - this.NoSpaceBeforeDot, this.NoSpaceAfterDot, - this.NoSpaceAfterUnaryPrefixOperator, - this.NoSpaceAfterUnaryPreincrementOperator, this.NoSpaceAfterUnaryPredecrementOperator, - this.NoSpaceBeforeUnaryPostincrementOperator, this.NoSpaceBeforeUnaryPostdecrementOperator, - this.SpaceAfterPostincrementWhenFollowedByAdd, - this.SpaceAfterAddWhenFollowedByUnaryPlus, this.SpaceAfterAddWhenFollowedByPreincrement, - this.SpaceAfterPostdecrementWhenFollowedBySubtract, - this.SpaceAfterSubtractWhenFollowedByUnaryMinus, this.SpaceAfterSubtractWhenFollowedByPredecrement, - this.NoSpaceAfterCloseBrace, - this.SpaceAfterOpenBrace, this.SpaceBeforeCloseBrace, this.NewLineBeforeCloseBraceInBlockContext, - this.SpaceAfterCloseBrace, this.SpaceBetweenCloseBraceAndElse, this.SpaceBetweenCloseBraceAndWhile, this.NoSpaceBetweenEmptyBraceBrackets, - this.NoSpaceBetweenFunctionKeywordAndStar, this.SpaceAfterStarInGeneratorDeclaration, - this.SpaceAfterFunctionInFuncDecl, this.NewLineAfterOpenBraceInBlockContext, this.SpaceAfterGetSetInMember, - this.NoSpaceBetweenYieldKeywordAndStar, this.SpaceBetweenYieldOrYieldStarAndOperand, - this.NoSpaceBetweenReturnAndSemicolon, - this.SpaceAfterCertainKeywords, - this.SpaceAfterLetConstInVariableDeclaration, - this.NoSpaceBeforeOpenParenInFuncCall, - this.SpaceBeforeBinaryKeywordOperator, this.SpaceAfterBinaryKeywordOperator, - this.SpaceAfterVoidOperator, - this.SpaceBetweenAsyncAndOpenParen, this.SpaceBetweenAsyncAndFunctionKeyword, - this.NoSpaceBetweenTagAndTemplateString, - this.SpaceBeforeJsxAttribute, this.SpaceBeforeSlashInJsxOpeningElement, this.NoSpaceBeforeGreaterThanTokenInJsxOpeningElement, - this.NoSpaceBeforeEqualInJsxAttribute, this.NoSpaceAfterEqualInJsxAttribute, - // TypeScript-specific rules - this.NoSpaceAfterConstructor, this.NoSpaceAfterModuleImport, - this.SpaceAfterCertainTypeScriptKeywords, this.SpaceBeforeCertainTypeScriptKeywords, - this.SpaceAfterModuleName, - this.SpaceBeforeArrow, this.SpaceAfterArrow, - this.NoSpaceAfterEllipsis, - this.NoSpaceAfterOptionalParameters, - this.NoSpaceBetweenEmptyInterfaceBraceBrackets, - this.NoSpaceBeforeOpenAngularBracket, - this.NoSpaceBetweenCloseParenAndAngularBracket, - this.NoSpaceAfterOpenAngularBracket, - this.NoSpaceBeforeCloseAngularBracket, - this.NoSpaceAfterCloseAngularBracket, - this.NoSpaceAfterTypeAssertion, - this.SpaceBeforeAt, - this.NoSpaceAfterAt, - this.SpaceAfterDecorator, - ]; - // These rules are lower in priority than user-configurable rules. - this.LowPriorityCommonRules = [ - this.NoSpaceBeforeSemicolon, - this.SpaceBeforeOpenBraceInControl, this.SpaceBeforeOpenBraceInFunction, this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock, - this.NoSpaceBeforeComma, - this.NoSpaceBeforeOpenBracket, - this.NoSpaceAfterCloseBracket, - this.SpaceAfterSemicolon, - this.NoSpaceBeforeOpenParenInFuncDecl, - this.SpaceBetweenStatements, this.SpaceAfterTryFinally - ]; - /// - /// Rules controlled by user options - /// - // Insert space after comma delimiter - this.SpaceAfterComma = new formatting.Rule(formatting.RuleDescriptor.create3(24 /* CommaToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNonJsxElementContext, Rules.IsNextTokenNotCloseBracket), 2 /* Space */)); - this.NoSpaceAfterComma = new formatting.Rule(formatting.RuleDescriptor.create3(24 /* CommaToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNonJsxElementContext), 8 /* Delete */)); - // Insert space before and after binary operators - this.SpaceBeforeBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.BinaryOperators), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); - this.SpaceAfterBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.BinaryOperators, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); - this.NoSpaceBeforeBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.BinaryOperators), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 8 /* Delete */)); - this.NoSpaceAfterBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.BinaryOperators, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 8 /* Delete */)); - // Insert space after keywords in control flow statements - this.SpaceAfterKeywordInControl = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Keywords, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext), 2 /* Space */)); - this.NoSpaceAfterKeywordInControl = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Keywords, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext), 8 /* Delete */)); - // Open Brace braces after function - // TypeScript: Function can have return types, which can be made of tons of different token kinds - this.NewLineBeforeOpenBraceInFunction = new formatting.Rule(formatting.RuleDescriptor.create2(this.FunctionOpenBraceLeftTokenRange, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext, Rules.IsBeforeMultilineBlockContext), 4 /* NewLine */), 1 /* CanDeleteNewLines */); - // Open Brace braces after TypeScript module/class/interface - this.NewLineBeforeOpenBraceInTypeScriptDeclWithBlock = new formatting.Rule(formatting.RuleDescriptor.create2(this.TypeScriptOpenBraceLeftTokenRange, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsTypeScriptDeclWithBlockContext, Rules.IsBeforeMultilineBlockContext), 4 /* NewLine */), 1 /* CanDeleteNewLines */); - // Open Brace braces after control block - this.NewLineBeforeOpenBraceInControl = new formatting.Rule(formatting.RuleDescriptor.create2(this.ControlOpenBraceLeftTokenRange, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext, Rules.IsBeforeMultilineBlockContext), 4 /* NewLine */), 1 /* CanDeleteNewLines */); - // Insert space after semicolon in for statement - this.SpaceAfterSemicolonInFor = new formatting.Rule(formatting.RuleDescriptor.create3(23 /* SemicolonToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsForContext), 2 /* Space */)); - this.NoSpaceAfterSemicolonInFor = new formatting.Rule(formatting.RuleDescriptor.create3(23 /* SemicolonToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsForContext), 8 /* Delete */)); - // Insert space after opening and before closing nonempty parenthesis - this.SpaceAfterOpenParen = new formatting.Rule(formatting.RuleDescriptor.create3(17 /* OpenParenToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.SpaceBeforeCloseParen = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 18 /* CloseParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.NoSpaceBetweenParens = new formatting.Rule(formatting.RuleDescriptor.create1(17 /* OpenParenToken */, 18 /* CloseParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceAfterOpenParen = new formatting.Rule(formatting.RuleDescriptor.create3(17 /* OpenParenToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceBeforeCloseParen = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 18 /* CloseParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - // Insert space after opening and before closing nonempty brackets - this.SpaceAfterOpenBracket = new formatting.Rule(formatting.RuleDescriptor.create3(19 /* OpenBracketToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.SpaceBeforeCloseBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 20 /* CloseBracketToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.NoSpaceBetweenBrackets = new formatting.Rule(formatting.RuleDescriptor.create1(19 /* OpenBracketToken */, 20 /* CloseBracketToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceAfterOpenBracket = new formatting.Rule(formatting.RuleDescriptor.create3(19 /* OpenBracketToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.NoSpaceBeforeCloseBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 20 /* CloseBracketToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - // Insert space after opening and before closing template string braces - this.NoSpaceAfterTemplateHeadAndMiddle = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([12 /* TemplateHead */, 13 /* TemplateMiddle */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.SpaceAfterTemplateHeadAndMiddle = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([12 /* TemplateHead */, 13 /* TemplateMiddle */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - this.NoSpaceBeforeTemplateMiddleAndTail = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.FromTokens([13 /* TemplateMiddle */, 14 /* TemplateTail */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); - this.SpaceBeforeTemplateMiddleAndTail = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.FromTokens([13 /* TemplateMiddle */, 14 /* TemplateTail */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); - // No space after { and before } in JSX expression - this.NoSpaceAfterOpenBraceInJsxExpression = new formatting.Rule(formatting.RuleDescriptor.create3(15 /* OpenBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsJsxExpressionContext), 8 /* Delete */)); - this.SpaceAfterOpenBraceInJsxExpression = new formatting.Rule(formatting.RuleDescriptor.create3(15 /* OpenBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsJsxExpressionContext), 2 /* Space */)); - this.NoSpaceBeforeCloseBraceInJsxExpression = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsJsxExpressionContext), 8 /* Delete */)); - this.SpaceBeforeCloseBraceInJsxExpression = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsJsxExpressionContext), 2 /* Space */)); - // Insert space after function keyword for anonymous functions - this.SpaceAfterAnonymousFunctionKeyword = new formatting.Rule(formatting.RuleDescriptor.create1(87 /* FunctionKeyword */, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 2 /* Space */)); - this.NoSpaceAfterAnonymousFunctionKeyword = new formatting.Rule(formatting.RuleDescriptor.create1(87 /* FunctionKeyword */, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 8 /* Delete */)); + var DocumentHighlights; + (function (DocumentHighlights) { + function getDocumentHighlights(typeChecker, cancellationToken, sourceFile, position, sourceFilesToSearch) { + var node = ts.getTouchingWord(sourceFile, position); + if (!node) { + return undefined; } - Rules.prototype.getRuleName = function (rule) { - var o = this; - for (var name_40 in o) { - if (o[name_40] === rule) { - return name_40; - } - } - throw new Error("Unknown rule"); - }; - /// - /// Contexts - /// - Rules.IsForContext = function (context) { - return context.contextNode.kind === 206 /* ForStatement */; - }; - Rules.IsNotForContext = function (context) { - return !Rules.IsForContext(context); - }; - Rules.IsBinaryOpContext = function (context) { - switch (context.contextNode.kind) { - case 187 /* BinaryExpression */: - case 188 /* ConditionalExpression */: - case 195 /* AsExpression */: - case 238 /* ExportSpecifier */: - case 234 /* ImportSpecifier */: - case 154 /* TypePredicate */: - case 162 /* UnionType */: - case 163 /* IntersectionType */: - return true; - // equals in binding elements: function foo([[x, y] = [1, 2]]) - case 169 /* BindingElement */: - // equals in type X = ... - case 223 /* TypeAliasDeclaration */: - // equal in import a = module('a'); - case 229 /* ImportEqualsDeclaration */: - // equal in let a = 0; - case 218 /* VariableDeclaration */: - // equal in p = 0; - case 142 /* Parameter */: - case 255 /* EnumMember */: - case 145 /* PropertyDeclaration */: - case 144 /* PropertySignature */: - return context.currentTokenSpan.kind === 56 /* EqualsToken */ || context.nextTokenSpan.kind === 56 /* EqualsToken */; - // "in" keyword in for (let x in []) { } - case 207 /* ForInStatement */: - return context.currentTokenSpan.kind === 90 /* InKeyword */ || context.nextTokenSpan.kind === 90 /* InKeyword */; - // Technically, "of" is not a binary operator, but format it the same way as "in" - case 208 /* ForOfStatement */: - return context.currentTokenSpan.kind === 138 /* OfKeyword */ || context.nextTokenSpan.kind === 138 /* OfKeyword */; + return getSemanticDocumentHighlights(node) || getSyntacticDocumentHighlights(node); + function getHighlightSpanForNode(node) { + var start = node.getStart(); + var end = node.getEnd(); + return { + fileName: sourceFile.fileName, + textSpan: ts.createTextSpanFromBounds(start, end), + kind: ts.HighlightSpanKind.none + }; + } + function getSemanticDocumentHighlights(node) { + if (node.kind === 69 /* Identifier */ || + node.kind === 97 /* ThisKeyword */ || + node.kind === 165 /* ThisType */ || + node.kind === 95 /* SuperKeyword */ || + node.kind === 9 /* StringLiteral */ || + ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(node)) { + var referencedSymbols = ts.FindAllReferences.getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFilesToSearch, /*findInStrings*/ false, /*findInComments*/ false, /*implementations*/ false); + return convertReferencedSymbols(referencedSymbols); } - return false; - }; - Rules.IsNotBinaryOpContext = function (context) { - return !Rules.IsBinaryOpContext(context); - }; - Rules.IsConditionalOperatorContext = function (context) { - return context.contextNode.kind === 188 /* ConditionalExpression */; - }; - Rules.IsSameLineTokenOrBeforeMultilineBlockContext = function (context) { - //// This check is mainly used inside SpaceBeforeOpenBraceInControl and SpaceBeforeOpenBraceInFunction. - //// - //// Ex: - //// if (1) { .... - //// * ) and { are on the same line so apply the rule. Here we don't care whether it's same or multi block context - //// - //// Ex: - //// if (1) - //// { ... } - //// * ) and { are on different lines. We only need to format if the block is multiline context. So in this case we don't format. - //// - //// Ex: - //// if (1) - //// { ... - //// } - //// * ) and { are on different lines. We only need to format if the block is multiline context. So in this case we format. - return context.TokensAreOnSameLine() || Rules.IsBeforeMultilineBlockContext(context); - }; - // This check is done before an open brace in a control construct, a function, or a typescript block declaration - Rules.IsBeforeMultilineBlockContext = function (context) { - return Rules.IsBeforeBlockContext(context) && !(context.NextNodeAllOnSameLine() || context.NextNodeBlockIsOnOneLine()); - }; - Rules.IsMultilineBlockContext = function (context) { - return Rules.IsBlockContext(context) && !(context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine()); - }; - Rules.IsSingleLineBlockContext = function (context) { - return Rules.IsBlockContext(context) && (context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine()); - }; - Rules.IsBlockContext = function (context) { - return Rules.NodeIsBlockContext(context.contextNode); - }; - Rules.IsBeforeBlockContext = function (context) { - return Rules.NodeIsBlockContext(context.nextTokenParent); - }; - // IMPORTANT!!! This method must return true ONLY for nodes with open and close braces as immediate children - Rules.NodeIsBlockContext = function (node) { - if (Rules.NodeIsTypeScriptDeclWithBlockContext(node)) { - // This means we are in a context that looks like a block to the user, but in the grammar is actually not a node (it's a class, module, enum, object type literal, etc). - return true; + return undefined; + function convertReferencedSymbols(referencedSymbols) { + if (!referencedSymbols) { + return undefined; + } + var fileNameToDocumentHighlights = ts.createMap(); + var result = []; + for (var _i = 0, referencedSymbols_1 = referencedSymbols; _i < referencedSymbols_1.length; _i++) { + var referencedSymbol = referencedSymbols_1[_i]; + for (var _a = 0, _b = referencedSymbol.references; _a < _b.length; _a++) { + var referenceEntry = _b[_a]; + var fileName = referenceEntry.fileName; + var documentHighlights = fileNameToDocumentHighlights[fileName]; + if (!documentHighlights) { + documentHighlights = { fileName: fileName, highlightSpans: [] }; + fileNameToDocumentHighlights[fileName] = documentHighlights; + result.push(documentHighlights); + } + documentHighlights.highlightSpans.push({ + textSpan: referenceEntry.textSpan, + kind: referenceEntry.isWriteAccess ? ts.HighlightSpanKind.writtenReference : ts.HighlightSpanKind.reference + }); + } + } + return result; } - switch (node.kind) { - case 199 /* Block */: - case 227 /* CaseBlock */: - case 171 /* ObjectLiteralExpression */: - case 226 /* ModuleBlock */: - return true; + } + function getSyntacticDocumentHighlights(node) { + var fileName = sourceFile.fileName; + var highlightSpans = getHighlightSpans(node); + if (!highlightSpans || highlightSpans.length === 0) { + return undefined; } - return false; - }; - Rules.IsFunctionDeclContext = function (context) { - switch (context.contextNode.kind) { - case 220 /* FunctionDeclaration */: - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - // case SyntaxKind.MemberFunctionDeclaration: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - // case SyntaxKind.MethodSignature: - case 151 /* CallSignature */: - case 179 /* FunctionExpression */: - case 148 /* Constructor */: - case 180 /* ArrowFunction */: - // case SyntaxKind.ConstructorDeclaration: - // case SyntaxKind.SimpleArrowFunctionExpression: - // case SyntaxKind.ParenthesizedArrowFunctionExpression: - case 222 /* InterfaceDeclaration */: - return true; + return [{ fileName: fileName, highlightSpans: highlightSpans }]; + // returns true if 'node' is defined and has a matching 'kind'. + function hasKind(node, kind) { + return node !== undefined && node.kind === kind; } - return false; - }; - Rules.IsFunctionDeclarationOrFunctionExpressionContext = function (context) { - return context.contextNode.kind === 220 /* FunctionDeclaration */ || context.contextNode.kind === 179 /* FunctionExpression */; - }; - Rules.IsTypeScriptDeclWithBlockContext = function (context) { - return Rules.NodeIsTypeScriptDeclWithBlockContext(context.contextNode); - }; - Rules.NodeIsTypeScriptDeclWithBlockContext = function (node) { - switch (node.kind) { - case 221 /* ClassDeclaration */: - case 192 /* ClassExpression */: - case 222 /* InterfaceDeclaration */: - case 224 /* EnumDeclaration */: - case 159 /* TypeLiteral */: - case 225 /* ModuleDeclaration */: - case 236 /* ExportDeclaration */: - case 237 /* NamedExports */: - case 230 /* ImportDeclaration */: - case 233 /* NamedImports */: - return true; + // Null-propagating 'parent' function. + function parent(node) { + return node && node.parent; } - return false; - }; - Rules.IsAfterCodeBlockContext = function (context) { - switch (context.currentTokenParent.kind) { - case 221 /* ClassDeclaration */: - case 225 /* ModuleDeclaration */: - case 224 /* EnumDeclaration */: - case 199 /* Block */: - case 252 /* CatchClause */: - case 226 /* ModuleBlock */: - case 213 /* SwitchStatement */: - return true; + function getHighlightSpans(node) { + if (node) { + switch (node.kind) { + case 88 /* IfKeyword */: + case 80 /* ElseKeyword */: + if (hasKind(node.parent, 203 /* IfStatement */)) { + return getIfElseOccurrences(node.parent); + } + break; + case 94 /* ReturnKeyword */: + if (hasKind(node.parent, 211 /* ReturnStatement */)) { + return getReturnOccurrences(node.parent); + } + break; + case 98 /* ThrowKeyword */: + if (hasKind(node.parent, 215 /* ThrowStatement */)) { + return getThrowOccurrences(node.parent); + } + break; + case 72 /* CatchKeyword */: + if (hasKind(parent(parent(node)), 216 /* TryStatement */)) { + return getTryCatchFinallyOccurrences(node.parent.parent); + } + break; + case 100 /* TryKeyword */: + case 85 /* FinallyKeyword */: + if (hasKind(parent(node), 216 /* TryStatement */)) { + return getTryCatchFinallyOccurrences(node.parent); + } + break; + case 96 /* SwitchKeyword */: + if (hasKind(node.parent, 213 /* SwitchStatement */)) { + return getSwitchCaseDefaultOccurrences(node.parent); + } + break; + case 71 /* CaseKeyword */: + case 77 /* DefaultKeyword */: + if (hasKind(parent(parent(parent(node))), 213 /* SwitchStatement */)) { + return getSwitchCaseDefaultOccurrences(node.parent.parent.parent); + } + break; + case 70 /* BreakKeyword */: + case 75 /* ContinueKeyword */: + if (hasKind(node.parent, 210 /* BreakStatement */) || hasKind(node.parent, 209 /* ContinueStatement */)) { + return getBreakOrContinueStatementOccurrences(node.parent); + } + break; + case 86 /* ForKeyword */: + if (hasKind(node.parent, 206 /* ForStatement */) || + hasKind(node.parent, 207 /* ForInStatement */) || + hasKind(node.parent, 208 /* ForOfStatement */)) { + return getLoopBreakContinueOccurrences(node.parent); + } + break; + case 104 /* WhileKeyword */: + case 79 /* DoKeyword */: + if (hasKind(node.parent, 205 /* WhileStatement */) || hasKind(node.parent, 204 /* DoStatement */)) { + return getLoopBreakContinueOccurrences(node.parent); + } + break; + case 121 /* ConstructorKeyword */: + if (hasKind(node.parent, 148 /* Constructor */)) { + return getConstructorOccurrences(node.parent); + } + break; + case 123 /* GetKeyword */: + case 131 /* SetKeyword */: + if (hasKind(node.parent, 149 /* GetAccessor */) || hasKind(node.parent, 150 /* SetAccessor */)) { + return getGetAndSetOccurrences(node.parent); + } + break; + default: + if (ts.isModifierKind(node.kind) && node.parent && + (ts.isDeclaration(node.parent) || node.parent.kind === 200 /* VariableStatement */)) { + return getModifierOccurrences(node.kind, node.parent); + } + } + } + return undefined; } - return false; - }; - Rules.IsControlDeclContext = function (context) { - switch (context.contextNode.kind) { - case 203 /* IfStatement */: - case 213 /* SwitchStatement */: - case 206 /* ForStatement */: - case 207 /* ForInStatement */: - case 208 /* ForOfStatement */: - case 205 /* WhileStatement */: - case 216 /* TryStatement */: - case 204 /* DoStatement */: - case 212 /* WithStatement */: - // TODO - // case SyntaxKind.ElseClause: - case 252 /* CatchClause */: - return true; - default: - return false; + /** + * Aggregates all throw-statements within this node *without* crossing + * into function boundaries and try-blocks with catch-clauses. + */ + function aggregateOwnedThrowStatements(node) { + var statementAccumulator = []; + aggregate(node); + return statementAccumulator; + function aggregate(node) { + if (node.kind === 215 /* ThrowStatement */) { + statementAccumulator.push(node); + } + else if (node.kind === 216 /* TryStatement */) { + var tryStatement = node; + if (tryStatement.catchClause) { + aggregate(tryStatement.catchClause); + } + else { + // Exceptions thrown within a try block lacking a catch clause + // are "owned" in the current context. + aggregate(tryStatement.tryBlock); + } + if (tryStatement.finallyBlock) { + aggregate(tryStatement.finallyBlock); + } + } + else if (!ts.isFunctionLike(node)) { + ts.forEachChild(node, aggregate); + } + } } - }; - Rules.IsObjectContext = function (context) { - return context.contextNode.kind === 171 /* ObjectLiteralExpression */; - }; - Rules.IsFunctionCallContext = function (context) { - return context.contextNode.kind === 174 /* CallExpression */; - }; - Rules.IsNewContext = function (context) { - return context.contextNode.kind === 175 /* NewExpression */; - }; - Rules.IsFunctionCallOrNewContext = function (context) { - return Rules.IsFunctionCallContext(context) || Rules.IsNewContext(context); - }; - Rules.IsPreviousTokenNotComma = function (context) { - return context.currentTokenSpan.kind !== 24 /* CommaToken */; - }; - Rules.IsNextTokenNotCloseBracket = function (context) { - return context.nextTokenSpan.kind !== 20 /* CloseBracketToken */; - }; - Rules.IsArrowFunctionContext = function (context) { - return context.contextNode.kind === 180 /* ArrowFunction */; - }; - Rules.IsNonJsxSameLineTokenContext = function (context) { - return context.TokensAreOnSameLine() && context.contextNode.kind !== 244 /* JsxText */; - }; - Rules.IsNonJsxElementContext = function (context) { - return context.contextNode.kind !== 241 /* JsxElement */; - }; - Rules.IsJsxExpressionContext = function (context) { - return context.contextNode.kind === 248 /* JsxExpression */; - }; - Rules.IsNextTokenParentJsxAttribute = function (context) { - return context.nextTokenParent.kind === 246 /* JsxAttribute */; - }; - Rules.IsJsxAttributeContext = function (context) { - return context.contextNode.kind === 246 /* JsxAttribute */; - }; - Rules.IsJsxSelfClosingElementContext = function (context) { - return context.contextNode.kind === 242 /* JsxSelfClosingElement */; - }; - Rules.IsNotBeforeBlockInFunctionDeclarationContext = function (context) { - return !Rules.IsFunctionDeclContext(context) && !Rules.IsBeforeBlockContext(context); - }; - Rules.IsEndOfDecoratorContextOnSameLine = function (context) { - return context.TokensAreOnSameLine() && - context.contextNode.decorators && - Rules.NodeIsInDecoratorContext(context.currentTokenParent) && - !Rules.NodeIsInDecoratorContext(context.nextTokenParent); - }; - Rules.NodeIsInDecoratorContext = function (node) { - while (ts.isExpression(node)) { - node = node.parent; + /** + * For lack of a better name, this function takes a throw statement and returns the + * nearest ancestor that is a try-block (whose try statement has a catch clause), + * function-block, or source file. + */ + function getThrowStatementOwner(throwStatement) { + var child = throwStatement; + while (child.parent) { + var parent_20 = child.parent; + if (ts.isFunctionBlock(parent_20) || parent_20.kind === 256 /* SourceFile */) { + return parent_20; + } + // A throw-statement is only owned by a try-statement if the try-statement has + // a catch clause, and if the throw-statement occurs within the try block. + if (parent_20.kind === 216 /* TryStatement */) { + var tryStatement = parent_20; + if (tryStatement.tryBlock === child && tryStatement.catchClause) { + return child; + } + } + child = parent_20; + } + return undefined; } - return node.kind === 143 /* Decorator */; - }; - Rules.IsStartOfVariableDeclarationList = function (context) { - return context.currentTokenParent.kind === 219 /* VariableDeclarationList */ && - context.currentTokenParent.getStart(context.sourceFile) === context.currentTokenSpan.pos; - }; - Rules.IsNotFormatOnEnter = function (context) { - return context.formattingRequestKind !== 2 /* FormatOnEnter */; - }; - Rules.IsModuleDeclContext = function (context) { - return context.contextNode.kind === 225 /* ModuleDeclaration */; - }; - Rules.IsObjectTypeContext = function (context) { - return context.contextNode.kind === 159 /* TypeLiteral */; // && context.contextNode.parent.kind !== SyntaxKind.InterfaceDeclaration; - }; - Rules.IsTypeArgumentOrParameterOrAssertion = function (token, parent) { - if (token.kind !== 25 /* LessThanToken */ && token.kind !== 27 /* GreaterThanToken */) { - return false; + function aggregateAllBreakAndContinueStatements(node) { + var statementAccumulator = []; + aggregate(node); + return statementAccumulator; + function aggregate(node) { + if (node.kind === 210 /* BreakStatement */ || node.kind === 209 /* ContinueStatement */) { + statementAccumulator.push(node); + } + else if (!ts.isFunctionLike(node)) { + ts.forEachChild(node, aggregate); + } + } } - switch (parent.kind) { - case 155 /* TypeReference */: - case 177 /* TypeAssertionExpression */: - case 221 /* ClassDeclaration */: - case 192 /* ClassExpression */: - case 222 /* InterfaceDeclaration */: - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - case 180 /* ArrowFunction */: - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - case 151 /* CallSignature */: - case 152 /* ConstructSignature */: - case 174 /* CallExpression */: - case 175 /* NewExpression */: - case 194 /* ExpressionWithTypeArguments */: - return true; - default: - return false; + function ownsBreakOrContinueStatement(owner, statement) { + var actualOwner = getBreakOrContinueOwner(statement); + return actualOwner && actualOwner === owner; } - }; - Rules.IsTypeArgumentOrParameterOrAssertionContext = function (context) { - return Rules.IsTypeArgumentOrParameterOrAssertion(context.currentTokenSpan, context.currentTokenParent) || - Rules.IsTypeArgumentOrParameterOrAssertion(context.nextTokenSpan, context.nextTokenParent); - }; - Rules.IsTypeAssertionContext = function (context) { - return context.contextNode.kind === 177 /* TypeAssertionExpression */; - }; - Rules.IsVoidOpContext = function (context) { - return context.currentTokenSpan.kind === 103 /* VoidKeyword */ && context.currentTokenParent.kind === 183 /* VoidExpression */; - }; - Rules.IsYieldOrYieldStarWithOperand = function (context) { - return context.contextNode.kind === 190 /* YieldExpression */ && context.contextNode.expression !== undefined; - }; - return Rules; - }()); - formatting.Rules = Rules; - })(formatting = ts.formatting || (ts.formatting = {})); -})(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - var formatting; - (function (formatting) { - var RulesMap = (function () { - function RulesMap() { - this.map = []; - this.mapRowLength = 0; - } - RulesMap.create = function (rules) { - var result = new RulesMap(); - result.Initialize(rules); - return result; - }; - RulesMap.prototype.Initialize = function (rules) { - this.mapRowLength = 138 /* LastToken */ + 1; - this.map = new Array(this.mapRowLength * this.mapRowLength); // new Array(this.mapRowLength * this.mapRowLength); - // This array is used only during construction of the rulesbucket in the map - var rulesBucketConstructionStateList = new Array(this.map.length); // new Array(this.map.length); - this.FillRules(rules, rulesBucketConstructionStateList); - return this.map; - }; - RulesMap.prototype.FillRules = function (rules, rulesBucketConstructionStateList) { - var _this = this; - rules.forEach(function (rule) { - _this.FillRule(rule, rulesBucketConstructionStateList); - }); - }; - RulesMap.prototype.GetRuleBucketIndex = function (row, column) { - var rulesBucketIndex = (row * this.mapRowLength) + column; - // Debug.Assert(rulesBucketIndex < this.map.Length, "Trying to access an index outside the array."); - return rulesBucketIndex; - }; - RulesMap.prototype.FillRule = function (rule, rulesBucketConstructionStateList) { - var _this = this; - var specificRule = rule.Descriptor.LeftTokenRange !== formatting.Shared.TokenRange.Any && - rule.Descriptor.RightTokenRange !== formatting.Shared.TokenRange.Any; - rule.Descriptor.LeftTokenRange.GetTokens().forEach(function (left) { - rule.Descriptor.RightTokenRange.GetTokens().forEach(function (right) { - var rulesBucketIndex = _this.GetRuleBucketIndex(left, right); - var rulesBucket = _this.map[rulesBucketIndex]; - if (rulesBucket === undefined) { - rulesBucket = _this.map[rulesBucketIndex] = new RulesBucket(); + function getBreakOrContinueOwner(statement) { + for (var node_1 = statement.parent; node_1; node_1 = node_1.parent) { + switch (node_1.kind) { + case 213 /* SwitchStatement */: + if (statement.kind === 209 /* ContinueStatement */) { + continue; + } + // Fall through. + case 206 /* ForStatement */: + case 207 /* ForInStatement */: + case 208 /* ForOfStatement */: + case 205 /* WhileStatement */: + case 204 /* DoStatement */: + if (!statement.label || isLabeledBy(node_1, statement.label.text)) { + return node_1; + } + break; + default: + // Don't cross function boundaries. + if (ts.isFunctionLike(node_1)) { + return undefined; + } + break; + } + } + return undefined; + } + function getModifierOccurrences(modifier, declaration) { + var container = declaration.parent; + // Make sure we only highlight the keyword when it makes sense to do so. + if (ts.isAccessibilityModifier(modifier)) { + if (!(container.kind === 221 /* ClassDeclaration */ || + container.kind === 192 /* ClassExpression */ || + (declaration.kind === 142 /* Parameter */ && hasKind(container, 148 /* Constructor */)))) { + return undefined; + } + } + else if (modifier === 113 /* StaticKeyword */) { + if (!(container.kind === 221 /* ClassDeclaration */ || container.kind === 192 /* ClassExpression */)) { + return undefined; + } + } + else if (modifier === 82 /* ExportKeyword */ || modifier === 122 /* DeclareKeyword */) { + if (!(container.kind === 226 /* ModuleBlock */ || container.kind === 256 /* SourceFile */)) { + return undefined; + } + } + else if (modifier === 115 /* AbstractKeyword */) { + if (!(container.kind === 221 /* ClassDeclaration */ || declaration.kind === 221 /* ClassDeclaration */)) { + return undefined; + } + } + else { + // unsupported modifier + return undefined; + } + var keywords = []; + var modifierFlag = getFlagFromModifier(modifier); + var nodes; + switch (container.kind) { + case 226 /* ModuleBlock */: + case 256 /* SourceFile */: + // Container is either a class declaration or the declaration is a classDeclaration + if (modifierFlag & 128 /* Abstract */) { + nodes = declaration.members.concat(declaration); + } + else { + nodes = container.statements; + } + break; + case 148 /* Constructor */: + nodes = container.parameters.concat(container.parent.members); + break; + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + nodes = container.members; + // If we're an accessibility modifier, we're in an instance member and should search + // the constructor's parameter list for instance members as well. + if (modifierFlag & 28 /* AccessibilityModifier */) { + var constructor = ts.forEach(container.members, function (member) { + return member.kind === 148 /* Constructor */ && member; + }); + if (constructor) { + nodes = nodes.concat(constructor.parameters); + } + } + else if (modifierFlag & 128 /* Abstract */) { + nodes = nodes.concat(container); + } + break; + default: + ts.Debug.fail("Invalid container kind."); + } + ts.forEach(nodes, function (node) { + if (ts.getModifierFlags(node) & modifierFlag) { + ts.forEach(node.modifiers, function (child) { return pushKeywordIf(keywords, child, modifier); }); } - rulesBucket.AddRule(rule, specificRule, rulesBucketConstructionStateList, rulesBucketIndex); }); - }); - }; - RulesMap.prototype.GetRule = function (context) { - var bucketIndex = this.GetRuleBucketIndex(context.currentTokenSpan.kind, context.nextTokenSpan.kind); - var bucket = this.map[bucketIndex]; - if (bucket) { - for (var _i = 0, _a = bucket.Rules(); _i < _a.length; _i++) { - var rule = _a[_i]; - if (rule.Operation.Context.InContext(context)) { - return rule; + return ts.map(keywords, getHighlightSpanForNode); + function getFlagFromModifier(modifier) { + switch (modifier) { + case 112 /* PublicKeyword */: + return 4 /* Public */; + case 110 /* PrivateKeyword */: + return 8 /* Private */; + case 111 /* ProtectedKeyword */: + return 16 /* Protected */; + case 113 /* StaticKeyword */: + return 32 /* Static */; + case 82 /* ExportKeyword */: + return 1 /* Export */; + case 122 /* DeclareKeyword */: + return 2 /* Ambient */; + case 115 /* AbstractKeyword */: + return 128 /* Abstract */; + default: + ts.Debug.fail(); } } } - return undefined; - }; - return RulesMap; - }()); - formatting.RulesMap = RulesMap; - var MaskBitSize = 5; - var Mask = 0x1f; - (function (RulesPosition) { - RulesPosition[RulesPosition["IgnoreRulesSpecific"] = 0] = "IgnoreRulesSpecific"; - RulesPosition[RulesPosition["IgnoreRulesAny"] = MaskBitSize * 1] = "IgnoreRulesAny"; - RulesPosition[RulesPosition["ContextRulesSpecific"] = MaskBitSize * 2] = "ContextRulesSpecific"; - RulesPosition[RulesPosition["ContextRulesAny"] = MaskBitSize * 3] = "ContextRulesAny"; - RulesPosition[RulesPosition["NoContextRulesSpecific"] = MaskBitSize * 4] = "NoContextRulesSpecific"; - RulesPosition[RulesPosition["NoContextRulesAny"] = MaskBitSize * 5] = "NoContextRulesAny"; - })(formatting.RulesPosition || (formatting.RulesPosition = {})); - var RulesPosition = formatting.RulesPosition; - var RulesBucketConstructionState = (function () { - function RulesBucketConstructionState() { - //// The Rules list contains all the inserted rules into a rulebucket in the following order: - //// 1- Ignore rules with specific token combination - //// 2- Ignore rules with any token combination - //// 3- Context rules with specific token combination - //// 4- Context rules with any token combination - //// 5- Non-context rules with specific token combination - //// 6- Non-context rules with any token combination - //// - //// The member rulesInsertionIndexBitmap is used to describe the number of rules - //// in each sub-bucket (above) hence can be used to know the index of where to insert - //// the next rule. It's a bitmap which contains 6 different sections each is given 5 bits. - //// - //// Example: - //// In order to insert a rule to the end of sub-bucket (3), we get the index by adding - //// the values in the bitmap segments 3rd, 2nd, and 1st. - this.rulesInsertionIndexBitmap = 0; - } - RulesBucketConstructionState.prototype.GetInsertionIndex = function (maskPosition) { - var index = 0; - var pos = 0; - var indexBitmap = this.rulesInsertionIndexBitmap; - while (pos <= maskPosition) { - index += (indexBitmap & Mask); - indexBitmap >>= MaskBitSize; - pos += MaskBitSize; - } - return index; - }; - RulesBucketConstructionState.prototype.IncreaseInsertionIndex = function (maskPosition) { - var value = (this.rulesInsertionIndexBitmap >> maskPosition) & Mask; - value++; - ts.Debug.assert((value & Mask) === value, "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules."); - var temp = this.rulesInsertionIndexBitmap & ~(Mask << maskPosition); - temp |= value << maskPosition; - this.rulesInsertionIndexBitmap = temp; - }; - return RulesBucketConstructionState; - }()); - formatting.RulesBucketConstructionState = RulesBucketConstructionState; - var RulesBucket = (function () { - function RulesBucket() { - this.rules = []; - } - RulesBucket.prototype.Rules = function () { - return this.rules; - }; - RulesBucket.prototype.AddRule = function (rule, specificTokens, constructionState, rulesBucketIndex) { - var position; - if (rule.Operation.Action === 1 /* Ignore */) { - position = specificTokens ? - RulesPosition.IgnoreRulesSpecific : - RulesPosition.IgnoreRulesAny; + function pushKeywordIf(keywordList, token) { + var expected = []; + for (var _i = 2; _i < arguments.length; _i++) { + expected[_i - 2] = arguments[_i]; + } + if (token && ts.contains(expected, token.kind)) { + keywordList.push(token); + return true; + } + return false; } - else if (!rule.Operation.Context.IsAny()) { - position = specificTokens ? - RulesPosition.ContextRulesSpecific : - RulesPosition.ContextRulesAny; + function getGetAndSetOccurrences(accessorDeclaration) { + var keywords = []; + tryPushAccessorKeyword(accessorDeclaration.symbol, 149 /* GetAccessor */); + tryPushAccessorKeyword(accessorDeclaration.symbol, 150 /* SetAccessor */); + return ts.map(keywords, getHighlightSpanForNode); + function tryPushAccessorKeyword(accessorSymbol, accessorKind) { + var accessor = ts.getDeclarationOfKind(accessorSymbol, accessorKind); + if (accessor) { + ts.forEach(accessor.getChildren(), function (child) { return pushKeywordIf(keywords, child, 123 /* GetKeyword */, 131 /* SetKeyword */); }); + } + } } - else { - position = specificTokens ? - RulesPosition.NoContextRulesSpecific : - RulesPosition.NoContextRulesAny; + function getConstructorOccurrences(constructorDeclaration) { + var declarations = constructorDeclaration.symbol.getDeclarations(); + var keywords = []; + ts.forEach(declarations, function (declaration) { + ts.forEach(declaration.getChildren(), function (token) { + return pushKeywordIf(keywords, token, 121 /* ConstructorKeyword */); + }); + }); + return ts.map(keywords, getHighlightSpanForNode); } - var state = constructionState[rulesBucketIndex]; - if (state === undefined) { - state = constructionState[rulesBucketIndex] = new RulesBucketConstructionState(); + function getLoopBreakContinueOccurrences(loopNode) { + var keywords = []; + if (pushKeywordIf(keywords, loopNode.getFirstToken(), 86 /* ForKeyword */, 104 /* WhileKeyword */, 79 /* DoKeyword */)) { + // If we succeeded and got a do-while loop, then start looking for a 'while' keyword. + if (loopNode.kind === 204 /* DoStatement */) { + var loopTokens = loopNode.getChildren(); + for (var i = loopTokens.length - 1; i >= 0; i--) { + if (pushKeywordIf(keywords, loopTokens[i], 104 /* WhileKeyword */)) { + break; + } + } + } + } + var breaksAndContinues = aggregateAllBreakAndContinueStatements(loopNode.statement); + ts.forEach(breaksAndContinues, function (statement) { + if (ownsBreakOrContinueStatement(loopNode, statement)) { + pushKeywordIf(keywords, statement.getFirstToken(), 70 /* BreakKeyword */, 75 /* ContinueKeyword */); + } + }); + return ts.map(keywords, getHighlightSpanForNode); } - var index = state.GetInsertionIndex(position); - this.rules.splice(index, 0, rule); - state.IncreaseInsertionIndex(position); - }; - return RulesBucket; - }()); - formatting.RulesBucket = RulesBucket; - })(formatting = ts.formatting || (ts.formatting = {})); -})(ts || (ts = {})); -/// -/* @internal */ -var ts; -(function (ts) { - var formatting; - (function (formatting) { - var Shared; - (function (Shared) { - var TokenRangeAccess = (function () { - function TokenRangeAccess(from, to, except) { - this.tokens = []; - for (var token = from; token <= to; token++) { - if (ts.indexOf(except, token) < 0) { - this.tokens.push(token); + function getBreakOrContinueStatementOccurrences(breakOrContinueStatement) { + var owner = getBreakOrContinueOwner(breakOrContinueStatement); + if (owner) { + switch (owner.kind) { + case 206 /* ForStatement */: + case 207 /* ForInStatement */: + case 208 /* ForOfStatement */: + case 204 /* DoStatement */: + case 205 /* WhileStatement */: + return getLoopBreakContinueOccurrences(owner); + case 213 /* SwitchStatement */: + return getSwitchCaseDefaultOccurrences(owner); } } + return undefined; } - TokenRangeAccess.prototype.GetTokens = function () { - return this.tokens; - }; - TokenRangeAccess.prototype.Contains = function (token) { - return this.tokens.indexOf(token) >= 0; - }; - return TokenRangeAccess; - }()); - Shared.TokenRangeAccess = TokenRangeAccess; - var TokenValuesAccess = (function () { - function TokenValuesAccess(tks) { - this.tokens = tks && tks.length ? tks : []; + function getSwitchCaseDefaultOccurrences(switchStatement) { + var keywords = []; + pushKeywordIf(keywords, switchStatement.getFirstToken(), 96 /* SwitchKeyword */); + // Go through each clause in the switch statement, collecting the 'case'/'default' keywords. + ts.forEach(switchStatement.caseBlock.clauses, function (clause) { + pushKeywordIf(keywords, clause.getFirstToken(), 71 /* CaseKeyword */, 77 /* DefaultKeyword */); + var breaksAndContinues = aggregateAllBreakAndContinueStatements(clause); + ts.forEach(breaksAndContinues, function (statement) { + if (ownsBreakOrContinueStatement(switchStatement, statement)) { + pushKeywordIf(keywords, statement.getFirstToken(), 70 /* BreakKeyword */); + } + }); + }); + return ts.map(keywords, getHighlightSpanForNode); } - TokenValuesAccess.prototype.GetTokens = function () { - return this.tokens; - }; - TokenValuesAccess.prototype.Contains = function (token) { - return this.tokens.indexOf(token) >= 0; - }; - return TokenValuesAccess; - }()); - Shared.TokenValuesAccess = TokenValuesAccess; - var TokenSingleValueAccess = (function () { - function TokenSingleValueAccess(token) { - this.token = token; + function getTryCatchFinallyOccurrences(tryStatement) { + var keywords = []; + pushKeywordIf(keywords, tryStatement.getFirstToken(), 100 /* TryKeyword */); + if (tryStatement.catchClause) { + pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken(), 72 /* CatchKeyword */); + } + if (tryStatement.finallyBlock) { + var finallyKeyword = ts.findChildOfKind(tryStatement, 85 /* FinallyKeyword */, sourceFile); + pushKeywordIf(keywords, finallyKeyword, 85 /* FinallyKeyword */); + } + return ts.map(keywords, getHighlightSpanForNode); } - TokenSingleValueAccess.prototype.GetTokens = function () { - return [this.token]; - }; - TokenSingleValueAccess.prototype.Contains = function (tokenValue) { - return tokenValue === this.token; - }; - return TokenSingleValueAccess; - }()); - Shared.TokenSingleValueAccess = TokenSingleValueAccess; - var TokenAllAccess = (function () { - function TokenAllAccess() { + function getThrowOccurrences(throwStatement) { + var owner = getThrowStatementOwner(throwStatement); + if (!owner) { + return undefined; + } + var keywords = []; + ts.forEach(aggregateOwnedThrowStatements(owner), function (throwStatement) { + pushKeywordIf(keywords, throwStatement.getFirstToken(), 98 /* ThrowKeyword */); + }); + // If the "owner" is a function, then we equate 'return' and 'throw' statements in their + // ability to "jump out" of the function, and include occurrences for both. + if (ts.isFunctionBlock(owner)) { + ts.forEachReturnStatement(owner, function (returnStatement) { + pushKeywordIf(keywords, returnStatement.getFirstToken(), 94 /* ReturnKeyword */); + }); + } + return ts.map(keywords, getHighlightSpanForNode); } - TokenAllAccess.prototype.GetTokens = function () { + function getReturnOccurrences(returnStatement) { + var func = ts.getContainingFunction(returnStatement); + // If we didn't find a containing function with a block body, bail out. + if (!(func && hasKind(func.body, 199 /* Block */))) { + return undefined; + } + var keywords = []; + ts.forEachReturnStatement(func.body, function (returnStatement) { + pushKeywordIf(keywords, returnStatement.getFirstToken(), 94 /* ReturnKeyword */); + }); + // Include 'throw' statements that do not occur within a try block. + ts.forEach(aggregateOwnedThrowStatements(func.body), function (throwStatement) { + pushKeywordIf(keywords, throwStatement.getFirstToken(), 98 /* ThrowKeyword */); + }); + return ts.map(keywords, getHighlightSpanForNode); + } + function getIfElseOccurrences(ifStatement) { + var keywords = []; + // Traverse upwards through all parent if-statements linked by their else-branches. + while (hasKind(ifStatement.parent, 203 /* IfStatement */) && ifStatement.parent.elseStatement === ifStatement) { + ifStatement = ifStatement.parent; + } + // Now traverse back down through the else branches, aggregating if/else keywords of if-statements. + while (ifStatement) { + var children = ifStatement.getChildren(); + pushKeywordIf(keywords, children[0], 88 /* IfKeyword */); + // Generally the 'else' keyword is second-to-last, so we traverse backwards. + for (var i = children.length - 1; i >= 0; i--) { + if (pushKeywordIf(keywords, children[i], 80 /* ElseKeyword */)) { + break; + } + } + if (!hasKind(ifStatement.elseStatement, 203 /* IfStatement */)) { + break; + } + ifStatement = ifStatement.elseStatement; + } var result = []; - for (var token = 0 /* FirstToken */; token <= 138 /* LastToken */; token++) { - result.push(token); + // We'd like to highlight else/ifs together if they are only separated by whitespace + // (i.e. the keywords are separated by no comments, no newlines). + for (var i = 0; i < keywords.length; i++) { + if (keywords[i].kind === 80 /* ElseKeyword */ && i < keywords.length - 1) { + var elseKeyword = keywords[i]; + var ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword. + var shouldCombindElseAndIf = true; + // Avoid recalculating getStart() by iterating backwards. + for (var j = ifKeyword.getStart() - 1; j >= elseKeyword.end; j--) { + if (!ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(j))) { + shouldCombindElseAndIf = false; + break; + } + } + if (shouldCombindElseAndIf) { + result.push({ + fileName: fileName, + textSpan: ts.createTextSpanFromBounds(elseKeyword.getStart(), ifKeyword.end), + kind: ts.HighlightSpanKind.reference + }); + i++; // skip the next keyword + continue; + } + } + // Ordinary case: just highlight the keyword. + result.push(getHighlightSpanForNode(keywords[i])); } return result; - }; - TokenAllAccess.prototype.Contains = function (tokenValue) { + } + } + } + DocumentHighlights.getDocumentHighlights = getDocumentHighlights; + /** + * Whether or not a 'node' is preceded by a label of the given string. + * Note: 'node' cannot be a SourceFile. + */ + function isLabeledBy(node, labelName) { + for (var owner = node.parent; owner.kind === 214 /* LabeledStatement */; owner = owner.parent) { + if (owner.label.text === labelName) { return true; - }; - TokenAllAccess.prototype.toString = function () { - return "[allTokens]"; - }; - return TokenAllAccess; - }()); - Shared.TokenAllAccess = TokenAllAccess; - var TokenRange = (function () { - function TokenRange(tokenAccess) { - this.tokenAccess = tokenAccess; } - TokenRange.FromToken = function (token) { - return new TokenRange(new TokenSingleValueAccess(token)); - }; - TokenRange.FromTokens = function (tokens) { - return new TokenRange(new TokenValuesAccess(tokens)); - }; - TokenRange.FromRange = function (f, to, except) { - if (except === void 0) { except = []; } - return new TokenRange(new TokenRangeAccess(f, to, except)); - }; - TokenRange.AllTokens = function () { - return new TokenRange(new TokenAllAccess()); - }; - TokenRange.prototype.GetTokens = function () { - return this.tokenAccess.GetTokens(); - }; - TokenRange.prototype.Contains = function (token) { - return this.tokenAccess.Contains(token); + } + return false; + } + })(DocumentHighlights = ts.DocumentHighlights || (ts.DocumentHighlights = {})); +})(ts || (ts = {})); +var ts; +(function (ts) { + function createDocumentRegistry(useCaseSensitiveFileNames, currentDirectory) { + if (currentDirectory === void 0) { currentDirectory = ""; } + // Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have + // for those settings. + var buckets = ts.createMap(); + var getCanonicalFileName = ts.createGetCanonicalFileName(!!useCaseSensitiveFileNames); + function getKeyForCompilationSettings(settings) { + return "_" + settings.target + "|" + settings.module + "|" + settings.noResolve + "|" + settings.jsx + "|" + settings.allowJs + "|" + settings.baseUrl + "|" + JSON.stringify(settings.typeRoots) + "|" + JSON.stringify(settings.rootDirs) + "|" + JSON.stringify(settings.paths); + } + function getBucketForCompilationSettings(key, createIfMissing) { + var bucket = buckets[key]; + if (!bucket && createIfMissing) { + buckets[key] = bucket = ts.createFileMap(); + } + return bucket; + } + function reportStats() { + var bucketInfoArray = Object.keys(buckets).filter(function (name) { return name && name.charAt(0) === "_"; }).map(function (name) { + var entries = buckets[name]; + var sourceFiles = []; + entries.forEachValue(function (key, entry) { + sourceFiles.push({ + name: key, + refCount: entry.languageServiceRefCount, + references: entry.owners.slice(0) + }); + }); + sourceFiles.sort(function (x, y) { return y.refCount - x.refCount; }); + return { + bucket: name, + sourceFiles: sourceFiles }; - TokenRange.prototype.toString = function () { - return this.tokenAccess.toString(); + }); + return JSON.stringify(bucketInfoArray, undefined, 2); + } + function acquireDocument(fileName, compilationSettings, scriptSnapshot, version, scriptKind) { + var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); + var key = getKeyForCompilationSettings(compilationSettings); + return acquireDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind); + } + function acquireDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind) { + return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, /*acquiring*/ true, scriptKind); + } + function updateDocument(fileName, compilationSettings, scriptSnapshot, version, scriptKind) { + var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); + var key = getKeyForCompilationSettings(compilationSettings); + return updateDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind); + } + function updateDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind) { + return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, /*acquiring*/ false, scriptKind); + } + function acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, acquiring, scriptKind) { + var bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ true); + var entry = bucket.get(path); + if (!entry) { + ts.Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?"); + // Have never seen this file with these settings. Create a new source file for it. + var sourceFile = ts.createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false, scriptKind); + entry = { + sourceFile: sourceFile, + languageServiceRefCount: 0, + owners: [] }; - TokenRange.Any = TokenRange.AllTokens(); - TokenRange.AnyIncludingMultilineComments = TokenRange.FromTokens(TokenRange.Any.GetTokens().concat([3 /* MultiLineCommentTrivia */])); - TokenRange.Keywords = TokenRange.FromRange(70 /* FirstKeyword */, 138 /* LastKeyword */); - TokenRange.BinaryOperators = TokenRange.FromRange(25 /* FirstBinaryOperator */, 68 /* LastBinaryOperator */); - TokenRange.BinaryKeywordOperators = TokenRange.FromTokens([90 /* InKeyword */, 91 /* InstanceOfKeyword */, 138 /* OfKeyword */, 116 /* AsKeyword */, 124 /* IsKeyword */]); - TokenRange.UnaryPrefixOperators = TokenRange.FromTokens([41 /* PlusPlusToken */, 42 /* MinusMinusToken */, 50 /* TildeToken */, 49 /* ExclamationToken */]); - TokenRange.UnaryPrefixExpressions = TokenRange.FromTokens([8 /* NumericLiteral */, 69 /* Identifier */, 17 /* OpenParenToken */, 19 /* OpenBracketToken */, 15 /* OpenBraceToken */, 97 /* ThisKeyword */, 92 /* NewKeyword */]); - TokenRange.UnaryPreincrementExpressions = TokenRange.FromTokens([69 /* Identifier */, 17 /* OpenParenToken */, 97 /* ThisKeyword */, 92 /* NewKeyword */]); - TokenRange.UnaryPostincrementExpressions = TokenRange.FromTokens([69 /* Identifier */, 18 /* CloseParenToken */, 20 /* CloseBracketToken */, 92 /* NewKeyword */]); - TokenRange.UnaryPredecrementExpressions = TokenRange.FromTokens([69 /* Identifier */, 17 /* OpenParenToken */, 97 /* ThisKeyword */, 92 /* NewKeyword */]); - TokenRange.UnaryPostdecrementExpressions = TokenRange.FromTokens([69 /* Identifier */, 18 /* CloseParenToken */, 20 /* CloseBracketToken */, 92 /* NewKeyword */]); - TokenRange.Comments = TokenRange.FromTokens([2 /* SingleLineCommentTrivia */, 3 /* MultiLineCommentTrivia */]); - TokenRange.TypeNames = TokenRange.FromTokens([69 /* Identifier */, 130 /* NumberKeyword */, 132 /* StringKeyword */, 120 /* BooleanKeyword */, 133 /* SymbolKeyword */, 103 /* VoidKeyword */, 117 /* AnyKeyword */]); - return TokenRange; - }()); - Shared.TokenRange = TokenRange; - })(Shared = formatting.Shared || (formatting.Shared = {})); - })(formatting = ts.formatting || (ts.formatting = {})); + bucket.set(path, entry); + } + else { + // We have an entry for this file. However, it may be for a different version of + // the script snapshot. If so, update it appropriately. Otherwise, we can just + // return it as is. + if (entry.sourceFile.version !== version) { + entry.sourceFile = ts.updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version, scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot)); + } + } + // If we're acquiring, then this is the first time this LS is asking for this document. + // Increase our ref count so we know there's another LS using the document. If we're + // not acquiring, then that means the LS is 'updating' the file instead, and that means + // it has already acquired the document previously. As such, we do not need to increase + // the ref count. + if (acquiring) { + entry.languageServiceRefCount++; + } + return entry.sourceFile; + } + function releaseDocument(fileName, compilationSettings) { + var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); + var key = getKeyForCompilationSettings(compilationSettings); + return releaseDocumentWithKey(path, key); + } + function releaseDocumentWithKey(path, key) { + var bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ false); + ts.Debug.assert(bucket !== undefined); + var entry = bucket.get(path); + entry.languageServiceRefCount--; + ts.Debug.assert(entry.languageServiceRefCount >= 0); + if (entry.languageServiceRefCount === 0) { + bucket.remove(path); + } + } + return { + acquireDocument: acquireDocument, + acquireDocumentWithKey: acquireDocumentWithKey, + updateDocument: updateDocument, + updateDocumentWithKey: updateDocumentWithKey, + releaseDocument: releaseDocument, + releaseDocumentWithKey: releaseDocumentWithKey, + reportStats: reportStats, + getKeyForCompilationSettings: getKeyForCompilationSettings + }; + } + ts.createDocumentRegistry = createDocumentRegistry; })(ts || (ts = {})); -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// /* @internal */ var ts; (function (ts) { - var formatting; - (function (formatting) { - var RulesProvider = (function () { - function RulesProvider() { - this.globalRules = new formatting.Rules(); + var FindAllReferences; + (function (FindAllReferences) { + function findReferencedSymbols(typeChecker, cancellationToken, sourceFiles, sourceFile, position, findInStrings, findInComments) { + var node = ts.getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true); + if (node === sourceFile) { + return undefined; } - RulesProvider.prototype.getRuleName = function (rule) { - return this.globalRules.getRuleName(rule); - }; - RulesProvider.prototype.getRuleByName = function (name) { - return this.globalRules[name]; - }; - RulesProvider.prototype.getRulesMap = function () { - return this.rulesMap; - }; - RulesProvider.prototype.ensureUpToDate = function (options) { - if (!this.options || !ts.compareDataObjects(this.options, options)) { - var activeRules = this.createActiveRules(options); - var rulesMap = formatting.RulesMap.create(activeRules); - this.activeRules = activeRules; - this.rulesMap = rulesMap; - this.options = ts.clone(options); + switch (node.kind) { + case 8 /* NumericLiteral */: + if (!ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(node)) { + break; + } + // Fallthrough + case 69 /* Identifier */: + case 97 /* ThisKeyword */: + // case SyntaxKind.SuperKeyword: TODO:GH#9268 + case 121 /* ConstructorKeyword */: + case 9 /* StringLiteral */: + return getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFiles, findInStrings, findInComments, /*implementations*/ false); + } + return undefined; + } + FindAllReferences.findReferencedSymbols = findReferencedSymbols; + function getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFiles, findInStrings, findInComments, implementations) { + if (!implementations) { + // Labels + if (ts.isLabelName(node)) { + if (ts.isJumpStatementTarget(node)) { + var labelDefinition = ts.getTargetLabel(node.parent, node.text); + // if we have a label definition, look within its statement for references, if not, then + // the label is undefined and we have no results.. + return labelDefinition ? getLabelReferencesInNode(labelDefinition.parent, labelDefinition) : undefined; + } + else { + // it is a label definition and not a target, search within the parent labeledStatement + return getLabelReferencesInNode(node.parent, node); + } } - }; - RulesProvider.prototype.createActiveRules = function (options) { - var rules = this.globalRules.HighPriorityCommonRules.slice(0); - if (options.InsertSpaceAfterCommaDelimiter) { - rules.push(this.globalRules.SpaceAfterComma); + if (ts.isThis(node)) { + return getReferencesForThisKeyword(node, sourceFiles); } - else { - rules.push(this.globalRules.NoSpaceAfterComma); + if (node.kind === 95 /* SuperKeyword */) { + return getReferencesForSuperKeyword(node); } - if (options.InsertSpaceAfterFunctionKeywordForAnonymousFunctions) { - rules.push(this.globalRules.SpaceAfterAnonymousFunctionKeyword); + } + // `getSymbolAtLocation` normally returns the symbol of the class when given the constructor keyword, + // so we have to specify that we want the constructor symbol. + var symbol = typeChecker.getSymbolAtLocation(node); + if (!implementations && !symbol && node.kind === 9 /* StringLiteral */) { + return getReferencesForStringLiteral(node, sourceFiles); + } + // Could not find a symbol e.g. unknown identifier + if (!symbol) { + // Can't have references to something that we have no symbol for. + return undefined; + } + var declarations = symbol.declarations; + // The symbol was an internal symbol and does not have a declaration e.g. undefined symbol + if (!declarations || !declarations.length) { + return undefined; + } + var result; + // Compute the meaning from the location and the symbol it references + var searchMeaning = getIntersectingMeaningFromDeclarations(ts.getMeaningFromLocation(node), declarations); + // Get the text to search for. + // Note: if this is an external module symbol, the name doesn't include quotes. + var declaredName = ts.stripQuotes(ts.getDeclaredName(typeChecker, symbol, node)); + // Try to get the smallest valid scope that we can limit our search to; + // otherwise we'll need to search globally (i.e. include each file). + var scope = getSymbolScope(symbol); + // Maps from a symbol ID to the ReferencedSymbol entry in 'result'. + var symbolToIndex = []; + if (scope) { + result = []; + getReferencesInNode(scope, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex); + } + else { + var internedName = getInternedName(symbol, node, declarations); + for (var _i = 0, sourceFiles_8 = sourceFiles; _i < sourceFiles_8.length; _i++) { + var sourceFile = sourceFiles_8[_i]; + cancellationToken.throwIfCancellationRequested(); + var nameTable = ts.getNameTable(sourceFile); + if (nameTable[internedName] !== undefined) { + result = result || []; + getReferencesInNode(sourceFile, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex); + } } - else { - rules.push(this.globalRules.NoSpaceAfterAnonymousFunctionKeyword); + } + return result; + function getDefinition(symbol) { + var info = ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, node.getSourceFile(), ts.getContainerNode(node), node); + var name = ts.map(info.displayParts, function (p) { return p.text; }).join(""); + var declarations = symbol.declarations; + if (!declarations || declarations.length === 0) { + return undefined; } - if (options.InsertSpaceAfterKeywordsInControlFlowStatements) { - rules.push(this.globalRules.SpaceAfterKeywordInControl); + return { + containerKind: "", + containerName: "", + name: name, + kind: info.symbolKind, + fileName: declarations[0].getSourceFile().fileName, + textSpan: ts.createTextSpan(declarations[0].getStart(), 0), + displayParts: info.displayParts + }; + } + function getAliasSymbolForPropertyNameSymbol(symbol, location) { + if (symbol.flags & 8388608 /* Alias */) { + // Default import get alias + var defaultImport = ts.getDeclarationOfKind(symbol, 231 /* ImportClause */); + if (defaultImport) { + return typeChecker.getAliasedSymbol(symbol); + } + var importOrExportSpecifier = ts.forEach(symbol.declarations, function (declaration) { return (declaration.kind === 234 /* ImportSpecifier */ || + declaration.kind === 238 /* ExportSpecifier */) ? declaration : undefined; }); + if (importOrExportSpecifier && + // export { a } + (!importOrExportSpecifier.propertyName || + // export {a as class } where a is location + importOrExportSpecifier.propertyName === location)) { + // If Import specifier -> get alias + // else Export specifier -> get local target + return importOrExportSpecifier.kind === 234 /* ImportSpecifier */ ? + typeChecker.getAliasedSymbol(symbol) : + typeChecker.getExportSpecifierLocalTargetSymbol(importOrExportSpecifier); + } } - else { - rules.push(this.globalRules.NoSpaceAfterKeywordInControl); + return undefined; + } + function followAliasIfNecessary(symbol, location) { + return getAliasSymbolForPropertyNameSymbol(symbol, location) || symbol; + } + function getPropertySymbolOfDestructuringAssignment(location) { + return ts.isArrayLiteralOrObjectLiteralDestructuringPattern(location.parent.parent) && + typeChecker.getPropertySymbolOfDestructuringAssignment(location); + } + function isObjectBindingPatternElementWithoutPropertyName(symbol) { + var bindingElement = ts.getDeclarationOfKind(symbol, 169 /* BindingElement */); + return bindingElement && + bindingElement.parent.kind === 167 /* ObjectBindingPattern */ && + !bindingElement.propertyName; + } + function getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol) { + if (isObjectBindingPatternElementWithoutPropertyName(symbol)) { + var bindingElement = ts.getDeclarationOfKind(symbol, 169 /* BindingElement */); + var typeOfPattern = typeChecker.getTypeAtLocation(bindingElement.parent); + return typeOfPattern && typeChecker.getPropertyOfType(typeOfPattern, bindingElement.name.text); } - if (options.InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis) { - rules.push(this.globalRules.SpaceAfterOpenParen); - rules.push(this.globalRules.SpaceBeforeCloseParen); - rules.push(this.globalRules.NoSpaceBetweenParens); + return undefined; + } + function getInternedName(symbol, location, declarations) { + // If this is an export or import specifier it could have been renamed using the 'as' syntax. + // If so we want to search for whatever under the cursor. + if (ts.isImportOrExportSpecifierName(location)) { + return location.getText(); } - else { - rules.push(this.globalRules.NoSpaceAfterOpenParen); - rules.push(this.globalRules.NoSpaceBeforeCloseParen); - rules.push(this.globalRules.NoSpaceBetweenParens); + // Try to get the local symbol if we're dealing with an 'export default' + // since that symbol has the "true" name. + var localExportDefaultSymbol = ts.getLocalSymbolForExportDefault(symbol); + symbol = localExportDefaultSymbol || symbol; + return ts.stripQuotes(symbol.name); + } + /** + * Determines the smallest scope in which a symbol may have named references. + * Note that not every construct has been accounted for. This function can + * probably be improved. + * + * @returns undefined if the scope cannot be determined, implying that + * a reference to a symbol can occur anywhere. + */ + function getSymbolScope(symbol) { + // If this is the symbol of a named function expression or named class expression, + // then named references are limited to its own scope. + var valueDeclaration = symbol.valueDeclaration; + if (valueDeclaration && (valueDeclaration.kind === 179 /* FunctionExpression */ || valueDeclaration.kind === 192 /* ClassExpression */)) { + return valueDeclaration; } - if (options.InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets) { - rules.push(this.globalRules.SpaceAfterOpenBracket); - rules.push(this.globalRules.SpaceBeforeCloseBracket); - rules.push(this.globalRules.NoSpaceBetweenBrackets); + // If this is private property or method, the scope is the containing class + if (symbol.flags & (4 /* Property */ | 8192 /* Method */)) { + var privateDeclaration = ts.forEach(symbol.getDeclarations(), function (d) { return (ts.getModifierFlags(d) & 8 /* Private */) ? d : undefined; }); + if (privateDeclaration) { + return ts.getAncestor(privateDeclaration, 221 /* ClassDeclaration */); + } } - else { - rules.push(this.globalRules.NoSpaceAfterOpenBracket); - rules.push(this.globalRules.NoSpaceBeforeCloseBracket); - rules.push(this.globalRules.NoSpaceBetweenBrackets); + // If the symbol is an import we would like to find it if we are looking for what it imports. + // So consider it visible outside its declaration scope. + if (symbol.flags & 8388608 /* Alias */) { + return undefined; } - if (options.InsertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces) { - rules.push(this.globalRules.SpaceAfterTemplateHeadAndMiddle); - rules.push(this.globalRules.SpaceBeforeTemplateMiddleAndTail); + // If symbol is of object binding pattern element without property name we would want to + // look for property too and that could be anywhere + if (isObjectBindingPatternElementWithoutPropertyName(symbol)) { + return undefined; } - else { - rules.push(this.globalRules.NoSpaceAfterTemplateHeadAndMiddle); - rules.push(this.globalRules.NoSpaceBeforeTemplateMiddleAndTail); + // if this symbol is visible from its parent container, e.g. exported, then bail out + // if symbol correspond to the union property - bail out + if (symbol.parent || (symbol.flags & 268435456 /* SyntheticProperty */)) { + return undefined; } - if (options.InsertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces) { - rules.push(this.globalRules.SpaceAfterOpenBraceInJsxExpression); - rules.push(this.globalRules.SpaceBeforeCloseBraceInJsxExpression); + var scope; + var declarations = symbol.getDeclarations(); + if (declarations) { + for (var _i = 0, declarations_7 = declarations; _i < declarations_7.length; _i++) { + var declaration = declarations_7[_i]; + var container = ts.getContainerNode(declaration); + if (!container) { + return undefined; + } + if (scope && scope !== container) { + // Different declarations have different containers, bail out + return undefined; + } + if (container.kind === 256 /* SourceFile */ && !ts.isExternalModule(container)) { + // This is a global variable and not an external module, any declaration defined + // within this scope is visible outside the file + return undefined; + } + // The search scope is the container node + scope = container; + } } - else { - rules.push(this.globalRules.NoSpaceAfterOpenBraceInJsxExpression); - rules.push(this.globalRules.NoSpaceBeforeCloseBraceInJsxExpression); + return scope; + } + function getPossibleSymbolReferencePositions(sourceFile, symbolName, start, end) { + var positions = []; + /// TODO: Cache symbol existence for files to save text search + // Also, need to make this work for unicode escapes. + // Be resilient in the face of a symbol with no name or zero length name + if (!symbolName || !symbolName.length) { + return positions; } - if (options.InsertSpaceAfterSemicolonInForStatements) { - rules.push(this.globalRules.SpaceAfterSemicolonInFor); + var text = sourceFile.text; + var sourceLength = text.length; + var symbolNameLength = symbolName.length; + var position = text.indexOf(symbolName, start); + while (position >= 0) { + cancellationToken.throwIfCancellationRequested(); + // If we are past the end, stop looking + if (position > end) + break; + // We found a match. Make sure it's not part of a larger word (i.e. the char + // before and after it have to be a non-identifier char). + var endPosition = position + symbolNameLength; + if ((position === 0 || !ts.isIdentifierPart(text.charCodeAt(position - 1), 2 /* Latest */)) && + (endPosition === sourceLength || !ts.isIdentifierPart(text.charCodeAt(endPosition), 2 /* Latest */))) { + // Found a real match. Keep searching. + positions.push(position); + } + position = text.indexOf(symbolName, position + symbolNameLength + 1); } - else { - rules.push(this.globalRules.NoSpaceAfterSemicolonInFor); + return positions; + } + function getLabelReferencesInNode(container, targetLabel) { + var references = []; + var sourceFile = container.getSourceFile(); + var labelName = targetLabel.text; + var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container.getStart(), container.getEnd()); + ts.forEach(possiblePositions, function (position) { + cancellationToken.throwIfCancellationRequested(); + var node = ts.getTouchingWord(sourceFile, position); + if (!node || node.getWidth() !== labelName.length) { + return; + } + // Only pick labels that are either the target label, or have a target that is the target label + if (node === targetLabel || + (ts.isJumpStatementTarget(node) && ts.getTargetLabel(node, labelName) === targetLabel)) { + references.push(getReferenceEntryFromNode(node)); + } + }); + var definition = { + containerKind: "", + containerName: "", + fileName: targetLabel.getSourceFile().fileName, + kind: ts.ScriptElementKind.label, + name: labelName, + textSpan: ts.createTextSpanFromBounds(targetLabel.getStart(), targetLabel.getEnd()), + displayParts: [ts.displayPart(labelName, ts.SymbolDisplayPartKind.text)] + }; + return [{ definition: definition, references: references }]; + } + function isValidReferencePosition(node, searchSymbolName) { + if (node) { + // Compare the length so we filter out strict superstrings of the symbol we are looking for + switch (node.kind) { + case 69 /* Identifier */: + return node.getWidth() === searchSymbolName.length; + case 9 /* StringLiteral */: + if (ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || + isNameOfExternalModuleImportOrDeclaration(node)) { + // For string literals we have two additional chars for the quotes + return node.getWidth() === searchSymbolName.length + 2; + } + break; + case 8 /* NumericLiteral */: + if (ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(node)) { + return node.getWidth() === searchSymbolName.length; + } + break; + } } - if (options.InsertSpaceBeforeAndAfterBinaryOperators) { - rules.push(this.globalRules.SpaceBeforeBinaryOperator); - rules.push(this.globalRules.SpaceAfterBinaryOperator); + return false; + } + /** Search within node "container" for references for a search value, where the search value is defined as a + * tuple of(searchSymbol, searchText, searchLocation, and searchMeaning). + * searchLocation: a node where the search value + */ + function getReferencesInNode(container, searchSymbol, searchText, searchLocation, searchMeaning, findInStrings, findInComments, result, symbolToIndex) { + var sourceFile = container.getSourceFile(); + var start = findInComments ? container.getFullStart() : container.getStart(); + var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, start, container.getEnd()); + var parents = getParentSymbolsOfPropertyAccess(); + var inheritsFromCache = ts.createMap(); + if (possiblePositions.length) { + // Build the set of symbols to search for, initially it has only the current symbol + var searchSymbols_1 = populateSearchSymbolSet(searchSymbol, searchLocation); + ts.forEach(possiblePositions, function (position) { + cancellationToken.throwIfCancellationRequested(); + var referenceLocation = ts.getTouchingPropertyName(sourceFile, position); + if (!isValidReferencePosition(referenceLocation, searchText)) { + // This wasn't the start of a token. Check to see if it might be a + // match in a comment or string if that's what the caller is asking + // for. + if (!implementations && ((findInStrings && ts.isInString(sourceFile, position)) || + (findInComments && ts.isInNonReferenceComment(sourceFile, position)))) { + // In the case where we're looking inside comments/strings, we don't have + // an actual definition. So just use 'undefined' here. Features like + // 'Rename' won't care (as they ignore the definitions), and features like + // 'FindReferences' will just filter out these results. + result.push({ + definition: undefined, + references: [{ + fileName: sourceFile.fileName, + textSpan: ts.createTextSpan(position, searchText.length), + isWriteAccess: false, + isDefinition: false + }] + }); + } + return; + } + if (!(ts.getMeaningFromLocation(referenceLocation) & searchMeaning)) { + return; + } + var referenceSymbol = typeChecker.getSymbolAtLocation(referenceLocation); + if (referenceSymbol) { + var referenceSymbolDeclaration = referenceSymbol.valueDeclaration; + var shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration); + var relatedSymbol = getRelatedSymbol(searchSymbols_1, referenceSymbol, referenceLocation, + /*searchLocationIsConstructor*/ searchLocation.kind === 121 /* ConstructorKeyword */, parents, inheritsFromCache); + if (relatedSymbol) { + addReferenceToRelatedSymbol(referenceLocation, relatedSymbol); + } + else if (!(referenceSymbol.flags & 67108864 /* Transient */) && searchSymbols_1.indexOf(shorthandValueSymbol) >= 0) { + addReferenceToRelatedSymbol(referenceSymbolDeclaration.name, shorthandValueSymbol); + } + else if (searchLocation.kind === 121 /* ConstructorKeyword */) { + findAdditionalConstructorReferences(referenceSymbol, referenceLocation); + } + } + }); } - else { - rules.push(this.globalRules.NoSpaceBeforeBinaryOperator); - rules.push(this.globalRules.NoSpaceAfterBinaryOperator); + return; + /* If we are just looking for implementations and this is a property access expression, we need to get the + * symbol of the local type of the symbol the property is being accessed on. This is because our search + * symbol may have a different parent symbol if the local type's symbol does not declare the property + * being accessed (i.e. it is declared in some parent class or interface) + */ + function getParentSymbolsOfPropertyAccess() { + if (implementations) { + var propertyAccessExpression = getPropertyAccessExpressionFromRightHandSide(searchLocation); + if (propertyAccessExpression) { + var localParentType = typeChecker.getTypeAtLocation(propertyAccessExpression.expression); + if (localParentType) { + if (localParentType.symbol && localParentType.symbol.flags & (32 /* Class */ | 64 /* Interface */) && localParentType.symbol !== searchSymbol.parent) { + return [localParentType.symbol]; + } + else if (localParentType.flags & 1572864 /* UnionOrIntersection */) { + return getSymbolsForClassAndInterfaceComponents(localParentType); + } + } + } + } } - if (options.PlaceOpenBraceOnNewLineForControlBlocks) { - rules.push(this.globalRules.NewLineBeforeOpenBraceInControl); + function getPropertyAccessExpressionFromRightHandSide(node) { + return ts.isRightSideOfPropertyAccess(node) && node.parent; } - if (options.PlaceOpenBraceOnNewLineForFunctions) { - rules.push(this.globalRules.NewLineBeforeOpenBraceInFunction); - rules.push(this.globalRules.NewLineBeforeOpenBraceInTypeScriptDeclWithBlock); + /** Adds references when a constructor is used with `new this()` in its own class and `super()` calls in subclasses. */ + function findAdditionalConstructorReferences(referenceSymbol, referenceLocation) { + ts.Debug.assert(ts.isClassLike(searchSymbol.valueDeclaration)); + var referenceClass = referenceLocation.parent; + if (referenceSymbol === searchSymbol && ts.isClassLike(referenceClass)) { + ts.Debug.assert(referenceClass.name === referenceLocation); + // This is the class declaration containing the constructor. + addReferences(findOwnConstructorCalls(searchSymbol)); + } + else { + // If this class appears in `extends C`, then the extending class' "super" calls are references. + var classExtending = tryGetClassByExtendingIdentifier(referenceLocation); + if (classExtending && ts.isClassLike(classExtending) && followAliasIfNecessary(referenceSymbol, referenceLocation) === searchSymbol) { + addReferences(superConstructorAccesses(classExtending)); + } + } + } + function addReferences(references) { + if (references.length) { + var referencedSymbol = getReferencedSymbol(searchSymbol); + ts.addRange(referencedSymbol.references, ts.map(references, getReferenceEntryFromNode)); + } + } + /** `classSymbol` is the class where the constructor was defined. + * Reference the constructor and all calls to `new this()`. + */ + function findOwnConstructorCalls(classSymbol) { + var result = []; + for (var _i = 0, _a = classSymbol.members["__constructor"].declarations; _i < _a.length; _i++) { + var decl = _a[_i]; + ts.Debug.assert(decl.kind === 148 /* Constructor */); + var ctrKeyword = decl.getChildAt(0); + ts.Debug.assert(ctrKeyword.kind === 121 /* ConstructorKeyword */); + result.push(ctrKeyword); + } + ts.forEachProperty(classSymbol.exports, function (member) { + var decl = member.valueDeclaration; + if (decl && decl.kind === 147 /* MethodDeclaration */) { + var body = decl.body; + if (body) { + forEachDescendantOfKind(body, 97 /* ThisKeyword */, function (thisKeyword) { + if (ts.isNewExpressionTarget(thisKeyword)) { + result.push(thisKeyword); + } + }); + } + } + }); + return result; + } + /** Find references to `super` in the constructor of an extending class. */ + function superConstructorAccesses(cls) { + var symbol = cls.symbol; + var ctr = symbol.members["__constructor"]; + if (!ctr) { + return []; + } + var result = []; + for (var _i = 0, _a = ctr.declarations; _i < _a.length; _i++) { + var decl = _a[_i]; + ts.Debug.assert(decl.kind === 148 /* Constructor */); + var body = decl.body; + if (body) { + forEachDescendantOfKind(body, 95 /* SuperKeyword */, function (node) { + if (ts.isCallExpressionTarget(node)) { + result.push(node); + } + }); + } + } + ; + return result; + } + function getReferencedSymbol(symbol) { + var symbolId = ts.getSymbolId(symbol); + var index = symbolToIndex[symbolId]; + if (index === undefined) { + index = result.length; + symbolToIndex[symbolId] = index; + result.push({ + definition: getDefinition(symbol), + references: [] + }); + } + return result[index]; + } + function addReferenceToRelatedSymbol(node, relatedSymbol) { + var references = getReferencedSymbol(relatedSymbol).references; + if (implementations) { + getImplementationReferenceEntryForNode(node, references); + } + else { + references.push(getReferenceEntryFromNode(node)); + } } - rules = rules.concat(this.globalRules.LowPriorityCommonRules); - return rules; - }; - return RulesProvider; - }()); - formatting.RulesProvider = RulesProvider; - })(formatting = ts.formatting || (ts.formatting = {})); -})(ts || (ts = {})); -/// -/// -/// -/// -/* @internal */ -var ts; -(function (ts) { - var formatting; - (function (formatting) { - var Constants; - (function (Constants) { - Constants[Constants["Unknown"] = -1] = "Unknown"; - })(Constants || (Constants = {})); - function formatOnEnter(position, sourceFile, rulesProvider, options) { - var line = sourceFile.getLineAndCharacterOfPosition(position).line; - if (line === 0) { - return []; - } - // After the enter key, the cursor is now at a new line. The new line may or may not contain non-whitespace characters. - // If the new line has only whitespaces, we won't want to format this line, because that would remove the indentation as - // trailing whitespaces. So the end of the formatting span should be the later one between: - // 1. the end of the previous line - // 2. the last non-whitespace character in the current line - var endOfFormatSpan = ts.getEndLinePosition(line, sourceFile); - while (ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(endOfFormatSpan))) { - endOfFormatSpan--; - } - // if the character at the end of the span is a line break, we shouldn't include it, because it indicates we don't want to - // touch the current line at all. Also, on some OSes the line break consists of two characters (\r\n), we should test if the - // previous character before the end of format span is line break character as well. - if (ts.isLineBreak(sourceFile.text.charCodeAt(endOfFormatSpan))) { - endOfFormatSpan--; - } - var span = { - // get start position for the previous line - pos: ts.getStartPositionOfLine(line - 1, sourceFile), - // end value is exclusive so add 1 to the result - end: endOfFormatSpan + 1 - }; - return formatSpan(span, sourceFile, options, rulesProvider, 2 /* FormatOnEnter */); - } - formatting.formatOnEnter = formatOnEnter; - function formatOnSemicolon(position, sourceFile, rulesProvider, options) { - return formatOutermostParent(position, 23 /* SemicolonToken */, sourceFile, options, rulesProvider, 3 /* FormatOnSemicolon */); - } - formatting.formatOnSemicolon = formatOnSemicolon; - function formatOnClosingCurly(position, sourceFile, rulesProvider, options) { - return formatOutermostParent(position, 16 /* CloseBraceToken */, sourceFile, options, rulesProvider, 4 /* FormatOnClosingCurlyBrace */); - } - formatting.formatOnClosingCurly = formatOnClosingCurly; - function formatDocument(sourceFile, rulesProvider, options) { - var span = { - pos: 0, - end: sourceFile.text.length - }; - return formatSpan(span, sourceFile, options, rulesProvider, 0 /* FormatDocument */); - } - formatting.formatDocument = formatDocument; - function formatSelection(start, end, sourceFile, rulesProvider, options) { - // format from the beginning of the line - var span = { - pos: ts.getLineStartPositionForPosition(start, sourceFile), - end: end - }; - return formatSpan(span, sourceFile, options, rulesProvider, 1 /* FormatSelection */); - } - formatting.formatSelection = formatSelection; - function formatOutermostParent(position, expectedLastToken, sourceFile, options, rulesProvider, requestKind) { - var parent = findOutermostParent(position, expectedLastToken, sourceFile); - if (!parent) { - return []; - } - var span = { - pos: ts.getLineStartPositionForPosition(parent.getStart(sourceFile), sourceFile), - end: parent.end - }; - return formatSpan(span, sourceFile, options, rulesProvider, requestKind); - } - function findOutermostParent(position, expectedTokenKind, sourceFile) { - var precedingToken = ts.findPrecedingToken(position, sourceFile); - // when it is claimed that trigger character was typed at given position - // we verify that there is a token with a matching kind whose end is equal to position (because the character was just typed). - // If this condition is not hold - then trigger character was typed in some other context, - // i.e.in comment and thus should not trigger autoformatting - if (!precedingToken || - precedingToken.kind !== expectedTokenKind || - position !== precedingToken.getEnd()) { - return undefined; } - // walk up and search for the parent node that ends at the same position with precedingToken. - // for cases like this - // - // let x = 1; - // while (true) { - // } - // after typing close curly in while statement we want to reformat just the while statement. - // However if we just walk upwards searching for the parent that has the same end value - - // we'll end up with the whole source file. isListElement allows to stop on the list element level - var current = precedingToken; - while (current && - current.parent && - current.parent.end === precedingToken.end && - !isListElement(current.parent, current)) { - current = current.parent; + function getImplementationReferenceEntryForNode(refNode, result) { + // Check if we found a function/propertyAssignment/method with an implementation or initializer + if (ts.isDeclarationName(refNode) && isImplementation(refNode.parent)) { + result.push(getReferenceEntryFromNode(refNode.parent)); + } + else if (refNode.kind === 69 /* Identifier */) { + if (refNode.parent.kind === 254 /* ShorthandPropertyAssignment */) { + // Go ahead and dereference the shorthand assignment by going to its definition + getReferenceEntriesForShorthandPropertyAssignment(refNode, typeChecker, result); + } + // Check if the node is within an extends or implements clause + var containingClass = getContainingClassIfInHeritageClause(refNode); + if (containingClass) { + result.push(getReferenceEntryFromNode(containingClass)); + return; + } + // If we got a type reference, try and see if the reference applies to any expressions that can implement an interface + var containingTypeReference = getContainingTypeReference(refNode); + if (containingTypeReference) { + var parent_21 = containingTypeReference.parent; + if (ts.isVariableLike(parent_21) && parent_21.type === containingTypeReference && parent_21.initializer && isImplementationExpression(parent_21.initializer)) { + maybeAdd(getReferenceEntryFromNode(parent_21.initializer)); + } + else if (ts.isFunctionLike(parent_21) && parent_21.type === containingTypeReference && parent_21.body) { + if (parent_21.body.kind === 199 /* Block */) { + ts.forEachReturnStatement(parent_21.body, function (returnStatement) { + if (returnStatement.expression && isImplementationExpression(returnStatement.expression)) { + maybeAdd(getReferenceEntryFromNode(returnStatement.expression)); + } + }); + } + else if (isImplementationExpression(parent_21.body)) { + maybeAdd(getReferenceEntryFromNode(parent_21.body)); + } + } + else if (ts.isAssertionExpression(parent_21) && isImplementationExpression(parent_21.expression)) { + maybeAdd(getReferenceEntryFromNode(parent_21.expression)); + } + } + } + // Type nodes can contain multiple references to the same type. For example: + // let x: Foo & (Foo & Bar) = ... + // Because we are returning the implementation locations and not the identifier locations, + // duplicate entries would be returned here as each of the type references is part of + // the same implementation. For that reason, check before we add a new entry + function maybeAdd(a) { + if (!ts.forEach(result, function (b) { return a.fileName === b.fileName && a.textSpan.start === b.textSpan.start && a.textSpan.length === b.textSpan.length; })) { + result.push(a); + } + } } - return current; - } - // Returns true if node is a element in some list in parent - // i.e. parent is class declaration with the list of members and node is one of members. - function isListElement(parent, node) { - switch (parent.kind) { - case 221 /* ClassDeclaration */: - case 222 /* InterfaceDeclaration */: - return ts.rangeContainsRange(parent.members, node); - case 225 /* ModuleDeclaration */: - var body = parent.body; - return body && body.kind === 199 /* Block */ && ts.rangeContainsRange(body.statements, node); - case 256 /* SourceFile */: - case 199 /* Block */: - case 226 /* ModuleBlock */: - return ts.rangeContainsRange(parent.statements, node); - case 252 /* CatchClause */: - return ts.rangeContainsRange(parent.block.statements, node); + function getSymbolsForClassAndInterfaceComponents(type, result) { + if (result === void 0) { result = []; } + for (var _i = 0, _a = type.types; _i < _a.length; _i++) { + var componentType = _a[_i]; + if (componentType.symbol && componentType.symbol.getFlags() & (32 /* Class */ | 64 /* Interface */)) { + result.push(componentType.symbol); + } + if (componentType.getFlags() & 1572864 /* UnionOrIntersection */) { + getSymbolsForClassAndInterfaceComponents(componentType, result); + } + } + return result; } - return false; - } - /** find node that fully contains given text range */ - function findEnclosingNode(range, sourceFile) { - return find(sourceFile); - function find(n) { - var candidate = ts.forEachChild(n, function (c) { return ts.startEndContainsRange(c.getStart(sourceFile), c.end, range) && c; }); - if (candidate) { - var result = find(candidate); - if (result) { - return result; + function getContainingTypeReference(node) { + var topLevelTypeReference = undefined; + while (node) { + if (ts.isTypeNode(node)) { + topLevelTypeReference = node; } + node = node.parent; } - return n; + return topLevelTypeReference; } - } - /** formatting is not applied to ranges that contain parse errors. - * This function will return a predicate that for a given text range will tell - * if there are any parse errors that overlap with the range. - */ - function prepareRangeContainsErrorFunction(errors, originalRange) { - if (!errors.length) { - return rangeHasNoErrors; + function getContainingClassIfInHeritageClause(node) { + if (node && node.parent) { + if (node.kind === 194 /* ExpressionWithTypeArguments */ + && node.parent.kind === 251 /* HeritageClause */ + && ts.isClassLike(node.parent.parent)) { + return node.parent.parent; + } + else if (node.kind === 69 /* Identifier */ || node.kind === 172 /* PropertyAccessExpression */) { + return getContainingClassIfInHeritageClause(node.parent); + } + } + return undefined; } - // pick only errors that fall in range - var sorted = errors - .filter(function (d) { return ts.rangeOverlapsWithStartEnd(originalRange, d.start, d.start + d.length); }) - .sort(function (e1, e2) { return e1.start - e2.start; }); - if (!sorted.length) { - return rangeHasNoErrors; + /** + * Returns true if this is an expression that can be considered an implementation + */ + function isImplementationExpression(node) { + // Unwrap parentheses + if (node.kind === 178 /* ParenthesizedExpression */) { + return isImplementationExpression(node.expression); + } + return node.kind === 180 /* ArrowFunction */ || + node.kind === 179 /* FunctionExpression */ || + node.kind === 171 /* ObjectLiteralExpression */ || + node.kind === 192 /* ClassExpression */ || + node.kind === 170 /* ArrayLiteralExpression */; } - var index = 0; - return function (r) { - // in current implementation sequence of arguments [r1, r2...] is monotonically increasing. - // 'index' tracks the index of the most recent error that was checked. - while (true) { - if (index >= sorted.length) { - // all errors in the range were already checked -> no error in specified range - return false; + /** + * Determines if the parent symbol occurs somewhere in the child's ancestry. If the parent symbol + * is an interface, determines if some ancestor of the child symbol extends or inherits from it. + * Also takes in a cache of previous results which makes this slightly more efficient and is + * necessary to avoid potential loops like so: + * class A extends B { } + * class B extends A { } + * + * We traverse the AST rather than using the type checker because users are typically only interested + * in explicit implementations of an interface/class when calling "Go to Implementation". Sibling + * implementations of types that share a common ancestor with the type whose implementation we are + * searching for need to be filtered out of the results. The type checker doesn't let us make the + * distinction between structurally compatible implementations and explicit implementations, so we + * must use the AST. + * + * @param child A class or interface Symbol + * @param parent Another class or interface Symbol + * @param cachedResults A map of symbol id pairs (i.e. "child,parent") to booleans indicating previous results + */ + function explicitlyInheritsFrom(child, parent, cachedResults) { + var parentIsInterface = parent.getFlags() & 64 /* Interface */; + return searchHierarchy(child); + function searchHierarchy(symbol) { + if (symbol === parent) { + return true; } - var error = sorted[index]; - if (r.end <= error.start) { - // specified range ends before the error refered by 'index' - no error in range - return false; + var key = ts.getSymbolId(symbol) + "," + ts.getSymbolId(parent); + if (key in cachedResults) { + return cachedResults[key]; } - if (ts.startEndOverlapsWithStartEnd(r.pos, r.end, error.start, error.start + error.length)) { - // specified range overlaps with error range - return true; + // Set the key so that we don't infinitely recurse + cachedResults[key] = false; + var inherits = ts.forEach(symbol.getDeclarations(), function (declaration) { + if (ts.isClassLike(declaration)) { + if (parentIsInterface) { + var interfaceReferences = ts.getClassImplementsHeritageClauseElements(declaration); + if (interfaceReferences) { + for (var _i = 0, interfaceReferences_1 = interfaceReferences; _i < interfaceReferences_1.length; _i++) { + var typeReference = interfaceReferences_1[_i]; + if (searchTypeReference(typeReference)) { + return true; + } + } + } + } + return searchTypeReference(ts.getClassExtendsHeritageClauseElement(declaration)); + } + else if (declaration.kind === 222 /* InterfaceDeclaration */) { + if (parentIsInterface) { + return ts.forEach(ts.getInterfaceBaseTypeNodes(declaration), searchTypeReference); + } + } + return false; + }); + cachedResults[key] = inherits; + return inherits; + } + function searchTypeReference(typeReference) { + if (typeReference) { + var type = typeChecker.getTypeAtLocation(typeReference); + if (type && type.symbol) { + return searchHierarchy(type.symbol); + } } - index++; + return false; } - }; - function rangeHasNoErrors(r) { - return false; - } - } - /** - * Start of the original range might fall inside the comment - scanner will not yield appropriate results - * This function will look for token that is located before the start of target range - * and return its end as start position for the scanner. - */ - function getScanStartPosition(enclosingNode, originalRange, sourceFile) { - var start = enclosingNode.getStart(sourceFile); - if (start === originalRange.pos && enclosingNode.end === originalRange.end) { - return start; - } - var precedingToken = ts.findPrecedingToken(originalRange.pos, sourceFile); - if (!precedingToken) { - // no preceding token found - start from the beginning of enclosing node - return enclosingNode.pos; - } - // preceding token ends after the start of original range (i.e when originalRange.pos falls in the middle of literal) - // start from the beginning of enclosingNode to handle the entire 'originalRange' - if (precedingToken.end >= originalRange.pos) { - return enclosingNode.pos; } - return precedingToken.end; - } - /* - * For cases like - * if (a || - * b ||$ - * c) {...} - * If we hit Enter at $ we want line ' b ||' to be indented. - * Formatting will be applied to the last two lines. - * Node that fully encloses these lines is binary expression 'a ||...'. - * Initial indentation for this node will be 0. - * Binary expressions don't introduce new indentation scopes, however it is possible - * that some parent node on the same line does - like if statement in this case. - * Note that we are considering parents only from the same line with initial node - - * if parent is on the different line - its delta was already contributed - * to the initial indentation. - */ - function getOwnOrInheritedDelta(n, options, sourceFile) { - var previousLine = -1 /* Unknown */; - var child; - while (n) { - var line = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)).line; - if (previousLine !== -1 /* Unknown */ && line !== previousLine) { - break; + function getReferencesForSuperKeyword(superKeyword) { + var searchSpaceNode = ts.getSuperContainer(superKeyword, /*stopOnFunctions*/ false); + if (!searchSpaceNode) { + return undefined; } - if (formatting.SmartIndenter.shouldIndentChildNode(n, child)) { - return options.IndentSize; + // Whether 'super' occurs in a static context within a class. + var staticFlag = 32 /* Static */; + switch (searchSpaceNode.kind) { + case 145 /* PropertyDeclaration */: + case 144 /* PropertySignature */: + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + case 148 /* Constructor */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + staticFlag &= ts.getModifierFlags(searchSpaceNode); + searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class + break; + default: + return undefined; } - previousLine = line; - child = n; - n = n.parent; + var references = []; + var sourceFile = searchSpaceNode.getSourceFile(); + var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); + ts.forEach(possiblePositions, function (position) { + cancellationToken.throwIfCancellationRequested(); + var node = ts.getTouchingWord(sourceFile, position); + if (!node || node.kind !== 95 /* SuperKeyword */) { + return; + } + var container = ts.getSuperContainer(node, /*stopOnFunctions*/ false); + // If we have a 'super' container, we must have an enclosing class. + // Now make sure the owning class is the same as the search-space + // and has the same static qualifier as the original 'super's owner. + if (container && (32 /* Static */ & ts.getModifierFlags(container)) === staticFlag && container.parent.symbol === searchSpaceNode.symbol) { + references.push(getReferenceEntryFromNode(node)); + } + }); + var definition = getDefinition(searchSpaceNode.symbol); + return [{ definition: definition, references: references }]; } - return 0; - } - function formatSpan(originalRange, sourceFile, options, rulesProvider, requestKind) { - var rangeContainsError = prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange); - // formatting context is used by rules provider - var formattingContext = new formatting.FormattingContext(sourceFile, requestKind); - // find the smallest node that fully wraps the range and compute the initial indentation for the node - var enclosingNode = findEnclosingNode(originalRange, sourceFile); - var formattingScanner = formatting.getFormattingScanner(sourceFile, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end); - var initialIndentation = formatting.SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, options); - var previousRangeHasError; - var previousRange; - var previousParent; - var previousRangeStartLine; - var lastIndentedLine; - var indentationOnLastIndentedLine; - var edits = []; - formattingScanner.advance(); - if (formattingScanner.isOnToken()) { - var startLine = sourceFile.getLineAndCharacterOfPosition(enclosingNode.getStart(sourceFile)).line; - var undecoratedStartLine = startLine; - if (enclosingNode.decorators) { - undecoratedStartLine = sourceFile.getLineAndCharacterOfPosition(ts.getNonDecoratorTokenPosOfNode(enclosingNode, sourceFile)).line; + function getReferencesForThisKeyword(thisOrSuperKeyword, sourceFiles) { + var searchSpaceNode = ts.getThisContainer(thisOrSuperKeyword, /* includeArrowFunctions */ false); + // Whether 'this' occurs in a static context within a class. + var staticFlag = 32 /* Static */; + switch (searchSpaceNode.kind) { + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + if (ts.isObjectLiteralMethod(searchSpaceNode)) { + break; + } + // fall through + case 145 /* PropertyDeclaration */: + case 144 /* PropertySignature */: + case 148 /* Constructor */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + staticFlag &= ts.getModifierFlags(searchSpaceNode); + searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class + break; + case 256 /* SourceFile */: + if (ts.isExternalModule(searchSpaceNode)) { + return undefined; + } + // Fall through + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + break; + // Computed properties in classes are not handled here because references to this are illegal, + // so there is no point finding references to them. + default: + return undefined; + } + var references = []; + var possiblePositions; + if (searchSpaceNode.kind === 256 /* SourceFile */) { + ts.forEach(sourceFiles, function (sourceFile) { + possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", sourceFile.getStart(), sourceFile.getEnd()); + getThisReferencesInFile(sourceFile, sourceFile, possiblePositions, references); + }); + } + else { + var sourceFile = searchSpaceNode.getSourceFile(); + possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); + getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, references); + } + var thisOrSuperSymbol = typeChecker.getSymbolAtLocation(thisOrSuperKeyword); + var displayParts = thisOrSuperSymbol && ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, thisOrSuperSymbol, thisOrSuperKeyword.getSourceFile(), ts.getContainerNode(thisOrSuperKeyword), thisOrSuperKeyword).displayParts; + return [{ + definition: { + containerKind: "", + containerName: "", + fileName: node.getSourceFile().fileName, + kind: ts.ScriptElementKind.variableElement, + name: "this", + textSpan: ts.createTextSpanFromBounds(node.getStart(), node.getEnd()), + displayParts: displayParts + }, + references: references + }]; + function getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, result) { + ts.forEach(possiblePositions, function (position) { + cancellationToken.throwIfCancellationRequested(); + var node = ts.getTouchingWord(sourceFile, position); + if (!node || !ts.isThis(node)) { + return; + } + var container = ts.getThisContainer(node, /* includeArrowFunctions */ false); + switch (searchSpaceNode.kind) { + case 179 /* FunctionExpression */: + case 220 /* FunctionDeclaration */: + if (searchSpaceNode.symbol === container.symbol) { + result.push(getReferenceEntryFromNode(node)); + } + break; + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + if (ts.isObjectLiteralMethod(searchSpaceNode) && searchSpaceNode.symbol === container.symbol) { + result.push(getReferenceEntryFromNode(node)); + } + break; + case 192 /* ClassExpression */: + case 221 /* ClassDeclaration */: + // Make sure the container belongs to the same class + // and has the appropriate static modifier from the original container. + if (container.parent && searchSpaceNode.symbol === container.parent.symbol && (ts.getModifierFlags(container) & 32 /* Static */) === staticFlag) { + result.push(getReferenceEntryFromNode(node)); + } + break; + case 256 /* SourceFile */: + if (container.kind === 256 /* SourceFile */ && !ts.isExternalModule(container)) { + result.push(getReferenceEntryFromNode(node)); + } + break; + } + }); } - var delta = getOwnOrInheritedDelta(enclosingNode, options, sourceFile); - processNode(enclosingNode, enclosingNode, startLine, undecoratedStartLine, initialIndentation, delta); } - if (!formattingScanner.isOnToken()) { - var leadingTrivia = formattingScanner.getCurrentLeadingTrivia(); - if (leadingTrivia) { - processTrivia(leadingTrivia, enclosingNode, enclosingNode, undefined); - trimTrailingWhitespacesForRemainingRange(); + function getReferencesForStringLiteral(node, sourceFiles) { + var type = ts.getStringLiteralTypeForNode(node, typeChecker); + if (!type) { + // nothing to do here. moving on + return undefined; + } + var references = []; + for (var _i = 0, sourceFiles_9 = sourceFiles; _i < sourceFiles_9.length; _i++) { + var sourceFile = sourceFiles_9[_i]; + var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, type.text, sourceFile.getStart(), sourceFile.getEnd()); + getReferencesForStringLiteralInFile(sourceFile, type, possiblePositions, references); + } + return [{ + definition: { + containerKind: "", + containerName: "", + fileName: node.getSourceFile().fileName, + kind: ts.ScriptElementKind.variableElement, + name: type.text, + textSpan: ts.createTextSpanFromBounds(node.getStart(), node.getEnd()), + displayParts: [ts.displayPart(ts.getTextOfNode(node), ts.SymbolDisplayPartKind.stringLiteral)] + }, + references: references + }]; + function getReferencesForStringLiteralInFile(sourceFile, searchType, possiblePositions, references) { + for (var _i = 0, possiblePositions_1 = possiblePositions; _i < possiblePositions_1.length; _i++) { + var position = possiblePositions_1[_i]; + cancellationToken.throwIfCancellationRequested(); + var node_2 = ts.getTouchingWord(sourceFile, position); + if (!node_2 || node_2.kind !== 9 /* StringLiteral */) { + return; + } + var type_1 = ts.getStringLiteralTypeForNode(node_2, typeChecker); + if (type_1 === searchType) { + references.push(getReferenceEntryFromNode(node_2)); + } + } } } - formattingScanner.close(); - return edits; - // local functions - /** Tries to compute the indentation for a list element. - * If list element is not in range then - * function will pick its actual indentation - * so it can be pushed downstream as inherited indentation. - * If list element is in the range - its indentation will be equal - * to inherited indentation from its predecessors. - */ - function tryComputeIndentationForListItem(startPos, endPos, parentStartLine, range, inheritedIndentation) { - if (ts.rangeOverlapsWithStartEnd(range, startPos, endPos) || - ts.rangeContainsStartEnd(range, startPos, endPos) /* Not to miss zero-range nodes e.g. JsxText */) { - if (inheritedIndentation !== -1 /* Unknown */) { - return inheritedIndentation; + function populateSearchSymbolSet(symbol, location) { + // The search set contains at least the current symbol + var result = [symbol]; + // If the location is name of property symbol from object literal destructuring pattern + // Search the property symbol + // for ( { property: p2 } of elems) { } + var containingObjectLiteralElement = getContainingObjectLiteralElement(location); + if (containingObjectLiteralElement && containingObjectLiteralElement.kind !== 254 /* ShorthandPropertyAssignment */) { + var propertySymbol = getPropertySymbolOfDestructuringAssignment(location); + if (propertySymbol) { + result.push(propertySymbol); } } - else { - var startLine = sourceFile.getLineAndCharacterOfPosition(startPos).line; - var startLinePosition = ts.getLineStartPositionForPosition(startPos, sourceFile); - var column = formatting.SmartIndenter.findFirstNonWhitespaceColumn(startLinePosition, startPos, sourceFile, options); - if (startLine !== parentStartLine || startPos === column) { - // Use the base indent size if it is greater than - // the indentation of the inherited predecessor. - var baseIndentSize = formatting.SmartIndenter.getBaseIndentation(options); - return baseIndentSize > column ? baseIndentSize : column; + // If the symbol is an alias, add what it aliases to the list + // import {a} from "mod"; + // export {a} + // If the symbol is an alias to default declaration, add what it aliases to the list + // declare "mod" { export default class B { } } + // import B from "mod"; + //// For export specifiers, the exported name can be referring to a local symbol, e.g.: + //// import {a} from "mod"; + //// export {a as somethingElse} + //// We want the *local* declaration of 'a' as declared in the import, + //// *not* as declared within "mod" (or farther) + var aliasSymbol = getAliasSymbolForPropertyNameSymbol(symbol, location); + if (aliasSymbol) { + result = result.concat(populateSearchSymbolSet(aliasSymbol, location)); + } + // If the location is in a context sensitive location (i.e. in an object literal) try + // to get a contextual type for it, and add the property symbol from the contextual + // type to the search set + if (containingObjectLiteralElement) { + ts.forEach(getPropertySymbolsFromContextualType(containingObjectLiteralElement), function (contextualSymbol) { + ts.addRange(result, typeChecker.getRootSymbols(contextualSymbol)); + }); + /* Because in short-hand property assignment, location has two meaning : property name and as value of the property + * When we do findAllReference at the position of the short-hand property assignment, we would want to have references to position of + * property name and variable declaration of the identifier. + * Like in below example, when querying for all references for an identifier 'name', of the property assignment, the language service + * should show both 'name' in 'obj' and 'name' in variable declaration + * const name = "Foo"; + * const obj = { name }; + * In order to do that, we will populate the search set with the value symbol of the identifier as a value of the property assignment + * so that when matching with potential reference symbol, both symbols from property declaration and variable declaration + * will be included correctly. + */ + var shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(location.parent); + if (shorthandValueSymbol) { + result.push(shorthandValueSymbol); } } - return -1 /* Unknown */; - } - function computeIndentation(node, startLine, inheritedIndentation, parent, parentDynamicIndentation, effectiveParentStartLine) { - var indentation = inheritedIndentation; - var delta = formatting.SmartIndenter.shouldIndentChildNode(node) ? options.IndentSize : 0; - if (effectiveParentStartLine === startLine) { - // if node is located on the same line with the parent - // - inherit indentation from the parent - // - push children if either parent of node itself has non-zero delta - indentation = startLine === lastIndentedLine - ? indentationOnLastIndentedLine - : parentDynamicIndentation.getIndentation(); - delta = Math.min(options.IndentSize, parentDynamicIndentation.getDelta(node) + delta); + // If the symbol.valueDeclaration is a property parameter declaration, + // we should include both parameter declaration symbol and property declaration symbol + // Parameter Declaration symbol is only visible within function scope, so the symbol is stored in constructor.locals. + // Property Declaration symbol is a member of the class, so the symbol is stored in its class Declaration.symbol.members + if (symbol.valueDeclaration && symbol.valueDeclaration.kind === 142 /* Parameter */ && + ts.isParameterPropertyDeclaration(symbol.valueDeclaration)) { + result = result.concat(typeChecker.getSymbolsOfParameterPropertyDeclaration(symbol.valueDeclaration, symbol.name)); } - else if (indentation === -1 /* Unknown */) { - if (formatting.SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement(parent, node, startLine, sourceFile)) { - indentation = parentDynamicIndentation.getIndentation(); + // If this is symbol of binding element without propertyName declaration in Object binding pattern + // Include the property in the search + var bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol); + if (bindingElementPropertySymbol) { + result.push(bindingElementPropertySymbol); + } + // If this is a union property, add all the symbols from all its source symbols in all unioned types. + // If the symbol is an instantiation from a another symbol (e.g. widened symbol) , add the root the list + ts.forEach(typeChecker.getRootSymbols(symbol), function (rootSymbol) { + if (rootSymbol !== symbol) { + result.push(rootSymbol); } - else { - indentation = parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta(node); + // Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions + if (!implementations && rootSymbol.parent && rootSymbol.parent.flags & (32 /* Class */ | 64 /* Interface */)) { + getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ ts.createMap()); } - } - return { - indentation: indentation, - delta: delta - }; + }); + return result; } - function getFirstNonDecoratorTokenOfNode(node) { - if (node.modifiers && node.modifiers.length) { - return node.modifiers[0].kind; - } - switch (node.kind) { - case 221 /* ClassDeclaration */: return 73 /* ClassKeyword */; - case 222 /* InterfaceDeclaration */: return 107 /* InterfaceKeyword */; - case 220 /* FunctionDeclaration */: return 87 /* FunctionKeyword */; - case 224 /* EnumDeclaration */: return 224 /* EnumDeclaration */; - case 149 /* GetAccessor */: return 123 /* GetKeyword */; - case 150 /* SetAccessor */: return 131 /* SetKeyword */; - case 147 /* MethodDeclaration */: - if (node.asteriskToken) { - return 37 /* AsteriskToken */; - } /* - fall-through - */ - case 145 /* PropertyDeclaration */: - case 142 /* Parameter */: - return node.name.kind; + /** + * Find symbol of the given property-name and add the symbol to the given result array + * @param symbol a symbol to start searching for the given propertyName + * @param propertyName a name of property to search for + * @param result an array of symbol of found property symbols + * @param previousIterationSymbolsCache a cache of symbol from previous iterations of calling this function to prevent infinite revisiting of the same symbol. + * The value of previousIterationSymbol is undefined when the function is first called. + */ + function getPropertySymbolsFromBaseTypes(symbol, propertyName, result, previousIterationSymbolsCache) { + if (!symbol) { + return; } - } - function getDynamicIndentation(node, nodeStartLine, indentation, delta) { - return { - getIndentationForComment: function (kind, tokenIndentation, container) { - switch (kind) { - // preceding comment to the token that closes the indentation scope inherits the indentation from the scope - // .. { - // // comment - // } - case 16 /* CloseBraceToken */: - case 20 /* CloseBracketToken */: - case 18 /* CloseParenToken */: - return indentation + getEffectiveDelta(delta, container); - } - return tokenIndentation !== -1 /* Unknown */ ? tokenIndentation : indentation; - }, - getIndentationForToken: function (line, kind, container) { - if (nodeStartLine !== line && node.decorators) { - if (kind === getFirstNonDecoratorTokenOfNode(node)) { - // if this token is the first token following the list of decorators, we do not need to indent - return indentation; - } + // If the current symbol is the same as the previous-iteration symbol, we can just return the symbol that has already been visited + // This is particularly important for the following cases, so that we do not infinitely visit the same symbol. + // For example: + // interface C extends C { + // /*findRef*/propName: string; + // } + // The first time getPropertySymbolsFromBaseTypes is called when finding-all-references at propName, + // the symbol argument will be the symbol of an interface "C" and previousIterationSymbol is undefined, + // the function will add any found symbol of the property-name, then its sub-routine will call + // getPropertySymbolsFromBaseTypes again to walk up any base types to prevent revisiting already + // visited symbol, interface "C", the sub-routine will pass the current symbol as previousIterationSymbol. + if (symbol.name in previousIterationSymbolsCache) { + return; + } + if (symbol.flags & (32 /* Class */ | 64 /* Interface */)) { + ts.forEach(symbol.getDeclarations(), function (declaration) { + if (ts.isClassLike(declaration)) { + getPropertySymbolFromTypeReference(ts.getClassExtendsHeritageClauseElement(declaration)); + ts.forEach(ts.getClassImplementsHeritageClauseElements(declaration), getPropertySymbolFromTypeReference); } - switch (kind) { - // open and close brace, 'else' and 'while' (in do statement) tokens has indentation of the parent - case 15 /* OpenBraceToken */: - case 16 /* CloseBraceToken */: - case 19 /* OpenBracketToken */: - case 20 /* CloseBracketToken */: - case 17 /* OpenParenToken */: - case 18 /* CloseParenToken */: - case 80 /* ElseKeyword */: - case 104 /* WhileKeyword */: - case 55 /* AtToken */: - return indentation; - default: - // if token line equals to the line of containing node (this is a first token in the node) - use node indentation - return nodeStartLine !== line ? indentation + getEffectiveDelta(delta, container) : indentation; + else if (declaration.kind === 222 /* InterfaceDeclaration */) { + ts.forEach(ts.getInterfaceBaseTypeNodes(declaration), getPropertySymbolFromTypeReference); } - }, - getIndentation: function () { return indentation; }, - getDelta: function (child) { return getEffectiveDelta(delta, child); }, - recomputeIndentation: function (lineAdded) { - if (node.parent && formatting.SmartIndenter.shouldIndentChildNode(node.parent, node)) { - if (lineAdded) { - indentation += options.IndentSize; - } - else { - indentation -= options.IndentSize; - } - if (formatting.SmartIndenter.shouldIndentChildNode(node)) { - delta = options.IndentSize; - } - else { - delta = 0; + }); + } + return; + function getPropertySymbolFromTypeReference(typeReference) { + if (typeReference) { + var type = typeChecker.getTypeAtLocation(typeReference); + if (type) { + var propertySymbol = typeChecker.getPropertyOfType(type, propertyName); + if (propertySymbol) { + result.push.apply(result, typeChecker.getRootSymbols(propertySymbol)); } + // Visit the typeReference as well to see if it directly or indirectly use that property + previousIterationSymbolsCache[symbol.name] = symbol; + getPropertySymbolsFromBaseTypes(type.symbol, propertyName, result, previousIterationSymbolsCache); } } - }; - function getEffectiveDelta(delta, child) { - // Delta value should be zero when the node explicitly prevents indentation of the child node - return formatting.SmartIndenter.nodeWillIndentChild(node, child, true) ? delta : 0; } } - function processNode(node, contextNode, nodeStartLine, undecoratedNodeStartLine, indentation, delta) { - if (!ts.rangeOverlapsWithStartEnd(originalRange, node.getStart(sourceFile), node.getEnd())) { - return; + function getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation, searchLocationIsConstructor, parents, cache) { + if (ts.contains(searchSymbols, referenceSymbol)) { + // If we are searching for constructor uses, they must be 'new' expressions. + return (!searchLocationIsConstructor || ts.isNewExpressionTarget(referenceLocation)) && referenceSymbol; } - var nodeDynamicIndentation = getDynamicIndentation(node, nodeStartLine, indentation, delta); - // a useful observations when tracking context node - // / - // [a] - // / | \ - // [b] [c] [d] - // node 'a' is a context node for nodes 'b', 'c', 'd' - // except for the leftmost leaf token in [b] - in this case context node ('e') is located somewhere above 'a' - // this rule can be applied recursively to child nodes of 'a'. - // - // context node is set to parent node value after processing every child node - // context node is set to parent of the token after processing every token - var childContextNode = contextNode; - // if there are any tokens that logically belong to node and interleave child nodes - // such tokens will be consumed in processChildNode for for the child that follows them - ts.forEachChild(node, function (child) { - processChildNode(child, /*inheritedIndentation*/ -1 /* Unknown */, node, nodeDynamicIndentation, nodeStartLine, undecoratedNodeStartLine, /*isListItem*/ false); - }, function (nodes) { - processChildNodes(nodes, node, nodeStartLine, nodeDynamicIndentation); - }); - // proceed any tokens in the node that are located after child nodes - while (formattingScanner.isOnToken()) { - var tokenInfo = formattingScanner.readTokenInfo(node); - if (tokenInfo.token.end > node.end) { - break; - } - consumeTokenAndAdvanceScanner(tokenInfo, node, nodeDynamicIndentation); + // If the reference symbol is an alias, check if what it is aliasing is one of the search + // symbols but by looking up for related symbol of this alias so it can handle multiple level of indirectness. + var aliasSymbol = getAliasSymbolForPropertyNameSymbol(referenceSymbol, referenceLocation); + if (aliasSymbol) { + return getRelatedSymbol(searchSymbols, aliasSymbol, referenceLocation, searchLocationIsConstructor, parents, cache); } - function processChildNode(child, inheritedIndentation, parent, parentDynamicIndentation, parentStartLine, undecoratedParentStartLine, isListItem, isFirstListItem) { - var childStartPos = child.getStart(sourceFile); - var childStartLine = sourceFile.getLineAndCharacterOfPosition(childStartPos).line; - var undecoratedChildStartLine = childStartLine; - if (child.decorators) { - undecoratedChildStartLine = sourceFile.getLineAndCharacterOfPosition(ts.getNonDecoratorTokenPosOfNode(child, sourceFile)).line; - } - // if child is a list item - try to get its indentation - var childIndentationAmount = -1 /* Unknown */; - if (isListItem) { - childIndentationAmount = tryComputeIndentationForListItem(childStartPos, child.end, parentStartLine, originalRange, inheritedIndentation); - if (childIndentationAmount !== -1 /* Unknown */) { - inheritedIndentation = childIndentationAmount; - } + // If the reference location is in an object literal, try to get the contextual type for the + // object literal, lookup the property symbol in the contextual type, and use this symbol to + // compare to our searchSymbol + var containingObjectLiteralElement = getContainingObjectLiteralElement(referenceLocation); + if (containingObjectLiteralElement) { + var contextualSymbol = ts.forEach(getPropertySymbolsFromContextualType(containingObjectLiteralElement), function (contextualSymbol) { + return ts.forEach(typeChecker.getRootSymbols(contextualSymbol), function (s) { return searchSymbols.indexOf(s) >= 0 ? s : undefined; }); + }); + if (contextualSymbol) { + return contextualSymbol; } - // child node is outside the target range - do not dive inside - if (!ts.rangeOverlapsWithStartEnd(originalRange, child.pos, child.end)) { - if (child.end < originalRange.pos) { - formattingScanner.skipToEndOf(child); - } - return inheritedIndentation; + // If the reference location is the name of property from object literal destructuring pattern + // Get the property symbol from the object literal's type and look if thats the search symbol + // In below eg. get 'property' from type of elems iterating type + // for ( { property: p2 } of elems) { } + var propertySymbol = getPropertySymbolOfDestructuringAssignment(referenceLocation); + if (propertySymbol && searchSymbols.indexOf(propertySymbol) >= 0) { + return propertySymbol; } - if (child.getFullWidth() === 0) { - return inheritedIndentation; + } + // If the reference location is the binding element and doesn't have property name + // then include the binding element in the related symbols + // let { a } : { a }; + var bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(referenceSymbol); + if (bindingElementPropertySymbol && searchSymbols.indexOf(bindingElementPropertySymbol) >= 0) { + return bindingElementPropertySymbol; + } + // Unwrap symbols to get to the root (e.g. transient symbols as a result of widening) + // Or a union property, use its underlying unioned symbols + return ts.forEach(typeChecker.getRootSymbols(referenceSymbol), function (rootSymbol) { + // if it is in the list, then we are done + if (searchSymbols.indexOf(rootSymbol) >= 0) { + return rootSymbol; } - while (formattingScanner.isOnToken()) { - // proceed any parent tokens that are located prior to child.getStart() - var tokenInfo = formattingScanner.readTokenInfo(node); - if (tokenInfo.token.end > childStartPos) { - // stop when formatting scanner advances past the beginning of the child - break; + // Finally, try all properties with the same name in any type the containing type extended or implemented, and + // see if any is in the list. If we were passed a parent symbol, only include types that are subtypes of the + // parent symbol + if (rootSymbol.parent && rootSymbol.parent.flags & (32 /* Class */ | 64 /* Interface */)) { + // Parents will only be defined if implementations is true + if (parents) { + if (!ts.forEach(parents, function (parent) { return explicitlyInheritsFrom(rootSymbol.parent, parent, cache); })) { + return undefined; + } } - consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation); - } - if (!formattingScanner.isOnToken()) { - return inheritedIndentation; + var result_3 = []; + getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result_3, /*previousIterationSymbolsCache*/ ts.createMap()); + return ts.forEach(result_3, function (s) { return searchSymbols.indexOf(s) >= 0 ? s : undefined; }); } - if (ts.isToken(child)) { - // if child node is a token, it does not impact indentation, proceed it using parent indentation scope rules - var tokenInfo = formattingScanner.readTokenInfo(child); - ts.Debug.assert(tokenInfo.token.end === child.end); - consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation, child); - return inheritedIndentation; - } - var effectiveParentStartLine = child.kind === 143 /* Decorator */ ? childStartLine : undecoratedParentStartLine; - var childIndentation = computeIndentation(child, childStartLine, childIndentationAmount, node, parentDynamicIndentation, effectiveParentStartLine); - processNode(child, childContextNode, childStartLine, undecoratedChildStartLine, childIndentation.indentation, childIndentation.delta); - childContextNode = node; - if (isFirstListItem && parent.kind === 170 /* ArrayLiteralExpression */ && inheritedIndentation === -1 /* Unknown */) { - inheritedIndentation = childIndentation.indentation; + return undefined; + }); + } + function getNameFromObjectLiteralElement(node) { + if (node.name.kind === 140 /* ComputedPropertyName */) { + var nameExpression = node.name.expression; + // treat computed property names where expression is string/numeric literal as just string/numeric literal + if (ts.isStringOrNumericLiteral(nameExpression.kind)) { + return nameExpression.text; } - return inheritedIndentation; + return undefined; } - function processChildNodes(nodes, parent, parentStartLine, parentDynamicIndentation) { - var listStartToken = getOpenTokenForList(parent, nodes); - var listEndToken = getCloseTokenForOpenToken(listStartToken); - var listDynamicIndentation = parentDynamicIndentation; - var startLine = parentStartLine; - if (listStartToken !== 0 /* Unknown */) { - // introduce a new indentation scope for lists (including list start and end tokens) - while (formattingScanner.isOnToken()) { - var tokenInfo = formattingScanner.readTokenInfo(parent); - if (tokenInfo.token.end > nodes.pos) { - // stop when formatting scanner moves past the beginning of node list - break; - } - else if (tokenInfo.token.kind === listStartToken) { - // consume list start token - startLine = sourceFile.getLineAndCharacterOfPosition(tokenInfo.token.pos).line; - var indentation_1 = computeIndentation(tokenInfo.token, startLine, -1 /* Unknown */, parent, parentDynamicIndentation, parentStartLine); - listDynamicIndentation = getDynamicIndentation(parent, parentStartLine, indentation_1.indentation, indentation_1.delta); - consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation); - } - else { - // consume any tokens that precede the list as child elements of 'node' using its indentation scope - consumeTokenAndAdvanceScanner(tokenInfo, parent, parentDynamicIndentation); - } - } - } - var inheritedIndentation = -1 /* Unknown */; - for (var i = 0; i < nodes.length; i++) { - var child = nodes[i]; - inheritedIndentation = processChildNode(child, inheritedIndentation, node, listDynamicIndentation, startLine, startLine, /*isListItem*/ true, /*isFirstListItem*/ i === 0); + return node.name.text; + } + function getPropertySymbolsFromContextualType(node) { + var objectLiteral = node.parent; + var contextualType = typeChecker.getContextualType(objectLiteral); + var name = getNameFromObjectLiteralElement(node); + if (name && contextualType) { + var result_4 = []; + var symbol_2 = contextualType.getProperty(name); + if (symbol_2) { + result_4.push(symbol_2); } - if (listEndToken !== 0 /* Unknown */) { - if (formattingScanner.isOnToken()) { - var tokenInfo = formattingScanner.readTokenInfo(parent); - // consume the list end token only if it is still belong to the parent - // there might be the case when current token matches end token but does not considered as one - // function (x: function) <-- - // without this check close paren will be interpreted as list end token for function expression which is wrong - if (tokenInfo.token.kind === listEndToken && ts.rangeContainsRange(parent, tokenInfo.token)) { - // consume list end token - consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation); + if (contextualType.flags & 524288 /* Union */) { + ts.forEach(contextualType.types, function (t) { + var symbol = t.getProperty(name); + if (symbol) { + result_4.push(symbol); } - } + }); } + return result_4; } - function consumeTokenAndAdvanceScanner(currentTokenInfo, parent, dynamicIndentation, container) { - ts.Debug.assert(ts.rangeContainsRange(parent, currentTokenInfo.token)); - var lastTriviaWasNewLine = formattingScanner.lastTrailingTriviaWasNewLine(); - var indentToken = false; - if (currentTokenInfo.leadingTrivia) { - processTrivia(currentTokenInfo.leadingTrivia, parent, childContextNode, dynamicIndentation); - } - var lineAdded; - var isTokenInRange = ts.rangeContainsRange(originalRange, currentTokenInfo.token); - var tokenStart = sourceFile.getLineAndCharacterOfPosition(currentTokenInfo.token.pos); - if (isTokenInRange) { - var rangeHasError = rangeContainsError(currentTokenInfo.token); - // save previousRange since processRange will overwrite this value with current one - var savePreviousRange = previousRange; - lineAdded = processRange(currentTokenInfo.token, tokenStart, parent, childContextNode, dynamicIndentation); - if (rangeHasError) { - // do not indent comments\token if token range overlaps with some error - indentToken = false; - } - else { - if (lineAdded !== undefined) { - indentToken = lineAdded; - } - else { - // indent token only if end line of previous range does not match start line of the token - var prevEndLine = savePreviousRange && sourceFile.getLineAndCharacterOfPosition(savePreviousRange.end).line; - indentToken = lastTriviaWasNewLine && tokenStart.line !== prevEndLine; + return undefined; + } + /** Given an initial searchMeaning, extracted from a location, widen the search scope based on the declarations + * of the corresponding symbol. e.g. if we are searching for "Foo" in value position, but "Foo" references a class + * then we need to widen the search to include type positions as well. + * On the contrary, if we are searching for "Bar" in type position and we trace bar to an interface, and an uninstantiated + * module, we want to keep the search limited to only types, as the two declarations (interface and uninstantiated module) + * do not intersect in any of the three spaces. + */ + function getIntersectingMeaningFromDeclarations(meaning, declarations) { + if (declarations) { + var lastIterationMeaning = void 0; + do { + // The result is order-sensitive, for instance if initialMeaning === Namespace, and declarations = [class, instantiated module] + // we need to consider both as they initialMeaning intersects with the module in the namespace space, and the module + // intersects with the class in the value space. + // To achieve that we will keep iterating until the result stabilizes. + // Remember the last meaning + lastIterationMeaning = meaning; + for (var _i = 0, declarations_8 = declarations; _i < declarations_8.length; _i++) { + var declaration = declarations_8[_i]; + var declarationMeaning = ts.getMeaningFromDeclaration(declaration); + if (declarationMeaning & meaning) { + meaning |= declarationMeaning; } } + } while (meaning !== lastIterationMeaning); + } + return meaning; + } + } + FindAllReferences.getReferencedSymbolsForNode = getReferencedSymbolsForNode; + function convertReferences(referenceSymbols) { + if (!referenceSymbols) { + return undefined; + } + var referenceEntries = []; + for (var _i = 0, referenceSymbols_1 = referenceSymbols; _i < referenceSymbols_1.length; _i++) { + var referenceSymbol = referenceSymbols_1[_i]; + ts.addRange(referenceEntries, referenceSymbol.references); + } + return referenceEntries; + } + FindAllReferences.convertReferences = convertReferences; + function isImplementation(node) { + if (!node) { + return false; + } + else if (ts.isVariableLike(node)) { + if (node.initializer) { + return true; + } + else if (node.kind === 218 /* VariableDeclaration */) { + var parentStatement = getParentStatementOfVariableDeclaration(node); + return parentStatement && ts.hasModifier(parentStatement, 2 /* Ambient */); + } + } + else if (ts.isFunctionLike(node)) { + return !!node.body || ts.hasModifier(node, 2 /* Ambient */); + } + else { + switch (node.kind) { + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + case 224 /* EnumDeclaration */: + case 225 /* ModuleDeclaration */: + return true; + } + } + return false; + } + function getParentStatementOfVariableDeclaration(node) { + if (node.parent && node.parent.parent && node.parent.parent.kind === 200 /* VariableStatement */) { + ts.Debug.assert(node.parent.kind === 219 /* VariableDeclarationList */); + return node.parent.parent; + } + } + function getReferenceEntriesForShorthandPropertyAssignment(node, typeChecker, result) { + var refSymbol = typeChecker.getSymbolAtLocation(node); + var shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(refSymbol.valueDeclaration); + if (shorthandSymbol) { + for (var _i = 0, _a = shorthandSymbol.getDeclarations(); _i < _a.length; _i++) { + var declaration = _a[_i]; + if (ts.getMeaningFromDeclaration(declaration) & 1 /* Value */) { + result.push(getReferenceEntryFromNode(declaration)); } - if (currentTokenInfo.trailingTrivia) { - processTrivia(currentTokenInfo.trailingTrivia, parent, childContextNode, dynamicIndentation); - } - if (indentToken) { - var tokenIndentation = (isTokenInRange && !rangeContainsError(currentTokenInfo.token)) ? - dynamicIndentation.getIndentationForToken(tokenStart.line, currentTokenInfo.token.kind, container) : - -1 /* Unknown */; - var indentNextTokenOrTrivia = true; - if (currentTokenInfo.leadingTrivia) { - var commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind, tokenIndentation, container); - for (var _i = 0, _a = currentTokenInfo.leadingTrivia; _i < _a.length; _i++) { - var triviaItem = _a[_i]; - var triviaInRange = ts.rangeContainsRange(originalRange, triviaItem); - switch (triviaItem.kind) { - case 3 /* MultiLineCommentTrivia */: - if (triviaInRange) { - indentMultilineComment(triviaItem, commentIndentation, /*firstLineIsIndented*/ !indentNextTokenOrTrivia); - } - indentNextTokenOrTrivia = false; - break; - case 2 /* SingleLineCommentTrivia */: - if (indentNextTokenOrTrivia && triviaInRange) { - insertIndentation(triviaItem.pos, commentIndentation, /*lineAdded*/ false); - } - indentNextTokenOrTrivia = false; - break; - case 4 /* NewLineTrivia */: - indentNextTokenOrTrivia = true; - break; - } - } - } - // indent token only if is it is in target range and does not overlap with any error ranges - if (tokenIndentation !== -1 /* Unknown */ && indentNextTokenOrTrivia) { - insertIndentation(currentTokenInfo.token.pos, tokenIndentation, lineAdded); - lastIndentedLine = tokenStart.line; - indentationOnLastIndentedLine = tokenIndentation; - } + } + } + } + FindAllReferences.getReferenceEntriesForShorthandPropertyAssignment = getReferenceEntriesForShorthandPropertyAssignment; + function getReferenceEntryFromNode(node) { + var start = node.getStart(); + var end = node.getEnd(); + if (node.kind === 9 /* StringLiteral */) { + start += 1; + end -= 1; + } + return { + fileName: node.getSourceFile().fileName, + textSpan: ts.createTextSpanFromBounds(start, end), + isWriteAccess: isWriteAccess(node), + isDefinition: ts.isDeclarationName(node) || ts.isLiteralComputedPropertyDeclarationName(node) + }; + } + FindAllReferences.getReferenceEntryFromNode = getReferenceEntryFromNode; + /** A node is considered a writeAccess iff it is a name of a declaration or a target of an assignment */ + function isWriteAccess(node) { + if (node.kind === 69 /* Identifier */ && ts.isDeclarationName(node)) { + return true; + } + var parent = node.parent; + if (parent) { + if (parent.kind === 186 /* PostfixUnaryExpression */ || parent.kind === 185 /* PrefixUnaryExpression */) { + return true; + } + else if (parent.kind === 187 /* BinaryExpression */ && parent.left === node) { + var operator = parent.operatorToken.kind; + return 56 /* FirstAssignment */ <= operator && operator <= 68 /* LastAssignment */; + } + } + return false; + } + function forEachDescendantOfKind(node, kind, action) { + ts.forEachChild(node, function (child) { + if (child.kind === kind) { + action(child); + } + forEachDescendantOfKind(child, kind, action); + }); + } + /** + * Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 } + */ + function getContainingObjectLiteralElement(node) { + switch (node.kind) { + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: + if (node.parent.kind === 140 /* ComputedPropertyName */) { + return isObjectLiteralPropertyDeclaration(node.parent.parent) ? node.parent.parent : undefined; } - formattingScanner.advance(); - childContextNode = parent; + // intential fall through + case 69 /* Identifier */: + return isObjectLiteralPropertyDeclaration(node.parent) && node.parent.name === node ? node.parent : undefined; + } + return undefined; + } + function isObjectLiteralPropertyDeclaration(node) { + switch (node.kind) { + case 253 /* PropertyAssignment */: + case 254 /* ShorthandPropertyAssignment */: + case 147 /* MethodDeclaration */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + return true; + } + return false; + } + /** Get `C` given `N` if `N` is in the position `class C extends N` or `class C extends foo.N` where `N` is an identifier. */ + function tryGetClassByExtendingIdentifier(node) { + return ts.tryGetClassExtendingExpressionWithTypeArguments(ts.climbPastPropertyAccess(node).parent); + } + function isNameOfExternalModuleImportOrDeclaration(node) { + if (node.kind === 9 /* StringLiteral */) { + return ts.isNameOfModuleDeclaration(node) || ts.isExpressionOfExternalModuleImportEqualsDeclaration(node); + } + return false; + } + })(FindAllReferences = ts.FindAllReferences || (ts.FindAllReferences = {})); +})(ts || (ts = {})); +/* @internal */ +var ts; +(function (ts) { + var GoToDefinition; + (function (GoToDefinition) { + function getDefinitionAtPosition(program, sourceFile, position) { + /// Triple slash reference comments + var comment = findReferenceInPosition(sourceFile.referencedFiles, position); + if (comment) { + var referenceFile = ts.tryResolveScriptReference(program, sourceFile, comment); + if (referenceFile) { + return [getDefinitionInfoForFileReference(comment.fileName, referenceFile.fileName)]; + } + return undefined; + } + // Type reference directives + var typeReferenceDirective = findReferenceInPosition(sourceFile.typeReferenceDirectives, position); + if (typeReferenceDirective) { + var referenceFile = program.getResolvedTypeReferenceDirectives()[typeReferenceDirective.fileName]; + if (referenceFile && referenceFile.resolvedFileName) { + return [getDefinitionInfoForFileReference(typeReferenceDirective.fileName, referenceFile.resolvedFileName)]; + } + return undefined; + } + var node = ts.getTouchingPropertyName(sourceFile, position); + if (node === sourceFile) { + return undefined; + } + // Labels + if (ts.isJumpStatementTarget(node)) { + var labelName = node.text; + var label = ts.getTargetLabel(node.parent, node.text); + return label ? [createDefinitionInfo(label, ts.ScriptElementKind.label, labelName, /*containerName*/ undefined)] : undefined; + } + var typeChecker = program.getTypeChecker(); + var calledDeclaration = tryGetSignatureDeclaration(typeChecker, node); + if (calledDeclaration) { + return [createDefinitionFromSignatureDeclaration(typeChecker, calledDeclaration)]; + } + var symbol = typeChecker.getSymbolAtLocation(node); + // Could not find a symbol e.g. node is string or number keyword, + // or the symbol was an internal symbol and does not have a declaration e.g. undefined symbol + if (!symbol) { + return undefined; + } + // If this is an alias, and the request came at the declaration location + // get the aliased symbol instead. This allows for goto def on an import e.g. + // import {A, B} from "mod"; + // to jump to the implementation directly. + if (symbol.flags & 8388608 /* Alias */) { + var declaration = symbol.declarations[0]; + // Go to the original declaration for cases: + // + // (1) when the aliased symbol was declared in the location(parent). + // (2) when the aliased symbol is originating from a named import. + // + if (node.kind === 69 /* Identifier */ && + (node.parent === declaration || + (declaration.kind === 234 /* ImportSpecifier */ && declaration.parent && declaration.parent.kind === 233 /* NamedImports */))) { + symbol = typeChecker.getAliasedSymbol(symbol); } } - function processTrivia(trivia, parent, contextNode, dynamicIndentation) { - for (var _i = 0, trivia_1 = trivia; _i < trivia_1.length; _i++) { - var triviaItem = trivia_1[_i]; - if (ts.isComment(triviaItem.kind) && ts.rangeContainsRange(originalRange, triviaItem)) { - var triviaItemStart = sourceFile.getLineAndCharacterOfPosition(triviaItem.pos); - processRange(triviaItem, triviaItemStart, parent, contextNode, dynamicIndentation); - } + // Because name in short-hand property assignment has two different meanings: property name and property value, + // using go-to-definition at such position should go to the variable declaration of the property value rather than + // go to the declaration of the property name (in this case stay at the same position). However, if go-to-definition + // is performed at the location of property access, we would like to go to definition of the property in the short-hand + // assignment. This case and others are handled by the following code. + if (node.parent.kind === 254 /* ShorthandPropertyAssignment */) { + var shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration); + if (!shorthandSymbol) { + return []; } + var shorthandDeclarations = shorthandSymbol.getDeclarations(); + var shorthandSymbolKind_1 = ts.SymbolDisplay.getSymbolKind(typeChecker, shorthandSymbol, node); + var shorthandSymbolName_1 = typeChecker.symbolToString(shorthandSymbol); + var shorthandContainerName_1 = typeChecker.symbolToString(symbol.parent, node); + return ts.map(shorthandDeclarations, function (declaration) { return createDefinitionInfo(declaration, shorthandSymbolKind_1, shorthandSymbolName_1, shorthandContainerName_1); }); } - function processRange(range, rangeStart, parent, contextNode, dynamicIndentation) { - var rangeHasError = rangeContainsError(range); - var lineAdded; - if (!rangeHasError && !previousRangeHasError) { - if (!previousRange) { - // trim whitespaces starting from the beginning of the span up to the current line - var originalStart = sourceFile.getLineAndCharacterOfPosition(originalRange.pos); - trimTrailingWhitespacesForLines(originalStart.line, rangeStart.line); - } - else { - lineAdded = - processPair(range, rangeStart.line, parent, previousRange, previousRangeStartLine, previousParent, contextNode, dynamicIndentation); - } - } - previousRange = range; - previousParent = parent; - previousRangeStartLine = rangeStart.line; - previousRangeHasError = rangeHasError; - return lineAdded; + return getDefinitionFromSymbol(typeChecker, symbol, node); + } + GoToDefinition.getDefinitionAtPosition = getDefinitionAtPosition; + /// Goto type + function getTypeDefinitionAtPosition(typeChecker, sourceFile, position) { + var node = ts.getTouchingPropertyName(sourceFile, position); + if (node === sourceFile) { + return undefined; } - function processPair(currentItem, currentStartLine, currentParent, previousItem, previousStartLine, previousParent, contextNode, dynamicIndentation) { - formattingContext.updateContext(previousItem, previousParent, currentItem, currentParent, contextNode); - var rule = rulesProvider.getRulesMap().GetRule(formattingContext); - var trimTrailingWhitespaces; - var lineAdded; - if (rule) { - applyRuleEdits(rule, previousItem, previousStartLine, currentItem, currentStartLine); - if (rule.Operation.Action & (2 /* Space */ | 8 /* Delete */) && currentStartLine !== previousStartLine) { - lineAdded = false; - // Handle the case where the next line is moved to be the end of this line. - // In this case we don't indent the next line in the next pass. - if (currentParent.getStart(sourceFile) === currentItem.pos) { - dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ false); - } - } - else if (rule.Operation.Action & 4 /* NewLine */ && currentStartLine === previousStartLine) { - lineAdded = true; - // Handle the case where token2 is moved to the new line. - // In this case we indent token2 in the next pass but we set - // sameLineIndent flag to notify the indenter that the indentation is within the line. - if (currentParent.getStart(sourceFile) === currentItem.pos) { - dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ true); - } - } - // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line - trimTrailingWhitespaces = !(rule.Operation.Action & 8 /* Delete */) && rule.Flag !== 1 /* CanDeleteNewLines */; - } - else { - trimTrailingWhitespaces = true; - } - if (currentStartLine !== previousStartLine && trimTrailingWhitespaces) { - // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line - trimTrailingWhitespacesForLines(previousStartLine, currentStartLine, previousItem); - } - return lineAdded; + var symbol = typeChecker.getSymbolAtLocation(node); + if (!symbol) { + return undefined; } - function insertIndentation(pos, indentation, lineAdded) { - var indentationString = getIndentationString(indentation, options); - if (lineAdded) { - // new line is added before the token by the formatting rules - // insert indentation string at the very beginning of the token - recordReplace(pos, 0, indentationString); - } - else { - var tokenStart = sourceFile.getLineAndCharacterOfPosition(pos); - var startLinePosition = ts.getStartPositionOfLine(tokenStart.line, sourceFile); - if (indentation !== tokenStart.character || indentationIsDifferent(indentationString, startLinePosition)) { - recordReplace(startLinePosition, tokenStart.character, indentationString); + var type = typeChecker.getTypeOfSymbolAtLocation(symbol, node); + if (!type) { + return undefined; + } + if (type.flags & 524288 /* Union */ && !(type.flags & 16 /* Enum */)) { + var result_5 = []; + ts.forEach(type.types, function (t) { + if (t.symbol) { + ts.addRange(/*to*/ result_5, /*from*/ getDefinitionFromSymbol(typeChecker, t.symbol, node)); } - } + }); + return result_5; } - function indentationIsDifferent(indentationString, startLinePosition) { - return indentationString !== sourceFile.text.substr(startLinePosition, indentationString.length); + if (!type.symbol) { + return undefined; } - function indentMultilineComment(commentRange, indentation, firstLineIsIndented) { - // split comment in lines - var startLine = sourceFile.getLineAndCharacterOfPosition(commentRange.pos).line; - var endLine = sourceFile.getLineAndCharacterOfPosition(commentRange.end).line; - var parts; - if (startLine === endLine) { - if (!firstLineIsIndented) { - // treat as single line comment - insertIndentation(commentRange.pos, indentation, /*lineAdded*/ false); - } - return; - } - else { - parts = []; - var startPos = commentRange.pos; - for (var line = startLine; line < endLine; line++) { - var endOfLine = ts.getEndLinePosition(line, sourceFile); - parts.push({ pos: startPos, end: endOfLine }); - startPos = ts.getStartPositionOfLine(line + 1, sourceFile); + return getDefinitionFromSymbol(typeChecker, type.symbol, node); + } + GoToDefinition.getTypeDefinitionAtPosition = getTypeDefinitionAtPosition; + function getDefinitionFromSymbol(typeChecker, symbol, node) { + var result = []; + var declarations = symbol.getDeclarations(); + var _a = getSymbolInfo(typeChecker, symbol, node), symbolName = _a.symbolName, symbolKind = _a.symbolKind, containerName = _a.containerName; + if (!tryAddConstructSignature(symbol, node, symbolKind, symbolName, containerName, result) && + !tryAddCallSignature(symbol, node, symbolKind, symbolName, containerName, result)) { + // Just add all the declarations. + ts.forEach(declarations, function (declaration) { + result.push(createDefinitionInfo(declaration, symbolKind, symbolName, containerName)); + }); + } + return result; + function tryAddConstructSignature(symbol, location, symbolKind, symbolName, containerName, result) { + // Applicable only if we are in a new expression, or we are on a constructor declaration + // and in either case the symbol has a construct signature definition, i.e. class + if (ts.isNewExpressionTarget(location) || location.kind === 121 /* ConstructorKeyword */) { + if (symbol.flags & 32 /* Class */) { + // Find the first class-like declaration and try to get the construct signature. + for (var _i = 0, _a = symbol.getDeclarations(); _i < _a.length; _i++) { + var declaration = _a[_i]; + if (ts.isClassLike(declaration)) { + return tryAddSignature(declaration.members, + /*selectConstructors*/ true, symbolKind, symbolName, containerName, result); + } + } + ts.Debug.fail("Expected declaration to have at least one class-like declaration"); } - parts.push({ pos: startPos, end: commentRange.end }); - } - var startLinePos = ts.getStartPositionOfLine(startLine, sourceFile); - var nonWhitespaceColumnInFirstPart = formatting.SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(startLinePos, parts[0].pos, sourceFile, options); - if (indentation === nonWhitespaceColumnInFirstPart.column) { - return; - } - var startIndex = 0; - if (firstLineIsIndented) { - startIndex = 1; - startLine++; } - // shift all parts on the delta size - var delta = indentation - nonWhitespaceColumnInFirstPart.column; - for (var i = startIndex, len = parts.length; i < len; i++, startLine++) { - var startLinePos_1 = ts.getStartPositionOfLine(startLine, sourceFile); - var nonWhitespaceCharacterAndColumn = i === 0 - ? nonWhitespaceColumnInFirstPart - : formatting.SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(parts[i].pos, parts[i].end, sourceFile, options); - var newIndentation = nonWhitespaceCharacterAndColumn.column + delta; - if (newIndentation > 0) { - var indentationString = getIndentationString(newIndentation, options); - recordReplace(startLinePos_1, nonWhitespaceCharacterAndColumn.character, indentationString); - } - else { - recordDelete(startLinePos_1, nonWhitespaceCharacterAndColumn.character); - } + return false; + } + function tryAddCallSignature(symbol, location, symbolKind, symbolName, containerName, result) { + if (ts.isCallExpressionTarget(location) || ts.isNewExpressionTarget(location) || ts.isNameOfFunctionDeclaration(location)) { + return tryAddSignature(symbol.declarations, /*selectConstructors*/ false, symbolKind, symbolName, containerName, result); } + return false; } - function trimTrailingWhitespacesForLines(line1, line2, range) { - for (var line = line1; line < line2; line++) { - var lineStartPosition = ts.getStartPositionOfLine(line, sourceFile); - var lineEndPosition = ts.getEndLinePosition(line, sourceFile); - // do not trim whitespaces in comments or template expression - if (range && (ts.isComment(range.kind) || ts.isStringOrRegularExpressionOrTemplateLiteral(range.kind)) && range.pos <= lineEndPosition && range.end > lineEndPosition) { - continue; - } - var whitespaceStart = getTrailingWhitespaceStartPosition(lineStartPosition, lineEndPosition); - if (whitespaceStart !== -1) { - ts.Debug.assert(whitespaceStart === lineStartPosition || !ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(whitespaceStart - 1))); - recordDelete(whitespaceStart, lineEndPosition + 1 - whitespaceStart); + function tryAddSignature(signatureDeclarations, selectConstructors, symbolKind, symbolName, containerName, result) { + var declarations = []; + var definition; + ts.forEach(signatureDeclarations, function (d) { + if ((selectConstructors && d.kind === 148 /* Constructor */) || + (!selectConstructors && (d.kind === 220 /* FunctionDeclaration */ || d.kind === 147 /* MethodDeclaration */ || d.kind === 146 /* MethodSignature */))) { + declarations.push(d); + if (d.body) + definition = d; } + }); + if (definition) { + result.push(createDefinitionInfo(definition, symbolKind, symbolName, containerName)); + return true; } - } - /** - * @param start The position of the first character in range - * @param end The position of the last character in range - */ - function getTrailingWhitespaceStartPosition(start, end) { - var pos = end; - while (pos >= start && ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(pos))) { - pos--; + else if (declarations.length) { + result.push(createDefinitionInfo(ts.lastOrUndefined(declarations), symbolKind, symbolName, containerName)); + return true; } - if (pos !== end) { - return pos + 1; + return false; + } + } + function createDefinitionInfo(node, symbolKind, symbolName, containerName) { + return { + fileName: node.getSourceFile().fileName, + textSpan: ts.createTextSpanFromBounds(node.getStart(), node.getEnd()), + kind: symbolKind, + name: symbolName, + containerKind: undefined, + containerName: containerName + }; + } + function getSymbolInfo(typeChecker, symbol, node) { + return { + symbolName: typeChecker.symbolToString(symbol), + symbolKind: ts.SymbolDisplay.getSymbolKind(typeChecker, symbol, node), + containerName: symbol.parent ? typeChecker.symbolToString(symbol.parent, node) : "" + }; + } + function createDefinitionFromSignatureDeclaration(typeChecker, decl) { + var _a = getSymbolInfo(typeChecker, decl.symbol, decl), symbolName = _a.symbolName, symbolKind = _a.symbolKind, containerName = _a.containerName; + return createDefinitionInfo(decl, symbolKind, symbolName, containerName); + } + function findReferenceInPosition(refs, pos) { + for (var _i = 0, refs_1 = refs; _i < refs_1.length; _i++) { + var ref = refs_1[_i]; + if (ref.pos <= pos && pos < ref.end) { + return ref; } - return -1; } - /** - * Trimming will be done for lines after the previous range - */ - function trimTrailingWhitespacesForRemainingRange() { - var startPosition = previousRange ? previousRange.end : originalRange.pos; - var startLine = sourceFile.getLineAndCharacterOfPosition(startPosition).line; - var endLine = sourceFile.getLineAndCharacterOfPosition(originalRange.end).line; - trimTrailingWhitespacesForLines(startLine, endLine + 1, previousRange); + return undefined; + } + function getDefinitionInfoForFileReference(name, targetFileName) { + return { + fileName: targetFileName, + textSpan: ts.createTextSpanFromBounds(0, 0), + kind: ts.ScriptElementKind.scriptElement, + name: name, + containerName: undefined, + containerKind: undefined + }; + } + /** Returns a CallLikeExpression where `node` is the target being invoked. */ + function getAncestorCallLikeExpression(node) { + var target = climbPastManyPropertyAccesses(node); + var callLike = target.parent; + return callLike && ts.isCallLikeExpression(callLike) && ts.getInvokedExpression(callLike) === target && callLike; + } + function climbPastManyPropertyAccesses(node) { + return ts.isRightSideOfPropertyAccess(node) ? climbPastManyPropertyAccesses(node.parent) : node; + } + function tryGetSignatureDeclaration(typeChecker, node) { + var callLike = getAncestorCallLikeExpression(node); + return callLike && typeChecker.getResolvedSignature(callLike).declaration; + } + })(GoToDefinition = ts.GoToDefinition || (ts.GoToDefinition = {})); +})(ts || (ts = {})); +/* @internal */ +var ts; +(function (ts) { + var GoToImplementation; + (function (GoToImplementation) { + function getImplementationAtPosition(typeChecker, cancellationToken, sourceFiles, node) { + // If invoked directly on a shorthand property assignment, then return + // the declaration of the symbol being assigned (not the symbol being assigned to). + if (node.parent.kind === 254 /* ShorthandPropertyAssignment */) { + var result = []; + ts.FindAllReferences.getReferenceEntriesForShorthandPropertyAssignment(node, typeChecker, result); + return result.length > 0 ? result : undefined; } - function newTextChange(start, len, newText) { - return { span: ts.createTextSpan(start, len), newText: newText }; + else if (node.kind === 95 /* SuperKeyword */ || ts.isSuperProperty(node.parent)) { + // References to and accesses on the super keyword only have one possible implementation, so no + // need to "Find all References" + var symbol = typeChecker.getSymbolAtLocation(node); + return symbol.valueDeclaration && [ts.FindAllReferences.getReferenceEntryFromNode(symbol.valueDeclaration)]; } - function recordDelete(start, len) { - if (len) { - edits.push(newTextChange(start, len, "")); - } + else { + // Perform "Find all References" and retrieve only those that are implementations + var referencedSymbols = ts.FindAllReferences.getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFiles, /*findInStrings*/ false, /*findInComments*/ false, /*implementations*/ true); + var result = ts.flatMap(referencedSymbols, function (symbol) { + return ts.map(symbol.references, function (_a) { + var textSpan = _a.textSpan, fileName = _a.fileName; + return ({ textSpan: textSpan, fileName: fileName }); + }); + }); + return result && result.length > 0 ? result : undefined; } - function recordReplace(start, len, newText) { - if (len || newText) { - edits.push(newTextChange(start, len, newText)); + } + GoToImplementation.getImplementationAtPosition = getImplementationAtPosition; + })(GoToImplementation = ts.GoToImplementation || (ts.GoToImplementation = {})); +})(ts || (ts = {})); +/* @internal */ +var ts; +(function (ts) { + var JsDoc; + (function (JsDoc) { + var jsDocTagNames = [ + "augments", + "author", + "argument", + "borrows", + "class", + "constant", + "constructor", + "constructs", + "default", + "deprecated", + "description", + "event", + "example", + "extends", + "field", + "fileOverview", + "function", + "ignore", + "inner", + "lends", + "link", + "memberOf", + "name", + "namespace", + "param", + "private", + "property", + "public", + "requires", + "returns", + "see", + "since", + "static", + "throws", + "type", + "typedef", + "property", + "prop", + "version" + ]; + var jsDocCompletionEntries; + function getJsDocCommentsFromDeclarations(declarations, name, canUseParsedParamTagComments) { + // Only collect doc comments from duplicate declarations once: + // In case of a union property there might be same declaration multiple times + // which only varies in type parameter + // Eg. const a: Array | Array; a.length + // The property length will have two declarations of property length coming + // from Array - Array and Array + var documentationComment = []; + forEachUnique(declarations, function (declaration) { + var comments = ts.getJSDocComments(declaration, /*checkParentVariableStatement*/ true); + if (!comments) { + return; } - } - function applyRuleEdits(rule, previousRange, previousStartLine, currentRange, currentStartLine) { - switch (rule.Operation.Action) { - case 1 /* Ignore */: - // no action required - return; - case 8 /* Delete */: - if (previousRange.end !== currentRange.pos) { - // delete characters starting from t1.end up to t2.pos exclusive - recordDelete(previousRange.end, currentRange.pos - previousRange.end); - } - break; - case 4 /* NewLine */: - // exit early if we on different lines and rule cannot change number of newlines - // if line1 and line2 are on subsequent lines then no edits are required - ok to exit - // if line1 and line2 are separated with more than one newline - ok to exit since we cannot delete extra new lines - if (rule.Flag !== 1 /* CanDeleteNewLines */ && previousStartLine !== currentStartLine) { - return; - } - // edit should not be applied only if we have one line feed between elements - var lineDelta = currentStartLine - previousStartLine; - if (lineDelta !== 1) { - recordReplace(previousRange.end, currentRange.pos - previousRange.end, options.NewLineCharacter); - } - break; - case 2 /* Space */: - // exit early if we on different lines and rule cannot change number of newlines - if (rule.Flag !== 1 /* CanDeleteNewLines */ && previousStartLine !== currentStartLine) { - return; + for (var _i = 0, comments_3 = comments; _i < comments_3.length; _i++) { + var comment = comments_3[_i]; + if (comment) { + if (documentationComment.length) { + documentationComment.push(ts.lineBreakPart()); } - var posDelta = currentRange.pos - previousRange.end; - if (posDelta !== 1 || sourceFile.text.charCodeAt(previousRange.end) !== 32 /* space */) { - recordReplace(previousRange.end, currentRange.pos - previousRange.end, " "); - } - break; + documentationComment.push(ts.textPart(comment)); + } } - } + }); + return documentationComment; } - function getOpenTokenForList(node, list) { - switch (node.kind) { - case 148 /* Constructor */: - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - case 180 /* ArrowFunction */: - if (node.typeParameters === list) { - return 25 /* LessThanToken */; - } - else if (node.parameters === list) { - return 17 /* OpenParenToken */; - } - break; - case 174 /* CallExpression */: - case 175 /* NewExpression */: - if (node.typeArguments === list) { - return 25 /* LessThanToken */; - } - else if (node.arguments === list) { - return 17 /* OpenParenToken */; - } - break; - case 155 /* TypeReference */: - if (node.typeArguments === list) { - return 25 /* LessThanToken */; + JsDoc.getJsDocCommentsFromDeclarations = getJsDocCommentsFromDeclarations; + /** + * Iterates through 'array' by index and performs the callback on each element of array until the callback + * returns a truthy value, then returns that value. + * If no such value is found, the callback is applied to each element of array and undefined is returned. + */ + function forEachUnique(array, callback) { + if (array) { + for (var i = 0, len = array.length; i < len; i++) { + if (ts.indexOf(array, array[i]) === i) { + var result = callback(array[i], i); + if (result) { + return result; + } } + } } - return 0 /* Unknown */; + return undefined; } - function getCloseTokenForOpenToken(kind) { - switch (kind) { - case 17 /* OpenParenToken */: - return 18 /* CloseParenToken */; - case 25 /* LessThanToken */: - return 27 /* GreaterThanToken */; - } - return 0 /* Unknown */; + function getAllJsDocCompletionEntries() { + return jsDocCompletionEntries || (jsDocCompletionEntries = ts.map(jsDocTagNames, function (tagName) { + return { + name: tagName, + kind: ts.ScriptElementKind.keyword, + kindModifiers: "", + sortText: "0", + }; + })); } - var internedSizes; - var internedTabsIndentation; - var internedSpacesIndentation; - function getIndentationString(indentation, options) { - // reset interned strings if FormatCodeOptions were changed - var resetInternedStrings = !internedSizes || (internedSizes.tabSize !== options.TabSize || internedSizes.indentSize !== options.IndentSize); - if (resetInternedStrings) { - internedSizes = { tabSize: options.TabSize, indentSize: options.IndentSize }; - internedTabsIndentation = internedSpacesIndentation = undefined; + JsDoc.getAllJsDocCompletionEntries = getAllJsDocCompletionEntries; + /** + * Checks if position points to a valid position to add JSDoc comments, and if so, + * returns the appropriate template. Otherwise returns an empty string. + * Valid positions are + * - outside of comments, statements, and expressions, and + * - preceding a: + * - function/constructor/method declaration + * - class declarations + * - variable statements + * - namespace declarations + * + * Hosts should ideally check that: + * - The line is all whitespace up to 'position' before performing the insertion. + * - If the keystroke sequence "/\*\*" induced the call, we also check that the next + * non-whitespace character is '*', which (approximately) indicates whether we added + * the second '*' to complete an existing (JSDoc) comment. + * @param fileName The file in which to perform the check. + * @param position The (character-indexed) position in the file where the check should + * be performed. + */ + function getDocCommentTemplateAtPosition(newLine, sourceFile, position) { + // Check if in a context where we don't want to perform any insertion + if (ts.isInString(sourceFile, position) || ts.isInComment(sourceFile, position) || ts.hasDocComment(sourceFile, position)) { + return undefined; } - if (!options.ConvertTabsToSpaces) { - var tabs = Math.floor(indentation / options.TabSize); - var spaces = indentation - tabs * options.TabSize; - var tabString = void 0; - if (!internedTabsIndentation) { - internedTabsIndentation = []; - } - if (internedTabsIndentation[tabs] === undefined) { - internedTabsIndentation[tabs] = tabString = repeat("\t", tabs); - } - else { - tabString = internedTabsIndentation[tabs]; - } - return spaces ? tabString + repeat(" ", spaces) : tabString; + var tokenAtPos = ts.getTokenAtPosition(sourceFile, position); + var tokenStart = tokenAtPos.getStart(); + if (!tokenAtPos || tokenStart < position) { + return undefined; } - else { - var spacesString = void 0; - var quotient = Math.floor(indentation / options.IndentSize); - var remainder = indentation % options.IndentSize; - if (!internedSpacesIndentation) { - internedSpacesIndentation = []; - } - if (internedSpacesIndentation[quotient] === undefined) { - spacesString = repeat(" ", options.IndentSize * quotient); - internedSpacesIndentation[quotient] = spacesString; + // TODO: add support for: + // - enums/enum members + // - interfaces + // - property declarations + // - potentially property assignments + var commentOwner; + findOwner: for (commentOwner = tokenAtPos; commentOwner; commentOwner = commentOwner.parent) { + switch (commentOwner.kind) { + case 220 /* FunctionDeclaration */: + case 147 /* MethodDeclaration */: + case 148 /* Constructor */: + case 221 /* ClassDeclaration */: + case 200 /* VariableStatement */: + break findOwner; + case 256 /* SourceFile */: + return undefined; + case 225 /* ModuleDeclaration */: + // If in walking up the tree, we hit a a nested namespace declaration, + // then we must be somewhere within a dotted namespace name; however we don't + // want to give back a JSDoc template for the 'b' or 'c' in 'namespace a.b.c { }'. + if (commentOwner.parent.kind === 225 /* ModuleDeclaration */) { + return undefined; + } + break findOwner; } - else { - spacesString = internedSpacesIndentation[quotient]; + } + if (!commentOwner || commentOwner.getStart() < position) { + return undefined; + } + var parameters = getParametersForJsDocOwningNode(commentOwner); + var posLineAndChar = sourceFile.getLineAndCharacterOfPosition(position); + var lineStart = sourceFile.getLineStarts()[posLineAndChar.line]; + var indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character); + var docParams = ""; + for (var i = 0, numParams = parameters.length; i < numParams; i++) { + var currentName = parameters[i].name; + var paramName = currentName.kind === 69 /* Identifier */ ? + currentName.text : + "param" + i; + docParams += indentationStr + " * @param " + paramName + newLine; + } + // A doc comment consists of the following + // * The opening comment line + // * the first line (without a param) for the object's untagged info (this is also where the caret ends up) + // * the '@param'-tagged lines + // * TODO: other tags. + // * the closing comment line + // * if the caret was directly in front of the object, then we add an extra line and indentation. + var preamble = "/**" + newLine + + indentationStr + " * "; + var result = preamble + newLine + + docParams + + indentationStr + " */" + + (tokenStart === position ? newLine + indentationStr : ""); + return { newText: result, caretOffset: preamble.length }; + } + JsDoc.getDocCommentTemplateAtPosition = getDocCommentTemplateAtPosition; + function getParametersForJsDocOwningNode(commentOwner) { + if (ts.isFunctionLike(commentOwner)) { + return commentOwner.parameters; + } + if (commentOwner.kind === 200 /* VariableStatement */) { + var varStatement = commentOwner; + var varDeclarations = varStatement.declarationList.declarations; + if (varDeclarations.length === 1 && varDeclarations[0].initializer) { + return getParametersFromRightHandSideOfAssignment(varDeclarations[0].initializer); } - return remainder ? spacesString + repeat(" ", remainder) : spacesString; } - function repeat(value, count) { - var s = ""; - for (var i = 0; i < count; i++) { - s += value; - } - return s; + return ts.emptyArray; + } + /** + * Digs into an an initializer or RHS operand of an assignment operation + * to get the parameters of an apt signature corresponding to a + * function expression or a class expression. + * + * @param rightHandSide the expression which may contain an appropriate set of parameters + * @returns the parameters of a signature found on the RHS if one exists; otherwise 'emptyArray'. + */ + function getParametersFromRightHandSideOfAssignment(rightHandSide) { + while (rightHandSide.kind === 178 /* ParenthesizedExpression */) { + rightHandSide = rightHandSide.expression; + } + switch (rightHandSide.kind) { + case 179 /* FunctionExpression */: + case 180 /* ArrowFunction */: + return rightHandSide.parameters; + case 192 /* ClassExpression */: + for (var _i = 0, _a = rightHandSide.members; _i < _a.length; _i++) { + var member = _a[_i]; + if (member.kind === 148 /* Constructor */) { + return member.parameters; + } + } + break; } + return ts.emptyArray; } - formatting.getIndentationString = getIndentationString; - })(formatting = ts.formatting || (ts.formatting = {})); + })(JsDoc = ts.JsDoc || (ts.JsDoc = {})); })(ts || (ts = {})); -/// +// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0. +// See LICENSE.txt in the project root for complete license information. +/// +/// +/// /* @internal */ var ts; (function (ts) { - var formatting; - (function (formatting) { - var SmartIndenter; - (function (SmartIndenter) { - var Value; - (function (Value) { - Value[Value["Unknown"] = -1] = "Unknown"; - })(Value || (Value = {})); - function getIndentation(position, sourceFile, options) { - if (position > sourceFile.text.length) { - return getBaseIndentation(options); // past EOF - } - // no indentation when the indent style is set to none, - // so we can return fast - if (options.IndentStyle === ts.IndentStyle.None) { - return 0; - } - var precedingToken = ts.findPrecedingToken(position, sourceFile); - if (!precedingToken) { - return getBaseIndentation(options); + var JsTyping; + (function (JsTyping) { + ; + ; + // A map of loose file names to library names + // that we are confident require typings + var safeList; + var EmptySafeList = ts.createMap(); + /** + * @param host is the object providing I/O related operations. + * @param fileNames are the file names that belong to the same project + * @param projectRootPath is the path to the project root directory + * @param safeListPath is the path used to retrieve the safe list + * @param packageNameToTypingLocation is the map of package names to their cached typing locations + * @param typingOptions are used to customize the typing inference process + * @param compilerOptions are used as a source for typing inference + */ + function discoverTypings(host, fileNames, projectRootPath, safeListPath, packageNameToTypingLocation, typingOptions, compilerOptions) { + // A typing name to typing file path mapping + var inferredTypings = ts.createMap(); + if (!typingOptions || !typingOptions.enableAutoDiscovery) { + return { cachedTypingPaths: [], newTypingNames: [], filesToWatch: [] }; + } + // Only infer typings for .js and .jsx files + fileNames = ts.filter(ts.map(fileNames, ts.normalizePath), function (f) { + var kind = ts.ensureScriptKind(f, ts.getScriptKindFromFileName(f)); + return kind === 1 /* JS */ || kind === 2 /* JSX */; + }); + if (!safeList) { + var result = ts.readConfigFile(safeListPath, function (path) { return host.readFile(path); }); + safeList = result.config ? ts.createMap(result.config) : EmptySafeList; + } + var filesToWatch = []; + // Directories to search for package.json, bower.json and other typing information + var searchDirs = []; + var exclude = []; + mergeTypings(typingOptions.include); + exclude = typingOptions.exclude || []; + var possibleSearchDirs = ts.map(fileNames, ts.getDirectoryPath); + if (projectRootPath !== undefined) { + possibleSearchDirs.push(projectRootPath); + } + searchDirs = ts.deduplicate(possibleSearchDirs); + for (var _i = 0, searchDirs_1 = searchDirs; _i < searchDirs_1.length; _i++) { + var searchDir = searchDirs_1[_i]; + var packageJsonPath = ts.combinePaths(searchDir, "package.json"); + getTypingNamesFromJson(packageJsonPath, filesToWatch); + var bowerJsonPath = ts.combinePaths(searchDir, "bower.json"); + getTypingNamesFromJson(bowerJsonPath, filesToWatch); + var nodeModulesPath = ts.combinePaths(searchDir, "node_modules"); + getTypingNamesFromNodeModuleFolder(nodeModulesPath); + } + getTypingNamesFromSourceFileNames(fileNames); + // Add the cached typing locations for inferred typings that are already installed + for (var name_51 in packageNameToTypingLocation) { + if (name_51 in inferredTypings && !inferredTypings[name_51]) { + inferredTypings[name_51] = packageNameToTypingLocation[name_51]; } - // no indentation in string \regex\template literals - var precedingTokenIsLiteral = ts.isStringOrRegularExpressionOrTemplateLiteral(precedingToken.kind); - if (precedingTokenIsLiteral && precedingToken.getStart(sourceFile) <= position && precedingToken.end > position) { - return 0; + } + // Remove typings that the user has added to the exclude list + for (var _a = 0, exclude_1 = exclude; _a < exclude_1.length; _a++) { + var excludeTypingName = exclude_1[_a]; + delete inferredTypings[excludeTypingName]; + } + var newTypingNames = []; + var cachedTypingPaths = []; + for (var typing in inferredTypings) { + if (inferredTypings[typing] !== undefined) { + cachedTypingPaths.push(inferredTypings[typing]); } - var lineAtPosition = sourceFile.getLineAndCharacterOfPosition(position).line; - // indentation is first non-whitespace character in a previous line - // for block indentation, we should look for a line which contains something that's not - // whitespace. - if (options.IndentStyle === ts.IndentStyle.Block) { - // move backwards until we find a line with a non-whitespace character, - // then find the first non-whitespace character for that line. - var current_1 = position; - while (current_1 > 0) { - var char = sourceFile.text.charCodeAt(current_1); - if (!ts.isWhiteSpace(char)) { - break; - } - current_1--; - } - var lineStart = ts.getLineStartPositionForPosition(current_1, sourceFile); - return SmartIndenter.findFirstNonWhitespaceColumn(lineStart, current_1, sourceFile, options); + else { + newTypingNames.push(typing); } - if (precedingToken.kind === 24 /* CommaToken */ && precedingToken.parent.kind !== 187 /* BinaryExpression */) { - // previous token is comma that separates items in list - find the previous item and try to derive indentation from it - var actualIndentation = getActualIndentationForListItemBeforeComma(precedingToken, sourceFile, options); - if (actualIndentation !== -1 /* Unknown */) { - return actualIndentation; - } + } + return { cachedTypingPaths: cachedTypingPaths, newTypingNames: newTypingNames, filesToWatch: filesToWatch }; + /** + * Merge a given list of typingNames to the inferredTypings map + */ + function mergeTypings(typingNames) { + if (!typingNames) { + return; } - // try to find node that can contribute to indentation and includes 'position' starting from 'precedingToken' - // if such node is found - compute initial indentation for 'position' inside this node - var previous; - var current = precedingToken; - var currentStart; - var indentationDelta; - while (current) { - if (ts.positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(current, previous)) { - currentStart = getStartLineAndCharacterForNode(current, sourceFile); - if (nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile)) { - indentationDelta = 0; - } - else { - indentationDelta = lineAtPosition !== currentStart.line ? options.IndentSize : 0; - } - break; - } - // check if current node is a list item - if yes, take indentation from it - var actualIndentation = getActualIndentationForListItem(current, sourceFile, options); - if (actualIndentation !== -1 /* Unknown */) { - return actualIndentation; - } - actualIndentation = getLineIndentationWhenExpressionIsInMultiLine(current, sourceFile, options); - if (actualIndentation !== -1 /* Unknown */) { - return actualIndentation + options.IndentSize; + for (var _i = 0, typingNames_1 = typingNames; _i < typingNames_1.length; _i++) { + var typing = typingNames_1[_i]; + if (!(typing in inferredTypings)) { + inferredTypings[typing] = undefined; } - previous = current; - current = current.parent; - } - if (!current) { - // no parent was found - return the base indentation of the SourceFile - return getBaseIndentation(options); } - return getIndentationForNodeWorker(current, currentStart, /*ignoreActualIndentationRange*/ undefined, indentationDelta, sourceFile, options); - } - SmartIndenter.getIndentation = getIndentation; - function getBaseIndentation(options) { - return options.BaseIndentSize || 0; - } - SmartIndenter.getBaseIndentation = getBaseIndentation; - function getIndentationForNode(n, ignoreActualIndentationRange, sourceFile, options) { - var start = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)); - return getIndentationForNodeWorker(n, start, ignoreActualIndentationRange, /*indentationDelta*/ 0, sourceFile, options); } - SmartIndenter.getIndentationForNode = getIndentationForNode; - function getIndentationForNodeWorker(current, currentStart, ignoreActualIndentationRange, indentationDelta, sourceFile, options) { - var parent = current.parent; - var parentStart; - // walk upwards and collect indentations for pairs of parent-child nodes - // indentation is not added if parent and child nodes start on the same line or if parent is IfStatement and child starts on the same line with 'else clause' - while (parent) { - var useActualIndentation = true; - if (ignoreActualIndentationRange) { - var start = current.getStart(sourceFile); - useActualIndentation = start < ignoreActualIndentationRange.pos || start > ignoreActualIndentationRange.end; + /** + * Get the typing info from common package manager json files like package.json or bower.json + */ + function getTypingNamesFromJson(jsonPath, filesToWatch) { + var result = ts.readConfigFile(jsonPath, function (path) { return host.readFile(path); }); + if (result.config) { + var jsonConfig = result.config; + filesToWatch.push(jsonPath); + if (jsonConfig.dependencies) { + mergeTypings(ts.getOwnKeys(jsonConfig.dependencies)); } - if (useActualIndentation) { - // check if current node is a list item - if yes, take indentation from it - var actualIndentation = getActualIndentationForListItem(current, sourceFile, options); - if (actualIndentation !== -1 /* Unknown */) { - return actualIndentation + indentationDelta; - } + if (jsonConfig.devDependencies) { + mergeTypings(ts.getOwnKeys(jsonConfig.devDependencies)); } - parentStart = getParentStart(parent, current, sourceFile); - var parentAndChildShareLine = parentStart.line === currentStart.line || - childStartsOnTheSameLineWithElseInIfStatement(parent, current, currentStart.line, sourceFile); - if (useActualIndentation) { - // try to fetch actual indentation for current node from source text - var actualIndentation = getActualIndentationForNode(current, parent, currentStart, parentAndChildShareLine, sourceFile, options); - if (actualIndentation !== -1 /* Unknown */) { - return actualIndentation + indentationDelta; - } - actualIndentation = getLineIndentationWhenExpressionIsInMultiLine(current, sourceFile, options); - if (actualIndentation !== -1 /* Unknown */) { - return actualIndentation + indentationDelta; - } + if (jsonConfig.optionalDependencies) { + mergeTypings(ts.getOwnKeys(jsonConfig.optionalDependencies)); } - // increase indentation if parent node wants its content to be indented and parent and child nodes don't start on the same line - if (shouldIndentChildNode(parent, current) && !parentAndChildShareLine) { - indentationDelta += options.IndentSize; + if (jsonConfig.peerDependencies) { + mergeTypings(ts.getOwnKeys(jsonConfig.peerDependencies)); } - current = parent; - currentStart = parentStart; - parent = current.parent; - } - return indentationDelta + getBaseIndentation(options); - } - function getParentStart(parent, child, sourceFile) { - var containingList = getContainingList(child, sourceFile); - if (containingList) { - return sourceFile.getLineAndCharacterOfPosition(containingList.pos); } - return sourceFile.getLineAndCharacterOfPosition(parent.getStart(sourceFile)); } - /* - * Function returns Value.Unknown if indentation cannot be determined + /** + * Infer typing names from given file names. For example, the file name "jquery-min.2.3.4.js" + * should be inferred to the 'jquery' typing name; and "angular-route.1.2.3.js" should be inferred + * to the 'angular-route' typing name. + * @param fileNames are the names for source files in the project */ - function getActualIndentationForListItemBeforeComma(commaToken, sourceFile, options) { - // previous token is comma that separates items in list - find the previous item and try to derive indentation from it - var commaItemInfo = ts.findListItemInfo(commaToken); - if (commaItemInfo && commaItemInfo.listItemIndex > 0) { - return deriveActualIndentationFromList(commaItemInfo.list.getChildren(), commaItemInfo.listItemIndex - 1, sourceFile, options); + function getTypingNamesFromSourceFileNames(fileNames) { + var jsFileNames = ts.filter(fileNames, ts.hasJavaScriptFileExtension); + var inferredTypingNames = ts.map(jsFileNames, function (f) { return ts.removeFileExtension(ts.getBaseFileName(f.toLowerCase())); }); + var cleanedTypingNames = ts.map(inferredTypingNames, function (f) { return f.replace(/((?:\.|-)min(?=\.|$))|((?:-|\.)\d+)/g, ""); }); + if (safeList !== EmptySafeList) { + mergeTypings(ts.filter(cleanedTypingNames, function (f) { return f in safeList; })); } - else { - // handle broken code gracefully - return -1 /* Unknown */; + var hasJsxFile = ts.forEach(fileNames, function (f) { return ts.ensureScriptKind(f, ts.getScriptKindFromFileName(f)) === 2 /* JSX */; }); + if (hasJsxFile) { + mergeTypings(["react"]); } } - /* - * Function returns Value.Unknown if actual indentation for node should not be used (i.e because node is nested expression) + /** + * Infer typing names from node_module folder + * @param nodeModulesPath is the path to the "node_modules" folder */ - function getActualIndentationForNode(current, parent, currentLineAndChar, parentAndChildShareLine, sourceFile, options) { - // actual indentation is used for statements\declarations if one of cases below is true: - // - parent is SourceFile - by default immediate children of SourceFile are not indented except when user indents them manually - // - parent and child are not on the same line - var useActualIndentation = (ts.isDeclaration(current) || ts.isStatement(current)) && - (parent.kind === 256 /* SourceFile */ || !parentAndChildShareLine); - if (!useActualIndentation) { - return -1 /* Unknown */; - } - return findColumnForFirstNonWhitespaceCharacterInLine(currentLineAndChar, sourceFile, options); - } - function nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile) { - var nextToken = ts.findNextToken(precedingToken, current); - if (!nextToken) { - return false; - } - if (nextToken.kind === 15 /* OpenBraceToken */) { - // open braces are always indented at the parent level - return true; + function getTypingNamesFromNodeModuleFolder(nodeModulesPath) { + // Todo: add support for ModuleResolutionHost too + if (!host.directoryExists(nodeModulesPath)) { + return; } - else if (nextToken.kind === 16 /* CloseBraceToken */) { - // close braces are indented at the parent level if they are located on the same line with cursor - // this means that if new line will be added at $ position, this case will be indented - // class A { - // $ - // } - /// and this one - not - // class A { - // $} - var nextTokenStartLine = getStartLineAndCharacterForNode(nextToken, sourceFile).line; - return lineAtPosition === nextTokenStartLine; + var typingNames = []; + var fileNames = host.readDirectory(nodeModulesPath, [".json"], /*excludes*/ undefined, /*includes*/ undefined, /*depth*/ 2); + for (var _i = 0, fileNames_2 = fileNames; _i < fileNames_2.length; _i++) { + var fileName = fileNames_2[_i]; + var normalizedFileName = ts.normalizePath(fileName); + if (ts.getBaseFileName(normalizedFileName) !== "package.json") { + continue; + } + var result = ts.readConfigFile(normalizedFileName, function (path) { return host.readFile(path); }); + if (!result.config) { + continue; + } + var packageJson = result.config; + // npm 3's package.json contains a "_requiredBy" field + // we should include all the top level module names for npm 2, and only module names whose + // "_requiredBy" field starts with "#" or equals "/" for npm 3. + if (packageJson._requiredBy && + ts.filter(packageJson._requiredBy, function (r) { return r[0] === "#" || r === "/"; }).length === 0) { + continue; + } + // If the package has its own d.ts typings, those will take precedence. Otherwise the package name will be used + // to download d.ts files from DefinitelyTyped + if (!packageJson.name) { + continue; + } + if (packageJson.typings) { + var absolutePath = ts.getNormalizedAbsolutePath(packageJson.typings, ts.getDirectoryPath(normalizedFileName)); + inferredTypings[packageJson.name] = absolutePath; + } + else { + typingNames.push(packageJson.name); + } } - return false; - } - function getStartLineAndCharacterForNode(n, sourceFile) { - return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)); + mergeTypings(typingNames); } - function childStartsOnTheSameLineWithElseInIfStatement(parent, child, childStartLine, sourceFile) { - if (parent.kind === 203 /* IfStatement */ && parent.elseStatement === child) { - var elseKeyword = ts.findChildOfKind(parent, 80 /* ElseKeyword */, sourceFile); - ts.Debug.assert(elseKeyword !== undefined); - var elseKeywordStartLine = getStartLineAndCharacterForNode(elseKeyword, sourceFile).line; - return elseKeywordStartLine === childStartLine; + } + JsTyping.discoverTypings = discoverTypings; + })(JsTyping = ts.JsTyping || (ts.JsTyping = {})); +})(ts || (ts = {})); +/* @internal */ +var ts; +(function (ts) { + var NavigateTo; + (function (NavigateTo) { + function getNavigateToItems(sourceFiles, checker, cancellationToken, searchValue, maxResultCount, excludeDtsFiles) { + var patternMatcher = ts.createPatternMatcher(searchValue); + var rawItems = []; + // This means "compare in a case insensitive manner." + var baseSensitivity = { sensitivity: "base" }; + // Search the declarations in all files and output matched NavigateToItem into array of NavigateToItem[] + ts.forEach(sourceFiles, function (sourceFile) { + cancellationToken.throwIfCancellationRequested(); + if (excludeDtsFiles && ts.fileExtensionIs(sourceFile.fileName, ".d.ts")) { + return; } - return false; - } - SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement = childStartsOnTheSameLineWithElseInIfStatement; - function getContainingList(node, sourceFile) { - if (node.parent) { - switch (node.parent.kind) { - case 155 /* TypeReference */: - if (node.parent.typeArguments && - ts.rangeContainsStartEnd(node.parent.typeArguments, node.getStart(sourceFile), node.getEnd())) { - return node.parent.typeArguments; - } - break; - case 171 /* ObjectLiteralExpression */: - return node.parent.properties; - case 170 /* ArrayLiteralExpression */: - return node.parent.elements; - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - case 180 /* ArrowFunction */: - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - case 151 /* CallSignature */: - case 152 /* ConstructSignature */: { - var start = node.getStart(sourceFile); - if (node.parent.typeParameters && - ts.rangeContainsStartEnd(node.parent.typeParameters, start, node.getEnd())) { - return node.parent.typeParameters; - } - if (ts.rangeContainsStartEnd(node.parent.parameters, start, node.getEnd())) { - return node.parent.parameters; - } - break; + var nameToDeclarations = sourceFile.getNamedDeclarations(); + for (var name_52 in nameToDeclarations) { + var declarations = nameToDeclarations[name_52]; + if (declarations) { + // First do a quick check to see if the name of the declaration matches the + // last portion of the (possibly) dotted name they're searching for. + var matches = patternMatcher.getMatchesForLastSegmentOfPattern(name_52); + if (!matches) { + continue; } - case 175 /* NewExpression */: - case 174 /* CallExpression */: { - var start = node.getStart(sourceFile); - if (node.parent.typeArguments && - ts.rangeContainsStartEnd(node.parent.typeArguments, start, node.getEnd())) { - return node.parent.typeArguments; - } - if (node.parent.arguments && - ts.rangeContainsStartEnd(node.parent.arguments, start, node.getEnd())) { - return node.parent.arguments; + for (var _i = 0, declarations_9 = declarations; _i < declarations_9.length; _i++) { + var declaration = declarations_9[_i]; + // It was a match! If the pattern has dots in it, then also see if the + // declaration container matches as well. + if (patternMatcher.patternContainsDots) { + var containers = getContainers(declaration); + if (!containers) { + return undefined; + } + matches = patternMatcher.getMatches(containers, name_52); + if (!matches) { + continue; + } } - break; + var fileName = sourceFile.fileName; + var matchKind = bestMatchKind(matches); + rawItems.push({ name: name_52, fileName: fileName, matchKind: matchKind, isCaseSensitive: allMatchesAreCaseSensitive(matches), declaration: declaration }); } } } - return undefined; - } - function getActualIndentationForListItem(node, sourceFile, options) { - var containingList = getContainingList(node, sourceFile); - return containingList ? getActualIndentationFromList(containingList) : -1 /* Unknown */; - function getActualIndentationFromList(list) { - var index = ts.indexOf(list, node); - return index !== -1 ? deriveActualIndentationFromList(list, index, sourceFile, options) : -1 /* Unknown */; - } - } - function getLineIndentationWhenExpressionIsInMultiLine(node, sourceFile, options) { - // actual indentation should not be used when: - // - node is close parenthesis - this is the end of the expression - if (node.kind === 18 /* CloseParenToken */) { - return -1 /* Unknown */; - } - if (node.parent && (node.parent.kind === 174 /* CallExpression */ || - node.parent.kind === 175 /* NewExpression */) && - node.parent.expression !== node) { - var fullCallOrNewExpression = node.parent.expression; - var startingExpression = getStartingExpression(fullCallOrNewExpression); - if (fullCallOrNewExpression === startingExpression) { - return -1 /* Unknown */; - } - var fullCallOrNewExpressionEnd = sourceFile.getLineAndCharacterOfPosition(fullCallOrNewExpression.end); - var startingExpressionEnd = sourceFile.getLineAndCharacterOfPosition(startingExpression.end); - if (fullCallOrNewExpressionEnd.line === startingExpressionEnd.line) { - return -1 /* Unknown */; - } - return findColumnForFirstNonWhitespaceCharacterInLine(fullCallOrNewExpressionEnd, sourceFile, options); + }); + // Remove imports when the imported declaration is already in the list and has the same name. + rawItems = ts.filter(rawItems, function (item) { + var decl = item.declaration; + if (decl.kind === 231 /* ImportClause */ || decl.kind === 234 /* ImportSpecifier */ || decl.kind === 229 /* ImportEqualsDeclaration */) { + var importer = checker.getSymbolAtLocation(decl.name); + var imported = checker.getAliasedSymbol(importer); + return importer.name !== imported.name; } - return -1 /* Unknown */; - function getStartingExpression(node) { - while (true) { - switch (node.kind) { - case 174 /* CallExpression */: - case 175 /* NewExpression */: - case 172 /* PropertyAccessExpression */: - case 173 /* ElementAccessExpression */: - node = node.expression; - break; - default: - return node; - } - } + else { + return true; } + }); + rawItems.sort(compareNavigateToItems); + if (maxResultCount !== undefined) { + rawItems = rawItems.slice(0, maxResultCount); } - function deriveActualIndentationFromList(list, index, sourceFile, options) { - ts.Debug.assert(index >= 0 && index < list.length); - var node = list[index]; - // walk toward the start of the list starting from current node and check if the line is the same for all items. - // if end line for item [i - 1] differs from the start line for item [i] - find column of the first non-whitespace character on the line of item [i] - var lineAndCharacter = getStartLineAndCharacterForNode(node, sourceFile); - for (var i = index - 1; i >= 0; i--) { - if (list[i].kind === 24 /* CommaToken */) { - continue; - } - // skip list items that ends on the same line with the current list element - var prevEndLine = sourceFile.getLineAndCharacterOfPosition(list[i].end).line; - if (prevEndLine !== lineAndCharacter.line) { - return findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options); + var items = ts.map(rawItems, createNavigateToItem); + return items; + function allMatchesAreCaseSensitive(matches) { + ts.Debug.assert(matches.length > 0); + // This is a case sensitive match, only if all the submatches were case sensitive. + for (var _i = 0, matches_2 = matches; _i < matches_2.length; _i++) { + var match = matches_2[_i]; + if (!match.isCaseSensitive) { + return false; } - lineAndCharacter = getStartLineAndCharacterForNode(list[i], sourceFile); } - return -1 /* Unknown */; + return true; } - function findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options) { - var lineStart = sourceFile.getPositionOfLineAndCharacter(lineAndCharacter.line, 0); - return findFirstNonWhitespaceColumn(lineStart, lineStart + lineAndCharacter.character, sourceFile, options); + function getTextOfIdentifierOrLiteral(node) { + if (node) { + if (node.kind === 69 /* Identifier */ || + node.kind === 9 /* StringLiteral */ || + node.kind === 8 /* NumericLiteral */) { + return node.text; + } + } + return undefined; } - /* - Character is the actual index of the character since the beginning of the line. - Column - position of the character after expanding tabs to spaces - "0\t2$" - value of 'character' for '$' is 3 - value of 'column' for '$' is 6 (assuming that tab size is 4) - */ - function findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options) { - var character = 0; - var column = 0; - for (var pos = startPos; pos < endPos; pos++) { - var ch = sourceFile.text.charCodeAt(pos); - if (!ts.isWhiteSpaceSingleLine(ch)) { - break; + function tryAddSingleDeclarationName(declaration, containers) { + if (declaration && declaration.name) { + var text = getTextOfIdentifierOrLiteral(declaration.name); + if (text !== undefined) { + containers.unshift(text); } - if (ch === 9 /* tab */) { - column += options.TabSize + (column % options.TabSize); + else if (declaration.name.kind === 140 /* ComputedPropertyName */) { + return tryAddComputedPropertyName(declaration.name.expression, containers, /*includeLastPortion*/ true); } else { - column++; + // Don't know how to add this. + return false; } - character++; } - return { column: column, character: character }; - } - SmartIndenter.findFirstNonWhitespaceCharacterAndColumn = findFirstNonWhitespaceCharacterAndColumn; - function findFirstNonWhitespaceColumn(startPos, endPos, sourceFile, options) { - return findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options).column; + return true; } - SmartIndenter.findFirstNonWhitespaceColumn = findFirstNonWhitespaceColumn; - function nodeContentIsAlwaysIndented(kind) { - switch (kind) { - case 202 /* ExpressionStatement */: - case 221 /* ClassDeclaration */: - case 192 /* ClassExpression */: - case 222 /* InterfaceDeclaration */: - case 224 /* EnumDeclaration */: - case 223 /* TypeAliasDeclaration */: - case 170 /* ArrayLiteralExpression */: - case 199 /* Block */: - case 226 /* ModuleBlock */: - case 171 /* ObjectLiteralExpression */: - case 159 /* TypeLiteral */: - case 161 /* TupleType */: - case 227 /* CaseBlock */: - case 250 /* DefaultClause */: - case 249 /* CaseClause */: - case 178 /* ParenthesizedExpression */: - case 172 /* PropertyAccessExpression */: - case 174 /* CallExpression */: - case 175 /* NewExpression */: - case 200 /* VariableStatement */: - case 218 /* VariableDeclaration */: - case 235 /* ExportAssignment */: - case 211 /* ReturnStatement */: - case 188 /* ConditionalExpression */: - case 168 /* ArrayBindingPattern */: - case 167 /* ObjectBindingPattern */: - case 243 /* JsxOpeningElement */: - case 242 /* JsxSelfClosingElement */: - case 248 /* JsxExpression */: - case 146 /* MethodSignature */: - case 151 /* CallSignature */: - case 152 /* ConstructSignature */: - case 142 /* Parameter */: - case 156 /* FunctionType */: - case 157 /* ConstructorType */: - case 164 /* ParenthesizedType */: - case 176 /* TaggedTemplateExpression */: - case 184 /* AwaitExpression */: - case 237 /* NamedExports */: - case 233 /* NamedImports */: - case 238 /* ExportSpecifier */: - case 234 /* ImportSpecifier */: - return true; + // Only added the names of computed properties if they're simple dotted expressions, like: + // + // [X.Y.Z]() { } + function tryAddComputedPropertyName(expression, containers, includeLastPortion) { + var text = getTextOfIdentifierOrLiteral(expression); + if (text !== undefined) { + if (includeLastPortion) { + containers.unshift(text); + } + return true; + } + if (expression.kind === 172 /* PropertyAccessExpression */) { + var propertyAccess = expression; + if (includeLastPortion) { + containers.unshift(propertyAccess.name.text); + } + return tryAddComputedPropertyName(propertyAccess.expression, containers, /*includeLastPortion*/ true); } return false; } - /* @internal */ - function nodeWillIndentChild(parent, child, indentByDefault) { - var childKind = child ? child.kind : 0 /* Unknown */; - switch (parent.kind) { - case 204 /* DoStatement */: - case 205 /* WhileStatement */: - case 207 /* ForInStatement */: - case 208 /* ForOfStatement */: - case 206 /* ForStatement */: - case 203 /* IfStatement */: - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - case 147 /* MethodDeclaration */: - case 180 /* ArrowFunction */: - case 148 /* Constructor */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - return childKind !== 199 /* Block */; - case 236 /* ExportDeclaration */: - return childKind !== 237 /* NamedExports */; - case 230 /* ImportDeclaration */: - return childKind !== 231 /* ImportClause */ || - (child.namedBindings && child.namedBindings.kind !== 233 /* NamedImports */); - case 241 /* JsxElement */: - return childKind !== 245 /* JsxClosingElement */; + function getContainers(declaration) { + var containers = []; + // First, if we started with a computed property name, then add all but the last + // portion into the container array. + if (declaration.name.kind === 140 /* ComputedPropertyName */) { + if (!tryAddComputedPropertyName(declaration.name.expression, containers, /*includeLastPortion*/ false)) { + return undefined; + } } - // No explicit rule for given nodes so the result will follow the default value argument - return indentByDefault; - } - SmartIndenter.nodeWillIndentChild = nodeWillIndentChild; - /* - Function returns true when the parent node should indent the given child by an explicit rule - */ - function shouldIndentChildNode(parent, child) { - return nodeContentIsAlwaysIndented(parent.kind) || nodeWillIndentChild(parent, child, /*indentByDefault*/ false); - } - SmartIndenter.shouldIndentChildNode = shouldIndentChildNode; - })(SmartIndenter = formatting.SmartIndenter || (formatting.SmartIndenter = {})); - })(formatting = ts.formatting || (ts.formatting = {})); -})(ts || (ts = {})); -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -var ts; -(function (ts) { - /** The version of the language service API */ - ts.servicesVersion = "0.5"; - var scanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ true); - var emptyArray = []; - var jsDocTagNames = [ - "augments", - "author", - "argument", - "borrows", - "class", - "constant", - "constructor", - "constructs", - "default", - "deprecated", - "description", - "event", - "example", - "extends", - "field", - "fileOverview", - "function", - "ignore", - "inner", - "lends", - "link", - "memberOf", - "name", - "namespace", - "param", - "private", - "property", - "public", - "requires", - "returns", - "see", - "since", - "static", - "throws", - "type", - "typedef", - "property", - "prop", - "version" - ]; - var jsDocCompletionEntries; - function createNode(kind, pos, end, parent) { - var node = kind >= 139 /* FirstNode */ ? new NodeObject(kind, pos, end) : - kind === 69 /* Identifier */ ? new IdentifierObject(kind, pos, end) : - new TokenObject(kind, pos, end); - node.parent = parent; - return node; - } - var NodeObject = (function () { - function NodeObject(kind, pos, end) { - this.pos = pos; - this.end = end; - this.flags = 0 /* None */; - this.parent = undefined; - this.kind = kind; - } - NodeObject.prototype.getSourceFile = function () { - return ts.getSourceFileOfNode(this); - }; - NodeObject.prototype.getStart = function (sourceFile, includeJsDocComment) { - return ts.getTokenPosOfNode(this, sourceFile, includeJsDocComment); - }; - NodeObject.prototype.getFullStart = function () { - return this.pos; - }; - NodeObject.prototype.getEnd = function () { - return this.end; - }; - NodeObject.prototype.getWidth = function (sourceFile) { - return this.getEnd() - this.getStart(sourceFile); - }; - NodeObject.prototype.getFullWidth = function () { - return this.end - this.pos; - }; - NodeObject.prototype.getLeadingTriviaWidth = function (sourceFile) { - return this.getStart(sourceFile) - this.pos; - }; - NodeObject.prototype.getFullText = function (sourceFile) { - return (sourceFile || this.getSourceFile()).text.substring(this.pos, this.end); - }; - NodeObject.prototype.getText = function (sourceFile) { - return (sourceFile || this.getSourceFile()).text.substring(this.getStart(), this.getEnd()); - }; - NodeObject.prototype.addSyntheticNodes = function (nodes, pos, end, useJSDocScanner) { - scanner.setTextPos(pos); - while (pos < end) { - var token = useJSDocScanner ? scanner.scanJSDocToken() : scanner.scan(); - var textPos = scanner.getTextPos(); - if (textPos <= end) { - nodes.push(createNode(token, pos, textPos, this)); + // Now, walk up our containers, adding all their names to the container array. + declaration = ts.getContainerNode(declaration); + while (declaration) { + if (!tryAddSingleDeclarationName(declaration, containers)) { + return undefined; + } + declaration = ts.getContainerNode(declaration); } - pos = textPos; + return containers; } - return pos; - }; - NodeObject.prototype.createSyntaxList = function (nodes) { - var list = createNode(286 /* SyntaxList */, nodes.pos, nodes.end, this); - list._children = []; - var pos = nodes.pos; - for (var _i = 0, nodes_4 = nodes; _i < nodes_4.length; _i++) { - var node = nodes_4[_i]; - if (pos < node.pos) { - pos = this.addSyntheticNodes(list._children, pos, node.pos); + function bestMatchKind(matches) { + ts.Debug.assert(matches.length > 0); + var bestMatchKind = ts.PatternMatchKind.camelCase; + for (var _i = 0, matches_3 = matches; _i < matches_3.length; _i++) { + var match = matches_3[_i]; + var kind = match.kind; + if (kind < bestMatchKind) { + bestMatchKind = kind; + } } - list._children.push(node); - pos = node.end; + return bestMatchKind; } - if (pos < nodes.end) { - this.addSyntheticNodes(list._children, pos, nodes.end); + function compareNavigateToItems(i1, i2) { + // TODO(cyrusn): get the gamut of comparisons that VS already uses here. + // Right now we just sort by kind first, and then by name of the item. + // We first sort case insensitively. So "Aaa" will come before "bar". + // Then we sort case sensitively, so "aaa" will come before "Aaa". + return i1.matchKind - i2.matchKind || + i1.name.localeCompare(i2.name, undefined, baseSensitivity) || + i1.name.localeCompare(i2.name); } - return list; - }; - NodeObject.prototype.createChildren = function (sourceFile) { - var _this = this; - var children; - if (this.kind >= 139 /* FirstNode */) { - scanner.setText((sourceFile || this.getSourceFile()).text); - children = []; - var pos_3 = this.pos; - var useJSDocScanner_1 = this.kind >= 273 /* FirstJSDocTagNode */ && this.kind <= 285 /* LastJSDocTagNode */; - var processNode = function (node) { - var isJSDocTagNode = ts.isJSDocTag(node); - if (!isJSDocTagNode && pos_3 < node.pos) { - pos_3 = _this.addSyntheticNodes(children, pos_3, node.pos, useJSDocScanner_1); - } - children.push(node); - if (!isJSDocTagNode) { - pos_3 = node.end; - } - }; - var processNodes = function (nodes) { - if (pos_3 < nodes.pos) { - pos_3 = _this.addSyntheticNodes(children, pos_3, nodes.pos, useJSDocScanner_1); - } - children.push(_this.createSyntaxList(nodes)); - pos_3 = nodes.end; + function createNavigateToItem(rawItem) { + var declaration = rawItem.declaration; + var container = ts.getContainerNode(declaration); + return { + name: rawItem.name, + kind: ts.getNodeKind(declaration), + kindModifiers: ts.getNodeModifiers(declaration), + matchKind: ts.PatternMatchKind[rawItem.matchKind], + isCaseSensitive: rawItem.isCaseSensitive, + fileName: rawItem.fileName, + textSpan: ts.createTextSpanFromBounds(declaration.getStart(), declaration.getEnd()), + // TODO(jfreeman): What should be the containerName when the container has a computed name? + containerName: container && container.name ? container.name.text : "", + containerKind: container && container.name ? ts.getNodeKind(container) : "" }; - // jsDocComments need to be the first children - if (this.jsDocComments) { - for (var _i = 0, _a = this.jsDocComments; _i < _a.length; _i++) { - var jsDocComment = _a[_i]; - processNode(jsDocComment); - } - } - ts.forEachChild(this, processNode, processNodes); - if (pos_3 < this.end) { - this.addSyntheticNodes(children, pos_3, this.end); - } - scanner.setText(undefined); } - this._children = children || emptyArray; - }; - NodeObject.prototype.getChildCount = function (sourceFile) { - if (!this._children) - this.createChildren(sourceFile); - return this._children.length; - }; - NodeObject.prototype.getChildAt = function (index, sourceFile) { - if (!this._children) - this.createChildren(sourceFile); - return this._children[index]; - }; - NodeObject.prototype.getChildren = function (sourceFile) { - if (!this._children) - this.createChildren(sourceFile); - return this._children; - }; - NodeObject.prototype.getFirstToken = function (sourceFile) { - var children = this.getChildren(sourceFile); - if (!children.length) { - return undefined; + } + NavigateTo.getNavigateToItems = getNavigateToItems; + })(NavigateTo = ts.NavigateTo || (ts.NavigateTo = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var NavigationBar; + (function (NavigationBar) { + function getNavigationBarItems(sourceFile) { + curSourceFile = sourceFile; + var result = ts.map(topLevelItems(rootNavigationBarNode(sourceFile)), convertToTopLevelItem); + curSourceFile = undefined; + return result; + } + NavigationBar.getNavigationBarItems = getNavigationBarItems; + // Keep sourceFile handy so we don't have to search for it every time we need to call `getText`. + var curSourceFile; + function nodeText(node) { + return node.getText(curSourceFile); + } + function navigationBarNodeKind(n) { + return n.node.kind; + } + function pushChild(parent, child) { + if (parent.children) { + parent.children.push(child); } - var child = children[0]; - return child.kind < 139 /* FirstNode */ ? child : child.getFirstToken(sourceFile); - }; - NodeObject.prototype.getLastToken = function (sourceFile) { - var children = this.getChildren(sourceFile); - var child = ts.lastOrUndefined(children); - if (!child) { - return undefined; + else { + parent.children = [child]; } - return child.kind < 139 /* FirstNode */ ? child : child.getLastToken(sourceFile); - }; - return NodeObject; - }()); - var TokenOrIdentifierObject = (function () { - function TokenOrIdentifierObject(pos, end) { - // Set properties in same order as NodeObject - this.pos = pos; - this.end = end; - this.flags = 0 /* None */; - this.parent = undefined; } - TokenOrIdentifierObject.prototype.getSourceFile = function () { - return ts.getSourceFileOfNode(this); - }; - TokenOrIdentifierObject.prototype.getStart = function (sourceFile, includeJsDocComment) { - return ts.getTokenPosOfNode(this, sourceFile, includeJsDocComment); - }; - TokenOrIdentifierObject.prototype.getFullStart = function () { - return this.pos; - }; - TokenOrIdentifierObject.prototype.getEnd = function () { - return this.end; - }; - TokenOrIdentifierObject.prototype.getWidth = function (sourceFile) { - return this.getEnd() - this.getStart(sourceFile); - }; - TokenOrIdentifierObject.prototype.getFullWidth = function () { - return this.end - this.pos; - }; - TokenOrIdentifierObject.prototype.getLeadingTriviaWidth = function (sourceFile) { - return this.getStart(sourceFile) - this.pos; - }; - TokenOrIdentifierObject.prototype.getFullText = function (sourceFile) { - return (sourceFile || this.getSourceFile()).text.substring(this.pos, this.end); - }; - TokenOrIdentifierObject.prototype.getText = function (sourceFile) { - return (sourceFile || this.getSourceFile()).text.substring(this.getStart(), this.getEnd()); - }; - TokenOrIdentifierObject.prototype.getChildCount = function (sourceFile) { - return 0; - }; - TokenOrIdentifierObject.prototype.getChildAt = function (index, sourceFile) { - return undefined; - }; - TokenOrIdentifierObject.prototype.getChildren = function (sourceFile) { - return emptyArray; - }; - TokenOrIdentifierObject.prototype.getFirstToken = function (sourceFile) { - return undefined; - }; - TokenOrIdentifierObject.prototype.getLastToken = function (sourceFile) { - return undefined; - }; - return TokenOrIdentifierObject; - }()); - var TokenObject = (function (_super) { - __extends(TokenObject, _super); - function TokenObject(kind, pos, end) { - _super.call(this, pos, end); - this.kind = kind; + /* + For performance, we keep navigation bar parents on a stack rather than passing them through each recursion. + `parent` is the current parent and is *not* stored in parentsStack. + `startNode` sets a new parent and `endNode` returns to the previous parent. + */ + var parentsStack = []; + var parent; + function rootNavigationBarNode(sourceFile) { + ts.Debug.assert(!parentsStack.length); + var root = { node: sourceFile, additionalNodes: undefined, parent: undefined, children: undefined, indent: 0 }; + parent = root; + for (var _i = 0, _a = sourceFile.statements; _i < _a.length; _i++) { + var statement = _a[_i]; + addChildrenRecursively(statement); + } + endNode(); + ts.Debug.assert(!parent && !parentsStack.length); + return root; } - return TokenObject; - }(TokenOrIdentifierObject)); - var IdentifierObject = (function (_super) { - __extends(IdentifierObject, _super); - function IdentifierObject(kind, pos, end) { - _super.call(this, pos, end); + function addLeafNode(node) { + pushChild(parent, emptyNavigationBarNode(node)); } - return IdentifierObject; - }(TokenOrIdentifierObject)); - IdentifierObject.prototype.kind = 69 /* Identifier */; - var SymbolObject = (function () { - function SymbolObject(flags, name) { - this.flags = flags; - this.name = name; + function emptyNavigationBarNode(node) { + return { + node: node, + additionalNodes: undefined, + parent: parent, + children: undefined, + indent: parent.indent + 1 + }; } - SymbolObject.prototype.getFlags = function () { - return this.flags; - }; - SymbolObject.prototype.getName = function () { - return this.name; - }; - SymbolObject.prototype.getDeclarations = function () { - return this.declarations; - }; - SymbolObject.prototype.getDocumentationComment = function () { - if (this.documentationComment === undefined) { - this.documentationComment = getJsDocCommentsFromDeclarations(this.declarations, this.name, !(this.flags & 4 /* Property */)); + /** + * Add a new level of NavigationBarNodes. + * This pushes to the stack, so you must call `endNode` when you are done adding to this node. + */ + function startNode(node) { + var navNode = emptyNavigationBarNode(node); + pushChild(parent, navNode); + // Save the old parent + parentsStack.push(parent); + parent = navNode; + } + /** Call after calling `startNode` and adding children to it. */ + function endNode() { + if (parent.children) { + mergeChildren(parent.children); + sortChildren(parent.children); } - return this.documentationComment; - }; - return SymbolObject; - }()); - function getJsDocCommentsFromDeclarations(declarations, name, canUseParsedParamTagComments) { - var documentationComment = []; - var docComments = getJsDocCommentsSeparatedByNewLines(); - ts.forEach(docComments, function (docComment) { - if (documentationComment.length) { - documentationComment.push(ts.lineBreakPart()); - } - documentationComment.push(docComment); - }); - return documentationComment; - function getJsDocCommentsSeparatedByNewLines() { - var paramTag = "@param"; - var jsDocCommentParts = []; - ts.forEach(declarations, function (declaration, indexOfDeclaration) { - // Make sure we are collecting doc comment from declaration once, - // In case of union property there might be same declaration multiple times - // which only varies in type parameter - // Eg. const a: Array | Array; a.length - // The property length will have two declarations of property length coming - // from Array - Array and Array - if (ts.indexOf(declarations, declaration) === indexOfDeclaration) { - var sourceFileOfDeclaration = ts.getSourceFileOfNode(declaration); - // If it is parameter - try and get the jsDoc comment with @param tag from function declaration's jsDoc comments - if (canUseParsedParamTagComments && declaration.kind === 142 /* Parameter */) { - if ((declaration.parent.kind === 179 /* FunctionExpression */ || declaration.parent.kind === 180 /* ArrowFunction */) && - declaration.parent.parent.kind === 218 /* VariableDeclaration */) { - addCommentParts(declaration.parent.parent.parent, sourceFileOfDeclaration, getCleanedParamJsDocComment); - } - addCommentParts(declaration.parent, sourceFileOfDeclaration, getCleanedParamJsDocComment); - } - // If this is left side of dotted module declaration, there is no doc comments associated with this node - if (declaration.kind === 225 /* ModuleDeclaration */ && declaration.body && declaration.body.kind === 225 /* ModuleDeclaration */) { - return; + parent = parentsStack.pop(); + } + function addNodeWithRecursiveChild(node, child) { + startNode(node); + addChildrenRecursively(child); + endNode(); + } + /** Look for navigation bar items in node's subtree, adding them to the current `parent`. */ + function addChildrenRecursively(node) { + if (!node || ts.isToken(node)) { + return; + } + switch (node.kind) { + case 148 /* Constructor */: + // Get parameter properties, and treat them as being on the *same* level as the constructor, not under it. + var ctr = node; + addNodeWithRecursiveChild(ctr, ctr.body); + // Parameter properties are children of the class, not the constructor. + for (var _i = 0, _a = ctr.parameters; _i < _a.length; _i++) { + var param = _a[_i]; + if (ts.isParameterPropertyDeclaration(param)) { + addLeafNode(param); + } + } + break; + case 147 /* MethodDeclaration */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 146 /* MethodSignature */: + if (!ts.hasDynamicName(node)) { + addNodeWithRecursiveChild(node, node.body); + } + break; + case 145 /* PropertyDeclaration */: + case 144 /* PropertySignature */: + if (!ts.hasDynamicName(node)) { + addLeafNode(node); + } + break; + case 231 /* ImportClause */: + var importClause = node; + // Handle default import case e.g.: + // import d from "mod"; + if (importClause.name) { + addLeafNode(importClause); + } + // Handle named bindings in imports e.g.: + // import * as NS from "mod"; + // import {a, b as B} from "mod"; + var namedBindings = importClause.namedBindings; + if (namedBindings) { + if (namedBindings.kind === 232 /* NamespaceImport */) { + addLeafNode(namedBindings); + } + else { + for (var _b = 0, _c = namedBindings.elements; _b < _c.length; _b++) { + var element = _c[_b]; + addLeafNode(element); + } + } + } + break; + case 169 /* BindingElement */: + case 218 /* VariableDeclaration */: + var decl = node; + var name_53 = decl.name; + if (ts.isBindingPattern(name_53)) { + addChildrenRecursively(name_53); + } + else if (decl.initializer && isFunctionOrClassExpression(decl.initializer)) { + // For `const x = function() {}`, just use the function node, not the const. + addChildrenRecursively(decl.initializer); + } + else { + addNodeWithRecursiveChild(decl, decl.initializer); } - if ((declaration.kind === 179 /* FunctionExpression */ || declaration.kind === 180 /* ArrowFunction */) && - declaration.parent.kind === 218 /* VariableDeclaration */) { - addCommentParts(declaration.parent.parent, sourceFileOfDeclaration, getCleanedJsDocComment); + break; + case 180 /* ArrowFunction */: + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + addNodeWithRecursiveChild(node, node.body); + break; + case 224 /* EnumDeclaration */: + startNode(node); + for (var _d = 0, _e = node.members; _d < _e.length; _d++) { + var member = _e[_d]; + if (!isComputedProperty(member)) { + addLeafNode(member); + } } - // If this is dotted module name, get the doc comments from the parent - while (declaration.kind === 225 /* ModuleDeclaration */ && declaration.parent.kind === 225 /* ModuleDeclaration */) { - declaration = declaration.parent; + endNode(); + break; + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + case 222 /* InterfaceDeclaration */: + startNode(node); + for (var _f = 0, _g = node.members; _f < _g.length; _f++) { + var member = _g[_f]; + addChildrenRecursively(member); } - addCommentParts(declaration.kind === 218 /* VariableDeclaration */ ? declaration.parent.parent : declaration, sourceFileOfDeclaration, getCleanedJsDocComment); - if (declaration.kind === 218 /* VariableDeclaration */) { - var init = declaration.initializer; - if (init && (init.kind === 179 /* FunctionExpression */ || init.kind === 180 /* ArrowFunction */)) { - // Get the cleaned js doc comment text from the initializer - addCommentParts(init, sourceFileOfDeclaration, getCleanedJsDocComment); + endNode(); + break; + case 225 /* ModuleDeclaration */: + addNodeWithRecursiveChild(node, getInteriorModule(node).body); + break; + case 238 /* ExportSpecifier */: + case 229 /* ImportEqualsDeclaration */: + case 153 /* IndexSignature */: + case 151 /* CallSignature */: + case 152 /* ConstructSignature */: + case 223 /* TypeAliasDeclaration */: + addLeafNode(node); + break; + default: + ts.forEach(node.jsDocComments, function (jsDocComment) { + ts.forEach(jsDocComment.tags, function (tag) { + if (tag.kind === 279 /* JSDocTypedefTag */) { + addLeafNode(tag); + } + }); + }); + ts.forEachChild(node, addChildrenRecursively); + } + } + /** Merge declarations of the same kind. */ + function mergeChildren(children) { + var nameToItems = ts.createMap(); + ts.filterMutate(children, function (child) { + var decl = child.node; + var name = decl.name && nodeText(decl.name); + if (!name) { + // Anonymous items are never merged. + return true; + } + var itemsWithSameName = nameToItems[name]; + if (!itemsWithSameName) { + nameToItems[name] = child; + return true; + } + if (itemsWithSameName instanceof Array) { + for (var _i = 0, itemsWithSameName_1 = itemsWithSameName; _i < itemsWithSameName_1.length; _i++) { + var itemWithSameName = itemsWithSameName_1[_i]; + if (tryMerge(itemWithSameName, child)) { + return false; } } + itemsWithSameName.push(child); + return true; + } + else { + var itemWithSameName = itemsWithSameName; + if (tryMerge(itemWithSameName, child)) { + return false; + } + nameToItems[name] = [itemWithSameName, child]; + return true; + } + function tryMerge(a, b) { + if (shouldReallyMerge(a.node, b.node)) { + merge(a, b); + return true; + } + return false; } }); - return jsDocCommentParts; - function addCommentParts(commented, sourceFileOfDeclaration, getCommentPart) { - var ranges = getJsDocCommentTextRange(commented, sourceFileOfDeclaration); - // Get the cleaned js doc comment text from the declaration - ts.forEach(ranges, function (jsDocCommentTextRange) { - var cleanedComment = getCommentPart(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); - if (cleanedComment) { - ts.addRange(jsDocCommentParts, cleanedComment); + /** a and b have the same name, but they may not be mergeable. */ + function shouldReallyMerge(a, b) { + return a.kind === b.kind && (a.kind !== 225 /* ModuleDeclaration */ || areSameModule(a, b)); + // We use 1 NavNode to represent 'A.B.C', but there are multiple source nodes. + // Only merge module nodes that have the same chain. Don't merge 'A.B.C' with 'A'! + function areSameModule(a, b) { + if (a.body.kind !== b.body.kind) { + return false; } - }); - } - function getJsDocCommentTextRange(node, sourceFile) { - return ts.map(ts.getJsDocComments(node, sourceFile), function (jsDocComment) { - return { - pos: jsDocComment.pos + "/*".length, - end: jsDocComment.end - "*/".length // Trim off comment end indicator - }; - }); + if (a.body.kind !== 225 /* ModuleDeclaration */) { + return true; + } + return areSameModule(a.body, b.body); + } } - function consumeWhiteSpacesOnTheLine(pos, end, sourceFile, maxSpacesToRemove) { - if (maxSpacesToRemove !== undefined) { - end = Math.min(end, pos + maxSpacesToRemove); + /** Merge source into target. Source should be thrown away after this is called. */ + function merge(target, source) { + target.additionalNodes = target.additionalNodes || []; + target.additionalNodes.push(source.node); + if (source.additionalNodes) { + (_a = target.additionalNodes).push.apply(_a, source.additionalNodes); } - for (; pos < end; pos++) { - var ch = sourceFile.text.charCodeAt(pos); - if (!ts.isWhiteSpaceSingleLine(ch)) { - return pos; - } + target.children = ts.concatenate(target.children, source.children); + if (target.children) { + mergeChildren(target.children); + sortChildren(target.children); } - return end; + var _a; } - function consumeLineBreaks(pos, end, sourceFile) { - while (pos < end && ts.isLineBreak(sourceFile.text.charCodeAt(pos))) { - pos++; + } + /** Recursively ensure that each NavNode's children are in sorted order. */ + function sortChildren(children) { + children.sort(compareChildren); + } + function compareChildren(child1, child2) { + var name1 = tryGetName(child1.node), name2 = tryGetName(child2.node); + if (name1 && name2) { + var cmp = localeCompareFix(name1, name2); + return cmp !== 0 ? cmp : navigationBarNodeKind(child1) - navigationBarNodeKind(child2); + } + else { + return name1 ? 1 : name2 ? -1 : navigationBarNodeKind(child1) - navigationBarNodeKind(child2); + } + } + // More efficient to create a collator once and use its `compare` than to call `a.localeCompare(b)` many times. + var collator = typeof Intl === "undefined" ? undefined : new Intl.Collator(); + // Intl is missing in Safari, and node 0.10 treats "a" as greater than "B". + var localeCompareIsCorrect = collator && collator.compare("a", "B") < 0; + var localeCompareFix = localeCompareIsCorrect ? collator.compare : function (a, b) { + // This isn't perfect, but it passes all of our tests. + for (var i = 0; i < Math.min(a.length, b.length); i++) { + var chA = a.charAt(i), chB = b.charAt(i); + if (chA === "\"" && chB === "'") { + return 1; + } + if (chA === "'" && chB === "\"") { + return -1; + } + var cmp = chA.toLocaleLowerCase().localeCompare(chB.toLocaleLowerCase()); + if (cmp !== 0) { + return cmp; } - return pos; } - function isName(pos, end, sourceFile, name) { - return pos + name.length < end && - sourceFile.text.substr(pos, name.length) === name && - ts.isWhiteSpace(sourceFile.text.charCodeAt(pos + name.length)); + return a.length - b.length; + }; + /** + * This differs from getItemName because this is just used for sorting. + * We only sort nodes by name that have a more-or-less "direct" name, as opposed to `new()` and the like. + * So `new()` can still come before an `aardvark` method. + */ + function tryGetName(node) { + if (node.kind === 225 /* ModuleDeclaration */) { + return getModuleName(node); + } + var decl = node; + if (decl.name) { + return ts.getPropertyNameForPropertyNameNode(decl.name); + } + switch (node.kind) { + case 179 /* FunctionExpression */: + case 180 /* ArrowFunction */: + case 192 /* ClassExpression */: + return getFunctionOrClassName(node); + case 279 /* JSDocTypedefTag */: + return getJSDocTypedefTagName(node); + default: + return undefined; } - function isParamTag(pos, end, sourceFile) { - // If it is @param tag - return isName(pos, end, sourceFile, paramTag); + } + function getItemName(node) { + if (node.kind === 225 /* ModuleDeclaration */) { + return getModuleName(node); } - function pushDocCommentLineText(docComments, text, blankLineCount) { - // Add the empty lines in between texts - while (blankLineCount) { - blankLineCount--; - docComments.push(ts.textPart("")); + var name = node.name; + if (name) { + var text = nodeText(name); + if (text.length > 0) { + return text; } - docComments.push(ts.textPart(text)); } - function getCleanedJsDocComment(pos, end, sourceFile) { - var spacesToRemoveAfterAsterisk; - var docComments = []; - var blankLineCount = 0; - var isInParamTag = false; - while (pos < end) { - var docCommentTextOfLine = ""; - // First consume leading white space - pos = consumeWhiteSpacesOnTheLine(pos, end, sourceFile); - // If the comment starts with '*' consume the spaces on this line - if (pos < end && sourceFile.text.charCodeAt(pos) === 42 /* asterisk */) { - var lineStartPos = pos + 1; - pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, spacesToRemoveAfterAsterisk); - // Set the spaces to remove after asterisk as margin if not already set - if (spacesToRemoveAfterAsterisk === undefined && pos < end && !ts.isLineBreak(sourceFile.text.charCodeAt(pos))) { - spacesToRemoveAfterAsterisk = pos - lineStartPos; - } - } - else if (spacesToRemoveAfterAsterisk === undefined) { - spacesToRemoveAfterAsterisk = 0; - } - // Analyze text on this line - while (pos < end && !ts.isLineBreak(sourceFile.text.charCodeAt(pos))) { - var ch = sourceFile.text.charAt(pos); - if (ch === "@") { - // If it is @param tag - if (isParamTag(pos, end, sourceFile)) { - isInParamTag = true; - pos += paramTag.length; - continue; - } - else { - isInParamTag = false; - } - } - // Add the ch to doc text if we arent in param tag - if (!isInParamTag) { - docCommentTextOfLine += ch; - } - // Scan next character - pos++; - } - // Continue with next line - pos = consumeLineBreaks(pos, end, sourceFile); - if (docCommentTextOfLine) { - pushDocCommentLineText(docComments, docCommentTextOfLine, blankLineCount); - blankLineCount = 0; + switch (node.kind) { + case 256 /* SourceFile */: + var sourceFile = node; + return ts.isExternalModule(sourceFile) + ? "\"" + ts.escapeString(ts.getBaseFileName(ts.removeFileExtension(ts.normalizePath(sourceFile.fileName)))) + "\"" + : ""; + case 180 /* ArrowFunction */: + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + if (ts.getModifierFlags(node) & 512 /* Default */) { + return "default"; } - else if (!isInParamTag && docComments.length) { - // This is blank line when there is text already parsed - blankLineCount++; + return getFunctionOrClassName(node); + case 148 /* Constructor */: + return "constructor"; + case 152 /* ConstructSignature */: + return "new()"; + case 151 /* CallSignature */: + return "()"; + case 153 /* IndexSignature */: + return "[]"; + case 279 /* JSDocTypedefTag */: + return getJSDocTypedefTagName(node); + default: + return ""; + } + } + function getJSDocTypedefTagName(node) { + if (node.name) { + return node.name.text; + } + else { + var parentNode = node.parent && node.parent.parent; + if (parentNode && parentNode.kind === 200 /* VariableStatement */) { + if (parentNode.declarationList.declarations.length > 0) { + var nameIdentifier = parentNode.declarationList.declarations[0].name; + if (nameIdentifier.kind === 69 /* Identifier */) { + return nameIdentifier.text; + } } } - return docComments; + return ""; } - function getCleanedParamJsDocComment(pos, end, sourceFile) { - var paramHelpStringMargin; - var paramDocComments = []; - while (pos < end) { - if (isParamTag(pos, end, sourceFile)) { - var blankLineCount = 0; - var recordedParamTag = false; - // Consume leading spaces - pos = consumeWhiteSpaces(pos + paramTag.length); - if (pos >= end) { - break; - } - // Ignore type expression - if (sourceFile.text.charCodeAt(pos) === 123 /* openBrace */) { - pos++; - for (var curlies = 1; pos < end; pos++) { - var charCode = sourceFile.text.charCodeAt(pos); - // { character means we need to find another } to match the found one - if (charCode === 123 /* openBrace */) { - curlies++; - continue; - } - // } char - if (charCode === 125 /* closeBrace */) { - curlies--; - if (curlies === 0) { - // We do not have any more } to match the type expression is ignored completely - pos++; - break; - } - else { - // there are more { to be matched with } - continue; - } - } - // Found start of another tag - if (charCode === 64 /* at */) { - break; - } - } - // Consume white spaces - pos = consumeWhiteSpaces(pos); - if (pos >= end) { - break; - } - } - // Parameter name - if (isName(pos, end, sourceFile, name)) { - // Found the parameter we are looking for consume white spaces - pos = consumeWhiteSpaces(pos + name.length); - if (pos >= end) { - break; - } - var paramHelpString = ""; - var firstLineParamHelpStringPos = pos; - while (pos < end) { - var ch = sourceFile.text.charCodeAt(pos); - // at line break, set this comment line text and go to next line - if (ts.isLineBreak(ch)) { - if (paramHelpString) { - pushDocCommentLineText(paramDocComments, paramHelpString, blankLineCount); - paramHelpString = ""; - blankLineCount = 0; - recordedParamTag = true; - } - else if (recordedParamTag) { - blankLineCount++; - } - // Get the pos after cleaning start of the line - setPosForParamHelpStringOnNextLine(firstLineParamHelpStringPos); - continue; - } - // Done scanning param help string - next tag found - if (ch === 64 /* at */) { - break; - } - paramHelpString += sourceFile.text.charAt(pos); - // Go to next character - pos++; - } - // If there is param help text, add it top the doc comments - if (paramHelpString) { - pushDocCommentLineText(paramDocComments, paramHelpString, blankLineCount); - } - paramHelpStringMargin = undefined; - } - // If this is the start of another tag, continue with the loop in search of param tag with symbol name - if (sourceFile.text.charCodeAt(pos) === 64 /* at */) { - continue; + } + /** Flattens the NavNode tree to a list, keeping only the top-level items. */ + function topLevelItems(root) { + var topLevel = []; + function recur(item) { + if (isTopLevel(item)) { + topLevel.push(item); + if (item.children) { + for (var _i = 0, _a = item.children; _i < _a.length; _i++) { + var child = _a[_i]; + recur(child); } } - // Next character - pos++; } - return paramDocComments; - function consumeWhiteSpaces(pos) { - while (pos < end && ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(pos))) { - pos++; - } - return pos; + } + recur(root); + return topLevel; + function isTopLevel(item) { + switch (navigationBarNodeKind(item)) { + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + case 224 /* EnumDeclaration */: + case 222 /* InterfaceDeclaration */: + case 225 /* ModuleDeclaration */: + case 256 /* SourceFile */: + case 223 /* TypeAliasDeclaration */: + case 279 /* JSDocTypedefTag */: + return true; + case 148 /* Constructor */: + case 147 /* MethodDeclaration */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + case 218 /* VariableDeclaration */: + return hasSomeImportantChild(item); + case 180 /* ArrowFunction */: + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + return isTopLevelFunctionDeclaration(item); + default: + return false; } - function setPosForParamHelpStringOnNextLine(firstLineParamHelpStringPos) { - // Get the pos after consuming line breaks - pos = consumeLineBreaks(pos, end, sourceFile); - if (pos >= end) { - return; - } - if (paramHelpStringMargin === undefined) { - paramHelpStringMargin = sourceFile.getLineAndCharacterOfPosition(firstLineParamHelpStringPos).character; + function isTopLevelFunctionDeclaration(item) { + if (!item.node.body) { + return false; } - // Now consume white spaces max - var startOfLinePos = pos; - pos = consumeWhiteSpacesOnTheLine(pos, end, sourceFile, paramHelpStringMargin); - if (pos >= end) { - return; + switch (navigationBarNodeKind(item.parent)) { + case 226 /* ModuleBlock */: + case 256 /* SourceFile */: + case 147 /* MethodDeclaration */: + case 148 /* Constructor */: + return true; + default: + return hasSomeImportantChild(item); } - var consumedSpaces = pos - startOfLinePos; - if (consumedSpaces < paramHelpStringMargin) { - var ch = sourceFile.text.charCodeAt(pos); - if (ch === 42 /* asterisk */) { - // Consume more spaces after asterisk - pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, paramHelpStringMargin - consumedSpaces - 1); - } + } + function hasSomeImportantChild(item) { + return ts.forEach(item.children, function (child) { + var childKind = navigationBarNodeKind(child); + return childKind !== 218 /* VariableDeclaration */ && childKind !== 169 /* BindingElement */; + }); + } + } + } + // NavigationBarItem requires an array, but will not mutate it, so just give it this for performance. + var emptyChildItemArray = []; + function convertToTopLevelItem(n) { + return { + text: getItemName(n.node), + kind: ts.getNodeKind(n.node), + kindModifiers: ts.getNodeModifiers(n.node), + spans: getSpans(n), + childItems: ts.map(n.children, convertToChildItem) || emptyChildItemArray, + indent: n.indent, + bolded: false, + grayed: false + }; + function convertToChildItem(n) { + return { + text: getItemName(n.node), + kind: ts.getNodeKind(n.node), + kindModifiers: ts.getNodeModifiers(n.node), + spans: getSpans(n), + childItems: emptyChildItemArray, + indent: 0, + bolded: false, + grayed: false + }; + } + function getSpans(n) { + var spans = [getNodeSpan(n.node)]; + if (n.additionalNodes) { + for (var _i = 0, _a = n.additionalNodes; _i < _a.length; _i++) { + var node = _a[_i]; + spans.push(getNodeSpan(node)); } } + return spans; } } - } - var TypeObject = (function () { - function TypeObject(checker, flags) { - this.checker = checker; - this.flags = flags; + function getModuleName(moduleDeclaration) { + // We want to maintain quotation marks. + if (ts.isAmbientModule(moduleDeclaration)) { + return ts.getTextOfNode(moduleDeclaration.name); + } + // Otherwise, we need to aggregate each identifier to build up the qualified name. + var result = []; + result.push(moduleDeclaration.name.text); + while (moduleDeclaration.body && moduleDeclaration.body.kind === 225 /* ModuleDeclaration */) { + moduleDeclaration = moduleDeclaration.body; + result.push(moduleDeclaration.name.text); + } + return result.join("."); } - TypeObject.prototype.getFlags = function () { - return this.flags; - }; - TypeObject.prototype.getSymbol = function () { - return this.symbol; - }; - TypeObject.prototype.getProperties = function () { - return this.checker.getPropertiesOfType(this); - }; - TypeObject.prototype.getProperty = function (propertyName) { - return this.checker.getPropertyOfType(this, propertyName); - }; - TypeObject.prototype.getApparentProperties = function () { - return this.checker.getAugmentedPropertiesOfType(this); - }; - TypeObject.prototype.getCallSignatures = function () { - return this.checker.getSignaturesOfType(this, 0 /* Call */); - }; - TypeObject.prototype.getConstructSignatures = function () { - return this.checker.getSignaturesOfType(this, 1 /* Construct */); - }; - TypeObject.prototype.getStringIndexType = function () { - return this.checker.getIndexTypeOfType(this, 0 /* String */); - }; - TypeObject.prototype.getNumberIndexType = function () { - return this.checker.getIndexTypeOfType(this, 1 /* Number */); - }; - TypeObject.prototype.getBaseTypes = function () { - return this.flags & (32768 /* Class */ | 65536 /* Interface */) - ? this.checker.getBaseTypes(this) - : undefined; - }; - TypeObject.prototype.getNonNullableType = function () { - return this.checker.getNonNullableType(this); - }; - return TypeObject; - }()); - var SignatureObject = (function () { - function SignatureObject(checker) { - this.checker = checker; + /** + * For 'module A.B.C', we want to get the node for 'C'. + * We store 'A' as associated with a NavNode, and use getModuleName to traverse down again. + */ + function getInteriorModule(decl) { + return decl.body.kind === 225 /* ModuleDeclaration */ ? getInteriorModule(decl.body) : decl; } - SignatureObject.prototype.getDeclaration = function () { - return this.declaration; - }; - SignatureObject.prototype.getTypeParameters = function () { - return this.typeParameters; - }; - SignatureObject.prototype.getParameters = function () { - return this.parameters; - }; - SignatureObject.prototype.getReturnType = function () { - return this.checker.getReturnTypeOfSignature(this); - }; - SignatureObject.prototype.getDocumentationComment = function () { - if (this.documentationComment === undefined) { - this.documentationComment = this.declaration ? getJsDocCommentsFromDeclarations([this.declaration], - /*name*/ undefined, - /*canUseParsedParamTagComments*/ false) : []; + function isComputedProperty(member) { + return !member.name || member.name.kind === 140 /* ComputedPropertyName */; + } + function getNodeSpan(node) { + return node.kind === 256 /* SourceFile */ + ? ts.createTextSpanFromBounds(node.getFullStart(), node.getEnd()) + : ts.createTextSpanFromBounds(node.getStart(curSourceFile), node.getEnd()); + } + function getFunctionOrClassName(node) { + if (node.name && ts.getFullWidth(node.name) > 0) { + return ts.declarationNameToString(node.name); + } + else if (node.parent.kind === 218 /* VariableDeclaration */) { + return ts.declarationNameToString(node.parent.name); + } + else if (node.parent.kind === 187 /* BinaryExpression */ && + node.parent.operatorToken.kind === 56 /* EqualsToken */) { + return nodeText(node.parent.left); + } + else if (node.parent.kind === 253 /* PropertyAssignment */ && node.parent.name) { + return nodeText(node.parent.name); + } + else if (ts.getModifierFlags(node) & 512 /* Default */) { + return "default"; + } + else { + return ts.isClassLike(node) ? "" : ""; } - return this.documentationComment; - }; - return SignatureObject; - }()); - var SourceFileObject = (function (_super) { - __extends(SourceFileObject, _super); - function SourceFileObject(kind, pos, end) { - _super.call(this, kind, pos, end); } - SourceFileObject.prototype.update = function (newText, textChangeRange) { - return ts.updateSourceFile(this, newText, textChangeRange); - }; - SourceFileObject.prototype.getLineAndCharacterOfPosition = function (position) { - return ts.getLineAndCharacterOfPosition(this, position); - }; - SourceFileObject.prototype.getLineStarts = function () { - return ts.getLineStarts(this); - }; - SourceFileObject.prototype.getPositionOfLineAndCharacter = function (line, character) { - return ts.getPositionOfLineAndCharacter(this, line, character); - }; - SourceFileObject.prototype.getNamedDeclarations = function () { - if (!this.namedDeclarations) { - this.namedDeclarations = this.computeNamedDeclarations(); - } - return this.namedDeclarations; - }; - SourceFileObject.prototype.computeNamedDeclarations = function () { - var result = ts.createMap(); - ts.forEachChild(this, visit); - return result; - function addDeclaration(declaration) { - var name = getDeclarationName(declaration); - if (name) { - ts.multiMapAdd(result, name, declaration); + function isFunctionOrClassExpression(node) { + return node.kind === 179 /* FunctionExpression */ || node.kind === 180 /* ArrowFunction */ || node.kind === 192 /* ClassExpression */; + } + })(NavigationBar = ts.NavigationBar || (ts.NavigationBar = {})); +})(ts || (ts = {})); +/* @internal */ +var ts; +(function (ts) { + var OutliningElementsCollector; + (function (OutliningElementsCollector) { + function collectElements(sourceFile) { + var elements = []; + var collapseText = "..."; + function addOutliningSpan(hintSpanNode, startElement, endElement, autoCollapse) { + if (hintSpanNode && startElement && endElement) { + var span_12 = { + textSpan: ts.createTextSpanFromBounds(startElement.pos, endElement.end), + hintSpan: ts.createTextSpanFromBounds(hintSpanNode.getStart(), hintSpanNode.end), + bannerText: collapseText, + autoCollapse: autoCollapse + }; + elements.push(span_12); } } - function getDeclarations(name) { - return result[name] || (result[name] = []); + function addOutliningSpanComments(commentSpan, autoCollapse) { + if (commentSpan) { + var span_13 = { + textSpan: ts.createTextSpanFromBounds(commentSpan.pos, commentSpan.end), + hintSpan: ts.createTextSpanFromBounds(commentSpan.pos, commentSpan.end), + bannerText: collapseText, + autoCollapse: autoCollapse + }; + elements.push(span_13); + } } - function getDeclarationName(declaration) { - if (declaration.name) { - var result_3 = getTextOfIdentifierOrLiteral(declaration.name); - if (result_3 !== undefined) { - return result_3; - } - if (declaration.name.kind === 140 /* ComputedPropertyName */) { - var expr = declaration.name.expression; - if (expr.kind === 172 /* PropertyAccessExpression */) { - return expr.name.text; + function addOutliningForLeadingCommentsForNode(n) { + var comments = ts.getLeadingCommentRangesOfNode(n, sourceFile); + if (comments) { + var firstSingleLineCommentStart = -1; + var lastSingleLineCommentEnd = -1; + var isFirstSingleLineComment = true; + var singleLineCommentCount = 0; + for (var _i = 0, comments_4 = comments; _i < comments_4.length; _i++) { + var currentComment = comments_4[_i]; + // For single line comments, combine consecutive ones (2 or more) into + // a single span from the start of the first till the end of the last + if (currentComment.kind === 2 /* SingleLineCommentTrivia */) { + if (isFirstSingleLineComment) { + firstSingleLineCommentStart = currentComment.pos; + } + isFirstSingleLineComment = false; + lastSingleLineCommentEnd = currentComment.end; + singleLineCommentCount++; + } + else if (currentComment.kind === 3 /* MultiLineCommentTrivia */) { + combineAndAddMultipleSingleLineComments(singleLineCommentCount, firstSingleLineCommentStart, lastSingleLineCommentEnd); + addOutliningSpanComments(currentComment, /*autoCollapse*/ false); + singleLineCommentCount = 0; + lastSingleLineCommentEnd = -1; + isFirstSingleLineComment = true; } - return getTextOfIdentifierOrLiteral(expr); } + combineAndAddMultipleSingleLineComments(singleLineCommentCount, firstSingleLineCommentStart, lastSingleLineCommentEnd); } - return undefined; } - function getTextOfIdentifierOrLiteral(node) { - if (node) { - if (node.kind === 69 /* Identifier */ || - node.kind === 9 /* StringLiteral */ || - node.kind === 8 /* NumericLiteral */) { - return node.text; - } + function combineAndAddMultipleSingleLineComments(count, start, end) { + // Only outline spans of two or more consecutive single line comments + if (count > 1) { + var multipleSingleLineComments = { + pos: start, + end: end, + kind: 2 /* SingleLineCommentTrivia */ + }; + addOutliningSpanComments(multipleSingleLineComments, /*autoCollapse*/ false); } - return undefined; } - function visit(node) { - switch (node.kind) { - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - var functionDeclaration = node; - var declarationName = getDeclarationName(functionDeclaration); - if (declarationName) { - var declarations = getDeclarations(declarationName); - var lastDeclaration = ts.lastOrUndefined(declarations); - // Check whether this declaration belongs to an "overload group". - if (lastDeclaration && functionDeclaration.parent === lastDeclaration.parent && functionDeclaration.symbol === lastDeclaration.symbol) { - // Overwrite the last declaration if it was an overload - // and this one is an implementation. - if (functionDeclaration.body && !lastDeclaration.body) { - declarations[declarations.length - 1] = functionDeclaration; - } + function autoCollapse(node) { + return ts.isFunctionBlock(node) && node.parent.kind !== 180 /* ArrowFunction */; + } + var depth = 0; + var maxDepth = 20; + function walk(n) { + if (depth > maxDepth) { + return; + } + if (ts.isDeclaration(n)) { + addOutliningForLeadingCommentsForNode(n); + } + switch (n.kind) { + case 199 /* Block */: + if (!ts.isFunctionBlock(n)) { + var parent_22 = n.parent; + var openBrace = ts.findChildOfKind(n, 15 /* OpenBraceToken */, sourceFile); + var closeBrace = ts.findChildOfKind(n, 16 /* CloseBraceToken */, sourceFile); + // Check if the block is standalone, or 'attached' to some parent statement. + // If the latter, we want to collapse the block, but consider its hint span + // to be the entire span of the parent. + if (parent_22.kind === 204 /* DoStatement */ || + parent_22.kind === 207 /* ForInStatement */ || + parent_22.kind === 208 /* ForOfStatement */ || + parent_22.kind === 206 /* ForStatement */ || + parent_22.kind === 203 /* IfStatement */ || + parent_22.kind === 205 /* WhileStatement */ || + parent_22.kind === 212 /* WithStatement */ || + parent_22.kind === 252 /* CatchClause */) { + addOutliningSpan(parent_22, openBrace, closeBrace, autoCollapse(n)); + break; } - else { - declarations.push(functionDeclaration); + if (parent_22.kind === 216 /* TryStatement */) { + // Could be the try-block, or the finally-block. + var tryStatement = parent_22; + if (tryStatement.tryBlock === n) { + addOutliningSpan(parent_22, openBrace, closeBrace, autoCollapse(n)); + break; + } + else if (tryStatement.finallyBlock === n) { + var finallyKeyword = ts.findChildOfKind(tryStatement, 85 /* FinallyKeyword */, sourceFile); + if (finallyKeyword) { + addOutliningSpan(finallyKeyword, openBrace, closeBrace, autoCollapse(n)); + break; + } + } } - ts.forEachChild(node, visit); + // Block was a standalone block. In this case we want to only collapse + // the span of the block, independent of any parent span. + var span_14 = ts.createTextSpanFromBounds(n.getStart(), n.end); + elements.push({ + textSpan: span_14, + hintSpan: span_14, + bannerText: collapseText, + autoCollapse: autoCollapse(n) + }); + break; } + // Fallthrough. + case 226 /* ModuleBlock */: { + var openBrace = ts.findChildOfKind(n, 15 /* OpenBraceToken */, sourceFile); + var closeBrace = ts.findChildOfKind(n, 16 /* CloseBraceToken */, sourceFile); + addOutliningSpan(n.parent, openBrace, closeBrace, autoCollapse(n)); break; + } case 221 /* ClassDeclaration */: - case 192 /* ClassExpression */: case 222 /* InterfaceDeclaration */: - case 223 /* TypeAliasDeclaration */: case 224 /* EnumDeclaration */: - case 225 /* ModuleDeclaration */: - case 229 /* ImportEqualsDeclaration */: - case 238 /* ExportSpecifier */: - case 234 /* ImportSpecifier */: - case 229 /* ImportEqualsDeclaration */: - case 231 /* ImportClause */: - case 232 /* NamespaceImport */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 159 /* TypeLiteral */: - addDeclaration(node); - ts.forEachChild(node, visit); + case 171 /* ObjectLiteralExpression */: + case 227 /* CaseBlock */: { + var openBrace = ts.findChildOfKind(n, 15 /* OpenBraceToken */, sourceFile); + var closeBrace = ts.findChildOfKind(n, 16 /* CloseBraceToken */, sourceFile); + addOutliningSpan(n, openBrace, closeBrace, autoCollapse(n)); break; - case 142 /* Parameter */: - // Only consider parameter properties - if (!(node.flags & 92 /* ParameterPropertyModifier */)) { - break; - } - // fall through - case 218 /* VariableDeclaration */: - case 169 /* BindingElement */: { - var decl = node; - if (ts.isBindingPattern(decl.name)) { - ts.forEachChild(decl.name, visit); - break; - } - if (decl.initializer) - visit(decl.initializer); } - case 255 /* EnumMember */: - case 145 /* PropertyDeclaration */: - case 144 /* PropertySignature */: - addDeclaration(node); - break; - case 236 /* ExportDeclaration */: - // Handle named exports case e.g.: - // export {a, b as B} from "mod"; - if (node.exportClause) { - ts.forEach(node.exportClause.elements, visit); - } - break; - case 230 /* ImportDeclaration */: - var importClause = node.importClause; - if (importClause) { - // Handle default import case e.g.: - // import d from "mod"; - if (importClause.name) { - addDeclaration(importClause); - } - // Handle named bindings in imports e.g.: - // import * as NS from "mod"; - // import {a, b as B} from "mod"; - if (importClause.namedBindings) { - if (importClause.namedBindings.kind === 232 /* NamespaceImport */) { - addDeclaration(importClause.namedBindings); - } - else { - ts.forEach(importClause.namedBindings.elements, visit); - } - } - } + case 170 /* ArrayLiteralExpression */: + var openBracket = ts.findChildOfKind(n, 19 /* OpenBracketToken */, sourceFile); + var closeBracket = ts.findChildOfKind(n, 20 /* CloseBracketToken */, sourceFile); + addOutliningSpan(n, openBracket, closeBracket, autoCollapse(n)); break; - default: - ts.forEachChild(node, visit); } + depth++; + ts.forEachChild(n, walk); + depth--; } - }; - return SourceFileObject; - }(NodeObject)); - function displayPartsToString(displayParts) { - if (displayParts) { - return ts.map(displayParts, function (displayPart) { return displayPart.text; }).join(""); - } - return ""; - } - ts.displayPartsToString = displayPartsToString; - function isLocalVariableOrFunction(symbol) { - if (symbol.parent) { - return false; // This is exported symbol + walk(sourceFile); + return elements; } - return ts.forEach(symbol.declarations, function (declaration) { - // Function expressions are local - if (declaration.kind === 179 /* FunctionExpression */) { - return true; - } - if (declaration.kind !== 218 /* VariableDeclaration */ && declaration.kind !== 220 /* FunctionDeclaration */) { - return false; - } - // If the parent is not sourceFile or module block it is local variable - for (var parent_17 = declaration.parent; !ts.isFunctionBlock(parent_17); parent_17 = parent_17.parent) { - // Reached source file or module block - if (parent_17.kind === 256 /* SourceFile */ || parent_17.kind === 226 /* ModuleBlock */) { - return false; - } - } - // parent is in function block - return true; - }); - } - function getDefaultCompilerOptions() { - // Always default to "ScriptTarget.ES5" for the language service + OutliningElementsCollector.collectElements = collectElements; + })(OutliningElementsCollector = ts.OutliningElementsCollector || (ts.OutliningElementsCollector = {})); +})(ts || (ts = {})); +/* @internal */ +var ts; +(function (ts) { + // Note(cyrusn): this enum is ordered from strongest match type to weakest match type. + (function (PatternMatchKind) { + PatternMatchKind[PatternMatchKind["exact"] = 0] = "exact"; + PatternMatchKind[PatternMatchKind["prefix"] = 1] = "prefix"; + PatternMatchKind[PatternMatchKind["substring"] = 2] = "substring"; + PatternMatchKind[PatternMatchKind["camelCase"] = 3] = "camelCase"; + })(ts.PatternMatchKind || (ts.PatternMatchKind = {})); + var PatternMatchKind = ts.PatternMatchKind; + function createPatternMatch(kind, punctuationStripped, isCaseSensitive, camelCaseWeight) { return { - target: 1 /* ES5 */, - jsx: 1 /* Preserve */ + kind: kind, + punctuationStripped: punctuationStripped, + isCaseSensitive: isCaseSensitive, + camelCaseWeight: camelCaseWeight }; } - ts.getDefaultCompilerOptions = getDefaultCompilerOptions; - // Cache host information about script should be refreshed - // at each language service public entry point, since we don't know when - // set of scripts handled by the host changes. - var HostCache = (function () { - function HostCache(host, getCanonicalFileName) { - this.host = host; - this.getCanonicalFileName = getCanonicalFileName; - // script id => script index - this.currentDirectory = host.getCurrentDirectory(); - this.fileNameToEntry = ts.createFileMap(); - // Initialize the list with the root file names - var rootFileNames = host.getScriptFileNames(); - for (var _i = 0, rootFileNames_1 = rootFileNames; _i < rootFileNames_1.length; _i++) { - var fileName = rootFileNames_1[_i]; - this.createEntry(fileName, ts.toPath(fileName, this.currentDirectory, getCanonicalFileName)); - } - // store the compilation settings - this._compilationSettings = host.getCompilationSettings() || getDefaultCompilerOptions(); - } - HostCache.prototype.compilationSettings = function () { - return this._compilationSettings; + function createPatternMatcher(pattern) { + // We'll often see the same candidate string many times when searching (For example, when + // we see the name of a module that is used everywhere, or the name of an overload). As + // such, we cache the information we compute about the candidate for the life of this + // pattern matcher so we don't have to compute it multiple times. + var stringToWordSpans = ts.createMap(); + pattern = pattern.trim(); + var dotSeparatedSegments = pattern.split(".").map(function (p) { return createSegment(p.trim()); }); + var invalidPattern = dotSeparatedSegments.length === 0 || ts.forEach(dotSeparatedSegments, segmentIsInvalid); + return { + getMatches: getMatches, + getMatchesForLastSegmentOfPattern: getMatchesForLastSegmentOfPattern, + patternContainsDots: dotSeparatedSegments.length > 1 }; - HostCache.prototype.createEntry = function (fileName, path) { - var entry; - var scriptSnapshot = this.host.getScriptSnapshot(fileName); - if (scriptSnapshot) { - entry = { - hostFileName: fileName, - version: this.host.getScriptVersion(fileName), - scriptSnapshot: scriptSnapshot, - scriptKind: ts.getScriptKind(fileName, this.host) - }; + // Quick checks so we can bail out when asked to match a candidate. + function skipMatch(candidate) { + return invalidPattern || !candidate; + } + function getMatchesForLastSegmentOfPattern(candidate) { + if (skipMatch(candidate)) { + return undefined; } - this.fileNameToEntry.set(path, entry); - return entry; - }; - HostCache.prototype.getEntry = function (path) { - return this.fileNameToEntry.get(path); - }; - HostCache.prototype.contains = function (path) { - return this.fileNameToEntry.contains(path); - }; - HostCache.prototype.getOrCreateEntry = function (fileName) { - var path = ts.toPath(fileName, this.currentDirectory, this.getCanonicalFileName); - return this.getOrCreateEntryByPath(fileName, path); - }; - HostCache.prototype.getOrCreateEntryByPath = function (fileName, path) { - return this.contains(path) - ? this.getEntry(path) - : this.createEntry(fileName, path); - }; - HostCache.prototype.getRootFileNames = function () { - var fileNames = []; - this.fileNameToEntry.forEachValue(function (path, value) { - if (value) { - fileNames.push(value.hostFileName); - } - }); - return fileNames; - }; - HostCache.prototype.getVersion = function (path) { - var file = this.getEntry(path); - return file && file.version; - }; - HostCache.prototype.getScriptSnapshot = function (path) { - var file = this.getEntry(path); - return file && file.scriptSnapshot; - }; - return HostCache; - }()); - var SyntaxTreeCache = (function () { - function SyntaxTreeCache(host) { - this.host = host; + return matchSegment(candidate, ts.lastOrUndefined(dotSeparatedSegments)); } - SyntaxTreeCache.prototype.getCurrentSourceFile = function (fileName) { - var scriptSnapshot = this.host.getScriptSnapshot(fileName); - if (!scriptSnapshot) { - // The host does not know about this file. - throw new Error("Could not find file: '" + fileName + "'."); + function getMatches(candidateContainers, candidate) { + if (skipMatch(candidate)) { + return undefined; } - var scriptKind = ts.getScriptKind(fileName, this.host); - var version = this.host.getScriptVersion(fileName); - var sourceFile; - if (this.currentFileName !== fileName) { - // This is a new file, just parse it - sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, 2 /* Latest */, version, /*setNodeParents*/ true, scriptKind); + // First, check that the last part of the dot separated pattern matches the name of the + // candidate. If not, then there's no point in proceeding and doing the more + // expensive work. + var candidateMatch = matchSegment(candidate, ts.lastOrUndefined(dotSeparatedSegments)); + if (!candidateMatch) { + return undefined; } - else if (this.currentFileVersion !== version) { - // This is the same file, just a newer version. Incrementally parse the file. - var editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot); - sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, editRange); + candidateContainers = candidateContainers || []; + // -1 because the last part was checked against the name, and only the rest + // of the parts are checked against the container. + if (dotSeparatedSegments.length - 1 > candidateContainers.length) { + // There weren't enough container parts to match against the pattern parts. + // So this definitely doesn't match. + return undefined; } - if (sourceFile) { - // All done, ensure state is up to date - this.currentFileVersion = version; - this.currentFileName = fileName; - this.currentFileScriptSnapshot = scriptSnapshot; - this.currentSourceFile = sourceFile; + // So far so good. Now break up the container for the candidate and check if all + // the dotted parts match up correctly. + var totalMatch = candidateMatch; + for (var i = dotSeparatedSegments.length - 2, j = candidateContainers.length - 1; i >= 0; i -= 1, j -= 1) { + var segment = dotSeparatedSegments[i]; + var containerName = candidateContainers[j]; + var containerMatch = matchSegment(containerName, segment); + if (!containerMatch) { + // This container didn't match the pattern piece. So there's no match at all. + return undefined; + } + ts.addRange(totalMatch, containerMatch); } - return this.currentSourceFile; - }; - return SyntaxTreeCache; - }()); - function setSourceFileFields(sourceFile, scriptSnapshot, version) { - sourceFile.version = version; - sourceFile.scriptSnapshot = scriptSnapshot; - } - var commandLineOptionsStringToEnum; - /** JS users may pass in string values for enum compiler options (such as ModuleKind), so convert. */ - function fixupCompilerOptions(options, diagnostics) { - // Lazily create this value to fix module loading errors. - commandLineOptionsStringToEnum = commandLineOptionsStringToEnum || ts.filter(ts.optionDeclarations, function (o) { - return typeof o.type === "object" && !ts.forEachProperty(o.type, function (v) { return typeof v !== "number"; }); - }); - options = ts.clone(options); - var _loop_3 = function(opt) { - if (!ts.hasProperty(options, opt.name)) { - return "continue"; + // Success, this symbol's full name matched against the dotted name the user was asking + // about. + return totalMatch; + } + function getWordSpans(word) { + if (!(word in stringToWordSpans)) { + stringToWordSpans[word] = breakIntoWordSpans(word); } - var value = options[opt.name]; - // Value should be a key of opt.type - if (typeof value === "string") { - // If value is not a string, this will fail - options[opt.name] = ts.parseCustomTypeOption(opt, value, diagnostics); + return stringToWordSpans[word]; + } + function matchTextChunk(candidate, chunk, punctuationStripped) { + var index = indexOfIgnoringCase(candidate, chunk.textLowerCase); + if (index === 0) { + if (chunk.text.length === candidate.length) { + // a) Check if the part matches the candidate entirely, in an case insensitive or + // sensitive manner. If it does, return that there was an exact match. + return createPatternMatch(PatternMatchKind.exact, punctuationStripped, /*isCaseSensitive:*/ candidate === chunk.text); + } + else { + // b) Check if the part is a prefix of the candidate, in a case insensitive or sensitive + // manner. If it does, return that there was a prefix match. + return createPatternMatch(PatternMatchKind.prefix, punctuationStripped, /*isCaseSensitive:*/ ts.startsWith(candidate, chunk.text)); + } + } + var isLowercase = chunk.isLowerCase; + if (isLowercase) { + if (index > 0) { + // c) If the part is entirely lowercase, then check if it is contained anywhere in the + // candidate in a case insensitive manner. If so, return that there was a substring + // match. + // + // Note: We only have a substring match if the lowercase part is prefix match of some + // word part. That way we don't match something like 'Class' when the user types 'a'. + // But we would match 'FooAttribute' (since 'Attribute' starts with 'a'). + var wordSpans = getWordSpans(candidate); + for (var _i = 0, wordSpans_1 = wordSpans; _i < wordSpans_1.length; _i++) { + var span_15 = wordSpans_1[_i]; + if (partStartsWith(candidate, span_15, chunk.text, /*ignoreCase:*/ true)) { + return createPatternMatch(PatternMatchKind.substring, punctuationStripped, + /*isCaseSensitive:*/ partStartsWith(candidate, span_15, chunk.text, /*ignoreCase:*/ false)); + } + } + } + } + else { + // d) If the part was not entirely lowercase, then check if it is contained in the + // candidate in a case *sensitive* manner. If so, return that there was a substring + // match. + if (candidate.indexOf(chunk.text) > 0) { + return createPatternMatch(PatternMatchKind.substring, punctuationStripped, /*isCaseSensitive:*/ true); + } } - else { - if (!ts.forEachProperty(opt.type, function (v) { return v === value; })) { - // Supplied value isn't a valid enum value. - diagnostics.push(ts.createCompilerDiagnosticForInvalidCustomType(opt)); + if (!isLowercase) { + // e) If the part was not entirely lowercase, then attempt a camel cased match as well. + if (chunk.characterSpans.length > 0) { + var candidateParts = getWordSpans(candidate); + var camelCaseWeight = tryCamelCaseMatch(candidate, candidateParts, chunk, /*ignoreCase:*/ false); + if (camelCaseWeight !== undefined) { + return createPatternMatch(PatternMatchKind.camelCase, punctuationStripped, /*isCaseSensitive:*/ true, /*camelCaseWeight:*/ camelCaseWeight); + } + camelCaseWeight = tryCamelCaseMatch(candidate, candidateParts, chunk, /*ignoreCase:*/ true); + if (camelCaseWeight !== undefined) { + return createPatternMatch(PatternMatchKind.camelCase, punctuationStripped, /*isCaseSensitive:*/ false, /*camelCaseWeight:*/ camelCaseWeight); + } } } - }; - for (var _i = 0, commandLineOptionsStringToEnum_1 = commandLineOptionsStringToEnum; _i < commandLineOptionsStringToEnum_1.length; _i++) { - var opt = commandLineOptionsStringToEnum_1[_i]; - _loop_3(opt); + if (isLowercase) { + // f) Is the pattern a substring of the candidate starting on one of the candidate's word boundaries? + // We could check every character boundary start of the candidate for the pattern. However, that's + // an m * n operation in the wost case. Instead, find the first instance of the pattern + // substring, and see if it starts on a capital letter. It seems unlikely that the user will try to + // filter the list based on a substring that starts on a capital letter and also with a lowercase one. + // (Pattern: fogbar, Candidate: quuxfogbarFogBar). + if (chunk.text.length < candidate.length) { + if (index > 0 && isUpperCaseLetter(candidate.charCodeAt(index))) { + return createPatternMatch(PatternMatchKind.substring, punctuationStripped, /*isCaseSensitive:*/ false); + } + } + } + return undefined; } - return options; - } - /* - * This function will compile source text from 'input' argument using specified compiler options. - * If not options are provided - it will use a set of default compiler options. - * Extra compiler options that will unconditionally be used by this function are: - * - isolatedModules = true - * - allowNonTsExtensions = true - * - noLib = true - * - noResolve = true - */ - function transpileModule(input, transpileOptions) { - var diagnostics = []; - var options = transpileOptions.compilerOptions ? fixupCompilerOptions(transpileOptions.compilerOptions, diagnostics) : getDefaultCompilerOptions(); - options.isolatedModules = true; - // transpileModule does not write anything to disk so there is no need to verify that there are no conflicts between input and output paths. - options.suppressOutputPathCheck = true; - // Filename can be non-ts file. - options.allowNonTsExtensions = true; - // We are not returning a sourceFile for lib file when asked by the program, - // so pass --noLib to avoid reporting a file not found error. - options.noLib = true; - // Clear out other settings that would not be used in transpiling this module - options.lib = undefined; - options.types = undefined; - options.noEmit = undefined; - options.noEmitOnError = undefined; - options.paths = undefined; - options.rootDirs = undefined; - options.declaration = undefined; - options.declarationDir = undefined; - options.out = undefined; - options.outFile = undefined; - // We are not doing a full typecheck, we are not resolving the whole context, - // so pass --noResolve to avoid reporting missing file errors. - options.noResolve = true; - // if jsx is specified then treat file as .tsx - var inputFileName = transpileOptions.fileName || (options.jsx ? "module.tsx" : "module.ts"); - var sourceFile = ts.createSourceFile(inputFileName, input, options.target); - if (transpileOptions.moduleName) { - sourceFile.moduleName = transpileOptions.moduleName; + function containsSpaceOrAsterisk(text) { + for (var i = 0; i < text.length; i++) { + var ch = text.charCodeAt(i); + if (ch === 32 /* space */ || ch === 42 /* asterisk */) { + return true; + } + } + return false; } - if (transpileOptions.renamedDependencies) { - sourceFile.renamedDependencies = ts.createMap(transpileOptions.renamedDependencies); + function matchSegment(candidate, segment) { + // First check if the segment matches as is. This is also useful if the segment contains + // characters we would normally strip when splitting into parts that we also may want to + // match in the candidate. For example if the segment is "@int" and the candidate is + // "@int", then that will show up as an exact match here. + // + // Note: if the segment contains a space or an asterisk then we must assume that it's a + // multi-word segment. + if (!containsSpaceOrAsterisk(segment.totalTextChunk.text)) { + var match = matchTextChunk(candidate, segment.totalTextChunk, /*punctuationStripped:*/ false); + if (match) { + return [match]; + } + } + // The logic for pattern matching is now as follows: + // + // 1) Break the segment passed in into words. Breaking is rather simple and a + // good way to think about it that if gives you all the individual alphanumeric words + // of the pattern. + // + // 2) For each word try to match the word against the candidate value. + // + // 3) Matching is as follows: + // + // a) Check if the word matches the candidate entirely, in an case insensitive or + // sensitive manner. If it does, return that there was an exact match. + // + // b) Check if the word is a prefix of the candidate, in a case insensitive or + // sensitive manner. If it does, return that there was a prefix match. + // + // c) If the word is entirely lowercase, then check if it is contained anywhere in the + // candidate in a case insensitive manner. If so, return that there was a substring + // match. + // + // Note: We only have a substring match if the lowercase part is prefix match of + // some word part. That way we don't match something like 'Class' when the user + // types 'a'. But we would match 'FooAttribute' (since 'Attribute' starts with + // 'a'). + // + // d) If the word was not entirely lowercase, then check if it is contained in the + // candidate in a case *sensitive* manner. If so, return that there was a substring + // match. + // + // e) If the word was not entirely lowercase, then attempt a camel cased match as + // well. + // + // f) The word is all lower case. Is it a case insensitive substring of the candidate starting + // on a part boundary of the candidate? + // + // Only if all words have some sort of match is the pattern considered matched. + var subWordTextChunks = segment.subWordTextChunks; + var matches = undefined; + for (var _i = 0, subWordTextChunks_1 = subWordTextChunks; _i < subWordTextChunks_1.length; _i++) { + var subWordTextChunk = subWordTextChunks_1[_i]; + // Try to match the candidate with this word + var result = matchTextChunk(candidate, subWordTextChunk, /*punctuationStripped:*/ true); + if (!result) { + return undefined; + } + matches = matches || []; + matches.push(result); + } + return matches; } - var newLine = ts.getNewLineCharacter(options); - // Output - var outputText; - var sourceMapText; - // Create a compilerHost object to allow the compiler to read and write files - var compilerHost = { - getSourceFile: function (fileName, target) { return fileName === ts.normalizePath(inputFileName) ? sourceFile : undefined; }, - writeFile: function (name, text, writeByteOrderMark) { - if (ts.fileExtensionIs(name, ".map")) { - ts.Debug.assert(sourceMapText === undefined, "Unexpected multiple source map outputs for the file '" + name + "'"); - sourceMapText = text; + function partStartsWith(candidate, candidateSpan, pattern, ignoreCase, patternSpan) { + var patternPartStart = patternSpan ? patternSpan.start : 0; + var patternPartLength = patternSpan ? patternSpan.length : pattern.length; + if (patternPartLength > candidateSpan.length) { + // Pattern part is longer than the candidate part. There can never be a match. + return false; + } + if (ignoreCase) { + for (var i = 0; i < patternPartLength; i++) { + var ch1 = pattern.charCodeAt(patternPartStart + i); + var ch2 = candidate.charCodeAt(candidateSpan.start + i); + if (toLowerCase(ch1) !== toLowerCase(ch2)) { + return false; + } } - else { - ts.Debug.assert(outputText === undefined, "Unexpected multiple outputs for the file: '" + name + "'"); - outputText = text; + } + else { + for (var i = 0; i < patternPartLength; i++) { + var ch1 = pattern.charCodeAt(patternPartStart + i); + var ch2 = candidate.charCodeAt(candidateSpan.start + i); + if (ch1 !== ch2) { + return false; + } } - }, - getDefaultLibFileName: function () { return "lib.d.ts"; }, - useCaseSensitiveFileNames: function () { return false; }, - getCanonicalFileName: function (fileName) { return fileName; }, - getCurrentDirectory: function () { return ""; }, - getNewLine: function () { return newLine; }, - fileExists: function (fileName) { return fileName === inputFileName; }, - readFile: function (fileName) { return ""; }, - directoryExists: function (directoryExists) { return true; }, - getDirectories: function (path) { return []; } - }; - var program = ts.createProgram([inputFileName], options, compilerHost); - if (transpileOptions.reportDiagnostics) { - ts.addRange(/*to*/ diagnostics, /*from*/ program.getSyntacticDiagnostics(sourceFile)); - ts.addRange(/*to*/ diagnostics, /*from*/ program.getOptionsDiagnostics()); + } + return true; } - // Emit - program.emit(); - ts.Debug.assert(outputText !== undefined, "Output generation failed"); - return { outputText: outputText, diagnostics: diagnostics, sourceMapText: sourceMapText }; - } - ts.transpileModule = transpileModule; - /* - * This is a shortcut function for transpileModule - it accepts transpileOptions as parameters and returns only outputText part of the result. - */ - function transpile(input, compilerOptions, fileName, diagnostics, moduleName) { - var output = transpileModule(input, { compilerOptions: compilerOptions, fileName: fileName, reportDiagnostics: !!diagnostics, moduleName: moduleName }); - // addRange correctly handles cases when wither 'from' or 'to' argument is missing - ts.addRange(diagnostics, output.diagnostics); - return output.outputText; - } - ts.transpile = transpile; - function createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget, version, setNodeParents, scriptKind) { - var text = scriptSnapshot.getText(0, scriptSnapshot.getLength()); - var sourceFile = ts.createSourceFile(fileName, text, scriptTarget, setNodeParents, scriptKind); - setSourceFileFields(sourceFile, scriptSnapshot, version); - return sourceFile; - } - ts.createLanguageServiceSourceFile = createLanguageServiceSourceFile; - ts.disableIncrementalParsing = false; - function updateLanguageServiceSourceFile(sourceFile, scriptSnapshot, version, textChangeRange, aggressiveChecks) { - // If we were given a text change range, and our version or open-ness changed, then - // incrementally parse this file. - if (textChangeRange) { - if (version !== sourceFile.version) { - // Once incremental parsing is ready, then just call into this function. - if (!ts.disableIncrementalParsing) { - var newText = void 0; - // grab the fragment from the beginning of the original text to the beginning of the span - var prefix = textChangeRange.span.start !== 0 - ? sourceFile.text.substr(0, textChangeRange.span.start) - : ""; - // grab the fragment from the end of the span till the end of the original text - var suffix = ts.textSpanEnd(textChangeRange.span) !== sourceFile.text.length - ? sourceFile.text.substr(ts.textSpanEnd(textChangeRange.span)) - : ""; - if (textChangeRange.newLength === 0) { - // edit was a deletion - just combine prefix and suffix - newText = prefix && suffix ? prefix + suffix : prefix || suffix; + function tryCamelCaseMatch(candidate, candidateParts, chunk, ignoreCase) { + var chunkCharacterSpans = chunk.characterSpans; + // Note: we may have more pattern parts than candidate parts. This is because multiple + // pattern parts may match a candidate part. For example "SiUI" against "SimpleUI". + // We'll have 3 pattern parts Si/U/I against two candidate parts Simple/UI. However, U + // and I will both match in UI. + var currentCandidate = 0; + var currentChunkSpan = 0; + var firstMatch = undefined; + var contiguous = undefined; + while (true) { + // Let's consider our termination cases + if (currentChunkSpan === chunkCharacterSpans.length) { + // We did match! We shall assign a weight to this + var weight = 0; + // Was this contiguous? + if (contiguous) { + weight += 1; } - else { - // it was actual edit, fetch the fragment of new text that correspond to new span - var changedText = scriptSnapshot.getText(textChangeRange.span.start, textChangeRange.span.start + textChangeRange.newLength); - // combine prefix, changed text and suffix - newText = prefix && suffix - ? prefix + changedText + suffix - : prefix - ? (prefix + changedText) - : (changedText + suffix); + // Did we start at the beginning of the candidate? + if (firstMatch === 0) { + weight += 2; } - var newSourceFile = ts.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); - setSourceFileFields(newSourceFile, scriptSnapshot, version); - // after incremental parsing nameTable might not be up-to-date - // drop it so it can be lazily recreated later - newSourceFile.nameTable = undefined; - // dispose all resources held by old script snapshot - if (sourceFile !== newSourceFile && sourceFile.scriptSnapshot) { - if (sourceFile.scriptSnapshot.dispose) { - sourceFile.scriptSnapshot.dispose(); + return weight; + } + else if (currentCandidate === candidateParts.length) { + // No match, since we still have more of the pattern to hit + return undefined; + } + var candidatePart = candidateParts[currentCandidate]; + var gotOneMatchThisCandidate = false; + // Consider the case of matching SiUI against SimpleUIElement. The candidate parts + // will be Simple/UI/Element, and the pattern parts will be Si/U/I. We'll match 'Si' + // against 'Simple' first. Then we'll match 'U' against 'UI'. However, we want to + // still keep matching pattern parts against that candidate part. + for (; currentChunkSpan < chunkCharacterSpans.length; currentChunkSpan++) { + var chunkCharacterSpan = chunkCharacterSpans[currentChunkSpan]; + if (gotOneMatchThisCandidate) { + // We've already gotten one pattern part match in this candidate. We will + // only continue trying to consumer pattern parts if the last part and this + // part are both upper case. + if (!isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan - 1].start)) || + !isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan].start))) { + break; } - sourceFile.scriptSnapshot = undefined; } - return newSourceFile; + if (!partStartsWith(candidate, candidatePart, chunk.text, ignoreCase, chunkCharacterSpan)) { + break; + } + gotOneMatchThisCandidate = true; + firstMatch = firstMatch === undefined ? currentCandidate : firstMatch; + // If we were contiguous, then keep that value. If we weren't, then keep that + // value. If we don't know, then set the value to 'true' as an initial match is + // obviously contiguous. + contiguous = contiguous === undefined ? true : contiguous; + candidatePart = ts.createTextSpan(candidatePart.start + chunkCharacterSpan.length, candidatePart.length - chunkCharacterSpan.length); + } + // Check if we matched anything at all. If we didn't, then we need to unset the + // contiguous bit if we currently had it set. + // If we haven't set the bit yet, then that means we haven't matched anything so + // far, and we don't want to change that. + if (!gotOneMatchThisCandidate && contiguous !== undefined) { + contiguous = false; } + // Move onto the next candidate. + currentCandidate++; } } - // Otherwise, just create a new source file. - return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents*/ true, sourceFile.scriptKind); } - ts.updateLanguageServiceSourceFile = updateLanguageServiceSourceFile; - function createDocumentRegistry(useCaseSensitiveFileNames, currentDirectory) { - if (currentDirectory === void 0) { currentDirectory = ""; } - // Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have - // for those settings. - var buckets = ts.createMap(); - var getCanonicalFileName = ts.createGetCanonicalFileName(!!useCaseSensitiveFileNames); - function getKeyForCompilationSettings(settings) { - return ("_" + settings.target + "|" + settings.module + "|" + settings.noResolve + "|" + settings.jsx + "|" + settings.allowJs + "|" + settings.baseUrl + "|" + JSON.stringify(settings.typeRoots) + "|" + JSON.stringify(settings.rootDirs) + "|" + JSON.stringify(settings.paths)); + ts.createPatternMatcher = createPatternMatcher; + function createSegment(text) { + return { + totalTextChunk: createTextChunk(text), + subWordTextChunks: breakPatternIntoTextChunks(text) + }; + } + // A segment is considered invalid if we couldn't find any words in it. + function segmentIsInvalid(segment) { + return segment.subWordTextChunks.length === 0; + } + function isUpperCaseLetter(ch) { + // Fast check for the ascii range. + if (ch >= 65 /* A */ && ch <= 90 /* Z */) { + return true; } - function getBucketForCompilationSettings(key, createIfMissing) { - var bucket = buckets[key]; - if (!bucket && createIfMissing) { - buckets[key] = bucket = ts.createFileMap(); - } - return bucket; + if (ch < 127 /* maxAsciiCharacter */ || !ts.isUnicodeIdentifierStart(ch, 2 /* Latest */)) { + return false; } - function reportStats() { - var bucketInfoArray = Object.keys(buckets).filter(function (name) { return name && name.charAt(0) === "_"; }).map(function (name) { - var entries = buckets[name]; - var sourceFiles = []; - entries.forEachValue(function (key, entry) { - sourceFiles.push({ - name: key, - refCount: entry.languageServiceRefCount, - references: entry.owners.slice(0) - }); - }); - sourceFiles.sort(function (x, y) { return y.refCount - x.refCount; }); - return { - bucket: name, - sourceFiles: sourceFiles - }; - }); - return JSON.stringify(bucketInfoArray, undefined, 2); + // TODO: find a way to determine this for any unicode characters in a + // non-allocating manner. + var str = String.fromCharCode(ch); + return str === str.toUpperCase(); + } + function isLowerCaseLetter(ch) { + // Fast check for the ascii range. + if (ch >= 97 /* a */ && ch <= 122 /* z */) { + return true; } - function acquireDocument(fileName, compilationSettings, scriptSnapshot, version, scriptKind) { - var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); - var key = getKeyForCompilationSettings(compilationSettings); - return acquireDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind); + if (ch < 127 /* maxAsciiCharacter */ || !ts.isUnicodeIdentifierStart(ch, 2 /* Latest */)) { + return false; } - function acquireDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind) { - return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, /*acquiring*/ true, scriptKind); + // TODO: find a way to determine this for any unicode characters in a + // non-allocating manner. + var str = String.fromCharCode(ch); + return str === str.toLowerCase(); + } + // Assumes 'value' is already lowercase. + function indexOfIgnoringCase(string, value) { + for (var i = 0, n = string.length - value.length; i <= n; i++) { + if (startsWithIgnoringCase(string, value, i)) { + return i; + } } - function updateDocument(fileName, compilationSettings, scriptSnapshot, version, scriptKind) { - var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); - var key = getKeyForCompilationSettings(compilationSettings); - return updateDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind); + return -1; + } + // Assumes 'value' is already lowercase. + function startsWithIgnoringCase(string, value, start) { + for (var i = 0, n = value.length; i < n; i++) { + var ch1 = toLowerCase(string.charCodeAt(i + start)); + var ch2 = value.charCodeAt(i); + if (ch1 !== ch2) { + return false; + } } - function updateDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind) { - return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, /*acquiring*/ false, scriptKind); + return true; + } + function toLowerCase(ch) { + // Fast convert for the ascii range. + if (ch >= 65 /* A */ && ch <= 90 /* Z */) { + return 97 /* a */ + (ch - 65 /* A */); } - function acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, acquiring, scriptKind) { - var bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ true); - var entry = bucket.get(path); - if (!entry) { - ts.Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?"); - // Have never seen this file with these settings. Create a new source file for it. - var sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false, scriptKind); - entry = { - sourceFile: sourceFile, - languageServiceRefCount: 0, - owners: [] - }; - bucket.set(path, entry); + if (ch < 127 /* maxAsciiCharacter */) { + return ch; + } + // TODO: find a way to compute this for any unicode characters in a + // non-allocating manner. + return String.fromCharCode(ch).toLowerCase().charCodeAt(0); + } + function isDigit(ch) { + // TODO(cyrusn): Find a way to support this for unicode digits. + return ch >= 48 /* _0 */ && ch <= 57 /* _9 */; + } + function isWordChar(ch) { + return isUpperCaseLetter(ch) || isLowerCaseLetter(ch) || isDigit(ch) || ch === 95 /* _ */ || ch === 36 /* $ */; + } + function breakPatternIntoTextChunks(pattern) { + var result = []; + var wordStart = 0; + var wordLength = 0; + for (var i = 0; i < pattern.length; i++) { + var ch = pattern.charCodeAt(i); + if (isWordChar(ch)) { + if (wordLength === 0) { + wordStart = i; + } + wordLength++; } else { - // We have an entry for this file. However, it may be for a different version of - // the script snapshot. If so, update it appropriately. Otherwise, we can just - // return it as is. - if (entry.sourceFile.version !== version) { - entry.sourceFile = updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version, scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot)); + if (wordLength > 0) { + result.push(createTextChunk(pattern.substr(wordStart, wordLength))); + wordLength = 0; } } - // If we're acquiring, then this is the first time this LS is asking for this document. - // Increase our ref count so we know there's another LS using the document. If we're - // not acquiring, then that means the LS is 'updating' the file instead, and that means - // it has already acquired the document previously. As such, we do not need to increase - // the ref count. - if (acquiring) { - entry.languageServiceRefCount++; + } + if (wordLength > 0) { + result.push(createTextChunk(pattern.substr(wordStart, wordLength))); + } + return result; + } + function createTextChunk(text) { + var textLowerCase = text.toLowerCase(); + return { + text: text, + textLowerCase: textLowerCase, + isLowerCase: text === textLowerCase, + characterSpans: breakIntoCharacterSpans(text) + }; + } + /* @internal */ function breakIntoCharacterSpans(identifier) { + return breakIntoSpans(identifier, /*word:*/ false); + } + ts.breakIntoCharacterSpans = breakIntoCharacterSpans; + /* @internal */ function breakIntoWordSpans(identifier) { + return breakIntoSpans(identifier, /*word:*/ true); + } + ts.breakIntoWordSpans = breakIntoWordSpans; + function breakIntoSpans(identifier, word) { + var result = []; + var wordStart = 0; + for (var i = 1, n = identifier.length; i < n; i++) { + var lastIsDigit = isDigit(identifier.charCodeAt(i - 1)); + var currentIsDigit = isDigit(identifier.charCodeAt(i)); + var hasTransitionFromLowerToUpper = transitionFromLowerToUpper(identifier, word, i); + var hasTransitionFromUpperToLower = transitionFromUpperToLower(identifier, word, i, wordStart); + if (charIsPunctuation(identifier.charCodeAt(i - 1)) || + charIsPunctuation(identifier.charCodeAt(i)) || + lastIsDigit !== currentIsDigit || + hasTransitionFromLowerToUpper || + hasTransitionFromUpperToLower) { + if (!isAllPunctuation(identifier, wordStart, i)) { + result.push(ts.createTextSpan(wordStart, i - wordStart)); + } + wordStart = i; } - return entry.sourceFile; } - function releaseDocument(fileName, compilationSettings) { - var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); - var key = getKeyForCompilationSettings(compilationSettings); - return releaseDocumentWithKey(path, key); + if (!isAllPunctuation(identifier, wordStart, identifier.length)) { + result.push(ts.createTextSpan(wordStart, identifier.length - wordStart)); } - function releaseDocumentWithKey(path, key) { - var bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ false); - ts.Debug.assert(bucket !== undefined); - var entry = bucket.get(path); - entry.languageServiceRefCount--; - ts.Debug.assert(entry.languageServiceRefCount >= 0); - if (entry.languageServiceRefCount === 0) { - bucket.remove(path); + return result; + } + function charIsPunctuation(ch) { + switch (ch) { + case 33 /* exclamation */: + case 34 /* doubleQuote */: + case 35 /* hash */: + case 37 /* percent */: + case 38 /* ampersand */: + case 39 /* singleQuote */: + case 40 /* openParen */: + case 41 /* closeParen */: + case 42 /* asterisk */: + case 44 /* comma */: + case 45 /* minus */: + case 46 /* dot */: + case 47 /* slash */: + case 58 /* colon */: + case 59 /* semicolon */: + case 63 /* question */: + case 64 /* at */: + case 91 /* openBracket */: + case 92 /* backslash */: + case 93 /* closeBracket */: + case 95 /* _ */: + case 123 /* openBrace */: + case 125 /* closeBrace */: + return true; + } + return false; + } + function isAllPunctuation(identifier, start, end) { + for (var i = start; i < end; i++) { + var ch = identifier.charCodeAt(i); + // We don't consider _ or $ as punctuation as there may be things with that name. + if (!charIsPunctuation(ch) || ch === 95 /* _ */ || ch === 36 /* $ */) { + return false; } } - return { - acquireDocument: acquireDocument, - acquireDocumentWithKey: acquireDocumentWithKey, - updateDocument: updateDocument, - updateDocumentWithKey: updateDocumentWithKey, - releaseDocument: releaseDocument, - releaseDocumentWithKey: releaseDocumentWithKey, - reportStats: reportStats, - getKeyForCompilationSettings: getKeyForCompilationSettings - }; + return true; } - ts.createDocumentRegistry = createDocumentRegistry; + function transitionFromUpperToLower(identifier, word, index, wordStart) { + if (word) { + // Cases this supports: + // 1) IDisposable -> I, Disposable + // 2) UIElement -> UI, Element + // 3) HTMLDocument -> HTML, Document + // + // etc. + if (index !== wordStart && + index + 1 < identifier.length) { + var currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index)); + var nextIsLower = isLowerCaseLetter(identifier.charCodeAt(index + 1)); + if (currentIsUpper && nextIsLower) { + // We have a transition from an upper to a lower letter here. But we only + // want to break if all the letters that preceded are uppercase. i.e. if we + // have "Foo" we don't want to break that into "F, oo". But if we have + // "IFoo" or "UIFoo", then we want to break that into "I, Foo" and "UI, + // Foo". i.e. the last uppercase letter belongs to the lowercase letters + // that follows. Note: this will make the following not split properly: + // "HELLOthere". However, these sorts of names do not show up in .Net + // programs. + for (var i = wordStart; i < index; i++) { + if (!isUpperCaseLetter(identifier.charCodeAt(i))) { + return false; + } + } + return true; + } + } + } + return false; + } + function transitionFromLowerToUpper(identifier, word, index) { + var lastIsUpper = isUpperCaseLetter(identifier.charCodeAt(index - 1)); + var currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index)); + // See if the casing indicates we're starting a new word. Note: if we're breaking on + // words, then just seeing an upper case character isn't enough. Instead, it has to + // be uppercase and the previous character can't be uppercase. + // + // For example, breaking "AddMetadata" on words would make: Add Metadata + // + // on characters would be: A dd M etadata + // + // Break "AM" on words would be: AM + // + // on characters would be: A M + // + // We break the search string on characters. But we break the symbol name on words. + var transition = word + ? (currentIsUpper && !lastIsUpper) + : currentIsUpper; + return transition; + } +})(ts || (ts = {})); +var ts; +(function (ts) { function preProcessFile(sourceText, readImportFiles, detectJavaScriptImports) { if (readImportFiles === void 0) { readImportFiles = true; } if (detectJavaScriptImports === void 0) { detectJavaScriptImports = false; } @@ -55284,7 +68918,7 @@ var ts; // ambient modules that are found inside external modules are interpreted as module augmentations var externalModule = false; function nextToken() { - var token = scanner.scan(); + var token = ts.scanner.scan(); if (token === 15 /* OpenBraceToken */) { braceNesting++; } @@ -55311,8 +68945,8 @@ var ts; }); } function getFileReference() { - var file = scanner.getTokenValue(); - var pos = scanner.getTokenPos(); + var file = ts.scanner.getTokenValue(); + var pos = ts.scanner.getTokenPos(); return { fileName: file, pos: pos, @@ -55338,7 +68972,7 @@ var ts; * Returns true if at least one token was consumed from the stream */ function tryConsumeDeclare() { - var token = scanner.getToken(); + var token = ts.scanner.getToken(); if (token === 122 /* DeclareKeyword */) { // declare module "mod" token = nextToken(); @@ -55356,7 +68990,7 @@ var ts; * Returns true if at least one token was consumed from the stream */ function tryConsumeImport() { - var token = scanner.getToken(); + var token = ts.scanner.getToken(); if (token === 89 /* ImportKeyword */) { token = nextToken(); if (token === 9 /* StringLiteral */) { @@ -55426,3988 +69060,5387 @@ var ts; } } } - return true; + return true; + } + return false; + } + function tryConsumeExport() { + var token = ts.scanner.getToken(); + if (token === 82 /* ExportKeyword */) { + markAsExternalModuleIfTopLevel(); + token = nextToken(); + if (token === 15 /* OpenBraceToken */) { + token = nextToken(); + // consume "{ a as B, c, d as D}" clauses + // make sure it stops on EOF + while (token !== 16 /* CloseBraceToken */ && token !== 1 /* EndOfFileToken */) { + token = nextToken(); + } + if (token === 16 /* CloseBraceToken */) { + token = nextToken(); + if (token === 136 /* FromKeyword */) { + token = nextToken(); + if (token === 9 /* StringLiteral */) { + // export {a as A} from "mod"; + // export {a, b as B} from "mod" + recordModuleName(); + } + } + } + } + else if (token === 37 /* AsteriskToken */) { + token = nextToken(); + if (token === 136 /* FromKeyword */) { + token = nextToken(); + if (token === 9 /* StringLiteral */) { + // export * from "mod" + recordModuleName(); + } + } + } + else if (token === 89 /* ImportKeyword */) { + token = nextToken(); + if (token === 69 /* Identifier */ || ts.isKeyword(token)) { + token = nextToken(); + if (token === 56 /* EqualsToken */) { + if (tryConsumeRequireCall(/*skipCurrentToken*/ true)) { + return true; + } + } + } + } + return true; + } + return false; + } + function tryConsumeRequireCall(skipCurrentToken) { + var token = skipCurrentToken ? nextToken() : ts.scanner.getToken(); + if (token === 129 /* RequireKeyword */) { + token = nextToken(); + if (token === 17 /* OpenParenToken */) { + token = nextToken(); + if (token === 9 /* StringLiteral */) { + // require("mod"); + recordModuleName(); + } + } + return true; + } + return false; + } + function tryConsumeDefine() { + var token = ts.scanner.getToken(); + if (token === 69 /* Identifier */ && ts.scanner.getTokenValue() === "define") { + token = nextToken(); + if (token !== 17 /* OpenParenToken */) { + return true; + } + token = nextToken(); + if (token === 9 /* StringLiteral */) { + // looks like define ("modname", ... - skip string literal and comma + token = nextToken(); + if (token === 24 /* CommaToken */) { + token = nextToken(); + } + else { + // unexpected token + return true; + } + } + // should be start of dependency list + if (token !== 19 /* OpenBracketToken */) { + return true; + } + // skip open bracket + token = nextToken(); + var i = 0; + // scan until ']' or EOF + while (token !== 20 /* CloseBracketToken */ && token !== 1 /* EndOfFileToken */) { + // record string literals as module names + if (token === 9 /* StringLiteral */) { + recordModuleName(); + i++; + } + token = nextToken(); + } + return true; + } + return false; + } + function processImports() { + ts.scanner.setText(sourceText); + nextToken(); + // Look for: + // import "mod"; + // import d from "mod" + // import {a as A } from "mod"; + // import * as NS from "mod" + // import d, {a, b as B} from "mod" + // import i = require("mod"); + // + // export * from "mod" + // export {a as b} from "mod" + // export import i = require("mod") + // (for JavaScript files) require("mod") + while (true) { + if (ts.scanner.getToken() === 1 /* EndOfFileToken */) { + break; + } + // check if at least one of alternative have moved scanner forward + if (tryConsumeDeclare() || + tryConsumeImport() || + tryConsumeExport() || + (detectJavaScriptImports && (tryConsumeRequireCall(/*skipCurrentToken*/ false) || tryConsumeDefine()))) { + continue; + } + else { + nextToken(); + } + } + ts.scanner.setText(undefined); + } + if (readImportFiles) { + processImports(); + } + processTripleSlashDirectives(); + if (externalModule) { + // for external modules module all nested ambient modules are augmentations + if (ambientExternalModules) { + // move all detected ambient modules to imported files since they need to be resolved + for (var _i = 0, ambientExternalModules_1 = ambientExternalModules; _i < ambientExternalModules_1.length; _i++) { + var decl = ambientExternalModules_1[_i]; + importedFiles.push(decl.ref); + } + } + return { referencedFiles: referencedFiles, typeReferenceDirectives: typeReferenceDirectives, importedFiles: importedFiles, isLibFile: isNoDefaultLib, ambientExternalModules: undefined }; + } + else { + // for global scripts ambient modules still can have augmentations - look for ambient modules with depth > 0 + var ambientModuleNames = void 0; + if (ambientExternalModules) { + for (var _a = 0, ambientExternalModules_2 = ambientExternalModules; _a < ambientExternalModules_2.length; _a++) { + var decl = ambientExternalModules_2[_a]; + if (decl.depth === 0) { + if (!ambientModuleNames) { + ambientModuleNames = []; + } + ambientModuleNames.push(decl.ref.fileName); + } + else { + importedFiles.push(decl.ref); + } + } + } + return { referencedFiles: referencedFiles, typeReferenceDirectives: typeReferenceDirectives, importedFiles: importedFiles, isLibFile: isNoDefaultLib, ambientExternalModules: ambientModuleNames }; + } + } + ts.preProcessFile = preProcessFile; +})(ts || (ts = {})); +/* @internal */ +var ts; +(function (ts) { + var Rename; + (function (Rename) { + function getRenameInfo(typeChecker, defaultLibFileName, getCanonicalFileName, sourceFile, position) { + var canonicalDefaultLibName = getCanonicalFileName(ts.normalizePath(defaultLibFileName)); + var node = ts.getTouchingWord(sourceFile, position, /*includeJsDocComment*/ true); + if (node) { + if (node.kind === 69 /* Identifier */ || + node.kind === 9 /* StringLiteral */ || + ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || + ts.isThis(node)) { + var symbol = typeChecker.getSymbolAtLocation(node); + // Only allow a symbol to be renamed if it actually has at least one declaration. + if (symbol) { + var declarations = symbol.getDeclarations(); + if (declarations && declarations.length > 0) { + // Disallow rename for elements that are defined in the standard TypeScript library. + if (ts.forEach(declarations, isDefinedInLibraryFile)) { + return getRenameInfoError(ts.getLocaleSpecificMessage(ts.Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library)); + } + var displayName = ts.stripQuotes(ts.getDeclaredName(typeChecker, symbol, node)); + var kind = ts.SymbolDisplay.getSymbolKind(typeChecker, symbol, node); + if (kind) { + return { + canRename: true, + kind: kind, + displayName: displayName, + localizedErrorMessage: undefined, + fullDisplayName: typeChecker.getFullyQualifiedName(symbol), + kindModifiers: ts.SymbolDisplay.getSymbolModifiers(symbol), + triggerSpan: createTriggerSpanForNode(node, sourceFile) + }; + } + } + } + else if (node.kind === 9 /* StringLiteral */) { + var type = ts.getStringLiteralTypeForNode(node, typeChecker); + if (type) { + if (isDefinedInLibraryFile(node)) { + return getRenameInfoError(ts.getLocaleSpecificMessage(ts.Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library)); + } + else { + var displayName = ts.stripQuotes(type.text); + return { + canRename: true, + kind: ts.ScriptElementKind.variableElement, + displayName: displayName, + localizedErrorMessage: undefined, + fullDisplayName: displayName, + kindModifiers: ts.ScriptElementKindModifier.none, + triggerSpan: createTriggerSpanForNode(node, sourceFile) + }; + } + } + } + } + } + return getRenameInfoError(ts.getLocaleSpecificMessage(ts.Diagnostics.You_cannot_rename_this_element)); + function getRenameInfoError(localizedErrorMessage) { + return { + canRename: false, + localizedErrorMessage: localizedErrorMessage, + displayName: undefined, + fullDisplayName: undefined, + kind: undefined, + kindModifiers: undefined, + triggerSpan: undefined + }; + } + function isDefinedInLibraryFile(declaration) { + if (defaultLibFileName) { + var sourceFile_2 = declaration.getSourceFile(); + var canonicalName = getCanonicalFileName(ts.normalizePath(sourceFile_2.fileName)); + if (canonicalName === canonicalDefaultLibName) { + return true; + } + } + return false; + } + function createTriggerSpanForNode(node, sourceFile) { + var start = node.getStart(sourceFile); + var width = node.getWidth(sourceFile); + if (node.kind === 9 /* StringLiteral */) { + // Exclude the quotes + start += 1; + width -= 2; + } + return ts.createTextSpan(start, width); + } + } + Rename.getRenameInfo = getRenameInfo; + })(Rename = ts.Rename || (ts.Rename = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var SignatureHelp; + (function (SignatureHelp) { + // A partially written generic type expression is not guaranteed to have the correct syntax tree. the expression could be parsed as less than/greater than expression or a comma expression + // or some other combination depending on what the user has typed so far. For the purposes of signature help we need to consider any location after "<" as a possible generic type reference. + // To do this, the method will back parse the expression starting at the position required. it will try to parse the current expression as a generic type expression, if it did succeed it + // will return the generic identifier that started the expression (e.g. "foo" in "foo(#a, b) -> The token introduces a list, and should begin a sig help session + // Case 2: + // fo#o#(a, b)# -> The token is either not associated with a list, or ends a list, so the session should end + // Case 3: + // foo(a#, #b#) -> The token is buried inside a list, and should give sig help + // Find out if 'node' is an argument, a type argument, or neither + if (node.kind === 25 /* LessThanToken */ || + node.kind === 17 /* OpenParenToken */) { + // Find the list that starts right *after* the < or ( token. + // If the user has just opened a list, consider this item 0. + var list = getChildListThatStartsWithOpenerToken(callExpression, node, sourceFile); + var isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos; + ts.Debug.assert(list !== undefined); + return { + kind: isTypeArgList ? 0 /* TypeArguments */ : 1 /* CallArguments */, + invocation: callExpression, + argumentsSpan: getApplicableSpanForArguments(list, sourceFile), + argumentIndex: 0, + argumentCount: getArgumentCount(list) + }; } - token = nextToken(); - if (token === 9 /* StringLiteral */) { - // looks like define ("modname", ... - skip string literal and comma - token = nextToken(); - if (token === 24 /* CommaToken */) { - token = nextToken(); - } - else { - // unexpected token - return true; - } + // findListItemInfo can return undefined if we are not in parent's argument list + // or type argument list. This includes cases where the cursor is: + // - To the right of the closing paren, non-substitution template, or template tail. + // - Between the type arguments and the arguments (greater than token) + // - On the target of the call (parent.func) + // - On the 'new' keyword in a 'new' expression + var listItemInfo = ts.findListItemInfo(node); + if (listItemInfo) { + var list = listItemInfo.list; + var isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos; + var argumentIndex = getArgumentIndex(list, node); + var argumentCount = getArgumentCount(list); + ts.Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, "argumentCount < argumentIndex, " + argumentCount + " < " + argumentIndex); + return { + kind: isTypeArgList ? 0 /* TypeArguments */ : 1 /* CallArguments */, + invocation: callExpression, + argumentsSpan: getApplicableSpanForArguments(list, sourceFile), + argumentIndex: argumentIndex, + argumentCount: argumentCount + }; } - // should be start of dependency list - if (token !== 19 /* OpenBracketToken */) { - return true; + return undefined; + } + else if (node.kind === 11 /* NoSubstitutionTemplateLiteral */ && node.parent.kind === 176 /* TaggedTemplateExpression */) { + // Check if we're actually inside the template; + // otherwise we'll fall out and return undefined. + if (ts.isInsideTemplateLiteral(node, position)) { + return getArgumentListInfoForTemplate(node.parent, /*argumentIndex*/ 0, sourceFile); } - // skip open bracket - token = nextToken(); - var i = 0; - // scan until ']' or EOF - while (token !== 20 /* CloseBracketToken */ && token !== 1 /* EndOfFileToken */) { - // record string literals as module names - if (token === 9 /* StringLiteral */) { - recordModuleName(); - i++; - } - token = nextToken(); + } + else if (node.kind === 12 /* TemplateHead */ && node.parent.parent.kind === 176 /* TaggedTemplateExpression */) { + var templateExpression = node.parent; + var tagExpression = templateExpression.parent; + ts.Debug.assert(templateExpression.kind === 189 /* TemplateExpression */); + var argumentIndex = ts.isInsideTemplateLiteral(node, position) ? 0 : 1; + return getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile); + } + else if (node.parent.kind === 197 /* TemplateSpan */ && node.parent.parent.parent.kind === 176 /* TaggedTemplateExpression */) { + var templateSpan = node.parent; + var templateExpression = templateSpan.parent; + var tagExpression = templateExpression.parent; + ts.Debug.assert(templateExpression.kind === 189 /* TemplateExpression */); + // If we're just after a template tail, don't show signature help. + if (node.kind === 14 /* TemplateTail */ && !ts.isInsideTemplateLiteral(node, position)) { + return undefined; } - return true; + var spanIndex = templateExpression.templateSpans.indexOf(templateSpan); + var argumentIndex = getArgumentIndexForTemplatePiece(spanIndex, node, position); + return getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile); } - return false; + return undefined; } - function processImports() { - scanner.setText(sourceText); - nextToken(); - // Look for: - // import "mod"; - // import d from "mod" - // import {a as A } from "mod"; - // import * as NS from "mod" - // import d, {a, b as B} from "mod" - // import i = require("mod"); + function getArgumentIndex(argumentsList, node) { + // The list we got back can include commas. In the presence of errors it may + // also just have nodes without commas. For example "Foo(a b c)" will have 3 + // args without commas. We want to find what index we're at. So we count + // forward until we hit ourselves, only incrementing the index if it isn't a + // comma. // - // export * from "mod" - // export {a as b} from "mod" - // export import i = require("mod") - // (for JavaScript files) require("mod") - while (true) { - if (scanner.getToken() === 1 /* EndOfFileToken */) { + // Note: the subtlety around trailing commas (in getArgumentCount) does not apply + // here. That's because we're only walking forward until we hit the node we're + // on. In that case, even if we're after the trailing comma, we'll still see + // that trailing comma in the list, and we'll have generated the appropriate + // arg index. + var argumentIndex = 0; + var listChildren = argumentsList.getChildren(); + for (var _i = 0, listChildren_1 = listChildren; _i < listChildren_1.length; _i++) { + var child = listChildren_1[_i]; + if (child === node) { break; } - // check if at least one of alternative have moved scanner forward - if (tryConsumeDeclare() || - tryConsumeImport() || - tryConsumeExport() || - (detectJavaScriptImports && (tryConsumeRequireCall(/*skipCurrentToken*/ false) || tryConsumeDefine()))) { - continue; - } - else { - nextToken(); + if (child.kind !== 24 /* CommaToken */) { + argumentIndex++; } } - scanner.setText(undefined); - } - if (readImportFiles) { - processImports(); + return argumentIndex; } - processTripleSlashDirectives(); - if (externalModule) { - // for external modules module all nested ambient modules are augmentations - if (ambientExternalModules) { - // move all detected ambient modules to imported files since they need to be resolved - for (var _i = 0, ambientExternalModules_1 = ambientExternalModules; _i < ambientExternalModules_1.length; _i++) { - var decl = ambientExternalModules_1[_i]; - importedFiles.push(decl.ref); - } + function getArgumentCount(argumentsList) { + // The argument count for a list is normally the number of non-comma children it has. + // For example, if you have "Foo(a,b)" then there will be three children of the arg + // list 'a' '' 'b'. So, in this case the arg count will be 2. However, there + // is a small subtlety. If you have "Foo(a,)", then the child list will just have + // 'a' ''. So, in the case where the last child is a comma, we increase the + // arg count by one to compensate. + // + // Note: this subtlety only applies to the last comma. If you had "Foo(a,," then + // we'll have: 'a' '' '' + // That will give us 2 non-commas. We then add one for the last comma, givin us an + // arg count of 3. + var listChildren = argumentsList.getChildren(); + var argumentCount = ts.countWhere(listChildren, function (arg) { return arg.kind !== 24 /* CommaToken */; }); + if (listChildren.length > 0 && ts.lastOrUndefined(listChildren).kind === 24 /* CommaToken */) { + argumentCount++; } - return { referencedFiles: referencedFiles, typeReferenceDirectives: typeReferenceDirectives, importedFiles: importedFiles, isLibFile: isNoDefaultLib, ambientExternalModules: undefined }; + return argumentCount; } - else { - // for global scripts ambient modules still can have augmentations - look for ambient modules with depth > 0 - var ambientModuleNames = void 0; - if (ambientExternalModules) { - for (var _a = 0, ambientExternalModules_2 = ambientExternalModules; _a < ambientExternalModules_2.length; _a++) { - var decl = ambientExternalModules_2[_a]; - if (decl.depth === 0) { - if (!ambientModuleNames) { - ambientModuleNames = []; - } - ambientModuleNames.push(decl.ref.fileName); - } - else { - importedFiles.push(decl.ref); - } + // spanIndex is either the index for a given template span. + // This does not give appropriate results for a NoSubstitutionTemplateLiteral + function getArgumentIndexForTemplatePiece(spanIndex, node, position) { + // Because the TemplateStringsArray is the first argument, we have to offset each substitution expression by 1. + // There are three cases we can encounter: + // 1. We are precisely in the template literal (argIndex = 0). + // 2. We are in or to the right of the substitution expression (argIndex = spanIndex + 1). + // 3. We are directly to the right of the template literal, but because we look for the token on the left, + // not enough to put us in the substitution expression; we should consider ourselves part of + // the *next* span's expression by offsetting the index (argIndex = (spanIndex + 1) + 1). + // + // Example: f `# abcd $#{# 1 + 1# }# efghi ${ #"#hello"# } # ` + // ^ ^ ^ ^ ^ ^ ^ ^ ^ + // Case: 1 1 3 2 1 3 2 2 1 + ts.Debug.assert(position >= node.getStart(), "Assumed 'position' could not occur before node."); + if (ts.isTemplateLiteralKind(node.kind)) { + if (ts.isInsideTemplateLiteral(node, position)) { + return 0; } + return spanIndex + 2; } - return { referencedFiles: referencedFiles, typeReferenceDirectives: typeReferenceDirectives, importedFiles: importedFiles, isLibFile: isNoDefaultLib, ambientExternalModules: ambientModuleNames }; + return spanIndex + 1; } - } - ts.preProcessFile = preProcessFile; - /// Helpers - function getTargetLabel(referenceNode, labelName) { - while (referenceNode) { - if (referenceNode.kind === 214 /* LabeledStatement */ && referenceNode.label.text === labelName) { - return referenceNode.label; - } - referenceNode = referenceNode.parent; + function getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile) { + // argumentCount is either 1 or (numSpans + 1) to account for the template strings array argument. + var argumentCount = tagExpression.template.kind === 11 /* NoSubstitutionTemplateLiteral */ + ? 1 + : tagExpression.template.templateSpans.length + 1; + ts.Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, "argumentCount < argumentIndex, " + argumentCount + " < " + argumentIndex); + return { + kind: 2 /* TaggedTemplateArguments */, + invocation: tagExpression, + argumentsSpan: getApplicableSpanForTaggedTemplate(tagExpression, sourceFile), + argumentIndex: argumentIndex, + argumentCount: argumentCount + }; } - return undefined; - } - function isJumpStatementTarget(node) { - return node.kind === 69 /* Identifier */ && - (node.parent.kind === 210 /* BreakStatement */ || node.parent.kind === 209 /* ContinueStatement */) && - node.parent.label === node; - } - function isLabelOfLabeledStatement(node) { - return node.kind === 69 /* Identifier */ && - node.parent.kind === 214 /* LabeledStatement */ && - node.parent.label === node; - } - /** - * Whether or not a 'node' is preceded by a label of the given string. - * Note: 'node' cannot be a SourceFile. - */ - function isLabeledBy(node, labelName) { - for (var owner = node.parent; owner.kind === 214 /* LabeledStatement */; owner = owner.parent) { - if (owner.label.text === labelName) { - return true; - } + function getApplicableSpanForArguments(argumentsList, sourceFile) { + // We use full start and skip trivia on the end because we want to include trivia on + // both sides. For example, + // + // foo( /*comment */ a, b, c /*comment*/ ) + // | | + // + // The applicable span is from the first bar to the second bar (inclusive, + // but not including parentheses) + var applicableSpanStart = argumentsList.getFullStart(); + var applicableSpanEnd = ts.skipTrivia(sourceFile.text, argumentsList.getEnd(), /*stopAfterLineBreak*/ false); + return ts.createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart); } - return false; - } - function isLabelName(node) { - return isLabelOfLabeledStatement(node) || isJumpStatementTarget(node); - } - function isRightSideOfQualifiedName(node) { - return node.parent.kind === 139 /* QualifiedName */ && node.parent.right === node; - } - function isRightSideOfPropertyAccess(node) { - return node && node.parent && node.parent.kind === 172 /* PropertyAccessExpression */ && node.parent.name === node; - } - function climbPastPropertyAccess(node) { - return isRightSideOfPropertyAccess(node) ? node.parent : node; - } - /** Get `C` given `N` if `N` is in the position `class C extends N` or `class C extends foo.N` where `N` is an identifier. */ - function tryGetClassByExtendingIdentifier(node) { - return ts.tryGetClassExtendingExpressionWithTypeArguments(climbPastPropertyAccess(node).parent); - } - function isCallExpressionTarget(node) { - return isCallOrNewExpressionTarget(node, 174 /* CallExpression */); - } - function isNewExpressionTarget(node) { - return isCallOrNewExpressionTarget(node, 175 /* NewExpression */); - } - function isCallOrNewExpressionTarget(node, kind) { - var target = climbPastPropertyAccess(node); - return target && target.parent && target.parent.kind === kind && target.parent.expression === target; - } - function climbPastManyPropertyAccesses(node) { - return isRightSideOfPropertyAccess(node) ? climbPastManyPropertyAccesses(node.parent) : node; - } - /** Returns a CallLikeExpression where `node` is the target being invoked. */ - function getAncestorCallLikeExpression(node) { - var target = climbPastManyPropertyAccesses(node); - var callLike = target.parent; - return callLike && ts.isCallLikeExpression(callLike) && ts.getInvokedExpression(callLike) === target && callLike; - } - function tryGetSignatureDeclaration(typeChecker, node) { - var callLike = getAncestorCallLikeExpression(node); - return callLike && typeChecker.getResolvedSignature(callLike).declaration; - } - function isNameOfModuleDeclaration(node) { - return node.parent.kind === 225 /* ModuleDeclaration */ && node.parent.name === node; - } - function isNameOfFunctionDeclaration(node) { - return node.kind === 69 /* Identifier */ && - ts.isFunctionLike(node.parent) && node.parent.name === node; - } - function isObjectLiteralPropertyDeclaration(node) { - switch (node.kind) { - case 253 /* PropertyAssignment */: - case 254 /* ShorthandPropertyAssignment */: - case 147 /* MethodDeclaration */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - return true; + function getApplicableSpanForTaggedTemplate(taggedTemplate, sourceFile) { + var template = taggedTemplate.template; + var applicableSpanStart = template.getStart(); + var applicableSpanEnd = template.getEnd(); + // We need to adjust the end position for the case where the template does not have a tail. + // Otherwise, we will not show signature help past the expression. + // For example, + // + // ` ${ 1 + 1 foo(10) + // | | + // + // This is because a Missing node has no width. However, what we actually want is to include trivia + // leading up to the next token in case the user is about to type in a TemplateMiddle or TemplateTail. + if (template.kind === 189 /* TemplateExpression */) { + var lastSpan = ts.lastOrUndefined(template.templateSpans); + if (lastSpan.literal.getFullWidth() === 0) { + applicableSpanEnd = ts.skipTrivia(sourceFile.text, applicableSpanEnd, /*stopAfterLineBreak*/ false); + } + } + return ts.createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart); } - return false; - } - /** - * Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 } - */ - function getContainingObjectLiteralElement(node) { - switch (node.kind) { - case 9 /* StringLiteral */: - case 8 /* NumericLiteral */: - if (node.parent.kind === 140 /* ComputedPropertyName */) { - return isObjectLiteralPropertyDeclaration(node.parent.parent) ? node.parent.parent : undefined; + function getContainingArgumentInfo(node, position, sourceFile) { + for (var n = node; n.kind !== 256 /* SourceFile */; n = n.parent) { + if (ts.isFunctionBlock(n)) { + return undefined; } - // intential fall through - case 69 /* Identifier */: - return isObjectLiteralPropertyDeclaration(node.parent) && node.parent.name === node ? node.parent : undefined; + // If the node is not a subspan of its parent, this is a big problem. + // There have been crashes that might be caused by this violation. + if (n.pos < n.parent.pos || n.end > n.parent.end) { + ts.Debug.fail("Node of kind " + n.kind + " is not a subspan of its parent of kind " + n.parent.kind); + } + var argumentInfo = getImmediatelyContainingArgumentInfo(n, position, sourceFile); + if (argumentInfo) { + return argumentInfo; + } + } + return undefined; } - return undefined; - } - function isLiteralNameOfPropertyDeclarationOrIndexAccess(node) { - if (node.kind === 9 /* StringLiteral */ || node.kind === 8 /* NumericLiteral */) { - switch (node.parent.kind) { - case 145 /* PropertyDeclaration */: - case 144 /* PropertySignature */: - case 253 /* PropertyAssignment */: - case 255 /* EnumMember */: - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 225 /* ModuleDeclaration */: - return node.parent.name === node; - case 173 /* ElementAccessExpression */: - return node.parent.argumentExpression === node; - case 140 /* ComputedPropertyName */: - return true; + SignatureHelp.getContainingArgumentInfo = getContainingArgumentInfo; + function getChildListThatStartsWithOpenerToken(parent, openerToken, sourceFile) { + var children = parent.getChildren(sourceFile); + var indexOfOpenerToken = children.indexOf(openerToken); + ts.Debug.assert(indexOfOpenerToken >= 0 && children.length > indexOfOpenerToken + 1); + return children[indexOfOpenerToken + 1]; + } + /** + * The selectedItemIndex could be negative for several reasons. + * 1. There are too many arguments for all of the overloads + * 2. None of the overloads were type compatible + * The solution here is to try to pick the best overload by picking + * either the first one that has an appropriate number of parameters, + * or the one with the most parameters. + */ + function selectBestInvalidOverloadIndex(candidates, argumentCount) { + var maxParamsSignatureIndex = -1; + var maxParams = -1; + for (var i = 0; i < candidates.length; i++) { + var candidate = candidates[i]; + if (candidate.hasRestParameter || candidate.parameters.length >= argumentCount) { + return i; + } + if (candidate.parameters.length > maxParams) { + maxParams = candidate.parameters.length; + maxParamsSignatureIndex = i; + } } + return maxParamsSignatureIndex; } - return false; - } - function isNameOfExternalModuleImportOrDeclaration(node) { - if (node.kind === 9 /* StringLiteral */) { - return isNameOfModuleDeclaration(node) || - (ts.isExternalModuleImportEqualsDeclaration(node.parent.parent) && ts.getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node); - } - return false; - } - /** Returns true if the position is within a comment */ - function isInsideComment(sourceFile, token, position) { - // The position has to be: 1. in the leading trivia (before token.getStart()), and 2. within a comment - return position <= token.getStart(sourceFile) && - (isInsideCommentRange(ts.getTrailingCommentRanges(sourceFile.text, token.getFullStart())) || - isInsideCommentRange(ts.getLeadingCommentRanges(sourceFile.text, token.getFullStart()))); - function isInsideCommentRange(comments) { - return ts.forEach(comments, function (comment) { - // either we are 1. completely inside the comment, or 2. at the end of the comment - if (comment.pos < position && position < comment.end) { - return true; + function createSignatureHelpItems(candidates, bestSignature, argumentListInfo, typeChecker) { + var applicableSpan = argumentListInfo.argumentsSpan; + var isTypeParameterList = argumentListInfo.kind === 0 /* TypeArguments */; + var invocation = argumentListInfo.invocation; + var callTarget = ts.getInvokedExpression(invocation); + var callTargetSymbol = typeChecker.getSymbolAtLocation(callTarget); + var callTargetDisplayParts = callTargetSymbol && ts.symbolToDisplayParts(typeChecker, callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined); + var items = ts.map(candidates, function (candidateSignature) { + var signatureHelpParameters; + var prefixDisplayParts = []; + var suffixDisplayParts = []; + if (callTargetDisplayParts) { + ts.addRange(prefixDisplayParts, callTargetDisplayParts); } - else if (position === comment.end) { - var text = sourceFile.text; - var width = comment.end - comment.pos; - // is single line comment or just /* - if (width <= 2 || text.charCodeAt(comment.pos + 1) === 47 /* slash */) { - return true; - } - else { - // is unterminated multi-line comment - return !(text.charCodeAt(comment.end - 1) === 47 /* slash */ && - text.charCodeAt(comment.end - 2) === 42 /* asterisk */); - } + if (isTypeParameterList) { + prefixDisplayParts.push(ts.punctuationPart(25 /* LessThanToken */)); + var typeParameters = candidateSignature.typeParameters; + signatureHelpParameters = typeParameters && typeParameters.length > 0 ? ts.map(typeParameters, createSignatureHelpParameterForTypeParameter) : emptyArray; + suffixDisplayParts.push(ts.punctuationPart(27 /* GreaterThanToken */)); + var parameterParts = ts.mapToDisplayParts(function (writer) { + return typeChecker.getSymbolDisplayBuilder().buildDisplayForParametersAndDelimiters(candidateSignature.thisParameter, candidateSignature.parameters, writer, invocation); + }); + ts.addRange(suffixDisplayParts, parameterParts); } - return false; + else { + var typeParameterParts = ts.mapToDisplayParts(function (writer) { + return typeChecker.getSymbolDisplayBuilder().buildDisplayForTypeParametersAndDelimiters(candidateSignature.typeParameters, writer, invocation); + }); + ts.addRange(prefixDisplayParts, typeParameterParts); + prefixDisplayParts.push(ts.punctuationPart(17 /* OpenParenToken */)); + var parameters = candidateSignature.parameters; + signatureHelpParameters = parameters.length > 0 ? ts.map(parameters, createSignatureHelpParameterForParameter) : emptyArray; + suffixDisplayParts.push(ts.punctuationPart(18 /* CloseParenToken */)); + } + var returnTypeParts = ts.mapToDisplayParts(function (writer) { + return typeChecker.getSymbolDisplayBuilder().buildReturnTypeDisplay(candidateSignature, writer, invocation); + }); + ts.addRange(suffixDisplayParts, returnTypeParts); + return { + isVariadic: candidateSignature.hasRestParameter, + prefixDisplayParts: prefixDisplayParts, + suffixDisplayParts: suffixDisplayParts, + separatorDisplayParts: [ts.punctuationPart(24 /* CommaToken */), ts.spacePart()], + parameters: signatureHelpParameters, + documentation: candidateSignature.getDocumentationComment() + }; }); - } - } - var SemanticMeaning; - (function (SemanticMeaning) { - SemanticMeaning[SemanticMeaning["None"] = 0] = "None"; - SemanticMeaning[SemanticMeaning["Value"] = 1] = "Value"; - SemanticMeaning[SemanticMeaning["Type"] = 2] = "Type"; - SemanticMeaning[SemanticMeaning["Namespace"] = 4] = "Namespace"; - SemanticMeaning[SemanticMeaning["All"] = 7] = "All"; - })(SemanticMeaning || (SemanticMeaning = {})); - var BreakContinueSearchType; - (function (BreakContinueSearchType) { - BreakContinueSearchType[BreakContinueSearchType["None"] = 0] = "None"; - BreakContinueSearchType[BreakContinueSearchType["Unlabeled"] = 1] = "Unlabeled"; - BreakContinueSearchType[BreakContinueSearchType["Labeled"] = 2] = "Labeled"; - BreakContinueSearchType[BreakContinueSearchType["All"] = 3] = "All"; - })(BreakContinueSearchType || (BreakContinueSearchType = {})); - // A cache of completion entries for keywords, these do not change between sessions - var keywordCompletions = []; - for (var i = 70 /* FirstKeyword */; i <= 138 /* LastKeyword */; i++) { - keywordCompletions.push({ - name: ts.tokenToString(i), - kind: ts.ScriptElementKind.keyword, - kindModifiers: ts.ScriptElementKindModifier.none, - sortText: "0" - }); - } - /* @internal */ function getContainerNode(node) { - while (true) { - node = node.parent; - if (!node) { - return undefined; + var argumentIndex = argumentListInfo.argumentIndex; + // argumentCount is the *apparent* number of arguments. + var argumentCount = argumentListInfo.argumentCount; + var selectedItemIndex = candidates.indexOf(bestSignature); + if (selectedItemIndex < 0) { + selectedItemIndex = selectBestInvalidOverloadIndex(candidates, argumentCount); } - switch (node.kind) { - case 256 /* SourceFile */: - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 221 /* ClassDeclaration */: - case 222 /* InterfaceDeclaration */: - case 224 /* EnumDeclaration */: - case 225 /* ModuleDeclaration */: - return node; + ts.Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, "argumentCount < argumentIndex, " + argumentCount + " < " + argumentIndex); + return { + items: items, + applicableSpan: applicableSpan, + selectedItemIndex: selectedItemIndex, + argumentIndex: argumentIndex, + argumentCount: argumentCount + }; + function createSignatureHelpParameterForParameter(parameter) { + var displayParts = ts.mapToDisplayParts(function (writer) { + return typeChecker.getSymbolDisplayBuilder().buildParameterDisplay(parameter, writer, invocation); + }); + return { + name: parameter.name, + documentation: parameter.getDocumentationComment(), + displayParts: displayParts, + isOptional: typeChecker.isOptionalParameter(parameter.valueDeclaration) + }; + } + function createSignatureHelpParameterForTypeParameter(typeParameter) { + var displayParts = ts.mapToDisplayParts(function (writer) { + return typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(typeParameter, writer, invocation); + }); + return { + name: typeParameter.symbol.name, + documentation: emptyArray, + displayParts: displayParts, + isOptional: false + }; } } - } - ts.getContainerNode = getContainerNode; - /* @internal */ function getNodeKind(node) { - switch (node.kind) { - case 256 /* SourceFile */: - return ts.isExternalModule(node) ? ts.ScriptElementKind.moduleElement : ts.ScriptElementKind.scriptElement; - case 225 /* ModuleDeclaration */: - return ts.ScriptElementKind.moduleElement; - case 221 /* ClassDeclaration */: - case 192 /* ClassExpression */: - return ts.ScriptElementKind.classElement; - case 222 /* InterfaceDeclaration */: return ts.ScriptElementKind.interfaceElement; - case 223 /* TypeAliasDeclaration */: return ts.ScriptElementKind.typeElement; - case 224 /* EnumDeclaration */: return ts.ScriptElementKind.enumElement; - case 218 /* VariableDeclaration */: - return getKindOfVariableDeclaration(node); - case 169 /* BindingElement */: - return getKindOfVariableDeclaration(ts.getRootDeclaration(node)); - case 180 /* ArrowFunction */: - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - return ts.ScriptElementKind.functionElement; - case 149 /* GetAccessor */: return ts.ScriptElementKind.memberGetAccessorElement; - case 150 /* SetAccessor */: return ts.ScriptElementKind.memberSetAccessorElement; - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - return ts.ScriptElementKind.memberFunctionElement; - case 145 /* PropertyDeclaration */: - case 144 /* PropertySignature */: - return ts.ScriptElementKind.memberVariableElement; - case 153 /* IndexSignature */: return ts.ScriptElementKind.indexSignatureElement; - case 152 /* ConstructSignature */: return ts.ScriptElementKind.constructSignatureElement; - case 151 /* CallSignature */: return ts.ScriptElementKind.callSignatureElement; - case 148 /* Constructor */: return ts.ScriptElementKind.constructorImplementationElement; - case 141 /* TypeParameter */: return ts.ScriptElementKind.typeParameterElement; - case 255 /* EnumMember */: return ts.ScriptElementKind.enumMemberElement; - case 142 /* Parameter */: return (node.flags & 92 /* ParameterPropertyModifier */) ? ts.ScriptElementKind.memberVariableElement : ts.ScriptElementKind.parameterElement; - case 229 /* ImportEqualsDeclaration */: - case 234 /* ImportSpecifier */: - case 231 /* ImportClause */: - case 238 /* ExportSpecifier */: - case 232 /* NamespaceImport */: - return ts.ScriptElementKind.alias; - case 279 /* JSDocTypedefTag */: + })(SignatureHelp = ts.SignatureHelp || (ts.SignatureHelp = {})); +})(ts || (ts = {})); +/* @internal */ +var ts; +(function (ts) { + var SymbolDisplay; + (function (SymbolDisplay) { + // TODO(drosen): use contextual SemanticMeaning. + function getSymbolKind(typeChecker, symbol, location) { + var flags = symbol.getFlags(); + if (flags & 32 /* Class */) + return ts.getDeclarationOfKind(symbol, 192 /* ClassExpression */) ? + ts.ScriptElementKind.localClassElement : ts.ScriptElementKind.classElement; + if (flags & 384 /* Enum */) + return ts.ScriptElementKind.enumElement; + if (flags & 524288 /* TypeAlias */) return ts.ScriptElementKind.typeElement; - default: - return ts.ScriptElementKind.unknown; - } - function getKindOfVariableDeclaration(v) { - return ts.isConst(v) - ? ts.ScriptElementKind.constElement - : ts.isLet(v) - ? ts.ScriptElementKind.letElement - : ts.ScriptElementKind.variableElement; - } - } - ts.getNodeKind = getNodeKind; - var CancellationTokenObject = (function () { - function CancellationTokenObject(cancellationToken) { - this.cancellationToken = cancellationToken; - } - CancellationTokenObject.prototype.isCancellationRequested = function () { - return this.cancellationToken && this.cancellationToken.isCancellationRequested(); - }; - CancellationTokenObject.prototype.throwIfCancellationRequested = function () { - if (this.isCancellationRequested()) { - throw new ts.OperationCanceledException(); + if (flags & 64 /* Interface */) + return ts.ScriptElementKind.interfaceElement; + if (flags & 262144 /* TypeParameter */) + return ts.ScriptElementKind.typeParameterElement; + var result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, flags, location); + if (result === ts.ScriptElementKind.unknown) { + if (flags & 262144 /* TypeParameter */) + return ts.ScriptElementKind.typeParameterElement; + if (flags & 8 /* EnumMember */) + return ts.ScriptElementKind.variableElement; + if (flags & 8388608 /* Alias */) + return ts.ScriptElementKind.alias; + if (flags & 1536 /* Module */) + return ts.ScriptElementKind.moduleElement; } - }; - return CancellationTokenObject; - }()); - function createLanguageService(host, documentRegistry) { - if (documentRegistry === void 0) { documentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory()); } - var syntaxTreeCache = new SyntaxTreeCache(host); - var ruleProvider; - var program; - var lastProjectVersion; - var useCaseSensitivefileNames = false; - var cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken()); - var currentDirectory = host.getCurrentDirectory(); - // Check if the localized messages json is set, otherwise query the host for it - if (!ts.localizedDiagnosticMessages && host.getLocalizedDiagnosticMessages) { - ts.localizedDiagnosticMessages = host.getLocalizedDiagnosticMessages(); + return result; } - function log(message) { - if (host.log) { - host.log(message); + SymbolDisplay.getSymbolKind = getSymbolKind; + function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, flags, location) { + if (typeChecker.isUndefinedSymbol(symbol)) { + return ts.ScriptElementKind.variableElement; } - } - var getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitivefileNames); - function getValidSourceFile(fileName) { - var sourceFile = program.getSourceFile(fileName); - if (!sourceFile) { - throw new Error("Could not find file: '" + fileName + "'."); + if (typeChecker.isArgumentsSymbol(symbol)) { + return ts.ScriptElementKind.localVariableElement; } - return sourceFile; - } - function getRuleProvider(options) { - // Ensure rules are initialized and up to date wrt to formatting options - if (!ruleProvider) { - ruleProvider = new ts.formatting.RulesProvider(); + if (location.kind === 97 /* ThisKeyword */ && ts.isExpression(location)) { + return ts.ScriptElementKind.parameterElement; } - ruleProvider.ensureUpToDate(options); - return ruleProvider; - } - function synchronizeHostData() { - // perform fast check if host supports it - if (host.getProjectVersion) { - var hostProjectVersion = host.getProjectVersion(); - if (hostProjectVersion) { - if (lastProjectVersion === hostProjectVersion) { - return; - } - lastProjectVersion = hostProjectVersion; + if (flags & 3 /* Variable */) { + if (ts.isFirstDeclarationOfSymbolParameter(symbol)) { + return ts.ScriptElementKind.parameterElement; } + else if (symbol.valueDeclaration && ts.isConst(symbol.valueDeclaration)) { + return ts.ScriptElementKind.constElement; + } + else if (ts.forEach(symbol.declarations, ts.isLet)) { + return ts.ScriptElementKind.letElement; + } + return isLocalVariableOrFunction(symbol) ? ts.ScriptElementKind.localVariableElement : ts.ScriptElementKind.variableElement; } - // Get a fresh cache of the host information - var hostCache = new HostCache(host, getCanonicalFileName); - // If the program is already up-to-date, we can reuse it - if (programUpToDate()) { - return; + if (flags & 16 /* Function */) + return isLocalVariableOrFunction(symbol) ? ts.ScriptElementKind.localFunctionElement : ts.ScriptElementKind.functionElement; + if (flags & 32768 /* GetAccessor */) + return ts.ScriptElementKind.memberGetAccessorElement; + if (flags & 65536 /* SetAccessor */) + return ts.ScriptElementKind.memberSetAccessorElement; + if (flags & 8192 /* Method */) + return ts.ScriptElementKind.memberFunctionElement; + if (flags & 16384 /* Constructor */) + return ts.ScriptElementKind.constructorImplementationElement; + if (flags & 4 /* Property */) { + if (flags & 268435456 /* SyntheticProperty */) { + // If union property is result of union of non method (property/accessors/variables), it is labeled as property + var unionPropertyKind = ts.forEach(typeChecker.getRootSymbols(symbol), function (rootSymbol) { + var rootSymbolFlags = rootSymbol.getFlags(); + if (rootSymbolFlags & (98308 /* PropertyOrAccessor */ | 3 /* Variable */)) { + return ts.ScriptElementKind.memberVariableElement; + } + ts.Debug.assert(!!(rootSymbolFlags & 8192 /* Method */)); + }); + if (!unionPropertyKind) { + // If this was union of all methods, + // make sure it has call signatures before we can label it as method + var typeOfUnionProperty = typeChecker.getTypeOfSymbolAtLocation(symbol, location); + if (typeOfUnionProperty.getCallSignatures().length) { + return ts.ScriptElementKind.memberFunctionElement; + } + return ts.ScriptElementKind.memberVariableElement; + } + return unionPropertyKind; + } + return ts.ScriptElementKind.memberVariableElement; } - // IMPORTANT - It is critical from this moment onward that we do not check - // cancellation tokens. We are about to mutate source files from a previous program - // instance. If we cancel midway through, we may end up in an inconsistent state where - // the program points to old source files that have been invalidated because of - // incremental parsing. - var oldSettings = program && program.getCompilerOptions(); - var newSettings = hostCache.compilationSettings(); - var shouldCreateNewSourceFiles = oldSettings && - (oldSettings.target !== newSettings.target || - oldSettings.module !== newSettings.module || - oldSettings.moduleResolution !== newSettings.moduleResolution || - oldSettings.noResolve !== newSettings.noResolve || - oldSettings.jsx !== newSettings.jsx || - oldSettings.allowJs !== newSettings.allowJs || - oldSettings.disableSizeLimit !== oldSettings.disableSizeLimit || - oldSettings.baseUrl !== newSettings.baseUrl || - !ts.equalOwnProperties(oldSettings.paths, newSettings.paths)); - // Now create a new compiler - var compilerHost = { - getSourceFile: getOrCreateSourceFile, - getSourceFileByPath: getOrCreateSourceFileByPath, - getCancellationToken: function () { return cancellationToken; }, - getCanonicalFileName: getCanonicalFileName, - useCaseSensitiveFileNames: function () { return useCaseSensitivefileNames; }, - getNewLine: function () { return ts.getNewLineOrDefaultFromHost(host); }, - getDefaultLibFileName: function (options) { return host.getDefaultLibFileName(options); }, - writeFile: function (fileName, data, writeByteOrderMark) { }, - getCurrentDirectory: function () { return currentDirectory; }, - fileExists: function (fileName) { - // stub missing host functionality - return hostCache.getOrCreateEntry(fileName) !== undefined; - }, - readFile: function (fileName) { - // stub missing host functionality - var entry = hostCache.getOrCreateEntry(fileName); - return entry && entry.scriptSnapshot.getText(0, entry.scriptSnapshot.getLength()); - }, - directoryExists: function (directoryName) { - return ts.directoryProbablyExists(directoryName, host); - }, - getDirectories: function (path) { - return host.getDirectories ? host.getDirectories(path) : []; + return ts.ScriptElementKind.unknown; + } + function getSymbolModifiers(symbol) { + return symbol && symbol.declarations && symbol.declarations.length > 0 + ? ts.getNodeModifiers(symbol.declarations[0]) + : ts.ScriptElementKindModifier.none; + } + SymbolDisplay.getSymbolModifiers = getSymbolModifiers; + // TODO(drosen): Currently completion entry details passes the SemanticMeaning.All instead of using semanticMeaning of location + function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, sourceFile, enclosingDeclaration, location, semanticMeaning) { + if (semanticMeaning === void 0) { semanticMeaning = ts.getMeaningFromLocation(location); } + var displayParts = []; + var documentation; + var symbolFlags = symbol.flags; + var symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, symbolFlags, location); + var hasAddedSymbolInfo; + var isThisExpression = location.kind === 97 /* ThisKeyword */ && ts.isExpression(location); + var type; + // Class at constructor site need to be shown as constructor apart from property,method, vars + if (symbolKind !== ts.ScriptElementKind.unknown || symbolFlags & 32 /* Class */ || symbolFlags & 8388608 /* Alias */) { + // If it is accessor they are allowed only if location is at name of the accessor + if (symbolKind === ts.ScriptElementKind.memberGetAccessorElement || symbolKind === ts.ScriptElementKind.memberSetAccessorElement) { + symbolKind = ts.ScriptElementKind.memberVariableElement; + } + var signature = void 0; + type = isThisExpression ? typeChecker.getTypeAtLocation(location) : typeChecker.getTypeOfSymbolAtLocation(symbol, location); + if (type) { + if (location.parent && location.parent.kind === 172 /* PropertyAccessExpression */) { + var right = location.parent.name; + // Either the location is on the right of a property access, or on the left and the right is missing + if (right === location || (right && right.getFullWidth() === 0)) { + location = location.parent; + } + } + // try get the call/construct signature from the type if it matches + var callExpression = void 0; + if (location.kind === 174 /* CallExpression */ || location.kind === 175 /* NewExpression */) { + callExpression = location; + } + else if (ts.isCallExpressionTarget(location) || ts.isNewExpressionTarget(location)) { + callExpression = location.parent; + } + if (callExpression) { + var candidateSignatures = []; + signature = typeChecker.getResolvedSignature(callExpression, candidateSignatures); + if (!signature && candidateSignatures.length) { + // Use the first candidate: + signature = candidateSignatures[0]; + } + var useConstructSignatures = callExpression.kind === 175 /* NewExpression */ || callExpression.expression.kind === 95 /* SuperKeyword */; + var allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures(); + if (!ts.contains(allSignatures, signature.target) && !ts.contains(allSignatures, signature)) { + // Get the first signature if there is one -- allSignatures may contain + // either the original signature or its target, so check for either + signature = allSignatures.length ? allSignatures[0] : undefined; + } + if (signature) { + if (useConstructSignatures && (symbolFlags & 32 /* Class */)) { + // Constructor + symbolKind = ts.ScriptElementKind.constructorImplementationElement; + addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); + } + else if (symbolFlags & 8388608 /* Alias */) { + symbolKind = ts.ScriptElementKind.alias; + pushTypePart(symbolKind); + displayParts.push(ts.spacePart()); + if (useConstructSignatures) { + displayParts.push(ts.keywordPart(92 /* NewKeyword */)); + displayParts.push(ts.spacePart()); + } + addFullSymbolName(symbol); + } + else { + addPrefixForAnyFunctionOrVar(symbol, symbolKind); + } + switch (symbolKind) { + case ts.ScriptElementKind.memberVariableElement: + case ts.ScriptElementKind.variableElement: + case ts.ScriptElementKind.constElement: + case ts.ScriptElementKind.letElement: + case ts.ScriptElementKind.parameterElement: + case ts.ScriptElementKind.localVariableElement: + // If it is call or construct signature of lambda's write type name + displayParts.push(ts.punctuationPart(54 /* ColonToken */)); + displayParts.push(ts.spacePart()); + if (useConstructSignatures) { + displayParts.push(ts.keywordPart(92 /* NewKeyword */)); + displayParts.push(ts.spacePart()); + } + if (!(type.flags & 2097152 /* Anonymous */) && type.symbol) { + ts.addRange(displayParts, ts.symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, 1 /* WriteTypeParametersOrArguments */)); + } + addSignatureDisplayParts(signature, allSignatures, 8 /* WriteArrowStyleSignature */); + break; + default: + // Just signature + addSignatureDisplayParts(signature, allSignatures); + } + hasAddedSymbolInfo = true; + } + } + else if ((ts.isNameOfFunctionDeclaration(location) && !(symbol.flags & 98304 /* Accessor */)) || + (location.kind === 121 /* ConstructorKeyword */ && location.parent.kind === 148 /* Constructor */)) { + // get the signature from the declaration and write it + var functionDeclaration = location.parent; + var allSignatures = functionDeclaration.kind === 148 /* Constructor */ ? type.getNonNullableType().getConstructSignatures() : type.getNonNullableType().getCallSignatures(); + if (!typeChecker.isImplementationOfOverload(functionDeclaration)) { + signature = typeChecker.getSignatureFromDeclaration(functionDeclaration); + } + else { + signature = allSignatures[0]; + } + if (functionDeclaration.kind === 148 /* Constructor */) { + // show (constructor) Type(...) signature + symbolKind = ts.ScriptElementKind.constructorImplementationElement; + addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); + } + else { + // (function/method) symbol(..signature) + addPrefixForAnyFunctionOrVar(functionDeclaration.kind === 151 /* CallSignature */ && + !(type.symbol.flags & 2048 /* TypeLiteral */ || type.symbol.flags & 4096 /* ObjectLiteral */) ? type.symbol : symbol, symbolKind); + } + addSignatureDisplayParts(signature, allSignatures); + hasAddedSymbolInfo = true; + } } - }; - if (host.trace) { - compilerHost.trace = function (message) { return host.trace(message); }; } - if (host.resolveModuleNames) { - compilerHost.resolveModuleNames = function (moduleNames, containingFile) { return host.resolveModuleNames(moduleNames, containingFile); }; + if (symbolFlags & 32 /* Class */ && !hasAddedSymbolInfo && !isThisExpression) { + if (ts.getDeclarationOfKind(symbol, 192 /* ClassExpression */)) { + // Special case for class expressions because we would like to indicate that + // the class name is local to the class body (similar to function expression) + // (local class) class + pushTypePart(ts.ScriptElementKind.localClassElement); + } + else { + // Class declaration has name which is not local. + displayParts.push(ts.keywordPart(73 /* ClassKeyword */)); + } + displayParts.push(ts.spacePart()); + addFullSymbolName(symbol); + writeTypeParametersOfSymbol(symbol, sourceFile); } - if (host.resolveTypeReferenceDirectives) { - compilerHost.resolveTypeReferenceDirectives = function (typeReferenceDirectiveNames, containingFile) { - return host.resolveTypeReferenceDirectives(typeReferenceDirectiveNames, containingFile); - }; + if ((symbolFlags & 64 /* Interface */) && (semanticMeaning & 2 /* Type */)) { + addNewLineIfDisplayPartsExist(); + displayParts.push(ts.keywordPart(107 /* InterfaceKeyword */)); + displayParts.push(ts.spacePart()); + addFullSymbolName(symbol); + writeTypeParametersOfSymbol(symbol, sourceFile); } - var documentRegistryBucketKey = documentRegistry.getKeyForCompilationSettings(newSettings); - var newProgram = ts.createProgram(hostCache.getRootFileNames(), newSettings, compilerHost, program); - // Release any files we have acquired in the old program but are - // not part of the new program. - if (program) { - var oldSourceFiles = program.getSourceFiles(); - var oldSettingsKey = documentRegistry.getKeyForCompilationSettings(oldSettings); - for (var _i = 0, oldSourceFiles_1 = oldSourceFiles; _i < oldSourceFiles_1.length; _i++) { - var oldSourceFile = oldSourceFiles_1[_i]; - if (!newProgram.getSourceFile(oldSourceFile.fileName) || shouldCreateNewSourceFiles) { - documentRegistry.releaseDocumentWithKey(oldSourceFile.path, oldSettingsKey); - } + if (symbolFlags & 524288 /* TypeAlias */) { + addNewLineIfDisplayPartsExist(); + displayParts.push(ts.keywordPart(134 /* TypeKeyword */)); + displayParts.push(ts.spacePart()); + addFullSymbolName(symbol); + writeTypeParametersOfSymbol(symbol, sourceFile); + displayParts.push(ts.spacePart()); + displayParts.push(ts.operatorPart(56 /* EqualsToken */)); + displayParts.push(ts.spacePart()); + ts.addRange(displayParts, ts.typeToDisplayParts(typeChecker, typeChecker.getDeclaredTypeOfSymbol(symbol), enclosingDeclaration, 512 /* InTypeAlias */)); + } + if (symbolFlags & 384 /* Enum */) { + addNewLineIfDisplayPartsExist(); + if (ts.forEach(symbol.declarations, ts.isConstEnumDeclaration)) { + displayParts.push(ts.keywordPart(74 /* ConstKeyword */)); + displayParts.push(ts.spacePart()); } + displayParts.push(ts.keywordPart(81 /* EnumKeyword */)); + displayParts.push(ts.spacePart()); + addFullSymbolName(symbol); } - // hostCache is captured in the closure for 'getOrCreateSourceFile' but it should not be used past this point. - // It needs to be cleared to allow all collected snapshots to be released - hostCache = undefined; - program = newProgram; - // Make sure all the nodes in the program are both bound, and have their parent - // pointers set property. - program.getTypeChecker(); - return; - function getOrCreateSourceFile(fileName) { - return getOrCreateSourceFileByPath(fileName, ts.toPath(fileName, currentDirectory, getCanonicalFileName)); + if (symbolFlags & 1536 /* Module */) { + addNewLineIfDisplayPartsExist(); + var declaration = ts.getDeclarationOfKind(symbol, 225 /* ModuleDeclaration */); + var isNamespace = declaration && declaration.name && declaration.name.kind === 69 /* Identifier */; + displayParts.push(ts.keywordPart(isNamespace ? 126 /* NamespaceKeyword */ : 125 /* ModuleKeyword */)); + displayParts.push(ts.spacePart()); + addFullSymbolName(symbol); } - function getOrCreateSourceFileByPath(fileName, path) { - ts.Debug.assert(hostCache !== undefined); - // The program is asking for this file, check first if the host can locate it. - // If the host can not locate the file, then it does not exist. return undefined - // to the program to allow reporting of errors for missing files. - var hostFileInformation = hostCache.getOrCreateEntryByPath(fileName, path); - if (!hostFileInformation) { - return undefined; + if ((symbolFlags & 262144 /* TypeParameter */) && (semanticMeaning & 2 /* Type */)) { + addNewLineIfDisplayPartsExist(); + displayParts.push(ts.punctuationPart(17 /* OpenParenToken */)); + displayParts.push(ts.textPart("type parameter")); + displayParts.push(ts.punctuationPart(18 /* CloseParenToken */)); + displayParts.push(ts.spacePart()); + addFullSymbolName(symbol); + displayParts.push(ts.spacePart()); + displayParts.push(ts.keywordPart(90 /* InKeyword */)); + displayParts.push(ts.spacePart()); + if (symbol.parent) { + // Class/Interface type parameter + addFullSymbolName(symbol.parent, enclosingDeclaration); + writeTypeParametersOfSymbol(symbol.parent, enclosingDeclaration); } - // Check if the language version has changed since we last created a program; if they are the same, - // it is safe to reuse the sourceFiles; if not, then the shape of the AST can change, and the oldSourceFile - // can not be reused. we have to dump all syntax trees and create new ones. - if (!shouldCreateNewSourceFiles) { - // Check if the old program had this file already - var oldSourceFile = program && program.getSourceFileByPath(path); - if (oldSourceFile) { - // We already had a source file for this file name. Go to the registry to - // ensure that we get the right up to date version of it. We need this to - // address the following race-condition. Specifically, say we have the following: - // - // LS1 - // \ - // DocumentRegistry - // / - // LS2 - // - // Each LS has a reference to file 'foo.ts' at version 1. LS2 then updates - // it's version of 'foo.ts' to version 2. This will cause LS2 and the - // DocumentRegistry to have version 2 of the document. HOwever, LS1 will - // have version 1. And *importantly* this source file will be *corrupt*. - // The act of creating version 2 of the file irrevocably damages the version - // 1 file. - // - // So, later when we call into LS1, we need to make sure that it doesn't use - // it's source file any more, and instead defers to DocumentRegistry to get - // either version 1, version 2 (or some other version) depending on what the - // host says should be used. - // We do not support the scenario where a host can modify a registered - // file's script kind, i.e. in one project some file is treated as ".ts" - // and in another as ".js" - ts.Debug.assert(hostFileInformation.scriptKind === oldSourceFile.scriptKind, "Registered script kind (" + oldSourceFile.scriptKind + ") should match new script kind (" + hostFileInformation.scriptKind + ") for file: " + path); - return documentRegistry.updateDocumentWithKey(fileName, path, newSettings, documentRegistryBucketKey, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind); + else { + // Method/function type parameter + var declaration = ts.getDeclarationOfKind(symbol, 141 /* TypeParameter */); + ts.Debug.assert(declaration !== undefined); + declaration = declaration.parent; + if (declaration) { + if (ts.isFunctionLikeKind(declaration.kind)) { + var signature = typeChecker.getSignatureFromDeclaration(declaration); + if (declaration.kind === 152 /* ConstructSignature */) { + displayParts.push(ts.keywordPart(92 /* NewKeyword */)); + displayParts.push(ts.spacePart()); + } + else if (declaration.kind !== 151 /* CallSignature */ && declaration.name) { + addFullSymbolName(declaration.symbol); + } + ts.addRange(displayParts, ts.signatureToDisplayParts(typeChecker, signature, sourceFile, 32 /* WriteTypeArgumentsOfSignature */)); + } + else { + // Type alias type parameter + // For example + // type list = T[]; // Both T will go through same code path + displayParts.push(ts.keywordPart(134 /* TypeKeyword */)); + displayParts.push(ts.spacePart()); + addFullSymbolName(declaration.symbol); + writeTypeParametersOfSymbol(declaration.symbol, sourceFile); + } } } - // Could not find this file in the old program, create a new SourceFile for it. - return documentRegistry.acquireDocumentWithKey(fileName, path, newSettings, documentRegistryBucketKey, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind); } - function sourceFileUpToDate(sourceFile) { - if (!sourceFile) { - return false; + if (symbolFlags & 8 /* EnumMember */) { + addPrefixForAnyFunctionOrVar(symbol, "enum member"); + var declaration = symbol.declarations[0]; + if (declaration.kind === 255 /* EnumMember */) { + var constantValue = typeChecker.getConstantValue(declaration); + if (constantValue !== undefined) { + displayParts.push(ts.spacePart()); + displayParts.push(ts.operatorPart(56 /* EqualsToken */)); + displayParts.push(ts.spacePart()); + displayParts.push(ts.displayPart(constantValue.toString(), ts.SymbolDisplayPartKind.numericLiteral)); + } } - var path = sourceFile.path || ts.toPath(sourceFile.fileName, currentDirectory, getCanonicalFileName); - return sourceFile.version === hostCache.getVersion(path); } - function programUpToDate() { - // If we haven't create a program yet, then it is not up-to-date - if (!program) { - return false; + if (symbolFlags & 8388608 /* Alias */) { + addNewLineIfDisplayPartsExist(); + if (symbol.declarations[0].kind === 228 /* NamespaceExportDeclaration */) { + displayParts.push(ts.keywordPart(82 /* ExportKeyword */)); + displayParts.push(ts.spacePart()); + displayParts.push(ts.keywordPart(126 /* NamespaceKeyword */)); } - // If number of files in the program do not match, it is not up-to-date - var rootFileNames = hostCache.getRootFileNames(); - if (program.getSourceFiles().length !== rootFileNames.length) { - return false; + else { + displayParts.push(ts.keywordPart(89 /* ImportKeyword */)); } - // If any file is not up-to-date, then the whole program is not up-to-date - for (var _i = 0, rootFileNames_2 = rootFileNames; _i < rootFileNames_2.length; _i++) { - var fileName = rootFileNames_2[_i]; - if (!sourceFileUpToDate(program.getSourceFile(fileName))) { - return false; + displayParts.push(ts.spacePart()); + addFullSymbolName(symbol); + ts.forEach(symbol.declarations, function (declaration) { + if (declaration.kind === 229 /* ImportEqualsDeclaration */) { + var importEqualsDeclaration = declaration; + if (ts.isExternalModuleImportEqualsDeclaration(importEqualsDeclaration)) { + displayParts.push(ts.spacePart()); + displayParts.push(ts.operatorPart(56 /* EqualsToken */)); + displayParts.push(ts.spacePart()); + displayParts.push(ts.keywordPart(129 /* RequireKeyword */)); + displayParts.push(ts.punctuationPart(17 /* OpenParenToken */)); + displayParts.push(ts.displayPart(ts.getTextOfNode(ts.getExternalModuleImportEqualsDeclarationExpression(importEqualsDeclaration)), ts.SymbolDisplayPartKind.stringLiteral)); + displayParts.push(ts.punctuationPart(18 /* CloseParenToken */)); + } + else { + var internalAliasSymbol = typeChecker.getSymbolAtLocation(importEqualsDeclaration.moduleReference); + if (internalAliasSymbol) { + displayParts.push(ts.spacePart()); + displayParts.push(ts.operatorPart(56 /* EqualsToken */)); + displayParts.push(ts.spacePart()); + addFullSymbolName(internalAliasSymbol, enclosingDeclaration); + } + } + return true; } - } - // If the compilation settings do no match, then the program is not up-to-date - return ts.compareDataObjects(program.getCompilerOptions(), hostCache.compilationSettings()); - } - } - function getProgram() { - synchronizeHostData(); - return program; - } - function cleanupSemanticCache() { - // TODO: Should we jettison the program (or it's type checker) here? - } - function dispose() { - if (program) { - ts.forEach(program.getSourceFiles(), function (f) { - return documentRegistry.releaseDocument(f.fileName, program.getCompilerOptions()); }); } - } - /// Diagnostics - function getSyntacticDiagnostics(fileName) { - synchronizeHostData(); - return program.getSyntacticDiagnostics(getValidSourceFile(fileName), cancellationToken); - } - /** - * getSemanticDiagnostics return array of Diagnostics. If '-d' is not enabled, only report semantic errors - * If '-d' enabled, report both semantic and emitter errors - */ - function getSemanticDiagnostics(fileName) { - synchronizeHostData(); - var targetSourceFile = getValidSourceFile(fileName); - // Only perform the action per file regardless of '-out' flag as LanguageServiceHost is expected to call this function per file. - // Therefore only get diagnostics for given file. - var semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken); - if (!program.getCompilerOptions().declaration) { - return semanticDiagnostics; + if (!hasAddedSymbolInfo) { + if (symbolKind !== ts.ScriptElementKind.unknown) { + if (type) { + if (isThisExpression) { + addNewLineIfDisplayPartsExist(); + displayParts.push(ts.keywordPart(97 /* ThisKeyword */)); + } + else { + addPrefixForAnyFunctionOrVar(symbol, symbolKind); + } + // For properties, variables and local vars: show the type + if (symbolKind === ts.ScriptElementKind.memberVariableElement || + symbolFlags & 3 /* Variable */ || + symbolKind === ts.ScriptElementKind.localVariableElement || + isThisExpression) { + displayParts.push(ts.punctuationPart(54 /* ColonToken */)); + displayParts.push(ts.spacePart()); + // If the type is type parameter, format it specially + if (type.symbol && type.symbol.flags & 262144 /* TypeParameter */) { + var typeParameterParts = ts.mapToDisplayParts(function (writer) { + typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(type, writer, enclosingDeclaration); + }); + ts.addRange(displayParts, typeParameterParts); + } + else { + ts.addRange(displayParts, ts.typeToDisplayParts(typeChecker, type, enclosingDeclaration)); + } + } + else if (symbolFlags & 16 /* Function */ || + symbolFlags & 8192 /* Method */ || + symbolFlags & 16384 /* Constructor */ || + symbolFlags & 131072 /* Signature */ || + symbolFlags & 98304 /* Accessor */ || + symbolKind === ts.ScriptElementKind.memberFunctionElement) { + var allSignatures = type.getNonNullableType().getCallSignatures(); + addSignatureDisplayParts(allSignatures[0], allSignatures); + } + } + } + else { + symbolKind = getSymbolKind(typeChecker, symbol, location); + } } - // If '-d' is enabled, check for emitter error. One example of emitter error is export class implements non-export interface - var declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile, cancellationToken); - return ts.concatenate(semanticDiagnostics, declarationDiagnostics); - } - function getCompilerOptionsDiagnostics() { - synchronizeHostData(); - return program.getOptionsDiagnostics(cancellationToken).concat(program.getGlobalDiagnostics(cancellationToken)); - } - /** - * Get the name to be display in completion from a given symbol. - * - * @return undefined if the name is of external module otherwise a name with striped of any quote - */ - function getCompletionEntryDisplayNameForSymbol(symbol, target, performCharacterChecks, location) { - var displayName = ts.getDeclaredName(program.getTypeChecker(), symbol, location); - if (displayName) { - var firstCharCode = displayName.charCodeAt(0); - // First check of the displayName is not external module; if it is an external module, it is not valid entry - if ((symbol.flags & 1920 /* Namespace */) && (firstCharCode === 39 /* singleQuote */ || firstCharCode === 34 /* doubleQuote */)) { - // If the symbol is external module, don't show it in the completion list - // (i.e declare module "http" { const x; } | // <= request completion here, "http" should not be there) - return undefined; + if (!documentation) { + documentation = symbol.getDocumentationComment(); + if (documentation.length === 0 && symbol.flags & 4 /* Property */) { + // For some special property access expressions like `experts.foo = foo` or `module.exports.foo = foo` + // there documentation comments might be attached to the right hand side symbol of their declarations. + // The pattern of such special property access is that the parent symbol is the symbol of the file. + if (symbol.parent && ts.forEach(symbol.parent.declarations, function (declaration) { return declaration.kind === 256 /* SourceFile */; })) { + for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { + var declaration = _a[_i]; + if (!declaration.parent || declaration.parent.kind !== 187 /* BinaryExpression */) { + continue; + } + var rhsSymbol = typeChecker.getSymbolAtLocation(declaration.parent.right); + if (!rhsSymbol) { + continue; + } + documentation = rhsSymbol.getDocumentationComment(); + if (documentation.length > 0) { + break; + } + } + } } } - return getCompletionEntryDisplayName(displayName, target, performCharacterChecks); - } - /** - * Get a displayName from a given for completion list, performing any necessary quotes stripping - * and checking whether the name is valid identifier name. - */ - function getCompletionEntryDisplayName(name, target, performCharacterChecks) { - if (!name) { - return undefined; + return { displayParts: displayParts, documentation: documentation, symbolKind: symbolKind }; + function addNewLineIfDisplayPartsExist() { + if (displayParts.length) { + displayParts.push(ts.lineBreakPart()); + } } - name = ts.stripQuotes(name); - if (!name) { - return undefined; + function addFullSymbolName(symbol, enclosingDeclaration) { + var fullSymbolDisplayParts = ts.symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration || sourceFile, /*meaning*/ undefined, 1 /* WriteTypeParametersOrArguments */ | 2 /* UseOnlyExternalAliasing */); + ts.addRange(displayParts, fullSymbolDisplayParts); } - // If the user entered name for the symbol was quoted, removing the quotes is not enough, as the name could be an - // invalid identifier name. We need to check if whatever was inside the quotes is actually a valid identifier name. - // e.g "b a" is valid quoted name but when we strip off the quotes, it is invalid. - // We, thus, need to check if whatever was inside the quotes is actually a valid identifier name. - if (performCharacterChecks) { - if (!ts.isIdentifier(name, target)) { - return undefined; + function addPrefixForAnyFunctionOrVar(symbol, symbolKind) { + addNewLineIfDisplayPartsExist(); + if (symbolKind) { + pushTypePart(symbolKind); + displayParts.push(ts.spacePart()); + addFullSymbolName(symbol); } } - return name; + function pushTypePart(symbolKind) { + switch (symbolKind) { + case ts.ScriptElementKind.variableElement: + case ts.ScriptElementKind.functionElement: + case ts.ScriptElementKind.letElement: + case ts.ScriptElementKind.constElement: + case ts.ScriptElementKind.constructorImplementationElement: + displayParts.push(ts.textOrKeywordPart(symbolKind)); + return; + default: + displayParts.push(ts.punctuationPart(17 /* OpenParenToken */)); + displayParts.push(ts.textOrKeywordPart(symbolKind)); + displayParts.push(ts.punctuationPart(18 /* CloseParenToken */)); + return; + } + } + function addSignatureDisplayParts(signature, allSignatures, flags) { + ts.addRange(displayParts, ts.signatureToDisplayParts(typeChecker, signature, enclosingDeclaration, flags | 32 /* WriteTypeArgumentsOfSignature */)); + if (allSignatures.length > 1) { + displayParts.push(ts.spacePart()); + displayParts.push(ts.punctuationPart(17 /* OpenParenToken */)); + displayParts.push(ts.operatorPart(35 /* PlusToken */)); + displayParts.push(ts.displayPart((allSignatures.length - 1).toString(), ts.SymbolDisplayPartKind.numericLiteral)); + displayParts.push(ts.spacePart()); + displayParts.push(ts.textPart(allSignatures.length === 2 ? "overload" : "overloads")); + displayParts.push(ts.punctuationPart(18 /* CloseParenToken */)); + } + documentation = signature.getDocumentationComment(); + } + function writeTypeParametersOfSymbol(symbol, enclosingDeclaration) { + var typeParameterParts = ts.mapToDisplayParts(function (writer) { + typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplayFromSymbol(symbol, writer, enclosingDeclaration); + }); + ts.addRange(displayParts, typeParameterParts); + } } - function getCompletionData(fileName, position) { - var typeChecker = program.getTypeChecker(); - var sourceFile = getValidSourceFile(fileName); - var isJavaScriptFile = ts.isSourceFileJavaScript(sourceFile); - var isJsDocTagName = false; - var start = ts.timestamp(); - var currentToken = ts.getTokenAtPosition(sourceFile, position); - log("getCompletionData: Get current token: " + (ts.timestamp() - start)); - start = ts.timestamp(); - // Completion not allowed inside comments, bail out if this is the case - var insideComment = isInsideComment(sourceFile, currentToken, position); - log("getCompletionData: Is inside comment: " + (ts.timestamp() - start)); - if (insideComment) { - // The current position is next to the '@' sign, when no tag name being provided yet. - // Provide a full list of tag names - if (ts.hasDocComment(sourceFile, position) && sourceFile.text.charCodeAt(position - 1) === 64 /* at */) { - isJsDocTagName = true; + SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind; + function isLocalVariableOrFunction(symbol) { + if (symbol.parent) { + return false; // This is exported symbol + } + return ts.forEach(symbol.declarations, function (declaration) { + // Function expressions are local + if (declaration.kind === 179 /* FunctionExpression */) { + return true; } - // Completion should work inside certain JsDoc tags. For example: - // /** @type {number | string} */ - // Completion should work in the brackets - var insideJsDocTagExpression = false; - var tag = ts.getJsDocTagAtPosition(sourceFile, position); - if (tag) { - if (tag.tagName.pos <= position && position <= tag.tagName.end) { - isJsDocTagName = true; - } - switch (tag.kind) { - case 277 /* JSDocTypeTag */: - case 275 /* JSDocParameterTag */: - case 276 /* JSDocReturnTag */: - var tagWithExpression = tag; - if (tagWithExpression.typeExpression) { - insideJsDocTagExpression = tagWithExpression.typeExpression.pos < position && position < tagWithExpression.typeExpression.end; - } - break; + if (declaration.kind !== 218 /* VariableDeclaration */ && declaration.kind !== 220 /* FunctionDeclaration */) { + return false; + } + // If the parent is not sourceFile or module block it is local variable + for (var parent_23 = declaration.parent; !ts.isFunctionBlock(parent_23); parent_23 = parent_23.parent) { + // Reached source file or module block + if (parent_23.kind === 256 /* SourceFile */ || parent_23.kind === 226 /* ModuleBlock */) { + return false; } } - if (isJsDocTagName) { - return { symbols: undefined, isMemberCompletion: false, isNewIdentifierLocation: false, location: undefined, isRightOfDot: false, isJsDocTagName: isJsDocTagName }; + // parent is in function block + return true; + }); + } + })(SymbolDisplay = ts.SymbolDisplay || (ts.SymbolDisplay = {})); +})(ts || (ts = {})); +var ts; +(function (ts) { + /* + * This function will compile source text from 'input' argument using specified compiler options. + * If not options are provided - it will use a set of default compiler options. + * Extra compiler options that will unconditionally be used by this function are: + * - isolatedModules = true + * - allowNonTsExtensions = true + * - noLib = true + * - noResolve = true + */ + function transpileModule(input, transpileOptions) { + var diagnostics = []; + var options = transpileOptions.compilerOptions ? fixupCompilerOptions(transpileOptions.compilerOptions, diagnostics) : ts.getDefaultCompilerOptions(); + options.isolatedModules = true; + // transpileModule does not write anything to disk so there is no need to verify that there are no conflicts between input and output paths. + options.suppressOutputPathCheck = true; + // Filename can be non-ts file. + options.allowNonTsExtensions = true; + // We are not returning a sourceFile for lib file when asked by the program, + // so pass --noLib to avoid reporting a file not found error. + options.noLib = true; + // Clear out other settings that would not be used in transpiling this module + options.lib = undefined; + options.types = undefined; + options.noEmit = undefined; + options.noEmitOnError = undefined; + options.paths = undefined; + options.rootDirs = undefined; + options.declaration = undefined; + options.declarationDir = undefined; + options.out = undefined; + options.outFile = undefined; + // We are not doing a full typecheck, we are not resolving the whole context, + // so pass --noResolve to avoid reporting missing file errors. + options.noResolve = true; + // if jsx is specified then treat file as .tsx + var inputFileName = transpileOptions.fileName || (options.jsx ? "module.tsx" : "module.ts"); + var sourceFile = ts.createSourceFile(inputFileName, input, options.target); + if (transpileOptions.moduleName) { + sourceFile.moduleName = transpileOptions.moduleName; + } + if (transpileOptions.renamedDependencies) { + sourceFile.renamedDependencies = ts.createMap(transpileOptions.renamedDependencies); + } + var newLine = ts.getNewLineCharacter(options); + // Output + var outputText; + var sourceMapText; + // Create a compilerHost object to allow the compiler to read and write files + var compilerHost = { + getSourceFile: function (fileName, target) { return fileName === ts.normalizePath(inputFileName) ? sourceFile : undefined; }, + writeFile: function (name, text, writeByteOrderMark) { + if (ts.fileExtensionIs(name, ".map")) { + ts.Debug.assert(sourceMapText === undefined, "Unexpected multiple source map outputs for the file '" + name + "'"); + sourceMapText = text; } - if (!insideJsDocTagExpression) { - // Proceed if the current position is in jsDoc tag expression; otherwise it is a normal - // comment or the plain text part of a jsDoc comment, so no completion should be available - log("Returning an empty list because completion was inside a regular comment or plain text part of a JsDoc comment."); - return undefined; + else { + ts.Debug.assert(outputText === undefined, "Unexpected multiple outputs for the file: '" + name + "'"); + outputText = text; } + }, + getDefaultLibFileName: function () { return "lib.d.ts"; }, + useCaseSensitiveFileNames: function () { return false; }, + getCanonicalFileName: function (fileName) { return fileName; }, + getCurrentDirectory: function () { return ""; }, + getNewLine: function () { return newLine; }, + fileExists: function (fileName) { return fileName === inputFileName; }, + readFile: function (fileName) { return ""; }, + directoryExists: function (directoryExists) { return true; }, + getDirectories: function (path) { return []; } + }; + var program = ts.createProgram([inputFileName], options, compilerHost); + if (transpileOptions.reportDiagnostics) { + ts.addRange(/*to*/ diagnostics, /*from*/ program.getSyntacticDiagnostics(sourceFile)); + ts.addRange(/*to*/ diagnostics, /*from*/ program.getOptionsDiagnostics()); + } + // Emit + program.emit(); + ts.Debug.assert(outputText !== undefined, "Output generation failed"); + return { outputText: outputText, diagnostics: diagnostics, sourceMapText: sourceMapText }; + } + ts.transpileModule = transpileModule; + /* + * This is a shortcut function for transpileModule - it accepts transpileOptions as parameters and returns only outputText part of the result. + */ + function transpile(input, compilerOptions, fileName, diagnostics, moduleName) { + var output = transpileModule(input, { compilerOptions: compilerOptions, fileName: fileName, reportDiagnostics: !!diagnostics, moduleName: moduleName }); + // addRange correctly handles cases when wither 'from' or 'to' argument is missing + ts.addRange(diagnostics, output.diagnostics); + return output.outputText; + } + ts.transpile = transpile; + var commandLineOptionsStringToEnum; + /** JS users may pass in string values for enum compiler options (such as ModuleKind), so convert. */ + function fixupCompilerOptions(options, diagnostics) { + // Lazily create this value to fix module loading errors. + commandLineOptionsStringToEnum = commandLineOptionsStringToEnum || ts.filter(ts.optionDeclarations, function (o) { + return typeof o.type === "object" && !ts.forEachProperty(o.type, function (v) { return typeof v !== "number"; }); + }); + options = ts.clone(options); + var _loop_2 = function (opt) { + if (!ts.hasProperty(options, opt.name)) { + return "continue"; } - start = ts.timestamp(); - var previousToken = ts.findPrecedingToken(position, sourceFile); - log("getCompletionData: Get previous token 1: " + (ts.timestamp() - start)); - // The decision to provide completion depends on the contextToken, which is determined through the previousToken. - // Note: 'previousToken' (and thus 'contextToken') can be undefined if we are the beginning of the file - var contextToken = previousToken; - // Check if the caret is at the end of an identifier; this is a partial identifier that we want to complete: e.g. a.toS| - // Skip this partial identifier and adjust the contextToken to the token that precedes it. - if (contextToken && position <= contextToken.end && ts.isWord(contextToken.kind)) { - var start_2 = ts.timestamp(); - contextToken = ts.findPrecedingToken(contextToken.getFullStart(), sourceFile); - log("getCompletionData: Get previous token 2: " + (ts.timestamp() - start_2)); + var value = options[opt.name]; + // Value should be a key of opt.type + if (typeof value === "string") { + // If value is not a string, this will fail + options[opt.name] = ts.parseCustomTypeOption(opt, value, diagnostics); } - // Find the node where completion is requested on. - // Also determine whether we are trying to complete with members of that node - // or attributes of a JSX tag. - var node = currentToken; - var isRightOfDot = false; - var isRightOfOpenTag = false; - var isStartingCloseTag = false; - var location = ts.getTouchingPropertyName(sourceFile, position); - if (contextToken) { - // Bail out if this is a known invalid completion location - if (isCompletionListBlocker(contextToken)) { - log("Returning an empty list because completion was requested in an invalid position."); - return undefined; + else { + if (!ts.forEachProperty(opt.type, function (v) { return v === value; })) { + // Supplied value isn't a valid enum value. + diagnostics.push(ts.createCompilerDiagnosticForInvalidCustomType(opt)); } - var parent_18 = contextToken.parent, kind = contextToken.kind; - if (kind === 21 /* DotToken */) { - if (parent_18.kind === 172 /* PropertyAccessExpression */) { - node = contextToken.parent.expression; - isRightOfDot = true; - } - else if (parent_18.kind === 139 /* QualifiedName */) { - node = contextToken.parent.left; - isRightOfDot = true; + } + }; + for (var _i = 0, commandLineOptionsStringToEnum_1 = commandLineOptionsStringToEnum; _i < commandLineOptionsStringToEnum_1.length; _i++) { + var opt = commandLineOptionsStringToEnum_1[_i]; + _loop_2(opt); + } + return options; + } +})(ts || (ts = {})); +/// +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + var standardScanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ false, 0 /* Standard */); + var jsxScanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ false, 1 /* JSX */); + /** + * Scanner that is currently used for formatting + */ + var scanner; + var ScanAction; + (function (ScanAction) { + ScanAction[ScanAction["Scan"] = 0] = "Scan"; + ScanAction[ScanAction["RescanGreaterThanToken"] = 1] = "RescanGreaterThanToken"; + ScanAction[ScanAction["RescanSlashToken"] = 2] = "RescanSlashToken"; + ScanAction[ScanAction["RescanTemplateToken"] = 3] = "RescanTemplateToken"; + ScanAction[ScanAction["RescanJsxIdentifier"] = 4] = "RescanJsxIdentifier"; + ScanAction[ScanAction["RescanJsxText"] = 5] = "RescanJsxText"; + })(ScanAction || (ScanAction = {})); + function getFormattingScanner(sourceFile, startPos, endPos) { + ts.Debug.assert(scanner === undefined); + scanner = sourceFile.languageVariant === 1 /* JSX */ ? jsxScanner : standardScanner; + scanner.setText(sourceFile.text); + scanner.setTextPos(startPos); + var wasNewLine = true; + var leadingTrivia; + var trailingTrivia; + var savedPos; + var lastScanAction; + var lastTokenInfo; + return { + advance: advance, + readTokenInfo: readTokenInfo, + isOnToken: isOnToken, + getCurrentLeadingTrivia: function () { return leadingTrivia; }, + lastTrailingTriviaWasNewLine: function () { return wasNewLine; }, + skipToEndOf: skipToEndOf, + close: function () { + ts.Debug.assert(scanner !== undefined); + lastTokenInfo = undefined; + scanner.setText(undefined); + scanner = undefined; + } + }; + function advance() { + ts.Debug.assert(scanner !== undefined); + lastTokenInfo = undefined; + var isStarted = scanner.getStartPos() !== startPos; + if (isStarted) { + if (trailingTrivia) { + ts.Debug.assert(trailingTrivia.length !== 0); + wasNewLine = ts.lastOrUndefined(trailingTrivia).kind === 4 /* NewLineTrivia */; } else { - // There is nothing that precedes the dot, so this likely just a stray character - // or leading into a '...' token. Just bail out instead. - return undefined; + wasNewLine = false; } } - else if (sourceFile.languageVariant === 1 /* JSX */) { - if (kind === 25 /* LessThanToken */) { - isRightOfOpenTag = true; - location = contextToken; + leadingTrivia = undefined; + trailingTrivia = undefined; + if (!isStarted) { + scanner.scan(); + } + var pos = scanner.getStartPos(); + // Read leading trivia and token + while (pos < endPos) { + var t = scanner.getToken(); + if (!ts.isTrivia(t)) { + break; } - else if (kind === 39 /* SlashToken */ && contextToken.parent.kind === 245 /* JsxClosingElement */) { - isStartingCloseTag = true; - location = contextToken; + // consume leading trivia + scanner.scan(); + var item = { + pos: pos, + end: scanner.getStartPos(), + kind: t + }; + pos = scanner.getStartPos(); + if (!leadingTrivia) { + leadingTrivia = []; } + leadingTrivia.push(item); } + savedPos = scanner.getStartPos(); } - var semanticStart = ts.timestamp(); - var isMemberCompletion; - var isNewIdentifierLocation; - var symbols = []; - if (isRightOfDot) { - getTypeScriptMemberSymbols(); - } - else if (isRightOfOpenTag) { - var tagSymbols = typeChecker.getJsxIntrinsicTagNames(); - if (tryGetGlobalSymbols()) { - symbols = tagSymbols.concat(symbols.filter(function (s) { return !!(s.flags & (107455 /* Value */ | 8388608 /* Alias */)); })); - } - else { - symbols = tagSymbols; + function shouldRescanGreaterThanToken(node) { + if (node) { + switch (node.kind) { + case 29 /* GreaterThanEqualsToken */: + case 64 /* GreaterThanGreaterThanEqualsToken */: + case 65 /* GreaterThanGreaterThanGreaterThanEqualsToken */: + case 45 /* GreaterThanGreaterThanGreaterThanToken */: + case 44 /* GreaterThanGreaterThanToken */: + return true; + } } - isMemberCompletion = true; - isNewIdentifierLocation = false; + return false; } - else if (isStartingCloseTag) { - var tagName = contextToken.parent.parent.openingElement.tagName; - var tagSymbol = typeChecker.getSymbolAtLocation(tagName); - if (!typeChecker.isUnknownSymbol(tagSymbol)) { - symbols = [tagSymbol]; + function shouldRescanJsxIdentifier(node) { + if (node.parent) { + switch (node.parent.kind) { + case 246 /* JsxAttribute */: + case 243 /* JsxOpeningElement */: + case 245 /* JsxClosingElement */: + case 242 /* JsxSelfClosingElement */: + return node.kind === 69 /* Identifier */; + } } - isMemberCompletion = true; - isNewIdentifierLocation = false; + return false; } - else { - // For JavaScript or TypeScript, if we're not after a dot, then just try to get the - // global symbols in scope. These results should be valid for either language as - // the set of symbols that can be referenced from this location. - if (!tryGetGlobalSymbols()) { - return undefined; - } + function shouldRescanJsxText(node) { + return node && node.kind === 244 /* JsxText */; } - log("getCompletionData: Semantic work: " + (ts.timestamp() - semanticStart)); - return { symbols: symbols, isMemberCompletion: isMemberCompletion, isNewIdentifierLocation: isNewIdentifierLocation, location: location, isRightOfDot: (isRightOfDot || isRightOfOpenTag), isJsDocTagName: isJsDocTagName }; - function getTypeScriptMemberSymbols() { - // Right of dot member completion list - isMemberCompletion = true; - isNewIdentifierLocation = false; - if (node.kind === 69 /* Identifier */ || node.kind === 139 /* QualifiedName */ || node.kind === 172 /* PropertyAccessExpression */) { - var symbol = typeChecker.getSymbolAtLocation(node); - // This is an alias, follow what it aliases - if (symbol && symbol.flags & 8388608 /* Alias */) { - symbol = typeChecker.getAliasedSymbol(symbol); - } - if (symbol && symbol.flags & 1952 /* HasExports */) { - // Extract module or enum members - var exportedSymbols = typeChecker.getExportsOfModule(symbol); - ts.forEach(exportedSymbols, function (symbol) { - if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) { - symbols.push(symbol); - } - }); - } - } - var type = typeChecker.getTypeAtLocation(node); - addTypeProperties(type); + function shouldRescanSlashToken(container) { + return container.kind === 10 /* RegularExpressionLiteral */; } - function addTypeProperties(type) { - if (type) { - // Filter private properties - for (var _i = 0, _a = type.getApparentProperties(); _i < _a.length; _i++) { - var symbol = _a[_i]; - if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) { - symbols.push(symbol); - } - } - if (isJavaScriptFile && type.flags & 524288 /* Union */) { - // In javascript files, for union types, we don't just get the members that - // the individual types have in common, we also include all the members that - // each individual type has. This is because we're going to add all identifiers - // anyways. So we might as well elevate the members that were at least part - // of the individual types to a higher status since we know what they are. - var unionType = type; - for (var _b = 0, _c = unionType.types; _b < _c.length; _b++) { - var elementType = _c[_b]; - addTypeProperties(elementType); - } - } - } + function shouldRescanTemplateToken(container) { + return container.kind === 13 /* TemplateMiddle */ || + container.kind === 14 /* TemplateTail */; } - function tryGetGlobalSymbols() { - var objectLikeContainer; - var namedImportsOrExports; - var jsxContainer; - if (objectLikeContainer = tryGetObjectLikeCompletionContainer(contextToken)) { - return tryGetObjectLikeCompletionSymbols(objectLikeContainer); + function startsWithSlashToken(t) { + return t === 39 /* SlashToken */ || t === 61 /* SlashEqualsToken */; + } + function readTokenInfo(n) { + ts.Debug.assert(scanner !== undefined); + if (!isOnToken()) { + // scanner is not on the token (either advance was not called yet or scanner is already past the end position) + return { + leadingTrivia: leadingTrivia, + trailingTrivia: undefined, + token: undefined + }; } - if (namedImportsOrExports = tryGetNamedImportsOrExportsForCompletion(contextToken)) { - // cursor is in an import clause - // try to show exported member for imported module - return tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports); + // normally scanner returns the smallest available token + // check the kind of context node to determine if scanner should have more greedy behavior and consume more text. + var expectedScanAction = shouldRescanGreaterThanToken(n) + ? 1 /* RescanGreaterThanToken */ + : shouldRescanSlashToken(n) + ? 2 /* RescanSlashToken */ + : shouldRescanTemplateToken(n) + ? 3 /* RescanTemplateToken */ + : shouldRescanJsxIdentifier(n) + ? 4 /* RescanJsxIdentifier */ + : shouldRescanJsxText(n) + ? 5 /* RescanJsxText */ + : 0 /* Scan */; + if (lastTokenInfo && expectedScanAction === lastScanAction) { + // readTokenInfo was called before with the same expected scan action. + // No need to re-scan text, return existing 'lastTokenInfo' + // it is ok to call fixTokenKind here since it does not affect + // what portion of text is consumed. In contrast rescanning can change it, + // i.e. for '>=' when originally scanner eats just one character + // and rescanning forces it to consume more. + return fixTokenKind(lastTokenInfo, n); } - if (jsxContainer = tryGetContainingJsxElement(contextToken)) { - var attrsType = void 0; - if ((jsxContainer.kind === 242 /* JsxSelfClosingElement */) || (jsxContainer.kind === 243 /* JsxOpeningElement */)) { - // Cursor is inside a JSX self-closing element or opening element - attrsType = typeChecker.getJsxElementAttributesType(jsxContainer); - if (attrsType) { - symbols = filterJsxAttributes(typeChecker.getPropertiesOfType(attrsType), jsxContainer.attributes); - isMemberCompletion = true; - isNewIdentifierLocation = false; - return true; - } - } + if (scanner.getStartPos() !== savedPos) { + ts.Debug.assert(lastTokenInfo !== undefined); + // readTokenInfo was called before but scan action differs - rescan text + scanner.setTextPos(savedPos); + scanner.scan(); } - // Get all entities in the current scope. - isMemberCompletion = false; - isNewIdentifierLocation = isNewIdentifierDefinitionLocation(contextToken); - if (previousToken !== contextToken) { - ts.Debug.assert(!!previousToken, "Expected 'contextToken' to be defined when different from 'previousToken'."); + var currentToken = scanner.getToken(); + if (expectedScanAction === 1 /* RescanGreaterThanToken */ && currentToken === 27 /* GreaterThanToken */) { + currentToken = scanner.reScanGreaterToken(); + ts.Debug.assert(n.kind === currentToken); + lastScanAction = 1 /* RescanGreaterThanToken */; } - // We need to find the node that will give us an appropriate scope to begin - // aggregating completion candidates. This is achieved in 'getScopeNode' - // by finding the first node that encompasses a position, accounting for whether a node - // is "complete" to decide whether a position belongs to the node. - // - // However, at the end of an identifier, we are interested in the scope of the identifier - // itself, but fall outside of the identifier. For instance: - // - // xyz => x$ - // - // the cursor is outside of both the 'x' and the arrow function 'xyz => x', - // so 'xyz' is not returned in our results. - // - // We define 'adjustedPosition' so that we may appropriately account for - // being at the end of an identifier. The intention is that if requesting completion - // at the end of an identifier, it should be effectively equivalent to requesting completion - // anywhere inside/at the beginning of the identifier. So in the previous case, the - // 'adjustedPosition' will work as if requesting completion in the following: - // - // xyz => $x - // - // If previousToken !== contextToken, then - // - 'contextToken' was adjusted to the token prior to 'previousToken' - // because we were at the end of an identifier. - // - 'previousToken' is defined. - var adjustedPosition = previousToken !== contextToken ? - previousToken.getStart() : - position; - var scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile; - /// TODO filter meaning based on the current context - var symbolMeanings = 793064 /* Type */ | 107455 /* Value */ | 1920 /* Namespace */ | 8388608 /* Alias */; - symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings); - return true; - } - /** - * Finds the first node that "embraces" the position, so that one may - * accurately aggregate locals from the closest containing scope. - */ - function getScopeNode(initialToken, position, sourceFile) { - var scope = initialToken; - while (scope && !ts.positionBelongsToNode(scope, position, sourceFile)) { - scope = scope.parent; + else if (expectedScanAction === 2 /* RescanSlashToken */ && startsWithSlashToken(currentToken)) { + currentToken = scanner.reScanSlashToken(); + ts.Debug.assert(n.kind === currentToken); + lastScanAction = 2 /* RescanSlashToken */; } - return scope; - } - function isCompletionListBlocker(contextToken) { - var start = ts.timestamp(); - var result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) || - isSolelyIdentifierDefinitionLocation(contextToken) || - isDotOfNumericLiteral(contextToken) || - isInJsxText(contextToken); - log("getCompletionsAtPosition: isCompletionListBlocker: " + (ts.timestamp() - start)); - return result; - } - function isInJsxText(contextToken) { - if (contextToken.kind === 244 /* JsxText */) { - return true; + else if (expectedScanAction === 3 /* RescanTemplateToken */ && currentToken === 16 /* CloseBraceToken */) { + currentToken = scanner.reScanTemplateToken(); + lastScanAction = 3 /* RescanTemplateToken */; } - if (contextToken.kind === 27 /* GreaterThanToken */ && contextToken.parent) { - if (contextToken.parent.kind === 243 /* JsxOpeningElement */) { - return true; - } - if (contextToken.parent.kind === 245 /* JsxClosingElement */ || contextToken.parent.kind === 242 /* JsxSelfClosingElement */) { - return contextToken.parent.parent && contextToken.parent.parent.kind === 241 /* JsxElement */; - } + else if (expectedScanAction === 4 /* RescanJsxIdentifier */ && currentToken === 69 /* Identifier */) { + currentToken = scanner.scanJsxIdentifier(); + lastScanAction = 4 /* RescanJsxIdentifier */; } - return false; - } - function isNewIdentifierDefinitionLocation(previousToken) { - if (previousToken) { - var containingNodeKind = previousToken.parent.kind; - switch (previousToken.kind) { - case 24 /* CommaToken */: - return containingNodeKind === 174 /* CallExpression */ // func( a, | - || containingNodeKind === 148 /* Constructor */ // constructor( a, | /* public, protected, private keywords are allowed here, so show completion */ - || containingNodeKind === 175 /* NewExpression */ // new C(a, | - || containingNodeKind === 170 /* ArrayLiteralExpression */ // [a, | - || containingNodeKind === 187 /* BinaryExpression */ // const x = (a, | - || containingNodeKind === 156 /* FunctionType */; // var x: (s: string, list| - case 17 /* OpenParenToken */: - return containingNodeKind === 174 /* CallExpression */ // func( | - || containingNodeKind === 148 /* Constructor */ // constructor( | - || containingNodeKind === 175 /* NewExpression */ // new C(a| - || containingNodeKind === 178 /* ParenthesizedExpression */ // const x = (a| - || containingNodeKind === 164 /* ParenthesizedType */; // function F(pred: (a| /* this can become an arrow function, where 'a' is the argument */ - case 19 /* OpenBracketToken */: - return containingNodeKind === 170 /* ArrayLiteralExpression */ // [ | - || containingNodeKind === 153 /* IndexSignature */ // [ | : string ] - || containingNodeKind === 140 /* ComputedPropertyName */; // [ | /* this can become an index signature */ - case 125 /* ModuleKeyword */: // module | - case 126 /* NamespaceKeyword */: - return true; - case 21 /* DotToken */: - return containingNodeKind === 225 /* ModuleDeclaration */; // module A.| - case 15 /* OpenBraceToken */: - return containingNodeKind === 221 /* ClassDeclaration */; // class A{ | - case 56 /* EqualsToken */: - return containingNodeKind === 218 /* VariableDeclaration */ // const x = a| - || containingNodeKind === 187 /* BinaryExpression */; // x = a| - case 12 /* TemplateHead */: - return containingNodeKind === 189 /* TemplateExpression */; // `aa ${| - case 13 /* TemplateMiddle */: - return containingNodeKind === 197 /* TemplateSpan */; // `aa ${10} dd ${| - case 112 /* PublicKeyword */: - case 110 /* PrivateKeyword */: - case 111 /* ProtectedKeyword */: - return containingNodeKind === 145 /* PropertyDeclaration */; // class A{ public | - } - // Previous token may have been a keyword that was converted to an identifier. - switch (previousToken.getText()) { - case "public": - case "protected": - case "private": - return true; - } + else if (expectedScanAction === 5 /* RescanJsxText */) { + currentToken = scanner.reScanJsxToken(); + lastScanAction = 5 /* RescanJsxText */; } - return false; - } - function isInStringOrRegularExpressionOrTemplateLiteral(contextToken) { - if (contextToken.kind === 9 /* StringLiteral */ - || contextToken.kind === 10 /* RegularExpressionLiteral */ - || ts.isTemplateLiteralKind(contextToken.kind)) { - var start_3 = contextToken.getStart(); - var end = contextToken.getEnd(); - // To be "in" one of these literals, the position has to be: - // 1. entirely within the token text. - // 2. at the end position of an unterminated token. - // 3. at the end of a regular expression (due to trailing flags like '/foo/g'). - if (start_3 < position && position < end) { - return true; + else { + lastScanAction = 0 /* Scan */; + } + var token = { + pos: scanner.getStartPos(), + end: scanner.getTextPos(), + kind: currentToken + }; + // consume trailing trivia + if (trailingTrivia) { + trailingTrivia = undefined; + } + while (scanner.getStartPos() < endPos) { + currentToken = scanner.scan(); + if (!ts.isTrivia(currentToken)) { + break; } - if (position === end) { - return !!contextToken.isUnterminated - || contextToken.kind === 10 /* RegularExpressionLiteral */; + var trivia = { + pos: scanner.getStartPos(), + end: scanner.getTextPos(), + kind: currentToken + }; + if (!trailingTrivia) { + trailingTrivia = []; + } + trailingTrivia.push(trivia); + if (currentToken === 4 /* NewLineTrivia */) { + // move past new line + scanner.scan(); + break; } } - return false; + lastTokenInfo = { + leadingTrivia: leadingTrivia, + trailingTrivia: trailingTrivia, + token: token + }; + return fixTokenKind(lastTokenInfo, n); + } + function isOnToken() { + ts.Debug.assert(scanner !== undefined); + var current = (lastTokenInfo && lastTokenInfo.token.kind) || scanner.getToken(); + var startPos = (lastTokenInfo && lastTokenInfo.token.pos) || scanner.getStartPos(); + return startPos < endPos && current !== 1 /* EndOfFileToken */ && !ts.isTrivia(current); + } + // when containing node in the tree is token + // but its kind differs from the kind that was returned by the scanner, + // then kind needs to be fixed. This might happen in cases + // when parser interprets token differently, i.e keyword treated as identifier + function fixTokenKind(tokenInfo, container) { + if (ts.isToken(container) && tokenInfo.token.kind !== container.kind) { + tokenInfo.token.kind = container.kind; + } + return tokenInfo; } - /** - * Aggregates relevant symbols for completion in object literals and object binding patterns. - * Relevant symbols are stored in the captured 'symbols' variable. - * - * @returns true if 'symbols' was successfully populated; false otherwise. - */ - function tryGetObjectLikeCompletionSymbols(objectLikeContainer) { - // We're looking up possible property names from contextual/inferred/declared type. - isMemberCompletion = true; - var typeForObject; - var existingMembers; - if (objectLikeContainer.kind === 171 /* ObjectLiteralExpression */) { - // We are completing on contextual types, but may also include properties - // other than those within the declared type. - isNewIdentifierLocation = true; - // If the object literal is being assigned to something of type 'null | { hello: string }', - // it clearly isn't trying to satisfy the 'null' type. So we grab the non-nullable type if possible. - typeForObject = typeChecker.getContextualType(objectLikeContainer); - typeForObject = typeForObject && typeForObject.getNonNullableType(); - existingMembers = objectLikeContainer.properties; + function skipToEndOf(node) { + scanner.setTextPos(node.end); + savedPos = scanner.getStartPos(); + lastScanAction = undefined; + lastTokenInfo = undefined; + wasNewLine = false; + leadingTrivia = undefined; + trailingTrivia = undefined; + } + } + formatting.getFormattingScanner = getFormattingScanner; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + var FormattingContext = (function () { + function FormattingContext(sourceFile, formattingRequestKind) { + this.sourceFile = sourceFile; + this.formattingRequestKind = formattingRequestKind; + } + FormattingContext.prototype.updateContext = function (currentRange, currentTokenParent, nextRange, nextTokenParent, commonParent) { + ts.Debug.assert(currentRange !== undefined, "currentTokenSpan is null"); + ts.Debug.assert(currentTokenParent !== undefined, "currentTokenParent is null"); + ts.Debug.assert(nextRange !== undefined, "nextTokenSpan is null"); + ts.Debug.assert(nextTokenParent !== undefined, "nextTokenParent is null"); + ts.Debug.assert(commonParent !== undefined, "commonParent is null"); + this.currentTokenSpan = currentRange; + this.currentTokenParent = currentTokenParent; + this.nextTokenSpan = nextRange; + this.nextTokenParent = nextTokenParent; + this.contextNode = commonParent; + // drop cached results + this.contextNodeAllOnSameLine = undefined; + this.nextNodeAllOnSameLine = undefined; + this.tokensAreOnSameLine = undefined; + this.contextNodeBlockIsOnOneLine = undefined; + this.nextNodeBlockIsOnOneLine = undefined; + }; + FormattingContext.prototype.ContextNodeAllOnSameLine = function () { + if (this.contextNodeAllOnSameLine === undefined) { + this.contextNodeAllOnSameLine = this.NodeIsOnOneLine(this.contextNode); } - else if (objectLikeContainer.kind === 167 /* ObjectBindingPattern */) { - // We are *only* completing on properties from the type being destructured. - isNewIdentifierLocation = false; - var rootDeclaration = ts.getRootDeclaration(objectLikeContainer.parent); - if (ts.isVariableLike(rootDeclaration)) { - // We don't want to complete using the type acquired by the shape - // of the binding pattern; we are only interested in types acquired - // through type declaration or inference. - // Also proceed if rootDeclaration is a parameter and if its containing function expression/arrow function is contextually typed - - // type of parameter will flow in from the contextual type of the function - var canGetType = !!(rootDeclaration.initializer || rootDeclaration.type); - if (!canGetType && rootDeclaration.kind === 142 /* Parameter */) { - if (ts.isExpression(rootDeclaration.parent)) { - canGetType = !!typeChecker.getContextualType(rootDeclaration.parent); - } - else if (rootDeclaration.parent.kind === 147 /* MethodDeclaration */ || rootDeclaration.parent.kind === 150 /* SetAccessor */) { - canGetType = ts.isExpression(rootDeclaration.parent.parent) && !!typeChecker.getContextualType(rootDeclaration.parent.parent); - } - } - if (canGetType) { - typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer); - existingMembers = objectLikeContainer.elements; - } - } - else { - ts.Debug.fail("Root declaration is not variable-like."); - } + return this.contextNodeAllOnSameLine; + }; + FormattingContext.prototype.NextNodeAllOnSameLine = function () { + if (this.nextNodeAllOnSameLine === undefined) { + this.nextNodeAllOnSameLine = this.NodeIsOnOneLine(this.nextTokenParent); } - else { - ts.Debug.fail("Expected object literal or binding pattern, got " + objectLikeContainer.kind); + return this.nextNodeAllOnSameLine; + }; + FormattingContext.prototype.TokensAreOnSameLine = function () { + if (this.tokensAreOnSameLine === undefined) { + var startLine = this.sourceFile.getLineAndCharacterOfPosition(this.currentTokenSpan.pos).line; + var endLine = this.sourceFile.getLineAndCharacterOfPosition(this.nextTokenSpan.pos).line; + this.tokensAreOnSameLine = (startLine === endLine); } - if (!typeForObject) { - return false; + return this.tokensAreOnSameLine; + }; + FormattingContext.prototype.ContextNodeBlockIsOnOneLine = function () { + if (this.contextNodeBlockIsOnOneLine === undefined) { + this.contextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.contextNode); } - var typeMembers = typeChecker.getPropertiesOfType(typeForObject); - if (typeMembers && typeMembers.length > 0) { - // Add filtered items to the completion list - symbols = filterObjectMembersList(typeMembers, existingMembers); + return this.contextNodeBlockIsOnOneLine; + }; + FormattingContext.prototype.NextNodeBlockIsOnOneLine = function () { + if (this.nextNodeBlockIsOnOneLine === undefined) { + this.nextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.nextTokenParent); } - return true; + return this.nextNodeBlockIsOnOneLine; + }; + FormattingContext.prototype.NodeIsOnOneLine = function (node) { + var startLine = this.sourceFile.getLineAndCharacterOfPosition(node.getStart(this.sourceFile)).line; + var endLine = this.sourceFile.getLineAndCharacterOfPosition(node.getEnd()).line; + return startLine === endLine; + }; + FormattingContext.prototype.BlockIsOnOneLine = function (node) { + var openBrace = ts.findChildOfKind(node, 15 /* OpenBraceToken */, this.sourceFile); + var closeBrace = ts.findChildOfKind(node, 16 /* CloseBraceToken */, this.sourceFile); + if (openBrace && closeBrace) { + var startLine = this.sourceFile.getLineAndCharacterOfPosition(openBrace.getEnd()).line; + var endLine = this.sourceFile.getLineAndCharacterOfPosition(closeBrace.getStart(this.sourceFile)).line; + return startLine === endLine; + } + return false; + }; + return FormattingContext; + }()); + formatting.FormattingContext = FormattingContext; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + (function (FormattingRequestKind) { + FormattingRequestKind[FormattingRequestKind["FormatDocument"] = 0] = "FormatDocument"; + FormattingRequestKind[FormattingRequestKind["FormatSelection"] = 1] = "FormatSelection"; + FormattingRequestKind[FormattingRequestKind["FormatOnEnter"] = 2] = "FormatOnEnter"; + FormattingRequestKind[FormattingRequestKind["FormatOnSemicolon"] = 3] = "FormatOnSemicolon"; + FormattingRequestKind[FormattingRequestKind["FormatOnClosingCurlyBrace"] = 4] = "FormatOnClosingCurlyBrace"; + })(formatting.FormattingRequestKind || (formatting.FormattingRequestKind = {})); + var FormattingRequestKind = formatting.FormattingRequestKind; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + var Rule = (function () { + function Rule(Descriptor, Operation, Flag) { + if (Flag === void 0) { Flag = 0 /* None */; } + this.Descriptor = Descriptor; + this.Operation = Operation; + this.Flag = Flag; } - /** - * Aggregates relevant symbols for completion in import clauses and export clauses - * whose declarations have a module specifier; for instance, symbols will be aggregated for - * - * import { | } from "moduleName"; - * export { a as foo, | } from "moduleName"; - * - * but not for - * - * export { | }; - * - * Relevant symbols are stored in the captured 'symbols' variable. - * - * @returns true if 'symbols' was successfully populated; false otherwise. - */ - function tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports) { - var declarationKind = namedImportsOrExports.kind === 233 /* NamedImports */ ? - 230 /* ImportDeclaration */ : - 236 /* ExportDeclaration */; - var importOrExportDeclaration = ts.getAncestor(namedImportsOrExports, declarationKind); - var moduleSpecifier = importOrExportDeclaration.moduleSpecifier; - if (!moduleSpecifier) { - return false; + Rule.prototype.toString = function () { + return "[desc=" + this.Descriptor + "," + + "operation=" + this.Operation + "," + + "flag=" + this.Flag + "]"; + }; + return Rule; + }()); + formatting.Rule = Rule; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + (function (RuleAction) { + RuleAction[RuleAction["Ignore"] = 1] = "Ignore"; + RuleAction[RuleAction["Space"] = 2] = "Space"; + RuleAction[RuleAction["NewLine"] = 4] = "NewLine"; + RuleAction[RuleAction["Delete"] = 8] = "Delete"; + })(formatting.RuleAction || (formatting.RuleAction = {})); + var RuleAction = formatting.RuleAction; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + var RuleDescriptor = (function () { + function RuleDescriptor(LeftTokenRange, RightTokenRange) { + this.LeftTokenRange = LeftTokenRange; + this.RightTokenRange = RightTokenRange; + } + RuleDescriptor.prototype.toString = function () { + return "[leftRange=" + this.LeftTokenRange + "," + + "rightRange=" + this.RightTokenRange + "]"; + }; + RuleDescriptor.create1 = function (left, right) { + return RuleDescriptor.create4(formatting.Shared.TokenRange.FromToken(left), formatting.Shared.TokenRange.FromToken(right)); + }; + RuleDescriptor.create2 = function (left, right) { + return RuleDescriptor.create4(left, formatting.Shared.TokenRange.FromToken(right)); + }; + RuleDescriptor.create3 = function (left, right) { + return RuleDescriptor.create4(formatting.Shared.TokenRange.FromToken(left), right); + }; + RuleDescriptor.create4 = function (left, right) { + return new RuleDescriptor(left, right); + }; + return RuleDescriptor; + }()); + formatting.RuleDescriptor = RuleDescriptor; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + (function (RuleFlags) { + RuleFlags[RuleFlags["None"] = 0] = "None"; + RuleFlags[RuleFlags["CanDeleteNewLines"] = 1] = "CanDeleteNewLines"; + })(formatting.RuleFlags || (formatting.RuleFlags = {})); + var RuleFlags = formatting.RuleFlags; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + var RuleOperation = (function () { + function RuleOperation(Context, Action) { + this.Context = Context; + this.Action = Action; + } + RuleOperation.prototype.toString = function () { + return "[context=" + this.Context + "," + + "action=" + this.Action + "]"; + }; + RuleOperation.create1 = function (action) { + return RuleOperation.create2(formatting.RuleOperationContext.Any, action); + }; + RuleOperation.create2 = function (context, action) { + return new RuleOperation(context, action); + }; + return RuleOperation; + }()); + formatting.RuleOperation = RuleOperation; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + var RuleOperationContext = (function () { + function RuleOperationContext() { + var funcs = []; + for (var _i = 0; _i < arguments.length; _i++) { + funcs[_i - 0] = arguments[_i]; } - isMemberCompletion = true; - isNewIdentifierLocation = false; - var exports; - var moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importOrExportDeclaration.moduleSpecifier); - if (moduleSpecifierSymbol) { - exports = typeChecker.getExportsOfModule(moduleSpecifierSymbol); + this.customContextChecks = funcs; + } + RuleOperationContext.prototype.IsAny = function () { + return this === RuleOperationContext.Any; + }; + RuleOperationContext.prototype.InContext = function (context) { + if (this.IsAny()) { + return true; + } + for (var _i = 0, _a = this.customContextChecks; _i < _a.length; _i++) { + var check = _a[_i]; + if (!check(context)) { + return false; + } } - symbols = exports ? filterNamedImportOrExportCompletionItems(exports, namedImportsOrExports.elements) : emptyArray; return true; + }; + return RuleOperationContext; + }()); + RuleOperationContext.Any = new RuleOperationContext(); + formatting.RuleOperationContext = RuleOperationContext; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + var Rules = (function () { + function Rules() { + /// + /// Common Rules + /// + // Leave comments alone + this.IgnoreBeforeComment = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.Comments), formatting.RuleOperation.create1(1 /* Ignore */)); + this.IgnoreAfterLineComment = new formatting.Rule(formatting.RuleDescriptor.create3(2 /* SingleLineCommentTrivia */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create1(1 /* Ignore */)); + // Space after keyword but not before ; or : or ? + this.NoSpaceBeforeSemicolon = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 23 /* SemicolonToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceBeforeColon = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 54 /* ColonToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), 8 /* Delete */)); + this.NoSpaceBeforeQuestionMark = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 53 /* QuestionToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), 8 /* Delete */)); + this.SpaceAfterColon = new formatting.Rule(formatting.RuleDescriptor.create3(54 /* ColonToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), 2 /* Space */)); + this.SpaceAfterQuestionMarkInConditionalOperator = new formatting.Rule(formatting.RuleDescriptor.create3(53 /* QuestionToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsConditionalOperatorContext), 2 /* Space */)); + this.NoSpaceAfterQuestionMark = new formatting.Rule(formatting.RuleDescriptor.create3(53 /* QuestionToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.SpaceAfterSemicolon = new formatting.Rule(formatting.RuleDescriptor.create3(23 /* SemicolonToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + // Space after }. + this.SpaceAfterCloseBrace = new formatting.Rule(formatting.RuleDescriptor.create3(16 /* CloseBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsAfterCodeBlockContext), 2 /* Space */)); + // Special case for (}, else) and (}, while) since else & while tokens are not part of the tree which makes SpaceAfterCloseBrace rule not applied + this.SpaceBetweenCloseBraceAndElse = new formatting.Rule(formatting.RuleDescriptor.create1(16 /* CloseBraceToken */, 80 /* ElseKeyword */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.SpaceBetweenCloseBraceAndWhile = new formatting.Rule(formatting.RuleDescriptor.create1(16 /* CloseBraceToken */, 104 /* WhileKeyword */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.NoSpaceAfterCloseBrace = new formatting.Rule(formatting.RuleDescriptor.create3(16 /* CloseBraceToken */, formatting.Shared.TokenRange.FromTokens([18 /* CloseParenToken */, 20 /* CloseBracketToken */, 24 /* CommaToken */, 23 /* SemicolonToken */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + // No space for dot + this.NoSpaceBeforeDot = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 21 /* DotToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceAfterDot = new formatting.Rule(formatting.RuleDescriptor.create3(21 /* DotToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + // No space before and after indexer + this.NoSpaceBeforeOpenBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 19 /* OpenBracketToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceAfterCloseBracket = new formatting.Rule(formatting.RuleDescriptor.create3(20 /* CloseBracketToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBeforeBlockInFunctionDeclarationContext), 8 /* Delete */)); + // Place a space before open brace in a function declaration + this.FunctionOpenBraceLeftTokenRange = formatting.Shared.TokenRange.AnyIncludingMultilineComments; + this.SpaceBeforeOpenBraceInFunction = new formatting.Rule(formatting.RuleDescriptor.create2(this.FunctionOpenBraceLeftTokenRange, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext, Rules.IsBeforeBlockContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), 2 /* Space */), 1 /* CanDeleteNewLines */); + // Place a space before open brace in a TypeScript declaration that has braces as children (class, module, enum, etc) + this.TypeScriptOpenBraceLeftTokenRange = formatting.Shared.TokenRange.FromTokens([69 /* Identifier */, 3 /* MultiLineCommentTrivia */, 73 /* ClassKeyword */, 82 /* ExportKeyword */, 89 /* ImportKeyword */]); + this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock = new formatting.Rule(formatting.RuleDescriptor.create2(this.TypeScriptOpenBraceLeftTokenRange, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsTypeScriptDeclWithBlockContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), 2 /* Space */), 1 /* CanDeleteNewLines */); + // Place a space before open brace in a control flow construct + this.ControlOpenBraceLeftTokenRange = formatting.Shared.TokenRange.FromTokens([18 /* CloseParenToken */, 3 /* MultiLineCommentTrivia */, 79 /* DoKeyword */, 100 /* TryKeyword */, 85 /* FinallyKeyword */, 80 /* ElseKeyword */]); + this.SpaceBeforeOpenBraceInControl = new formatting.Rule(formatting.RuleDescriptor.create2(this.ControlOpenBraceLeftTokenRange, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeMultilineBlockContext), 2 /* Space */), 1 /* CanDeleteNewLines */); + // Insert a space after { and before } in single-line contexts, but remove space from empty object literals {}. + this.SpaceAfterOpenBrace = new formatting.Rule(formatting.RuleDescriptor.create3(15 /* OpenBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSingleLineBlockContext), 2 /* Space */)); + this.SpaceBeforeCloseBrace = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSingleLineBlockContext), 2 /* Space */)); + this.NoSpaceAfterOpenBrace = new formatting.Rule(formatting.RuleDescriptor.create3(15 /* OpenBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSingleLineBlockContext), 8 /* Delete */)); + this.NoSpaceBeforeCloseBrace = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsSingleLineBlockContext), 8 /* Delete */)); + this.NoSpaceBetweenEmptyBraceBrackets = new formatting.Rule(formatting.RuleDescriptor.create1(15 /* OpenBraceToken */, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsObjectContext), 8 /* Delete */)); + // Insert new line after { and before } in multi-line contexts. + this.NewLineAfterOpenBraceInBlockContext = new formatting.Rule(formatting.RuleDescriptor.create3(15 /* OpenBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsMultilineBlockContext), 4 /* NewLine */)); + // For functions and control block place } on a new line [multi-line rule] + this.NewLineBeforeCloseBraceInBlockContext = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.AnyIncludingMultilineComments, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsMultilineBlockContext), 4 /* NewLine */)); + // Special handling of unary operators. + // Prefix operators generally shouldn't have a space between + // them and their target unary expression. + this.NoSpaceAfterUnaryPrefixOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.UnaryPrefixOperators, formatting.Shared.TokenRange.UnaryPrefixExpressions), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), 8 /* Delete */)); + this.NoSpaceAfterUnaryPreincrementOperator = new formatting.Rule(formatting.RuleDescriptor.create3(41 /* PlusPlusToken */, formatting.Shared.TokenRange.UnaryPreincrementExpressions), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceAfterUnaryPredecrementOperator = new formatting.Rule(formatting.RuleDescriptor.create3(42 /* MinusMinusToken */, formatting.Shared.TokenRange.UnaryPredecrementExpressions), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceBeforeUnaryPostincrementOperator = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.UnaryPostincrementExpressions, 41 /* PlusPlusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceBeforeUnaryPostdecrementOperator = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.UnaryPostdecrementExpressions, 42 /* MinusMinusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + // More unary operator special-casing. + // DevDiv 181814: Be careful when removing leading whitespace + // around unary operators. Examples: + // 1 - -2 --X--> 1--2 + // a + ++b --X--> a+++b + this.SpaceAfterPostincrementWhenFollowedByAdd = new formatting.Rule(formatting.RuleDescriptor.create1(41 /* PlusPlusToken */, 35 /* PlusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); + this.SpaceAfterAddWhenFollowedByUnaryPlus = new formatting.Rule(formatting.RuleDescriptor.create1(35 /* PlusToken */, 35 /* PlusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); + this.SpaceAfterAddWhenFollowedByPreincrement = new formatting.Rule(formatting.RuleDescriptor.create1(35 /* PlusToken */, 41 /* PlusPlusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); + this.SpaceAfterPostdecrementWhenFollowedBySubtract = new formatting.Rule(formatting.RuleDescriptor.create1(42 /* MinusMinusToken */, 36 /* MinusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); + this.SpaceAfterSubtractWhenFollowedByUnaryMinus = new formatting.Rule(formatting.RuleDescriptor.create1(36 /* MinusToken */, 36 /* MinusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); + this.SpaceAfterSubtractWhenFollowedByPredecrement = new formatting.Rule(formatting.RuleDescriptor.create1(36 /* MinusToken */, 42 /* MinusMinusToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); + this.NoSpaceBeforeComma = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 24 /* CommaToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.SpaceAfterCertainKeywords = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([102 /* VarKeyword */, 98 /* ThrowKeyword */, 92 /* NewKeyword */, 78 /* DeleteKeyword */, 94 /* ReturnKeyword */, 101 /* TypeOfKeyword */, 119 /* AwaitKeyword */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.SpaceAfterLetConstInVariableDeclaration = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([108 /* LetKeyword */, 74 /* ConstKeyword */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsStartOfVariableDeclarationList), 2 /* Space */)); + this.NoSpaceBeforeOpenParenInFuncCall = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsFunctionCallOrNewContext, Rules.IsPreviousTokenNotComma), 8 /* Delete */)); + this.SpaceAfterFunctionInFuncDecl = new formatting.Rule(formatting.RuleDescriptor.create3(87 /* FunctionKeyword */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 2 /* Space */)); + this.NoSpaceBeforeOpenParenInFuncDecl = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsFunctionDeclContext), 8 /* Delete */)); + this.SpaceAfterVoidOperator = new formatting.Rule(formatting.RuleDescriptor.create3(103 /* VoidKeyword */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsVoidOpContext), 2 /* Space */)); + this.NoSpaceBetweenReturnAndSemicolon = new formatting.Rule(formatting.RuleDescriptor.create1(94 /* ReturnKeyword */, 23 /* SemicolonToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + // Add a space between statements. All keywords except (do,else,case) has open/close parens after them. + // So, we have a rule to add a space for [),Any], [do,Any], [else,Any], and [case,Any] + this.SpaceBetweenStatements = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([18 /* CloseParenToken */, 79 /* DoKeyword */, 80 /* ElseKeyword */, 71 /* CaseKeyword */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNonJsxElementContext, Rules.IsNotForContext), 2 /* Space */)); + // This low-pri rule takes care of "try {" and "finally {" in case the rule SpaceBeforeOpenBraceInControl didn't execute on FormatOnEnter. + this.SpaceAfterTryFinally = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.FromTokens([100 /* TryKeyword */, 85 /* FinallyKeyword */]), 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + // get x() {} + // set x(val) {} + this.SpaceAfterGetSetInMember = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.FromTokens([123 /* GetKeyword */, 131 /* SetKeyword */]), 69 /* Identifier */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 2 /* Space */)); + // Special case for binary operators (that are keywords). For these we have to add a space and shouldn't follow any user options. + this.SpaceBeforeBinaryKeywordOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.BinaryKeywordOperators), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); + this.SpaceAfterBinaryKeywordOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.BinaryKeywordOperators, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); + // TypeScript-specific higher priority rules + // Treat constructor as an identifier in a function declaration, and remove spaces between constructor and following left parentheses + this.NoSpaceAfterConstructor = new formatting.Rule(formatting.RuleDescriptor.create1(121 /* ConstructorKeyword */, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + // Use of module as a function call. e.g.: import m2 = module("m2"); + this.NoSpaceAfterModuleImport = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.FromTokens([125 /* ModuleKeyword */, 129 /* RequireKeyword */]), 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + // Add a space around certain TypeScript keywords + this.SpaceAfterCertainTypeScriptKeywords = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([115 /* AbstractKeyword */, 73 /* ClassKeyword */, 122 /* DeclareKeyword */, 77 /* DefaultKeyword */, 81 /* EnumKeyword */, 82 /* ExportKeyword */, 83 /* ExtendsKeyword */, 123 /* GetKeyword */, 106 /* ImplementsKeyword */, 89 /* ImportKeyword */, 107 /* InterfaceKeyword */, 125 /* ModuleKeyword */, 126 /* NamespaceKeyword */, 110 /* PrivateKeyword */, 112 /* PublicKeyword */, 111 /* ProtectedKeyword */, 131 /* SetKeyword */, 113 /* StaticKeyword */, 134 /* TypeKeyword */, 136 /* FromKeyword */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.SpaceBeforeCertainTypeScriptKeywords = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.FromTokens([83 /* ExtendsKeyword */, 106 /* ImplementsKeyword */, 136 /* FromKeyword */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + // Treat string literals in module names as identifiers, and add a space between the literal and the opening Brace braces, e.g.: module "m2" { + this.SpaceAfterModuleName = new formatting.Rule(formatting.RuleDescriptor.create1(9 /* StringLiteral */, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsModuleDeclContext), 2 /* Space */)); + // Lambda expressions + this.SpaceBeforeArrow = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 34 /* EqualsGreaterThanToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.SpaceAfterArrow = new formatting.Rule(formatting.RuleDescriptor.create3(34 /* EqualsGreaterThanToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + // Optional parameters and let args + this.NoSpaceAfterEllipsis = new formatting.Rule(formatting.RuleDescriptor.create1(22 /* DotDotDotToken */, 69 /* Identifier */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceAfterOptionalParameters = new formatting.Rule(formatting.RuleDescriptor.create3(53 /* QuestionToken */, formatting.Shared.TokenRange.FromTokens([18 /* CloseParenToken */, 24 /* CommaToken */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), 8 /* Delete */)); + // generics and type assertions + this.NoSpaceBeforeOpenAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.TypeNames, 25 /* LessThanToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), 8 /* Delete */)); + this.NoSpaceBetweenCloseParenAndAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create1(18 /* CloseParenToken */, 25 /* LessThanToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), 8 /* Delete */)); + this.NoSpaceAfterOpenAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create3(25 /* LessThanToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), 8 /* Delete */)); + this.NoSpaceBeforeCloseAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 27 /* GreaterThanToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), 8 /* Delete */)); + this.NoSpaceAfterCloseAngularBracket = new formatting.Rule(formatting.RuleDescriptor.create3(27 /* GreaterThanToken */, formatting.Shared.TokenRange.FromTokens([17 /* OpenParenToken */, 19 /* OpenBracketToken */, 27 /* GreaterThanToken */, 24 /* CommaToken */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), 8 /* Delete */)); + // Remove spaces in empty interface literals. e.g.: x: {} + this.NoSpaceBetweenEmptyInterfaceBraceBrackets = new formatting.Rule(formatting.RuleDescriptor.create1(15 /* OpenBraceToken */, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsObjectTypeContext), 8 /* Delete */)); + // decorators + this.SpaceBeforeAt = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 55 /* AtToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.NoSpaceAfterAt = new formatting.Rule(formatting.RuleDescriptor.create3(55 /* AtToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.SpaceAfterDecorator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.FromTokens([115 /* AbstractKeyword */, 69 /* Identifier */, 82 /* ExportKeyword */, 77 /* DefaultKeyword */, 73 /* ClassKeyword */, 113 /* StaticKeyword */, 112 /* PublicKeyword */, 110 /* PrivateKeyword */, 111 /* ProtectedKeyword */, 123 /* GetKeyword */, 131 /* SetKeyword */, 19 /* OpenBracketToken */, 37 /* AsteriskToken */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsEndOfDecoratorContextOnSameLine), 2 /* Space */)); + this.NoSpaceBetweenFunctionKeywordAndStar = new formatting.Rule(formatting.RuleDescriptor.create1(87 /* FunctionKeyword */, 37 /* AsteriskToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclarationOrFunctionExpressionContext), 8 /* Delete */)); + this.SpaceAfterStarInGeneratorDeclaration = new formatting.Rule(formatting.RuleDescriptor.create3(37 /* AsteriskToken */, formatting.Shared.TokenRange.FromTokens([69 /* Identifier */, 17 /* OpenParenToken */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclarationOrFunctionExpressionContext), 2 /* Space */)); + this.NoSpaceBetweenYieldKeywordAndStar = new formatting.Rule(formatting.RuleDescriptor.create1(114 /* YieldKeyword */, 37 /* AsteriskToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsYieldOrYieldStarWithOperand), 8 /* Delete */)); + this.SpaceBetweenYieldOrYieldStarAndOperand = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([114 /* YieldKeyword */, 37 /* AsteriskToken */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsYieldOrYieldStarWithOperand), 2 /* Space */)); + // Async-await + this.SpaceBetweenAsyncAndOpenParen = new formatting.Rule(formatting.RuleDescriptor.create1(118 /* AsyncKeyword */, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsArrowFunctionContext, Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.SpaceBetweenAsyncAndFunctionKeyword = new formatting.Rule(formatting.RuleDescriptor.create1(118 /* AsyncKeyword */, 87 /* FunctionKeyword */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + // template string + this.NoSpaceBetweenTagAndTemplateString = new formatting.Rule(formatting.RuleDescriptor.create3(69 /* Identifier */, formatting.Shared.TokenRange.FromTokens([11 /* NoSubstitutionTemplateLiteral */, 12 /* TemplateHead */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + // jsx opening element + this.SpaceBeforeJsxAttribute = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 69 /* Identifier */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNextTokenParentJsxAttribute, Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.SpaceBeforeSlashInJsxOpeningElement = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 39 /* SlashToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsJsxSelfClosingElementContext, Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.NoSpaceBeforeGreaterThanTokenInJsxOpeningElement = new formatting.Rule(formatting.RuleDescriptor.create1(39 /* SlashToken */, 27 /* GreaterThanToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsJsxSelfClosingElementContext, Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceBeforeEqualInJsxAttribute = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 56 /* EqualsToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsJsxAttributeContext, Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceAfterEqualInJsxAttribute = new formatting.Rule(formatting.RuleDescriptor.create3(56 /* EqualsToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsJsxAttributeContext, Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + // These rules are higher in priority than user-configurable rules. + this.HighPriorityCommonRules = [ + this.IgnoreBeforeComment, this.IgnoreAfterLineComment, + this.NoSpaceBeforeColon, this.SpaceAfterColon, this.NoSpaceBeforeQuestionMark, this.SpaceAfterQuestionMarkInConditionalOperator, + this.NoSpaceAfterQuestionMark, + this.NoSpaceBeforeDot, this.NoSpaceAfterDot, + this.NoSpaceAfterUnaryPrefixOperator, + this.NoSpaceAfterUnaryPreincrementOperator, this.NoSpaceAfterUnaryPredecrementOperator, + this.NoSpaceBeforeUnaryPostincrementOperator, this.NoSpaceBeforeUnaryPostdecrementOperator, + this.SpaceAfterPostincrementWhenFollowedByAdd, + this.SpaceAfterAddWhenFollowedByUnaryPlus, this.SpaceAfterAddWhenFollowedByPreincrement, + this.SpaceAfterPostdecrementWhenFollowedBySubtract, + this.SpaceAfterSubtractWhenFollowedByUnaryMinus, this.SpaceAfterSubtractWhenFollowedByPredecrement, + this.NoSpaceAfterCloseBrace, + this.NewLineBeforeCloseBraceInBlockContext, + this.SpaceAfterCloseBrace, this.SpaceBetweenCloseBraceAndElse, this.SpaceBetweenCloseBraceAndWhile, this.NoSpaceBetweenEmptyBraceBrackets, + this.NoSpaceBetweenFunctionKeywordAndStar, this.SpaceAfterStarInGeneratorDeclaration, + this.SpaceAfterFunctionInFuncDecl, this.NewLineAfterOpenBraceInBlockContext, this.SpaceAfterGetSetInMember, + this.NoSpaceBetweenYieldKeywordAndStar, this.SpaceBetweenYieldOrYieldStarAndOperand, + this.NoSpaceBetweenReturnAndSemicolon, + this.SpaceAfterCertainKeywords, + this.SpaceAfterLetConstInVariableDeclaration, + this.NoSpaceBeforeOpenParenInFuncCall, + this.SpaceBeforeBinaryKeywordOperator, this.SpaceAfterBinaryKeywordOperator, + this.SpaceAfterVoidOperator, + this.SpaceBetweenAsyncAndOpenParen, this.SpaceBetweenAsyncAndFunctionKeyword, + this.NoSpaceBetweenTagAndTemplateString, + this.SpaceBeforeJsxAttribute, this.SpaceBeforeSlashInJsxOpeningElement, this.NoSpaceBeforeGreaterThanTokenInJsxOpeningElement, + this.NoSpaceBeforeEqualInJsxAttribute, this.NoSpaceAfterEqualInJsxAttribute, + // TypeScript-specific rules + this.NoSpaceAfterConstructor, this.NoSpaceAfterModuleImport, + this.SpaceAfterCertainTypeScriptKeywords, this.SpaceBeforeCertainTypeScriptKeywords, + this.SpaceAfterModuleName, + this.SpaceBeforeArrow, this.SpaceAfterArrow, + this.NoSpaceAfterEllipsis, + this.NoSpaceAfterOptionalParameters, + this.NoSpaceBetweenEmptyInterfaceBraceBrackets, + this.NoSpaceBeforeOpenAngularBracket, + this.NoSpaceBetweenCloseParenAndAngularBracket, + this.NoSpaceAfterOpenAngularBracket, + this.NoSpaceBeforeCloseAngularBracket, + this.NoSpaceAfterCloseAngularBracket, + this.SpaceBeforeAt, + this.NoSpaceAfterAt, + this.SpaceAfterDecorator, + ]; + // These rules are lower in priority than user-configurable rules. + this.LowPriorityCommonRules = [ + this.NoSpaceBeforeSemicolon, + this.SpaceBeforeOpenBraceInControl, this.SpaceBeforeOpenBraceInFunction, this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock, + this.NoSpaceBeforeComma, + this.NoSpaceBeforeOpenBracket, + this.NoSpaceAfterCloseBracket, + this.SpaceAfterSemicolon, + this.NoSpaceBeforeOpenParenInFuncDecl, + this.SpaceBetweenStatements, this.SpaceAfterTryFinally + ]; + /// + /// Rules controlled by user options + /// + // Insert space after comma delimiter + this.SpaceAfterComma = new formatting.Rule(formatting.RuleDescriptor.create3(24 /* CommaToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNonJsxElementContext, Rules.IsNextTokenNotCloseBracket), 2 /* Space */)); + this.NoSpaceAfterComma = new formatting.Rule(formatting.RuleDescriptor.create3(24 /* CommaToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNonJsxElementContext), 8 /* Delete */)); + // Insert space before and after binary operators + this.SpaceBeforeBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.BinaryOperators), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); + this.SpaceAfterBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.BinaryOperators, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 2 /* Space */)); + this.NoSpaceBeforeBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.BinaryOperators), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 8 /* Delete */)); + this.NoSpaceAfterBinaryOperator = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.BinaryOperators, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), 8 /* Delete */)); + // Insert space after keywords in control flow statements + this.SpaceAfterKeywordInControl = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Keywords, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext), 2 /* Space */)); + this.NoSpaceAfterKeywordInControl = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Keywords, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext), 8 /* Delete */)); + // Open Brace braces after function + // TypeScript: Function can have return types, which can be made of tons of different token kinds + this.NewLineBeforeOpenBraceInFunction = new formatting.Rule(formatting.RuleDescriptor.create2(this.FunctionOpenBraceLeftTokenRange, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext, Rules.IsBeforeMultilineBlockContext), 4 /* NewLine */), 1 /* CanDeleteNewLines */); + // Open Brace braces after TypeScript module/class/interface + this.NewLineBeforeOpenBraceInTypeScriptDeclWithBlock = new formatting.Rule(formatting.RuleDescriptor.create2(this.TypeScriptOpenBraceLeftTokenRange, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsTypeScriptDeclWithBlockContext, Rules.IsBeforeMultilineBlockContext), 4 /* NewLine */), 1 /* CanDeleteNewLines */); + // Open Brace braces after control block + this.NewLineBeforeOpenBraceInControl = new formatting.Rule(formatting.RuleDescriptor.create2(this.ControlOpenBraceLeftTokenRange, 15 /* OpenBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsControlDeclContext, Rules.IsBeforeMultilineBlockContext), 4 /* NewLine */), 1 /* CanDeleteNewLines */); + // Insert space after semicolon in for statement + this.SpaceAfterSemicolonInFor = new formatting.Rule(formatting.RuleDescriptor.create3(23 /* SemicolonToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsForContext), 2 /* Space */)); + this.NoSpaceAfterSemicolonInFor = new formatting.Rule(formatting.RuleDescriptor.create3(23 /* SemicolonToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsForContext), 8 /* Delete */)); + // Insert space after opening and before closing nonempty parenthesis + this.SpaceAfterOpenParen = new formatting.Rule(formatting.RuleDescriptor.create3(17 /* OpenParenToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.SpaceBeforeCloseParen = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 18 /* CloseParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.NoSpaceBetweenParens = new formatting.Rule(formatting.RuleDescriptor.create1(17 /* OpenParenToken */, 18 /* CloseParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceAfterOpenParen = new formatting.Rule(formatting.RuleDescriptor.create3(17 /* OpenParenToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceBeforeCloseParen = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 18 /* CloseParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + // Insert space after opening and before closing nonempty brackets + this.SpaceAfterOpenBracket = new formatting.Rule(formatting.RuleDescriptor.create3(19 /* OpenBracketToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.SpaceBeforeCloseBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 20 /* CloseBracketToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.NoSpaceBetweenBrackets = new formatting.Rule(formatting.RuleDescriptor.create1(19 /* OpenBracketToken */, 20 /* CloseBracketToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceAfterOpenBracket = new formatting.Rule(formatting.RuleDescriptor.create3(19 /* OpenBracketToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.NoSpaceBeforeCloseBracket = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 20 /* CloseBracketToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + // Insert space after opening and before closing template string braces + this.NoSpaceAfterTemplateHeadAndMiddle = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([12 /* TemplateHead */, 13 /* TemplateMiddle */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.SpaceAfterTemplateHeadAndMiddle = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.FromTokens([12 /* TemplateHead */, 13 /* TemplateMiddle */]), formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + this.NoSpaceBeforeTemplateMiddleAndTail = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.FromTokens([13 /* TemplateMiddle */, 14 /* TemplateTail */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 8 /* Delete */)); + this.SpaceBeforeTemplateMiddleAndTail = new formatting.Rule(formatting.RuleDescriptor.create4(formatting.Shared.TokenRange.Any, formatting.Shared.TokenRange.FromTokens([13 /* TemplateMiddle */, 14 /* TemplateTail */])), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), 2 /* Space */)); + // No space after { and before } in JSX expression + this.NoSpaceAfterOpenBraceInJsxExpression = new formatting.Rule(formatting.RuleDescriptor.create3(15 /* OpenBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsJsxExpressionContext), 8 /* Delete */)); + this.SpaceAfterOpenBraceInJsxExpression = new formatting.Rule(formatting.RuleDescriptor.create3(15 /* OpenBraceToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsJsxExpressionContext), 2 /* Space */)); + this.NoSpaceBeforeCloseBraceInJsxExpression = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsJsxExpressionContext), 8 /* Delete */)); + this.SpaceBeforeCloseBraceInJsxExpression = new formatting.Rule(formatting.RuleDescriptor.create2(formatting.Shared.TokenRange.Any, 16 /* CloseBraceToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsJsxExpressionContext), 2 /* Space */)); + // Insert space after function keyword for anonymous functions + this.SpaceAfterAnonymousFunctionKeyword = new formatting.Rule(formatting.RuleDescriptor.create1(87 /* FunctionKeyword */, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 2 /* Space */)); + this.NoSpaceAfterAnonymousFunctionKeyword = new formatting.Rule(formatting.RuleDescriptor.create1(87 /* FunctionKeyword */, 17 /* OpenParenToken */), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsFunctionDeclContext), 8 /* Delete */)); + // No space after type assertion + this.NoSpaceAfterTypeAssertion = new formatting.Rule(formatting.RuleDescriptor.create3(27 /* GreaterThanToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeAssertionContext), 8 /* Delete */)); + this.SpaceAfterTypeAssertion = new formatting.Rule(formatting.RuleDescriptor.create3(27 /* GreaterThanToken */, formatting.Shared.TokenRange.Any), formatting.RuleOperation.create2(new formatting.RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeAssertionContext), 2 /* Space */)); } - /** - * Returns the immediate owning object literal or binding pattern of a context token, - * on the condition that one exists and that the context implies completion should be given. - */ - function tryGetObjectLikeCompletionContainer(contextToken) { - if (contextToken) { - switch (contextToken.kind) { - case 15 /* OpenBraceToken */: // const x = { | - case 24 /* CommaToken */: - var parent_19 = contextToken.parent; - if (parent_19 && (parent_19.kind === 171 /* ObjectLiteralExpression */ || parent_19.kind === 167 /* ObjectBindingPattern */)) { - return parent_19; - } - break; + Rules.prototype.getRuleName = function (rule) { + var o = this; + for (var name_54 in o) { + if (o[name_54] === rule) { + return name_54; } } - return undefined; - } - /** - * Returns the containing list of named imports or exports of a context token, - * on the condition that one exists and that the context implies completion should be given. - */ - function tryGetNamedImportsOrExportsForCompletion(contextToken) { - if (contextToken) { - switch (contextToken.kind) { - case 15 /* OpenBraceToken */: // import { | - case 24 /* CommaToken */: - switch (contextToken.parent.kind) { - case 233 /* NamedImports */: - case 237 /* NamedExports */: - return contextToken.parent; - } - } + throw new Error("Unknown rule"); + }; + /// + /// Contexts + /// + Rules.IsForContext = function (context) { + return context.contextNode.kind === 206 /* ForStatement */; + }; + Rules.IsNotForContext = function (context) { + return !Rules.IsForContext(context); + }; + Rules.IsBinaryOpContext = function (context) { + switch (context.contextNode.kind) { + case 187 /* BinaryExpression */: + case 188 /* ConditionalExpression */: + case 195 /* AsExpression */: + case 238 /* ExportSpecifier */: + case 234 /* ImportSpecifier */: + case 154 /* TypePredicate */: + case 162 /* UnionType */: + case 163 /* IntersectionType */: + return true; + // equals in binding elements: function foo([[x, y] = [1, 2]]) + case 169 /* BindingElement */: + // equals in type X = ... + case 223 /* TypeAliasDeclaration */: + // equal in import a = module('a'); + case 229 /* ImportEqualsDeclaration */: + // equal in let a = 0; + case 218 /* VariableDeclaration */: + // equal in p = 0; + case 142 /* Parameter */: + case 255 /* EnumMember */: + case 145 /* PropertyDeclaration */: + case 144 /* PropertySignature */: + return context.currentTokenSpan.kind === 56 /* EqualsToken */ || context.nextTokenSpan.kind === 56 /* EqualsToken */; + // "in" keyword in for (let x in []) { } + case 207 /* ForInStatement */: + return context.currentTokenSpan.kind === 90 /* InKeyword */ || context.nextTokenSpan.kind === 90 /* InKeyword */; + // Technically, "of" is not a binary operator, but format it the same way as "in" + case 208 /* ForOfStatement */: + return context.currentTokenSpan.kind === 138 /* OfKeyword */ || context.nextTokenSpan.kind === 138 /* OfKeyword */; } - return undefined; - } - function tryGetContainingJsxElement(contextToken) { - if (contextToken) { - var parent_20 = contextToken.parent; - switch (contextToken.kind) { - case 26 /* LessThanSlashToken */: - case 39 /* SlashToken */: - case 69 /* Identifier */: - case 246 /* JsxAttribute */: - case 247 /* JsxSpreadAttribute */: - if (parent_20 && (parent_20.kind === 242 /* JsxSelfClosingElement */ || parent_20.kind === 243 /* JsxOpeningElement */)) { - return parent_20; - } - else if (parent_20.kind === 246 /* JsxAttribute */) { - return parent_20.parent; - } - break; - // The context token is the closing } or " of an attribute, which means - // its parent is a JsxExpression, whose parent is a JsxAttribute, - // whose parent is a JsxOpeningLikeElement - case 9 /* StringLiteral */: - if (parent_20 && ((parent_20.kind === 246 /* JsxAttribute */) || (parent_20.kind === 247 /* JsxSpreadAttribute */))) { - return parent_20.parent; - } - break; - case 16 /* CloseBraceToken */: - if (parent_20 && - parent_20.kind === 248 /* JsxExpression */ && - parent_20.parent && - (parent_20.parent.kind === 246 /* JsxAttribute */)) { - return parent_20.parent.parent; - } - if (parent_20 && parent_20.kind === 247 /* JsxSpreadAttribute */) { - return parent_20.parent; - } - break; - } + return false; + }; + Rules.IsNotBinaryOpContext = function (context) { + return !Rules.IsBinaryOpContext(context); + }; + Rules.IsConditionalOperatorContext = function (context) { + return context.contextNode.kind === 188 /* ConditionalExpression */; + }; + Rules.IsSameLineTokenOrBeforeMultilineBlockContext = function (context) { + //// This check is mainly used inside SpaceBeforeOpenBraceInControl and SpaceBeforeOpenBraceInFunction. + //// + //// Ex: + //// if (1) { .... + //// * ) and { are on the same line so apply the rule. Here we don't care whether it's same or multi block context + //// + //// Ex: + //// if (1) + //// { ... } + //// * ) and { are on different lines. We only need to format if the block is multiline context. So in this case we don't format. + //// + //// Ex: + //// if (1) + //// { ... + //// } + //// * ) and { are on different lines. We only need to format if the block is multiline context. So in this case we format. + return context.TokensAreOnSameLine() || Rules.IsBeforeMultilineBlockContext(context); + }; + // This check is done before an open brace in a control construct, a function, or a typescript block declaration + Rules.IsBeforeMultilineBlockContext = function (context) { + return Rules.IsBeforeBlockContext(context) && !(context.NextNodeAllOnSameLine() || context.NextNodeBlockIsOnOneLine()); + }; + Rules.IsMultilineBlockContext = function (context) { + return Rules.IsBlockContext(context) && !(context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine()); + }; + Rules.IsSingleLineBlockContext = function (context) { + return Rules.IsBlockContext(context) && (context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine()); + }; + Rules.IsBlockContext = function (context) { + return Rules.NodeIsBlockContext(context.contextNode); + }; + Rules.IsBeforeBlockContext = function (context) { + return Rules.NodeIsBlockContext(context.nextTokenParent); + }; + // IMPORTANT!!! This method must return true ONLY for nodes with open and close braces as immediate children + Rules.NodeIsBlockContext = function (node) { + if (Rules.NodeIsTypeScriptDeclWithBlockContext(node)) { + // This means we are in a context that looks like a block to the user, but in the grammar is actually not a node (it's a class, module, enum, object type literal, etc). + return true; } - return undefined; - } - function isFunction(kind) { - switch (kind) { - case 179 /* FunctionExpression */: - case 180 /* ArrowFunction */: + switch (node.kind) { + case 199 /* Block */: + case 227 /* CaseBlock */: + case 171 /* ObjectLiteralExpression */: + case 226 /* ModuleBlock */: + return true; + } + return false; + }; + Rules.IsFunctionDeclContext = function (context) { + switch (context.contextNode.kind) { case 220 /* FunctionDeclaration */: case 147 /* MethodDeclaration */: case 146 /* MethodSignature */: + // case SyntaxKind.MemberFunctionDeclaration: case 149 /* GetAccessor */: case 150 /* SetAccessor */: + // case SyntaxKind.MethodSignature: case 151 /* CallSignature */: - case 152 /* ConstructSignature */: - case 153 /* IndexSignature */: + case 179 /* FunctionExpression */: + case 148 /* Constructor */: + case 180 /* ArrowFunction */: + // case SyntaxKind.ConstructorDeclaration: + // case SyntaxKind.SimpleArrowFunctionExpression: + // case SyntaxKind.ParenthesizedArrowFunctionExpression: + case 222 /* InterfaceDeclaration */: return true; } return false; - } - /** - * @returns true if we are certain that the currently edited location must define a new location; false otherwise. - */ - function isSolelyIdentifierDefinitionLocation(contextToken) { - var containingNodeKind = contextToken.parent.kind; - switch (contextToken.kind) { - case 24 /* CommaToken */: - return containingNodeKind === 218 /* VariableDeclaration */ || - containingNodeKind === 219 /* VariableDeclarationList */ || - containingNodeKind === 200 /* VariableStatement */ || - containingNodeKind === 224 /* EnumDeclaration */ || - isFunction(containingNodeKind) || - containingNodeKind === 221 /* ClassDeclaration */ || - containingNodeKind === 192 /* ClassExpression */ || - containingNodeKind === 222 /* InterfaceDeclaration */ || - containingNodeKind === 168 /* ArrayBindingPattern */ || - containingNodeKind === 223 /* TypeAliasDeclaration */; // type Map, K, | - case 21 /* DotToken */: - return containingNodeKind === 168 /* ArrayBindingPattern */; // var [.| - case 54 /* ColonToken */: - return containingNodeKind === 169 /* BindingElement */; // var {x :html| - case 19 /* OpenBracketToken */: - return containingNodeKind === 168 /* ArrayBindingPattern */; // var [x| - case 17 /* OpenParenToken */: - return containingNodeKind === 252 /* CatchClause */ || - isFunction(containingNodeKind); - case 15 /* OpenBraceToken */: - return containingNodeKind === 224 /* EnumDeclaration */ || - containingNodeKind === 222 /* InterfaceDeclaration */ || - containingNodeKind === 159 /* TypeLiteral */; // const x : { | - case 23 /* SemicolonToken */: - return containingNodeKind === 144 /* PropertySignature */ && - contextToken.parent && contextToken.parent.parent && - (contextToken.parent.parent.kind === 222 /* InterfaceDeclaration */ || - contextToken.parent.parent.kind === 159 /* TypeLiteral */); // const x : { a; | - case 25 /* LessThanToken */: - return containingNodeKind === 221 /* ClassDeclaration */ || - containingNodeKind === 192 /* ClassExpression */ || - containingNodeKind === 222 /* InterfaceDeclaration */ || - containingNodeKind === 223 /* TypeAliasDeclaration */ || - isFunction(containingNodeKind); - case 113 /* StaticKeyword */: - return containingNodeKind === 145 /* PropertyDeclaration */; - case 22 /* DotDotDotToken */: - return containingNodeKind === 142 /* Parameter */ || - (contextToken.parent && contextToken.parent.parent && - contextToken.parent.parent.kind === 168 /* ArrayBindingPattern */); // var [...z| - case 112 /* PublicKeyword */: - case 110 /* PrivateKeyword */: - case 111 /* ProtectedKeyword */: - return containingNodeKind === 142 /* Parameter */; - case 116 /* AsKeyword */: - return containingNodeKind === 234 /* ImportSpecifier */ || - containingNodeKind === 238 /* ExportSpecifier */ || - containingNodeKind === 232 /* NamespaceImport */; - case 73 /* ClassKeyword */: - case 81 /* EnumKeyword */: - case 107 /* InterfaceKeyword */: - case 87 /* FunctionKeyword */: - case 102 /* VarKeyword */: - case 123 /* GetKeyword */: - case 131 /* SetKeyword */: - case 89 /* ImportKeyword */: - case 108 /* LetKeyword */: - case 74 /* ConstKeyword */: - case 114 /* YieldKeyword */: - case 134 /* TypeKeyword */: - return true; - } - // Previous token may have been a keyword that was converted to an identifier. - switch (contextToken.getText()) { - case "abstract": - case "async": - case "class": - case "const": - case "declare": - case "enum": - case "function": - case "interface": - case "let": - case "private": - case "protected": - case "public": - case "static": - case "var": - case "yield": + }; + Rules.IsFunctionDeclarationOrFunctionExpressionContext = function (context) { + return context.contextNode.kind === 220 /* FunctionDeclaration */ || context.contextNode.kind === 179 /* FunctionExpression */; + }; + Rules.IsTypeScriptDeclWithBlockContext = function (context) { + return Rules.NodeIsTypeScriptDeclWithBlockContext(context.contextNode); + }; + Rules.NodeIsTypeScriptDeclWithBlockContext = function (node) { + switch (node.kind) { + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + case 222 /* InterfaceDeclaration */: + case 224 /* EnumDeclaration */: + case 159 /* TypeLiteral */: + case 225 /* ModuleDeclaration */: + case 236 /* ExportDeclaration */: + case 237 /* NamedExports */: + case 230 /* ImportDeclaration */: + case 233 /* NamedImports */: return true; } return false; - } - function isDotOfNumericLiteral(contextToken) { - if (contextToken.kind === 8 /* NumericLiteral */) { - var text = contextToken.getFullText(); - return text.charAt(text.length - 1) === "."; + }; + Rules.IsAfterCodeBlockContext = function (context) { + switch (context.currentTokenParent.kind) { + case 221 /* ClassDeclaration */: + case 225 /* ModuleDeclaration */: + case 224 /* EnumDeclaration */: + case 199 /* Block */: + case 252 /* CatchClause */: + case 226 /* ModuleBlock */: + case 213 /* SwitchStatement */: + return true; } return false; - } - /** - * Filters out completion suggestions for named imports or exports. - * - * @param exportsOfModule The list of symbols which a module exposes. - * @param namedImportsOrExports The list of existing import/export specifiers in the import/export clause. - * - * @returns Symbols to be suggested at an import/export clause, barring those whose named imports/exports - * do not occur at the current position and have not otherwise been typed. - */ - function filterNamedImportOrExportCompletionItems(exportsOfModule, namedImportsOrExports) { - var existingImportsOrExports = ts.createMap(); - for (var _i = 0, namedImportsOrExports_1 = namedImportsOrExports; _i < namedImportsOrExports_1.length; _i++) { - var element = namedImportsOrExports_1[_i]; - // If this is the current item we are editing right now, do not filter it out - if (element.getStart() <= position && position <= element.getEnd()) { - continue; - } - var name_41 = element.propertyName || element.name; - existingImportsOrExports[name_41.text] = true; - } - if (!ts.someProperties(existingImportsOrExports)) { - return ts.filter(exportsOfModule, function (e) { return e.name !== "default"; }); - } - return ts.filter(exportsOfModule, function (e) { return e.name !== "default" && !existingImportsOrExports[e.name]; }); - } - /** - * Filters out completion suggestions for named imports or exports. - * - * @returns Symbols to be suggested in an object binding pattern or object literal expression, barring those whose declarations - * do not occur at the current position and have not otherwise been typed. - */ - function filterObjectMembersList(contextualMemberSymbols, existingMembers) { - if (!existingMembers || existingMembers.length === 0) { - return contextualMemberSymbols; - } - var existingMemberNames = ts.createMap(); - for (var _i = 0, existingMembers_1 = existingMembers; _i < existingMembers_1.length; _i++) { - var m = existingMembers_1[_i]; - // Ignore omitted expressions for missing members - if (m.kind !== 253 /* PropertyAssignment */ && - m.kind !== 254 /* ShorthandPropertyAssignment */ && - m.kind !== 169 /* BindingElement */ && - m.kind !== 147 /* MethodDeclaration */) { - continue; - } - // If this is the current item we are editing right now, do not filter it out - if (m.getStart() <= position && position <= m.getEnd()) { - continue; - } - var existingName = void 0; - if (m.kind === 169 /* BindingElement */ && m.propertyName) { - // include only identifiers in completion list - if (m.propertyName.kind === 69 /* Identifier */) { - existingName = m.propertyName.text; - } - } - else { - // TODO(jfreeman): Account for computed property name - // NOTE: if one only performs this step when m.name is an identifier, - // things like '__proto__' are not filtered out. - existingName = m.name.text; - } - existingMemberNames[existingName] = true; - } - return ts.filter(contextualMemberSymbols, function (m) { return !existingMemberNames[m.name]; }); - } - /** - * Filters out completion suggestions from 'symbols' according to existing JSX attributes. - * - * @returns Symbols to be suggested in a JSX element, barring those whose attributes - * do not occur at the current position and have not otherwise been typed. - */ - function filterJsxAttributes(symbols, attributes) { - var seenNames = ts.createMap(); - for (var _i = 0, attributes_1 = attributes; _i < attributes_1.length; _i++) { - var attr = attributes_1[_i]; - // If this is the current item we are editing right now, do not filter it out - if (attr.getStart() <= position && position <= attr.getEnd()) { - continue; - } - if (attr.kind === 246 /* JsxAttribute */) { - seenNames[attr.name.text] = true; - } + }; + Rules.IsControlDeclContext = function (context) { + switch (context.contextNode.kind) { + case 203 /* IfStatement */: + case 213 /* SwitchStatement */: + case 206 /* ForStatement */: + case 207 /* ForInStatement */: + case 208 /* ForOfStatement */: + case 205 /* WhileStatement */: + case 216 /* TryStatement */: + case 204 /* DoStatement */: + case 212 /* WithStatement */: + // TODO + // case SyntaxKind.ElseClause: + case 252 /* CatchClause */: + return true; + default: + return false; } - return ts.filter(symbols, function (a) { return !seenNames[a.name]; }); - } - } - function getCompletionsAtPosition(fileName, position) { - synchronizeHostData(); - var sourceFile = getValidSourceFile(fileName); - if (ts.isInString(sourceFile, position)) { - return getStringLiteralCompletionEntries(sourceFile, position); - } - var completionData = getCompletionData(fileName, position); - if (!completionData) { - return undefined; - } - var symbols = completionData.symbols, isMemberCompletion = completionData.isMemberCompletion, isNewIdentifierLocation = completionData.isNewIdentifierLocation, location = completionData.location, isJsDocTagName = completionData.isJsDocTagName; - if (isJsDocTagName) { - // If the current position is a jsDoc tag name, only tag names should be provided for completion - return { isMemberCompletion: false, isNewIdentifierLocation: false, entries: getAllJsDocCompletionEntries() }; - } - var entries = []; - if (ts.isSourceFileJavaScript(sourceFile)) { - var uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, /*performCharacterChecks*/ false); - ts.addRange(entries, getJavaScriptCompletionEntries(sourceFile, location.pos, uniqueNames)); - } - else { - if (!symbols || symbols.length === 0) { - if (sourceFile.languageVariant === 1 /* JSX */ && - location.parent && location.parent.kind === 245 /* JsxClosingElement */) { - // In the TypeScript JSX element, if such element is not defined. When users query for completion at closing tag, - // instead of simply giving unknown value, the completion will return the tag-name of an associated opening-element. - // For example: - // var x =
completion list at "1" will contain "div" with type any - var tagName = location.parent.parent.openingElement.tagName; - entries.push({ - name: tagName.text, - kind: undefined, - kindModifiers: undefined, - sortText: "0", - }); - } - else { - return undefined; - } + }; + Rules.IsObjectContext = function (context) { + return context.contextNode.kind === 171 /* ObjectLiteralExpression */; + }; + Rules.IsFunctionCallContext = function (context) { + return context.contextNode.kind === 174 /* CallExpression */; + }; + Rules.IsNewContext = function (context) { + return context.contextNode.kind === 175 /* NewExpression */; + }; + Rules.IsFunctionCallOrNewContext = function (context) { + return Rules.IsFunctionCallContext(context) || Rules.IsNewContext(context); + }; + Rules.IsPreviousTokenNotComma = function (context) { + return context.currentTokenSpan.kind !== 24 /* CommaToken */; + }; + Rules.IsNextTokenNotCloseBracket = function (context) { + return context.nextTokenSpan.kind !== 20 /* CloseBracketToken */; + }; + Rules.IsArrowFunctionContext = function (context) { + return context.contextNode.kind === 180 /* ArrowFunction */; + }; + Rules.IsNonJsxSameLineTokenContext = function (context) { + return context.TokensAreOnSameLine() && context.contextNode.kind !== 244 /* JsxText */; + }; + Rules.IsNonJsxElementContext = function (context) { + return context.contextNode.kind !== 241 /* JsxElement */; + }; + Rules.IsJsxExpressionContext = function (context) { + return context.contextNode.kind === 248 /* JsxExpression */; + }; + Rules.IsNextTokenParentJsxAttribute = function (context) { + return context.nextTokenParent.kind === 246 /* JsxAttribute */; + }; + Rules.IsJsxAttributeContext = function (context) { + return context.contextNode.kind === 246 /* JsxAttribute */; + }; + Rules.IsJsxSelfClosingElementContext = function (context) { + return context.contextNode.kind === 242 /* JsxSelfClosingElement */; + }; + Rules.IsNotBeforeBlockInFunctionDeclarationContext = function (context) { + return !Rules.IsFunctionDeclContext(context) && !Rules.IsBeforeBlockContext(context); + }; + Rules.IsEndOfDecoratorContextOnSameLine = function (context) { + return context.TokensAreOnSameLine() && + context.contextNode.decorators && + Rules.NodeIsInDecoratorContext(context.currentTokenParent) && + !Rules.NodeIsInDecoratorContext(context.nextTokenParent); + }; + Rules.NodeIsInDecoratorContext = function (node) { + while (ts.isPartOfExpression(node)) { + node = node.parent; } - getCompletionEntriesFromSymbols(symbols, entries, location, /*performCharacterChecks*/ true); - } - // Add keywords if this is not a member completion list - if (!isMemberCompletion && !isJsDocTagName) { - ts.addRange(entries, keywordCompletions); - } - return { isMemberCompletion: isMemberCompletion, isNewIdentifierLocation: isNewIdentifierLocation || ts.isSourceFileJavaScript(sourceFile), entries: entries }; - function getJavaScriptCompletionEntries(sourceFile, position, uniqueNames) { - var entries = []; - var target = program.getCompilerOptions().target; - var nameTable = getNameTable(sourceFile); - for (var name_42 in nameTable) { - // Skip identifiers produced only from the current location - if (nameTable[name_42] === position) { - continue; - } - if (!uniqueNames[name_42]) { - uniqueNames[name_42] = name_42; - var displayName = getCompletionEntryDisplayName(ts.unescapeIdentifier(name_42), target, /*performCharacterChecks*/ true); - if (displayName) { - var entry = { - name: displayName, - kind: ts.ScriptElementKind.warning, - kindModifiers: "", - sortText: "1" - }; - entries.push(entry); - } - } + return node.kind === 143 /* Decorator */; + }; + Rules.IsStartOfVariableDeclarationList = function (context) { + return context.currentTokenParent.kind === 219 /* VariableDeclarationList */ && + context.currentTokenParent.getStart(context.sourceFile) === context.currentTokenSpan.pos; + }; + Rules.IsNotFormatOnEnter = function (context) { + return context.formattingRequestKind !== 2 /* FormatOnEnter */; + }; + Rules.IsModuleDeclContext = function (context) { + return context.contextNode.kind === 225 /* ModuleDeclaration */; + }; + Rules.IsObjectTypeContext = function (context) { + return context.contextNode.kind === 159 /* TypeLiteral */; // && context.contextNode.parent.kind !== SyntaxKind.InterfaceDeclaration; + }; + Rules.IsTypeArgumentOrParameterOrAssertion = function (token, parent) { + if (token.kind !== 25 /* LessThanToken */ && token.kind !== 27 /* GreaterThanToken */) { + return false; } - return entries; - } - function getAllJsDocCompletionEntries() { - return jsDocCompletionEntries || (jsDocCompletionEntries = ts.map(jsDocTagNames, function (tagName) { - return { - name: tagName, - kind: ts.ScriptElementKind.keyword, - kindModifiers: "", - sortText: "0", - }; - })); - } - function createCompletionEntry(symbol, location, performCharacterChecks) { - // Try to get a valid display name for this symbol, if we could not find one, then ignore it. - // We would like to only show things that can be added after a dot, so for instance numeric properties can - // not be accessed with a dot (a.1 <- invalid) - var displayName = getCompletionEntryDisplayNameForSymbol(symbol, program.getCompilerOptions().target, performCharacterChecks, location); - if (!displayName) { - return undefined; + switch (parent.kind) { + case 155 /* TypeReference */: + case 177 /* TypeAssertionExpression */: + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + case 222 /* InterfaceDeclaration */: + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + case 180 /* ArrowFunction */: + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + case 151 /* CallSignature */: + case 152 /* ConstructSignature */: + case 174 /* CallExpression */: + case 175 /* NewExpression */: + case 194 /* ExpressionWithTypeArguments */: + return true; + default: + return false; } - // TODO(drosen): Right now we just permit *all* semantic meanings when calling - // 'getSymbolKind' which is permissible given that it is backwards compatible; but - // really we should consider passing the meaning for the node so that we don't report - // that a suggestion for a value is an interface. We COULD also just do what - // 'getSymbolModifiers' does, which is to use the first declaration. - // Use a 'sortText' of 0' so that all symbol completion entries come before any other - // entries (like JavaScript identifier entries). - return { - name: displayName, - kind: getSymbolKind(symbol, location), - kindModifiers: getSymbolModifiers(symbol), - sortText: "0", - }; + }; + Rules.IsTypeArgumentOrParameterOrAssertionContext = function (context) { + return Rules.IsTypeArgumentOrParameterOrAssertion(context.currentTokenSpan, context.currentTokenParent) || + Rules.IsTypeArgumentOrParameterOrAssertion(context.nextTokenSpan, context.nextTokenParent); + }; + Rules.IsTypeAssertionContext = function (context) { + return context.contextNode.kind === 177 /* TypeAssertionExpression */; + }; + Rules.IsVoidOpContext = function (context) { + return context.currentTokenSpan.kind === 103 /* VoidKeyword */ && context.currentTokenParent.kind === 183 /* VoidExpression */; + }; + Rules.IsYieldOrYieldStarWithOperand = function (context) { + return context.contextNode.kind === 190 /* YieldExpression */ && context.contextNode.expression !== undefined; + }; + return Rules; + }()); + formatting.Rules = Rules; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + var RulesMap = (function () { + function RulesMap() { + this.map = []; + this.mapRowLength = 0; } - function getCompletionEntriesFromSymbols(symbols, entries, location, performCharacterChecks) { - var start = ts.timestamp(); - var uniqueNames = ts.createMap(); - if (symbols) { - for (var _i = 0, symbols_4 = symbols; _i < symbols_4.length; _i++) { - var symbol = symbols_4[_i]; - var entry = createCompletionEntry(symbol, location, performCharacterChecks); - if (entry) { - var id = ts.escapeIdentifier(entry.name); - if (!uniqueNames[id]) { - entries.push(entry); - uniqueNames[id] = id; - } + RulesMap.create = function (rules) { + var result = new RulesMap(); + result.Initialize(rules); + return result; + }; + RulesMap.prototype.Initialize = function (rules) { + this.mapRowLength = 138 /* LastToken */ + 1; + this.map = new Array(this.mapRowLength * this.mapRowLength); // new Array(this.mapRowLength * this.mapRowLength); + // This array is used only during construction of the rulesbucket in the map + var rulesBucketConstructionStateList = new Array(this.map.length); // new Array(this.map.length); + this.FillRules(rules, rulesBucketConstructionStateList); + return this.map; + }; + RulesMap.prototype.FillRules = function (rules, rulesBucketConstructionStateList) { + var _this = this; + rules.forEach(function (rule) { + _this.FillRule(rule, rulesBucketConstructionStateList); + }); + }; + RulesMap.prototype.GetRuleBucketIndex = function (row, column) { + var rulesBucketIndex = (row * this.mapRowLength) + column; + // Debug.Assert(rulesBucketIndex < this.map.Length, "Trying to access an index outside the array."); + return rulesBucketIndex; + }; + RulesMap.prototype.FillRule = function (rule, rulesBucketConstructionStateList) { + var _this = this; + var specificRule = rule.Descriptor.LeftTokenRange !== formatting.Shared.TokenRange.Any && + rule.Descriptor.RightTokenRange !== formatting.Shared.TokenRange.Any; + rule.Descriptor.LeftTokenRange.GetTokens().forEach(function (left) { + rule.Descriptor.RightTokenRange.GetTokens().forEach(function (right) { + var rulesBucketIndex = _this.GetRuleBucketIndex(left, right); + var rulesBucket = _this.map[rulesBucketIndex]; + if (rulesBucket === undefined) { + rulesBucket = _this.map[rulesBucketIndex] = new RulesBucket(); + } + rulesBucket.AddRule(rule, specificRule, rulesBucketConstructionStateList, rulesBucketIndex); + }); + }); + }; + RulesMap.prototype.GetRule = function (context) { + var bucketIndex = this.GetRuleBucketIndex(context.currentTokenSpan.kind, context.nextTokenSpan.kind); + var bucket = this.map[bucketIndex]; + if (bucket) { + for (var _i = 0, _a = bucket.Rules(); _i < _a.length; _i++) { + var rule = _a[_i]; + if (rule.Operation.Context.InContext(context)) { + return rule; } } } - log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (ts.timestamp() - start)); - return uniqueNames; + return undefined; + }; + return RulesMap; + }()); + formatting.RulesMap = RulesMap; + var MaskBitSize = 5; + var Mask = 0x1f; + (function (RulesPosition) { + RulesPosition[RulesPosition["IgnoreRulesSpecific"] = 0] = "IgnoreRulesSpecific"; + RulesPosition[RulesPosition["IgnoreRulesAny"] = MaskBitSize * 1] = "IgnoreRulesAny"; + RulesPosition[RulesPosition["ContextRulesSpecific"] = MaskBitSize * 2] = "ContextRulesSpecific"; + RulesPosition[RulesPosition["ContextRulesAny"] = MaskBitSize * 3] = "ContextRulesAny"; + RulesPosition[RulesPosition["NoContextRulesSpecific"] = MaskBitSize * 4] = "NoContextRulesSpecific"; + RulesPosition[RulesPosition["NoContextRulesAny"] = MaskBitSize * 5] = "NoContextRulesAny"; + })(formatting.RulesPosition || (formatting.RulesPosition = {})); + var RulesPosition = formatting.RulesPosition; + var RulesBucketConstructionState = (function () { + function RulesBucketConstructionState() { + //// The Rules list contains all the inserted rules into a rulebucket in the following order: + //// 1- Ignore rules with specific token combination + //// 2- Ignore rules with any token combination + //// 3- Context rules with specific token combination + //// 4- Context rules with any token combination + //// 5- Non-context rules with specific token combination + //// 6- Non-context rules with any token combination + //// + //// The member rulesInsertionIndexBitmap is used to describe the number of rules + //// in each sub-bucket (above) hence can be used to know the index of where to insert + //// the next rule. It's a bitmap which contains 6 different sections each is given 5 bits. + //// + //// Example: + //// In order to insert a rule to the end of sub-bucket (3), we get the index by adding + //// the values in the bitmap segments 3rd, 2nd, and 1st. + this.rulesInsertionIndexBitmap = 0; } - function getStringLiteralCompletionEntries(sourceFile, position) { - var node = ts.findPrecedingToken(position, sourceFile); - if (!node || node.kind !== 9 /* StringLiteral */) { - return undefined; + RulesBucketConstructionState.prototype.GetInsertionIndex = function (maskPosition) { + var index = 0; + var pos = 0; + var indexBitmap = this.rulesInsertionIndexBitmap; + while (pos <= maskPosition) { + index += (indexBitmap & Mask); + indexBitmap >>= MaskBitSize; + pos += MaskBitSize; } - if (node.parent.kind === 253 /* PropertyAssignment */ && node.parent.parent.kind === 171 /* ObjectLiteralExpression */) { - // Get quoted name of properties of the object literal expression - // i.e. interface ConfigFiles { - // 'jspm:dev': string - // } - // let files: ConfigFiles = { - // '/*completion position*/' - // } - // - // function foo(c: ConfigFiles) {} - // foo({ - // '/*completion position*/' - // }); - return getStringLiteralCompletionEntriesFromPropertyAssignment(node.parent); + return index; + }; + RulesBucketConstructionState.prototype.IncreaseInsertionIndex = function (maskPosition) { + var value = (this.rulesInsertionIndexBitmap >> maskPosition) & Mask; + value++; + ts.Debug.assert((value & Mask) === value, "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules."); + var temp = this.rulesInsertionIndexBitmap & ~(Mask << maskPosition); + temp |= value << maskPosition; + this.rulesInsertionIndexBitmap = temp; + }; + return RulesBucketConstructionState; + }()); + formatting.RulesBucketConstructionState = RulesBucketConstructionState; + var RulesBucket = (function () { + function RulesBucket() { + this.rules = []; + } + RulesBucket.prototype.Rules = function () { + return this.rules; + }; + RulesBucket.prototype.AddRule = function (rule, specificTokens, constructionState, rulesBucketIndex) { + var position; + if (rule.Operation.Action === 1 /* Ignore */) { + position = specificTokens ? + RulesPosition.IgnoreRulesSpecific : + RulesPosition.IgnoreRulesAny; } - else if (ts.isElementAccessExpression(node.parent) && node.parent.argumentExpression === node) { - // Get all names of properties on the expression - // i.e. interface A { - // 'prop1': string - // } - // let a: A; - // a['/*completion position*/'] - return getStringLiteralCompletionEntriesFromElementAccess(node.parent); + else if (!rule.Operation.Context.IsAny()) { + position = specificTokens ? + RulesPosition.ContextRulesSpecific : + RulesPosition.ContextRulesAny; } else { - var argumentInfo = ts.SignatureHelp.getContainingArgumentInfo(node, position, sourceFile); - if (argumentInfo) { - // Get string literal completions from specialized signatures of the target - // i.e. declare function f(a: 'A'); - // f("/*completion position*/") - return getStringLiteralCompletionEntriesFromCallExpression(argumentInfo, node); - } - // Get completion for string literal from string literal type - // i.e. var x: "hi" | "hello" = "/*completion position*/" - return getStringLiteralCompletionEntriesFromContextualType(node); + position = specificTokens ? + RulesPosition.NoContextRulesSpecific : + RulesPosition.NoContextRulesAny; } - } - function getStringLiteralCompletionEntriesFromPropertyAssignment(element) { - var typeChecker = program.getTypeChecker(); - var type = typeChecker.getContextualType(element.parent); - var entries = []; - if (type) { - getCompletionEntriesFromSymbols(type.getApparentProperties(), entries, element, /*performCharacterChecks*/ false); - if (entries.length) { - return { isMemberCompletion: true, isNewIdentifierLocation: true, entries: entries }; - } + var state = constructionState[rulesBucketIndex]; + if (state === undefined) { + state = constructionState[rulesBucketIndex] = new RulesBucketConstructionState(); } - } - function getStringLiteralCompletionEntriesFromCallExpression(argumentInfo, location) { - var typeChecker = program.getTypeChecker(); - var candidates = []; - var entries = []; - typeChecker.getResolvedSignature(argumentInfo.invocation, candidates); - for (var _i = 0, candidates_3 = candidates; _i < candidates_3.length; _i++) { - var candidate = candidates_3[_i]; - if (candidate.parameters.length > argumentInfo.argumentIndex) { - var parameter = candidate.parameters[argumentInfo.argumentIndex]; - addStringLiteralCompletionsFromType(typeChecker.getTypeAtLocation(parameter.valueDeclaration), entries); + var index = state.GetInsertionIndex(position); + this.rules.splice(index, 0, rule); + state.IncreaseInsertionIndex(position); + }; + return RulesBucket; + }()); + formatting.RulesBucket = RulesBucket; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + var Shared; + (function (Shared) { + var TokenRangeAccess = (function () { + function TokenRangeAccess(from, to, except) { + this.tokens = []; + for (var token = from; token <= to; token++) { + if (ts.indexOf(except, token) < 0) { + this.tokens.push(token); + } } } - if (entries.length) { - return { isMemberCompletion: false, isNewIdentifierLocation: true, entries: entries }; + TokenRangeAccess.prototype.GetTokens = function () { + return this.tokens; + }; + TokenRangeAccess.prototype.Contains = function (token) { + return this.tokens.indexOf(token) >= 0; + }; + return TokenRangeAccess; + }()); + Shared.TokenRangeAccess = TokenRangeAccess; + var TokenValuesAccess = (function () { + function TokenValuesAccess(tks) { + this.tokens = tks && tks.length ? tks : []; } - return undefined; - } - function getStringLiteralCompletionEntriesFromElementAccess(node) { - var typeChecker = program.getTypeChecker(); - var type = typeChecker.getTypeAtLocation(node.expression); - var entries = []; - if (type) { - getCompletionEntriesFromSymbols(type.getApparentProperties(), entries, node, /*performCharacterChecks*/ false); - if (entries.length) { - return { isMemberCompletion: true, isNewIdentifierLocation: true, entries: entries }; - } + TokenValuesAccess.prototype.GetTokens = function () { + return this.tokens; + }; + TokenValuesAccess.prototype.Contains = function (token) { + return this.tokens.indexOf(token) >= 0; + }; + return TokenValuesAccess; + }()); + Shared.TokenValuesAccess = TokenValuesAccess; + var TokenSingleValueAccess = (function () { + function TokenSingleValueAccess(token) { + this.token = token; } - return undefined; - } - function getStringLiteralCompletionEntriesFromContextualType(node) { - var typeChecker = program.getTypeChecker(); - var type = typeChecker.getContextualType(node); - if (type) { - var entries_2 = []; - addStringLiteralCompletionsFromType(type, entries_2); - if (entries_2.length) { - return { isMemberCompletion: false, isNewIdentifierLocation: false, entries: entries_2 }; + TokenSingleValueAccess.prototype.GetTokens = function () { + return [this.token]; + }; + TokenSingleValueAccess.prototype.Contains = function (tokenValue) { + return tokenValue === this.token; + }; + return TokenSingleValueAccess; + }()); + Shared.TokenSingleValueAccess = TokenSingleValueAccess; + var TokenAllAccess = (function () { + function TokenAllAccess() { + } + TokenAllAccess.prototype.GetTokens = function () { + var result = []; + for (var token = 0 /* FirstToken */; token <= 138 /* LastToken */; token++) { + result.push(token); } + return result; + }; + TokenAllAccess.prototype.Contains = function (tokenValue) { + return true; + }; + TokenAllAccess.prototype.toString = function () { + return "[allTokens]"; + }; + return TokenAllAccess; + }()); + Shared.TokenAllAccess = TokenAllAccess; + var TokenRange = (function () { + function TokenRange(tokenAccess) { + this.tokenAccess = tokenAccess; } - return undefined; + TokenRange.FromToken = function (token) { + return new TokenRange(new TokenSingleValueAccess(token)); + }; + TokenRange.FromTokens = function (tokens) { + return new TokenRange(new TokenValuesAccess(tokens)); + }; + TokenRange.FromRange = function (f, to, except) { + if (except === void 0) { except = []; } + return new TokenRange(new TokenRangeAccess(f, to, except)); + }; + TokenRange.AllTokens = function () { + return new TokenRange(new TokenAllAccess()); + }; + TokenRange.prototype.GetTokens = function () { + return this.tokenAccess.GetTokens(); + }; + TokenRange.prototype.Contains = function (token) { + return this.tokenAccess.Contains(token); + }; + TokenRange.prototype.toString = function () { + return this.tokenAccess.toString(); + }; + return TokenRange; + }()); + TokenRange.Any = TokenRange.AllTokens(); + TokenRange.AnyIncludingMultilineComments = TokenRange.FromTokens(TokenRange.Any.GetTokens().concat([3 /* MultiLineCommentTrivia */])); + TokenRange.Keywords = TokenRange.FromRange(70 /* FirstKeyword */, 138 /* LastKeyword */); + TokenRange.BinaryOperators = TokenRange.FromRange(25 /* FirstBinaryOperator */, 68 /* LastBinaryOperator */); + TokenRange.BinaryKeywordOperators = TokenRange.FromTokens([90 /* InKeyword */, 91 /* InstanceOfKeyword */, 138 /* OfKeyword */, 116 /* AsKeyword */, 124 /* IsKeyword */]); + TokenRange.UnaryPrefixOperators = TokenRange.FromTokens([41 /* PlusPlusToken */, 42 /* MinusMinusToken */, 50 /* TildeToken */, 49 /* ExclamationToken */]); + TokenRange.UnaryPrefixExpressions = TokenRange.FromTokens([8 /* NumericLiteral */, 69 /* Identifier */, 17 /* OpenParenToken */, 19 /* OpenBracketToken */, 15 /* OpenBraceToken */, 97 /* ThisKeyword */, 92 /* NewKeyword */]); + TokenRange.UnaryPreincrementExpressions = TokenRange.FromTokens([69 /* Identifier */, 17 /* OpenParenToken */, 97 /* ThisKeyword */, 92 /* NewKeyword */]); + TokenRange.UnaryPostincrementExpressions = TokenRange.FromTokens([69 /* Identifier */, 18 /* CloseParenToken */, 20 /* CloseBracketToken */, 92 /* NewKeyword */]); + TokenRange.UnaryPredecrementExpressions = TokenRange.FromTokens([69 /* Identifier */, 17 /* OpenParenToken */, 97 /* ThisKeyword */, 92 /* NewKeyword */]); + TokenRange.UnaryPostdecrementExpressions = TokenRange.FromTokens([69 /* Identifier */, 18 /* CloseParenToken */, 20 /* CloseBracketToken */, 92 /* NewKeyword */]); + TokenRange.Comments = TokenRange.FromTokens([2 /* SingleLineCommentTrivia */, 3 /* MultiLineCommentTrivia */]); + TokenRange.TypeNames = TokenRange.FromTokens([69 /* Identifier */, 130 /* NumberKeyword */, 132 /* StringKeyword */, 120 /* BooleanKeyword */, 133 /* SymbolKeyword */, 103 /* VoidKeyword */, 117 /* AnyKeyword */]); + Shared.TokenRange = TokenRange; + })(Shared = formatting.Shared || (formatting.Shared = {})); + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + var RulesProvider = (function () { + function RulesProvider() { + this.globalRules = new formatting.Rules(); } - function addStringLiteralCompletionsFromType(type, result) { - if (!type) { - return; + RulesProvider.prototype.getRuleName = function (rule) { + return this.globalRules.getRuleName(rule); + }; + RulesProvider.prototype.getRuleByName = function (name) { + return this.globalRules[name]; + }; + RulesProvider.prototype.getRulesMap = function () { + return this.rulesMap; + }; + RulesProvider.prototype.ensureUpToDate = function (options) { + if (!this.options || !ts.compareDataObjects(this.options, options)) { + var activeRules = this.createActiveRules(options); + var rulesMap = formatting.RulesMap.create(activeRules); + this.activeRules = activeRules; + this.rulesMap = rulesMap; + this.options = ts.clone(options); } - if (type.flags & 524288 /* Union */) { - ts.forEach(type.types, function (t) { return addStringLiteralCompletionsFromType(t, result); }); + }; + RulesProvider.prototype.createActiveRules = function (options) { + var rules = this.globalRules.HighPriorityCommonRules.slice(0); + if (options.insertSpaceAfterCommaDelimiter) { + rules.push(this.globalRules.SpaceAfterComma); } else { - if (type.flags & 32 /* StringLiteral */) { - result.push({ - name: type.text, - kindModifiers: ts.ScriptElementKindModifier.none, - kind: ts.ScriptElementKind.variableElement, - sortText: "0" - }); - } - } - } - } - function getCompletionEntryDetails(fileName, position, entryName) { - synchronizeHostData(); - // Compute all the completion symbols again. - var completionData = getCompletionData(fileName, position); - if (completionData) { - var symbols = completionData.symbols, location_2 = completionData.location; - // Find the symbol with the matching entry name. - var target_2 = program.getCompilerOptions().target; - // We don't need to perform character checks here because we're only comparing the - // name against 'entryName' (which is known to be good), not building a new - // completion entry. - var symbol = ts.forEach(symbols, function (s) { return getCompletionEntryDisplayNameForSymbol(s, target_2, /*performCharacterChecks*/ false, location_2) === entryName ? s : undefined; }); - if (symbol) { - var _a = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getValidSourceFile(fileName), location_2, location_2, 7 /* All */), displayParts = _a.displayParts, documentation = _a.documentation, symbolKind = _a.symbolKind; - return { - name: entryName, - kindModifiers: getSymbolModifiers(symbol), - kind: symbolKind, - displayParts: displayParts, - documentation: documentation - }; + rules.push(this.globalRules.NoSpaceAfterComma); } - } - // Didn't find a symbol with this name. See if we can find a keyword instead. - var keywordCompletion = ts.forEach(keywordCompletions, function (c) { return c.name === entryName; }); - if (keywordCompletion) { - return { - name: entryName, - kind: ts.ScriptElementKind.keyword, - kindModifiers: ts.ScriptElementKindModifier.none, - displayParts: [ts.displayPart(entryName, ts.SymbolDisplayPartKind.keyword)], - documentation: undefined - }; - } - return undefined; - } - // TODO(drosen): use contextual SemanticMeaning. - function getSymbolKind(symbol, location) { - var flags = symbol.getFlags(); - if (flags & 32 /* Class */) - return ts.getDeclarationOfKind(symbol, 192 /* ClassExpression */) ? - ts.ScriptElementKind.localClassElement : ts.ScriptElementKind.classElement; - if (flags & 384 /* Enum */) - return ts.ScriptElementKind.enumElement; - if (flags & 524288 /* TypeAlias */) - return ts.ScriptElementKind.typeElement; - if (flags & 64 /* Interface */) - return ts.ScriptElementKind.interfaceElement; - if (flags & 262144 /* TypeParameter */) - return ts.ScriptElementKind.typeParameterElement; - var result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, location); - if (result === ts.ScriptElementKind.unknown) { - if (flags & 262144 /* TypeParameter */) - return ts.ScriptElementKind.typeParameterElement; - if (flags & 8 /* EnumMember */) - return ts.ScriptElementKind.variableElement; - if (flags & 8388608 /* Alias */) - return ts.ScriptElementKind.alias; - if (flags & 1536 /* Module */) - return ts.ScriptElementKind.moduleElement; - } - return result; - } - function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, location) { - var typeChecker = program.getTypeChecker(); - if (typeChecker.isUndefinedSymbol(symbol)) { - return ts.ScriptElementKind.variableElement; - } - if (typeChecker.isArgumentsSymbol(symbol)) { - return ts.ScriptElementKind.localVariableElement; - } - if (location.kind === 97 /* ThisKeyword */ && ts.isExpression(location)) { - return ts.ScriptElementKind.parameterElement; - } - if (flags & 3 /* Variable */) { - if (ts.isFirstDeclarationOfSymbolParameter(symbol)) { - return ts.ScriptElementKind.parameterElement; + if (options.insertSpaceAfterFunctionKeywordForAnonymousFunctions) { + rules.push(this.globalRules.SpaceAfterAnonymousFunctionKeyword); } - else if (symbol.valueDeclaration && ts.isConst(symbol.valueDeclaration)) { - return ts.ScriptElementKind.constElement; + else { + rules.push(this.globalRules.NoSpaceAfterAnonymousFunctionKeyword); } - else if (ts.forEach(symbol.declarations, ts.isLet)) { - return ts.ScriptElementKind.letElement; + if (options.insertSpaceAfterKeywordsInControlFlowStatements) { + rules.push(this.globalRules.SpaceAfterKeywordInControl); } - return isLocalVariableOrFunction(symbol) ? ts.ScriptElementKind.localVariableElement : ts.ScriptElementKind.variableElement; - } - if (flags & 16 /* Function */) - return isLocalVariableOrFunction(symbol) ? ts.ScriptElementKind.localFunctionElement : ts.ScriptElementKind.functionElement; - if (flags & 32768 /* GetAccessor */) - return ts.ScriptElementKind.memberGetAccessorElement; - if (flags & 65536 /* SetAccessor */) - return ts.ScriptElementKind.memberSetAccessorElement; - if (flags & 8192 /* Method */) - return ts.ScriptElementKind.memberFunctionElement; - if (flags & 16384 /* Constructor */) - return ts.ScriptElementKind.constructorImplementationElement; - if (flags & 4 /* Property */) { - if (flags & 268435456 /* SyntheticProperty */) { - // If union property is result of union of non method (property/accessors/variables), it is labeled as property - var unionPropertyKind = ts.forEach(typeChecker.getRootSymbols(symbol), function (rootSymbol) { - var rootSymbolFlags = rootSymbol.getFlags(); - if (rootSymbolFlags & (98308 /* PropertyOrAccessor */ | 3 /* Variable */)) { - return ts.ScriptElementKind.memberVariableElement; - } - ts.Debug.assert(!!(rootSymbolFlags & 8192 /* Method */)); - }); - if (!unionPropertyKind) { - // If this was union of all methods, - // make sure it has call signatures before we can label it as method - var typeOfUnionProperty = typeChecker.getTypeOfSymbolAtLocation(symbol, location); - if (typeOfUnionProperty.getCallSignatures().length) { - return ts.ScriptElementKind.memberFunctionElement; - } - return ts.ScriptElementKind.memberVariableElement; - } - return unionPropertyKind; + else { + rules.push(this.globalRules.NoSpaceAfterKeywordInControl); } - return ts.ScriptElementKind.memberVariableElement; - } - return ts.ScriptElementKind.unknown; - } - function getSymbolModifiers(symbol) { - return symbol && symbol.declarations && symbol.declarations.length > 0 - ? ts.getNodeModifiers(symbol.declarations[0]) - : ts.ScriptElementKindModifier.none; - } - // TODO(drosen): Currently completion entry details passes the SemanticMeaning.All instead of using semanticMeaning of location - function getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, sourceFile, enclosingDeclaration, location, semanticMeaning) { - if (semanticMeaning === void 0) { semanticMeaning = getMeaningFromLocation(location); } - var typeChecker = program.getTypeChecker(); - var displayParts = []; - var documentation; - var symbolFlags = symbol.flags; - var symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags, location); - var hasAddedSymbolInfo; - var isThisExpression = location.kind === 97 /* ThisKeyword */ && ts.isExpression(location); - var type; - // Class at constructor site need to be shown as constructor apart from property,method, vars - if (symbolKind !== ts.ScriptElementKind.unknown || symbolFlags & 32 /* Class */ || symbolFlags & 8388608 /* Alias */) { - // If it is accessor they are allowed only if location is at name of the accessor - if (symbolKind === ts.ScriptElementKind.memberGetAccessorElement || symbolKind === ts.ScriptElementKind.memberSetAccessorElement) { - symbolKind = ts.ScriptElementKind.memberVariableElement; + if (options.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis) { + rules.push(this.globalRules.SpaceAfterOpenParen); + rules.push(this.globalRules.SpaceBeforeCloseParen); + rules.push(this.globalRules.NoSpaceBetweenParens); } - var signature = void 0; - type = isThisExpression ? typeChecker.getTypeAtLocation(location) : typeChecker.getTypeOfSymbolAtLocation(symbol, location); - if (type) { - if (location.parent && location.parent.kind === 172 /* PropertyAccessExpression */) { - var right = location.parent.name; - // Either the location is on the right of a property access, or on the left and the right is missing - if (right === location || (right && right.getFullWidth() === 0)) { - location = location.parent; - } - } - // try get the call/construct signature from the type if it matches - var callExpression = void 0; - if (location.kind === 174 /* CallExpression */ || location.kind === 175 /* NewExpression */) { - callExpression = location; - } - else if (isCallExpressionTarget(location) || isNewExpressionTarget(location)) { - callExpression = location.parent; - } - if (callExpression) { - var candidateSignatures = []; - signature = typeChecker.getResolvedSignature(callExpression, candidateSignatures); - if (!signature && candidateSignatures.length) { - // Use the first candidate: - signature = candidateSignatures[0]; - } - var useConstructSignatures = callExpression.kind === 175 /* NewExpression */ || callExpression.expression.kind === 95 /* SuperKeyword */; - var allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures(); - if (!ts.contains(allSignatures, signature.target) && !ts.contains(allSignatures, signature)) { - // Get the first signature if there is one -- allSignatures may contain - // either the original signature or its target, so check for either - signature = allSignatures.length ? allSignatures[0] : undefined; - } - if (signature) { - if (useConstructSignatures && (symbolFlags & 32 /* Class */)) { - // Constructor - symbolKind = ts.ScriptElementKind.constructorImplementationElement; - addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); - } - else if (symbolFlags & 8388608 /* Alias */) { - symbolKind = ts.ScriptElementKind.alias; - pushTypePart(symbolKind); - displayParts.push(ts.spacePart()); - if (useConstructSignatures) { - displayParts.push(ts.keywordPart(92 /* NewKeyword */)); - displayParts.push(ts.spacePart()); - } - addFullSymbolName(symbol); - } - else { - addPrefixForAnyFunctionOrVar(symbol, symbolKind); - } - switch (symbolKind) { - case ts.ScriptElementKind.memberVariableElement: - case ts.ScriptElementKind.variableElement: - case ts.ScriptElementKind.constElement: - case ts.ScriptElementKind.letElement: - case ts.ScriptElementKind.parameterElement: - case ts.ScriptElementKind.localVariableElement: - // If it is call or construct signature of lambda's write type name - displayParts.push(ts.punctuationPart(54 /* ColonToken */)); - displayParts.push(ts.spacePart()); - if (useConstructSignatures) { - displayParts.push(ts.keywordPart(92 /* NewKeyword */)); - displayParts.push(ts.spacePart()); - } - if (!(type.flags & 2097152 /* Anonymous */) && type.symbol) { - ts.addRange(displayParts, ts.symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, 1 /* WriteTypeParametersOrArguments */)); - } - addSignatureDisplayParts(signature, allSignatures, 8 /* WriteArrowStyleSignature */); - break; - default: - // Just signature - addSignatureDisplayParts(signature, allSignatures); - } - hasAddedSymbolInfo = true; - } - } - else if ((isNameOfFunctionDeclaration(location) && !(symbol.flags & 98304 /* Accessor */)) || - (location.kind === 121 /* ConstructorKeyword */ && location.parent.kind === 148 /* Constructor */)) { - // get the signature from the declaration and write it - var functionDeclaration = location.parent; - var allSignatures = functionDeclaration.kind === 148 /* Constructor */ ? type.getNonNullableType().getConstructSignatures() : type.getNonNullableType().getCallSignatures(); - if (!typeChecker.isImplementationOfOverload(functionDeclaration)) { - signature = typeChecker.getSignatureFromDeclaration(functionDeclaration); - } - else { - signature = allSignatures[0]; - } - if (functionDeclaration.kind === 148 /* Constructor */) { - // show (constructor) Type(...) signature - symbolKind = ts.ScriptElementKind.constructorImplementationElement; - addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); - } - else { - // (function/method) symbol(..signature) - addPrefixForAnyFunctionOrVar(functionDeclaration.kind === 151 /* CallSignature */ && - !(type.symbol.flags & 2048 /* TypeLiteral */ || type.symbol.flags & 4096 /* ObjectLiteral */) ? type.symbol : symbol, symbolKind); - } - addSignatureDisplayParts(signature, allSignatures); - hasAddedSymbolInfo = true; - } + else { + rules.push(this.globalRules.NoSpaceAfterOpenParen); + rules.push(this.globalRules.NoSpaceBeforeCloseParen); + rules.push(this.globalRules.NoSpaceBetweenParens); } - } - if (symbolFlags & 32 /* Class */ && !hasAddedSymbolInfo && !isThisExpression) { - if (ts.getDeclarationOfKind(symbol, 192 /* ClassExpression */)) { - // Special case for class expressions because we would like to indicate that - // the class name is local to the class body (similar to function expression) - // (local class) class - pushTypePart(ts.ScriptElementKind.localClassElement); + if (options.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets) { + rules.push(this.globalRules.SpaceAfterOpenBracket); + rules.push(this.globalRules.SpaceBeforeCloseBracket); + rules.push(this.globalRules.NoSpaceBetweenBrackets); } else { - // Class declaration has name which is not local. - displayParts.push(ts.keywordPart(73 /* ClassKeyword */)); - } - displayParts.push(ts.spacePart()); - addFullSymbolName(symbol); - writeTypeParametersOfSymbol(symbol, sourceFile); - } - if ((symbolFlags & 64 /* Interface */) && (semanticMeaning & 2 /* Type */)) { - addNewLineIfDisplayPartsExist(); - displayParts.push(ts.keywordPart(107 /* InterfaceKeyword */)); - displayParts.push(ts.spacePart()); - addFullSymbolName(symbol); - writeTypeParametersOfSymbol(symbol, sourceFile); - } - if (symbolFlags & 524288 /* TypeAlias */) { - addNewLineIfDisplayPartsExist(); - displayParts.push(ts.keywordPart(134 /* TypeKeyword */)); - displayParts.push(ts.spacePart()); - addFullSymbolName(symbol); - writeTypeParametersOfSymbol(symbol, sourceFile); - displayParts.push(ts.spacePart()); - displayParts.push(ts.operatorPart(56 /* EqualsToken */)); - displayParts.push(ts.spacePart()); - ts.addRange(displayParts, ts.typeToDisplayParts(typeChecker, typeChecker.getDeclaredTypeOfSymbol(symbol), enclosingDeclaration, 512 /* InTypeAlias */)); - } - if (symbolFlags & 384 /* Enum */) { - addNewLineIfDisplayPartsExist(); - if (ts.forEach(symbol.declarations, ts.isConstEnumDeclaration)) { - displayParts.push(ts.keywordPart(74 /* ConstKeyword */)); - displayParts.push(ts.spacePart()); + rules.push(this.globalRules.NoSpaceAfterOpenBracket); + rules.push(this.globalRules.NoSpaceBeforeCloseBracket); + rules.push(this.globalRules.NoSpaceBetweenBrackets); } - displayParts.push(ts.keywordPart(81 /* EnumKeyword */)); - displayParts.push(ts.spacePart()); - addFullSymbolName(symbol); - } - if (symbolFlags & 1536 /* Module */) { - addNewLineIfDisplayPartsExist(); - var declaration = ts.getDeclarationOfKind(symbol, 225 /* ModuleDeclaration */); - var isNamespace = declaration && declaration.name && declaration.name.kind === 69 /* Identifier */; - displayParts.push(ts.keywordPart(isNamespace ? 126 /* NamespaceKeyword */ : 125 /* ModuleKeyword */)); - displayParts.push(ts.spacePart()); - addFullSymbolName(symbol); - } - if ((symbolFlags & 262144 /* TypeParameter */) && (semanticMeaning & 2 /* Type */)) { - addNewLineIfDisplayPartsExist(); - displayParts.push(ts.punctuationPart(17 /* OpenParenToken */)); - displayParts.push(ts.textPart("type parameter")); - displayParts.push(ts.punctuationPart(18 /* CloseParenToken */)); - displayParts.push(ts.spacePart()); - addFullSymbolName(symbol); - displayParts.push(ts.spacePart()); - displayParts.push(ts.keywordPart(90 /* InKeyword */)); - displayParts.push(ts.spacePart()); - if (symbol.parent) { - // Class/Interface type parameter - addFullSymbolName(symbol.parent, enclosingDeclaration); - writeTypeParametersOfSymbol(symbol.parent, enclosingDeclaration); + // The default value of InsertSpaceAfterOpeningAndBeforeClosingNonemptyBraces is true + // so if the option is undefined, we should treat it as true as well + if (options.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces !== false) { + rules.push(this.globalRules.SpaceAfterOpenBrace); + rules.push(this.globalRules.SpaceBeforeCloseBrace); + rules.push(this.globalRules.NoSpaceBetweenEmptyBraceBrackets); } else { - // Method/function type parameter - var declaration = ts.getDeclarationOfKind(symbol, 141 /* TypeParameter */); - ts.Debug.assert(declaration !== undefined); - declaration = declaration.parent; - if (declaration) { - if (ts.isFunctionLikeKind(declaration.kind)) { - var signature = typeChecker.getSignatureFromDeclaration(declaration); - if (declaration.kind === 152 /* ConstructSignature */) { - displayParts.push(ts.keywordPart(92 /* NewKeyword */)); - displayParts.push(ts.spacePart()); - } - else if (declaration.kind !== 151 /* CallSignature */ && declaration.name) { - addFullSymbolName(declaration.symbol); - } - ts.addRange(displayParts, ts.signatureToDisplayParts(typeChecker, signature, sourceFile, 32 /* WriteTypeArgumentsOfSignature */)); - } - else { - // Type alias type parameter - // For example - // type list = T[]; // Both T will go through same code path - displayParts.push(ts.keywordPart(134 /* TypeKeyword */)); - displayParts.push(ts.spacePart()); - addFullSymbolName(declaration.symbol); - writeTypeParametersOfSymbol(declaration.symbol, sourceFile); - } - } + rules.push(this.globalRules.NoSpaceAfterOpenBrace); + rules.push(this.globalRules.NoSpaceBeforeCloseBrace); + rules.push(this.globalRules.NoSpaceBetweenEmptyBraceBrackets); } - } - if (symbolFlags & 8 /* EnumMember */) { - addPrefixForAnyFunctionOrVar(symbol, "enum member"); - var declaration = symbol.declarations[0]; - if (declaration.kind === 255 /* EnumMember */) { - var constantValue = typeChecker.getConstantValue(declaration); - if (constantValue !== undefined) { - displayParts.push(ts.spacePart()); - displayParts.push(ts.operatorPart(56 /* EqualsToken */)); - displayParts.push(ts.spacePart()); - displayParts.push(ts.displayPart(constantValue.toString(), ts.SymbolDisplayPartKind.numericLiteral)); - } + if (options.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces) { + rules.push(this.globalRules.SpaceAfterTemplateHeadAndMiddle); + rules.push(this.globalRules.SpaceBeforeTemplateMiddleAndTail); } - } - if (symbolFlags & 8388608 /* Alias */) { - addNewLineIfDisplayPartsExist(); - if (symbol.declarations[0].kind === 228 /* NamespaceExportDeclaration */) { - displayParts.push(ts.keywordPart(82 /* ExportKeyword */)); - displayParts.push(ts.spacePart()); - displayParts.push(ts.keywordPart(126 /* NamespaceKeyword */)); + else { + rules.push(this.globalRules.NoSpaceAfterTemplateHeadAndMiddle); + rules.push(this.globalRules.NoSpaceBeforeTemplateMiddleAndTail); + } + if (options.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces) { + rules.push(this.globalRules.SpaceAfterOpenBraceInJsxExpression); + rules.push(this.globalRules.SpaceBeforeCloseBraceInJsxExpression); } else { - displayParts.push(ts.keywordPart(89 /* ImportKeyword */)); + rules.push(this.globalRules.NoSpaceAfterOpenBraceInJsxExpression); + rules.push(this.globalRules.NoSpaceBeforeCloseBraceInJsxExpression); } - displayParts.push(ts.spacePart()); - addFullSymbolName(symbol); - ts.forEach(symbol.declarations, function (declaration) { - if (declaration.kind === 229 /* ImportEqualsDeclaration */) { - var importEqualsDeclaration = declaration; - if (ts.isExternalModuleImportEqualsDeclaration(importEqualsDeclaration)) { - displayParts.push(ts.spacePart()); - displayParts.push(ts.operatorPart(56 /* EqualsToken */)); - displayParts.push(ts.spacePart()); - displayParts.push(ts.keywordPart(129 /* RequireKeyword */)); - displayParts.push(ts.punctuationPart(17 /* OpenParenToken */)); - displayParts.push(ts.displayPart(ts.getTextOfNode(ts.getExternalModuleImportEqualsDeclarationExpression(importEqualsDeclaration)), ts.SymbolDisplayPartKind.stringLiteral)); - displayParts.push(ts.punctuationPart(18 /* CloseParenToken */)); - } - else { - var internalAliasSymbol = typeChecker.getSymbolAtLocation(importEqualsDeclaration.moduleReference); - if (internalAliasSymbol) { - displayParts.push(ts.spacePart()); - displayParts.push(ts.operatorPart(56 /* EqualsToken */)); - displayParts.push(ts.spacePart()); - addFullSymbolName(internalAliasSymbol, enclosingDeclaration); - } - } - return true; - } - }); - } - if (!hasAddedSymbolInfo) { - if (symbolKind !== ts.ScriptElementKind.unknown) { - if (type) { - if (isThisExpression) { - addNewLineIfDisplayPartsExist(); - displayParts.push(ts.keywordPart(97 /* ThisKeyword */)); - } - else { - addPrefixForAnyFunctionOrVar(symbol, symbolKind); - } - // For properties, variables and local vars: show the type - if (symbolKind === ts.ScriptElementKind.memberVariableElement || - symbolFlags & 3 /* Variable */ || - symbolKind === ts.ScriptElementKind.localVariableElement || - isThisExpression) { - displayParts.push(ts.punctuationPart(54 /* ColonToken */)); - displayParts.push(ts.spacePart()); - // If the type is type parameter, format it specially - if (type.symbol && type.symbol.flags & 262144 /* TypeParameter */) { - var typeParameterParts = ts.mapToDisplayParts(function (writer) { - typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(type, writer, enclosingDeclaration); - }); - ts.addRange(displayParts, typeParameterParts); - } - else { - ts.addRange(displayParts, ts.typeToDisplayParts(typeChecker, type, enclosingDeclaration)); - } - } - else if (symbolFlags & 16 /* Function */ || - symbolFlags & 8192 /* Method */ || - symbolFlags & 16384 /* Constructor */ || - symbolFlags & 131072 /* Signature */ || - symbolFlags & 98304 /* Accessor */ || - symbolKind === ts.ScriptElementKind.memberFunctionElement) { - var allSignatures = type.getNonNullableType().getCallSignatures(); - addSignatureDisplayParts(allSignatures[0], allSignatures); - } - } + if (options.insertSpaceAfterSemicolonInForStatements) { + rules.push(this.globalRules.SpaceAfterSemicolonInFor); } else { - symbolKind = getSymbolKind(symbol, location); + rules.push(this.globalRules.NoSpaceAfterSemicolonInFor); } - } - if (!documentation) { - documentation = symbol.getDocumentationComment(); - if (documentation.length === 0 && symbol.flags & 4 /* Property */) { - // For some special property access expressions like `experts.foo = foo` or `module.exports.foo = foo` - // there documentation comments might be attached to the right hand side symbol of their declarations. - // The pattern of such special property access is that the parent symbol is the symbol of the file. - if (symbol.parent && ts.forEach(symbol.parent.declarations, function (declaration) { return declaration.kind === 256 /* SourceFile */; })) { - for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { - var declaration = _a[_i]; - if (!declaration.parent || declaration.parent.kind !== 187 /* BinaryExpression */) { - continue; - } - var rhsSymbol = program.getTypeChecker().getSymbolAtLocation(declaration.parent.right); - if (!rhsSymbol) { - continue; - } - documentation = rhsSymbol.getDocumentationComment(); - if (documentation.length > 0) { - break; - } - } - } + if (options.insertSpaceBeforeAndAfterBinaryOperators) { + rules.push(this.globalRules.SpaceBeforeBinaryOperator); + rules.push(this.globalRules.SpaceAfterBinaryOperator); } - } - return { displayParts: displayParts, documentation: documentation, symbolKind: symbolKind }; - function addNewLineIfDisplayPartsExist() { - if (displayParts.length) { - displayParts.push(ts.lineBreakPart()); + else { + rules.push(this.globalRules.NoSpaceBeforeBinaryOperator); + rules.push(this.globalRules.NoSpaceAfterBinaryOperator); } - } - function addFullSymbolName(symbol, enclosingDeclaration) { - var fullSymbolDisplayParts = ts.symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration || sourceFile, /*meaning*/ undefined, 1 /* WriteTypeParametersOrArguments */ | 2 /* UseOnlyExternalAliasing */); - ts.addRange(displayParts, fullSymbolDisplayParts); - } - function addPrefixForAnyFunctionOrVar(symbol, symbolKind) { - addNewLineIfDisplayPartsExist(); - if (symbolKind) { - pushTypePart(symbolKind); - displayParts.push(ts.spacePart()); - addFullSymbolName(symbol); + if (options.placeOpenBraceOnNewLineForControlBlocks) { + rules.push(this.globalRules.NewLineBeforeOpenBraceInControl); } - } - function pushTypePart(symbolKind) { - switch (symbolKind) { - case ts.ScriptElementKind.variableElement: - case ts.ScriptElementKind.functionElement: - case ts.ScriptElementKind.letElement: - case ts.ScriptElementKind.constElement: - case ts.ScriptElementKind.constructorImplementationElement: - displayParts.push(ts.textOrKeywordPart(symbolKind)); - return; - default: - displayParts.push(ts.punctuationPart(17 /* OpenParenToken */)); - displayParts.push(ts.textOrKeywordPart(symbolKind)); - displayParts.push(ts.punctuationPart(18 /* CloseParenToken */)); - return; + if (options.placeOpenBraceOnNewLineForFunctions) { + rules.push(this.globalRules.NewLineBeforeOpenBraceInFunction); + rules.push(this.globalRules.NewLineBeforeOpenBraceInTypeScriptDeclWithBlock); } - } - function addSignatureDisplayParts(signature, allSignatures, flags) { - ts.addRange(displayParts, ts.signatureToDisplayParts(typeChecker, signature, enclosingDeclaration, flags | 32 /* WriteTypeArgumentsOfSignature */)); - if (allSignatures.length > 1) { - displayParts.push(ts.spacePart()); - displayParts.push(ts.punctuationPart(17 /* OpenParenToken */)); - displayParts.push(ts.operatorPart(35 /* PlusToken */)); - displayParts.push(ts.displayPart((allSignatures.length - 1).toString(), ts.SymbolDisplayPartKind.numericLiteral)); - displayParts.push(ts.spacePart()); - displayParts.push(ts.textPart(allSignatures.length === 2 ? "overload" : "overloads")); - displayParts.push(ts.punctuationPart(18 /* CloseParenToken */)); + if (options.insertSpaceAfterTypeAssertion) { + rules.push(this.globalRules.SpaceAfterTypeAssertion); } - documentation = signature.getDocumentationComment(); - } - function writeTypeParametersOfSymbol(symbol, enclosingDeclaration) { - var typeParameterParts = ts.mapToDisplayParts(function (writer) { - typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplayFromSymbol(symbol, writer, enclosingDeclaration); - }); - ts.addRange(displayParts, typeParameterParts); - } - } - function getQuickInfoAtPosition(fileName, position) { - synchronizeHostData(); - var sourceFile = getValidSourceFile(fileName); - var node = ts.getTouchingPropertyName(sourceFile, position); - if (node === sourceFile) { - return undefined; + else { + rules.push(this.globalRules.NoSpaceAfterTypeAssertion); + } + rules = rules.concat(this.globalRules.LowPriorityCommonRules); + return rules; + }; + return RulesProvider; + }()); + formatting.RulesProvider = RulesProvider; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/// +/// +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + var Constants; + (function (Constants) { + Constants[Constants["Unknown"] = -1] = "Unknown"; + })(Constants || (Constants = {})); + function formatOnEnter(position, sourceFile, rulesProvider, options) { + var line = sourceFile.getLineAndCharacterOfPosition(position).line; + if (line === 0) { + return []; } - if (isLabelName(node)) { - return undefined; + // After the enter key, the cursor is now at a new line. The new line may or may not contain non-whitespace characters. + // If the new line has only whitespaces, we won't want to format this line, because that would remove the indentation as + // trailing whitespaces. So the end of the formatting span should be the later one between: + // 1. the end of the previous line + // 2. the last non-whitespace character in the current line + var endOfFormatSpan = ts.getEndLinePosition(line, sourceFile); + while (ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(endOfFormatSpan))) { + endOfFormatSpan--; } - var typeChecker = program.getTypeChecker(); - var symbol = typeChecker.getSymbolAtLocation(node); - if (!symbol || typeChecker.isUnknownSymbol(symbol)) { - // Try getting just type at this position and show - switch (node.kind) { - case 69 /* Identifier */: - case 172 /* PropertyAccessExpression */: - case 139 /* QualifiedName */: - case 97 /* ThisKeyword */: - case 165 /* ThisType */: - case 95 /* SuperKeyword */: - // For the identifiers/this/super etc get the type at position - var type = typeChecker.getTypeAtLocation(node); - if (type) { - return { - kind: ts.ScriptElementKind.unknown, - kindModifiers: ts.ScriptElementKindModifier.none, - textSpan: ts.createTextSpan(node.getStart(), node.getWidth()), - displayParts: ts.typeToDisplayParts(typeChecker, type, getContainerNode(node)), - documentation: type.symbol ? type.symbol.getDocumentationComment() : undefined - }; - } - } - return undefined; + // if the character at the end of the span is a line break, we shouldn't include it, because it indicates we don't want to + // touch the current line at all. Also, on some OSes the line break consists of two characters (\r\n), we should test if the + // previous character before the end of format span is line break character as well. + if (ts.isLineBreak(sourceFile.text.charCodeAt(endOfFormatSpan))) { + endOfFormatSpan--; } - var displayPartsDocumentationsAndKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, sourceFile, getContainerNode(node), node); - return { - kind: displayPartsDocumentationsAndKind.symbolKind, - kindModifiers: getSymbolModifiers(symbol), - textSpan: ts.createTextSpan(node.getStart(), node.getWidth()), - displayParts: displayPartsDocumentationsAndKind.displayParts, - documentation: displayPartsDocumentationsAndKind.documentation + var span = { + // get start position for the previous line + pos: ts.getStartPositionOfLine(line - 1, sourceFile), + // end value is exclusive so add 1 to the result + end: endOfFormatSpan + 1 }; + return formatSpan(span, sourceFile, options, rulesProvider, 2 /* FormatOnEnter */); } - function createDefinitionInfo(node, symbolKind, symbolName, containerName) { - return { - fileName: node.getSourceFile().fileName, - textSpan: ts.createTextSpanFromBounds(node.getStart(), node.getEnd()), - kind: symbolKind, - name: symbolName, - containerKind: undefined, - containerName: containerName + formatting.formatOnEnter = formatOnEnter; + function formatOnSemicolon(position, sourceFile, rulesProvider, options) { + return formatOutermostParent(position, 23 /* SemicolonToken */, sourceFile, options, rulesProvider, 3 /* FormatOnSemicolon */); + } + formatting.formatOnSemicolon = formatOnSemicolon; + function formatOnClosingCurly(position, sourceFile, rulesProvider, options) { + return formatOutermostParent(position, 16 /* CloseBraceToken */, sourceFile, options, rulesProvider, 4 /* FormatOnClosingCurlyBrace */); + } + formatting.formatOnClosingCurly = formatOnClosingCurly; + function formatDocument(sourceFile, rulesProvider, options) { + var span = { + pos: 0, + end: sourceFile.text.length }; + return formatSpan(span, sourceFile, options, rulesProvider, 0 /* FormatDocument */); } - function getSymbolInfo(typeChecker, symbol, node) { - return { - symbolName: typeChecker.symbolToString(symbol), - symbolKind: getSymbolKind(symbol, node), - containerName: symbol.parent ? typeChecker.symbolToString(symbol.parent, node) : "" + formatting.formatDocument = formatDocument; + function formatSelection(start, end, sourceFile, rulesProvider, options) { + // format from the beginning of the line + var span = { + pos: ts.getLineStartPositionForPosition(start, sourceFile), + end: end }; + return formatSpan(span, sourceFile, options, rulesProvider, 1 /* FormatSelection */); } - function createDefinitionFromSignatureDeclaration(decl) { - var typeChecker = program.getTypeChecker(); - var _a = getSymbolInfo(typeChecker, decl.symbol, decl), symbolName = _a.symbolName, symbolKind = _a.symbolKind, containerName = _a.containerName; - return createDefinitionInfo(decl, symbolKind, symbolName, containerName); + formatting.formatSelection = formatSelection; + function formatOutermostParent(position, expectedLastToken, sourceFile, options, rulesProvider, requestKind) { + var parent = findOutermostParent(position, expectedLastToken, sourceFile); + if (!parent) { + return []; + } + var span = { + pos: ts.getLineStartPositionForPosition(parent.getStart(sourceFile), sourceFile), + end: parent.end + }; + return formatSpan(span, sourceFile, options, rulesProvider, requestKind); } - function getDefinitionFromSymbol(symbol, node) { - var typeChecker = program.getTypeChecker(); - var result = []; - var declarations = symbol.getDeclarations(); - var _a = getSymbolInfo(typeChecker, symbol, node), symbolName = _a.symbolName, symbolKind = _a.symbolKind, containerName = _a.containerName; - if (!tryAddConstructSignature(symbol, node, symbolKind, symbolName, containerName, result) && - !tryAddCallSignature(symbol, node, symbolKind, symbolName, containerName, result)) { - // Just add all the declarations. - ts.forEach(declarations, function (declaration) { - result.push(createDefinitionInfo(declaration, symbolKind, symbolName, containerName)); - }); + function findOutermostParent(position, expectedTokenKind, sourceFile) { + var precedingToken = ts.findPrecedingToken(position, sourceFile); + // when it is claimed that trigger character was typed at given position + // we verify that there is a token with a matching kind whose end is equal to position (because the character was just typed). + // If this condition is not hold - then trigger character was typed in some other context, + // i.e.in comment and thus should not trigger autoformatting + if (!precedingToken || + precedingToken.kind !== expectedTokenKind || + position !== precedingToken.getEnd()) { + return undefined; } - return result; - function tryAddConstructSignature(symbol, location, symbolKind, symbolName, containerName, result) { - // Applicable only if we are in a new expression, or we are on a constructor declaration - // and in either case the symbol has a construct signature definition, i.e. class - if (isNewExpressionTarget(location) || location.kind === 121 /* ConstructorKeyword */) { - if (symbol.flags & 32 /* Class */) { - // Find the first class-like declaration and try to get the construct signature. - for (var _i = 0, _a = symbol.getDeclarations(); _i < _a.length; _i++) { - var declaration = _a[_i]; - if (ts.isClassLike(declaration)) { - return tryAddSignature(declaration.members, - /*selectConstructors*/ true, symbolKind, symbolName, containerName, result); - } - } - ts.Debug.fail("Expected declaration to have at least one class-like declaration"); - } - } - return false; + // walk up and search for the parent node that ends at the same position with precedingToken. + // for cases like this + // + // let x = 1; + // while (true) { + // } + // after typing close curly in while statement we want to reformat just the while statement. + // However if we just walk upwards searching for the parent that has the same end value - + // we'll end up with the whole source file. isListElement allows to stop on the list element level + var current = precedingToken; + while (current && + current.parent && + current.parent.end === precedingToken.end && + !isListElement(current.parent, current)) { + current = current.parent; } - function tryAddCallSignature(symbol, location, symbolKind, symbolName, containerName, result) { - if (isCallExpressionTarget(location) || isNewExpressionTarget(location) || isNameOfFunctionDeclaration(location)) { - return tryAddSignature(symbol.declarations, /*selectConstructors*/ false, symbolKind, symbolName, containerName, result); - } - return false; + return current; + } + // Returns true if node is a element in some list in parent + // i.e. parent is class declaration with the list of members and node is one of members. + function isListElement(parent, node) { + switch (parent.kind) { + case 221 /* ClassDeclaration */: + case 222 /* InterfaceDeclaration */: + return ts.rangeContainsRange(parent.members, node); + case 225 /* ModuleDeclaration */: + var body = parent.body; + return body && body.kind === 199 /* Block */ && ts.rangeContainsRange(body.statements, node); + case 256 /* SourceFile */: + case 199 /* Block */: + case 226 /* ModuleBlock */: + return ts.rangeContainsRange(parent.statements, node); + case 252 /* CatchClause */: + return ts.rangeContainsRange(parent.block.statements, node); } - function tryAddSignature(signatureDeclarations, selectConstructors, symbolKind, symbolName, containerName, result) { - var declarations = []; - var definition; - ts.forEach(signatureDeclarations, function (d) { - if ((selectConstructors && d.kind === 148 /* Constructor */) || - (!selectConstructors && (d.kind === 220 /* FunctionDeclaration */ || d.kind === 147 /* MethodDeclaration */ || d.kind === 146 /* MethodSignature */))) { - declarations.push(d); - if (d.body) - definition = d; + return false; + } + /** find node that fully contains given text range */ + function findEnclosingNode(range, sourceFile) { + return find(sourceFile); + function find(n) { + var candidate = ts.forEachChild(n, function (c) { return ts.startEndContainsRange(c.getStart(sourceFile), c.end, range) && c; }); + if (candidate) { + var result = find(candidate); + if (result) { + return result; } - }); - if (definition) { - result.push(createDefinitionInfo(definition, symbolKind, symbolName, containerName)); - return true; } - else if (declarations.length) { - result.push(createDefinitionInfo(ts.lastOrUndefined(declarations), symbolKind, symbolName, containerName)); - return true; - } - return false; + return n; } } - function findReferenceInPosition(refs, pos) { - for (var _i = 0, refs_1 = refs; _i < refs_1.length; _i++) { - var ref = refs_1[_i]; - if (ref.pos <= pos && pos < ref.end) { - return ref; - } + /** formatting is not applied to ranges that contain parse errors. + * This function will return a predicate that for a given text range will tell + * if there are any parse errors that overlap with the range. + */ + function prepareRangeContainsErrorFunction(errors, originalRange) { + if (!errors.length) { + return rangeHasNoErrors; } - return undefined; - } - function getDefinitionInfoForFileReference(name, targetFileName) { - return { - fileName: targetFileName, - textSpan: ts.createTextSpanFromBounds(0, 0), - kind: ts.ScriptElementKind.scriptElement, - name: name, - containerName: undefined, - containerKind: undefined - }; - } - /// Goto definition - function getDefinitionAtPosition(fileName, position) { - synchronizeHostData(); - var sourceFile = getValidSourceFile(fileName); - /// Triple slash reference comments - var comment = findReferenceInPosition(sourceFile.referencedFiles, position); - if (comment) { - var referenceFile = ts.tryResolveScriptReference(program, sourceFile, comment); - if (referenceFile) { - return [getDefinitionInfoForFileReference(comment.fileName, referenceFile.fileName)]; - } - return undefined; + // pick only errors that fall in range + var sorted = errors + .filter(function (d) { return ts.rangeOverlapsWithStartEnd(originalRange, d.start, d.start + d.length); }) + .sort(function (e1, e2) { return e1.start - e2.start; }); + if (!sorted.length) { + return rangeHasNoErrors; } - // Type reference directives - var typeReferenceDirective = findReferenceInPosition(sourceFile.typeReferenceDirectives, position); - if (typeReferenceDirective) { - var referenceFile = program.getResolvedTypeReferenceDirectives()[typeReferenceDirective.fileName]; - if (referenceFile && referenceFile.resolvedFileName) { - return [getDefinitionInfoForFileReference(typeReferenceDirective.fileName, referenceFile.resolvedFileName)]; + var index = 0; + return function (r) { + // in current implementation sequence of arguments [r1, r2...] is monotonically increasing. + // 'index' tracks the index of the most recent error that was checked. + while (true) { + if (index >= sorted.length) { + // all errors in the range were already checked -> no error in specified range + return false; + } + var error = sorted[index]; + if (r.end <= error.start) { + // specified range ends before the error refered by 'index' - no error in range + return false; + } + if (ts.startEndOverlapsWithStartEnd(r.pos, r.end, error.start, error.start + error.length)) { + // specified range overlaps with error range + return true; + } + index++; } - return undefined; - } - var node = ts.getTouchingPropertyName(sourceFile, position); - if (node === sourceFile) { - return undefined; + }; + function rangeHasNoErrors(r) { + return false; } - // Labels - if (isJumpStatementTarget(node)) { - var labelName = node.text; - var label = getTargetLabel(node.parent, node.text); - return label ? [createDefinitionInfo(label, ts.ScriptElementKind.label, labelName, /*containerName*/ undefined)] : undefined; + } + /** + * Start of the original range might fall inside the comment - scanner will not yield appropriate results + * This function will look for token that is located before the start of target range + * and return its end as start position for the scanner. + */ + function getScanStartPosition(enclosingNode, originalRange, sourceFile) { + var start = enclosingNode.getStart(sourceFile); + if (start === originalRange.pos && enclosingNode.end === originalRange.end) { + return start; } - var typeChecker = program.getTypeChecker(); - var calledDeclaration = tryGetSignatureDeclaration(typeChecker, node); - if (calledDeclaration) { - return [createDefinitionFromSignatureDeclaration(calledDeclaration)]; + var precedingToken = ts.findPrecedingToken(originalRange.pos, sourceFile); + if (!precedingToken) { + // no preceding token found - start from the beginning of enclosing node + return enclosingNode.pos; } - var symbol = typeChecker.getSymbolAtLocation(node); - // Could not find a symbol e.g. node is string or number keyword, - // or the symbol was an internal symbol and does not have a declaration e.g. undefined symbol - if (!symbol) { - return undefined; + // preceding token ends after the start of original range (i.e when originalRange.pos falls in the middle of literal) + // start from the beginning of enclosingNode to handle the entire 'originalRange' + if (precedingToken.end >= originalRange.pos) { + return enclosingNode.pos; } - // If this is an alias, and the request came at the declaration location - // get the aliased symbol instead. This allows for goto def on an import e.g. - // import {A, B} from "mod"; - // to jump to the implementation directly. - if (symbol.flags & 8388608 /* Alias */) { - var declaration = symbol.declarations[0]; - // Go to the original declaration for cases: - // - // (1) when the aliased symbol was declared in the location(parent). - // (2) when the aliased symbol is originating from a named import. - // - if (node.kind === 69 /* Identifier */ && - (node.parent === declaration || - (declaration.kind === 234 /* ImportSpecifier */ && declaration.parent && declaration.parent.kind === 233 /* NamedImports */))) { - symbol = typeChecker.getAliasedSymbol(symbol); + return precedingToken.end; + } + /* + * For cases like + * if (a || + * b ||$ + * c) {...} + * If we hit Enter at $ we want line ' b ||' to be indented. + * Formatting will be applied to the last two lines. + * Node that fully encloses these lines is binary expression 'a ||...'. + * Initial indentation for this node will be 0. + * Binary expressions don't introduce new indentation scopes, however it is possible + * that some parent node on the same line does - like if statement in this case. + * Note that we are considering parents only from the same line with initial node - + * if parent is on the different line - its delta was already contributed + * to the initial indentation. + */ + function getOwnOrInheritedDelta(n, options, sourceFile) { + var previousLine = -1 /* Unknown */; + var child; + while (n) { + var line = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)).line; + if (previousLine !== -1 /* Unknown */ && line !== previousLine) { + break; } - } - // Because name in short-hand property assignment has two different meanings: property name and property value, - // using go-to-definition at such position should go to the variable declaration of the property value rather than - // go to the declaration of the property name (in this case stay at the same position). However, if go-to-definition - // is performed at the location of property access, we would like to go to definition of the property in the short-hand - // assignment. This case and others are handled by the following code. - if (node.parent.kind === 254 /* ShorthandPropertyAssignment */) { - var shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration); - if (!shorthandSymbol) { - return []; + if (formatting.SmartIndenter.shouldIndentChildNode(n, child)) { + return options.indentSize; } - var shorthandDeclarations = shorthandSymbol.getDeclarations(); - var shorthandSymbolKind_1 = getSymbolKind(shorthandSymbol, node); - var shorthandSymbolName_1 = typeChecker.symbolToString(shorthandSymbol); - var shorthandContainerName_1 = typeChecker.symbolToString(symbol.parent, node); - return ts.map(shorthandDeclarations, function (declaration) { return createDefinitionInfo(declaration, shorthandSymbolKind_1, shorthandSymbolName_1, shorthandContainerName_1); }); + previousLine = line; + child = n; + n = n.parent; } - return getDefinitionFromSymbol(symbol, node); + return 0; } - /// Goto type - function getTypeDefinitionAtPosition(fileName, position) { - synchronizeHostData(); - var sourceFile = getValidSourceFile(fileName); - var node = ts.getTouchingPropertyName(sourceFile, position); - if (node === sourceFile) { - return undefined; - } - var typeChecker = program.getTypeChecker(); - var symbol = typeChecker.getSymbolAtLocation(node); - if (!symbol) { - return undefined; + function formatSpan(originalRange, sourceFile, options, rulesProvider, requestKind) { + var rangeContainsError = prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange); + // formatting context is used by rules provider + var formattingContext = new formatting.FormattingContext(sourceFile, requestKind); + // find the smallest node that fully wraps the range and compute the initial indentation for the node + var enclosingNode = findEnclosingNode(originalRange, sourceFile); + var formattingScanner = formatting.getFormattingScanner(sourceFile, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end); + var initialIndentation = formatting.SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, options); + var previousRangeHasError; + var previousRange; + var previousParent; + var previousRangeStartLine; + var lastIndentedLine; + var indentationOnLastIndentedLine; + var edits = []; + formattingScanner.advance(); + if (formattingScanner.isOnToken()) { + var startLine = sourceFile.getLineAndCharacterOfPosition(enclosingNode.getStart(sourceFile)).line; + var undecoratedStartLine = startLine; + if (enclosingNode.decorators) { + undecoratedStartLine = sourceFile.getLineAndCharacterOfPosition(ts.getNonDecoratorTokenPosOfNode(enclosingNode, sourceFile)).line; + } + var delta = getOwnOrInheritedDelta(enclosingNode, options, sourceFile); + processNode(enclosingNode, enclosingNode, startLine, undecoratedStartLine, initialIndentation, delta); } - var type = typeChecker.getTypeOfSymbolAtLocation(symbol, node); - if (!type) { - return undefined; + if (!formattingScanner.isOnToken()) { + var leadingTrivia = formattingScanner.getCurrentLeadingTrivia(); + if (leadingTrivia) { + processTrivia(leadingTrivia, enclosingNode, enclosingNode, undefined); + trimTrailingWhitespacesForRemainingRange(); + } } - if (type.flags & 524288 /* Union */ && !(type.flags & 16 /* Enum */)) { - var result_4 = []; - ts.forEach(type.types, function (t) { - if (t.symbol) { - ts.addRange(/*to*/ result_4, /*from*/ getDefinitionFromSymbol(t.symbol, node)); + formattingScanner.close(); + return edits; + // local functions + /** Tries to compute the indentation for a list element. + * If list element is not in range then + * function will pick its actual indentation + * so it can be pushed downstream as inherited indentation. + * If list element is in the range - its indentation will be equal + * to inherited indentation from its predecessors. + */ + function tryComputeIndentationForListItem(startPos, endPos, parentStartLine, range, inheritedIndentation) { + if (ts.rangeOverlapsWithStartEnd(range, startPos, endPos) || + ts.rangeContainsStartEnd(range, startPos, endPos) /* Not to miss zero-range nodes e.g. JsxText */) { + if (inheritedIndentation !== -1 /* Unknown */) { + return inheritedIndentation; } - }); - return result_4; - } - if (!type.symbol) { - return undefined; - } - return getDefinitionFromSymbol(type.symbol, node); - } - function getOccurrencesAtPosition(fileName, position) { - var results = getOccurrencesAtPositionCore(fileName, position); - if (results) { - var sourceFile_2 = getCanonicalFileName(ts.normalizeSlashes(fileName)); - // Get occurrences only supports reporting occurrences for the file queried. So - // filter down to that list. - results = ts.filter(results, function (r) { return getCanonicalFileName(ts.normalizeSlashes(r.fileName)) === sourceFile_2; }); - } - return results; - } - function getDocumentHighlights(fileName, position, filesToSearch) { - synchronizeHostData(); - var sourceFilesToSearch = ts.map(filesToSearch, function (f) { return program.getSourceFile(f); }); - var sourceFile = getValidSourceFile(fileName); - var node = ts.getTouchingWord(sourceFile, position); - if (!node) { - return undefined; - } - return getSemanticDocumentHighlights(node) || getSyntacticDocumentHighlights(node); - function getHighlightSpanForNode(node) { - var start = node.getStart(); - var end = node.getEnd(); - return { - fileName: sourceFile.fileName, - textSpan: ts.createTextSpanFromBounds(start, end), - kind: ts.HighlightSpanKind.none - }; + } + else { + var startLine = sourceFile.getLineAndCharacterOfPosition(startPos).line; + var startLinePosition = ts.getLineStartPositionForPosition(startPos, sourceFile); + var column = formatting.SmartIndenter.findFirstNonWhitespaceColumn(startLinePosition, startPos, sourceFile, options); + if (startLine !== parentStartLine || startPos === column) { + // Use the base indent size if it is greater than + // the indentation of the inherited predecessor. + var baseIndentSize = formatting.SmartIndenter.getBaseIndentation(options); + return baseIndentSize > column ? baseIndentSize : column; + } + } + return -1 /* Unknown */; } - function getSemanticDocumentHighlights(node) { - if (node.kind === 69 /* Identifier */ || - node.kind === 97 /* ThisKeyword */ || - node.kind === 165 /* ThisType */ || - node.kind === 95 /* SuperKeyword */ || - node.kind === 9 /* StringLiteral */ || - isLiteralNameOfPropertyDeclarationOrIndexAccess(node)) { - var referencedSymbols = getReferencedSymbolsForNode(node, sourceFilesToSearch, /*findInStrings*/ false, /*findInComments*/ false); - return convertReferencedSymbols(referencedSymbols); + function computeIndentation(node, startLine, inheritedIndentation, parent, parentDynamicIndentation, effectiveParentStartLine) { + var indentation = inheritedIndentation; + var delta = formatting.SmartIndenter.shouldIndentChildNode(node) ? options.indentSize : 0; + if (effectiveParentStartLine === startLine) { + // if node is located on the same line with the parent + // - inherit indentation from the parent + // - push children if either parent of node itself has non-zero delta + indentation = startLine === lastIndentedLine + ? indentationOnLastIndentedLine + : parentDynamicIndentation.getIndentation(); + delta = Math.min(options.indentSize, parentDynamicIndentation.getDelta(node) + delta); } - return undefined; - function convertReferencedSymbols(referencedSymbols) { - if (!referencedSymbols) { - return undefined; + else if (indentation === -1 /* Unknown */) { + if (formatting.SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement(parent, node, startLine, sourceFile)) { + indentation = parentDynamicIndentation.getIndentation(); } - var fileNameToDocumentHighlights = ts.createMap(); - var result = []; - for (var _i = 0, referencedSymbols_1 = referencedSymbols; _i < referencedSymbols_1.length; _i++) { - var referencedSymbol = referencedSymbols_1[_i]; - for (var _a = 0, _b = referencedSymbol.references; _a < _b.length; _a++) { - var referenceEntry = _b[_a]; - var fileName_1 = referenceEntry.fileName; - var documentHighlights = fileNameToDocumentHighlights[fileName_1]; - if (!documentHighlights) { - documentHighlights = { fileName: fileName_1, highlightSpans: [] }; - fileNameToDocumentHighlights[fileName_1] = documentHighlights; - result.push(documentHighlights); - } - documentHighlights.highlightSpans.push({ - textSpan: referenceEntry.textSpan, - kind: referenceEntry.isWriteAccess ? ts.HighlightSpanKind.writtenReference : ts.HighlightSpanKind.reference - }); - } + else { + indentation = parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta(node); } - return result; } + return { + indentation: indentation, + delta: delta + }; } - function getSyntacticDocumentHighlights(node) { - var fileName = sourceFile.fileName; - var highlightSpans = getHighlightSpans(node); - if (!highlightSpans || highlightSpans.length === 0) { - return undefined; - } - return [{ fileName: fileName, highlightSpans: highlightSpans }]; - // returns true if 'node' is defined and has a matching 'kind'. - function hasKind(node, kind) { - return node !== undefined && node.kind === kind; + function getFirstNonDecoratorTokenOfNode(node) { + if (node.modifiers && node.modifiers.length) { + return node.modifiers[0].kind; } - // Null-propagating 'parent' function. - function parent(node) { - return node && node.parent; + switch (node.kind) { + case 221 /* ClassDeclaration */: return 73 /* ClassKeyword */; + case 222 /* InterfaceDeclaration */: return 107 /* InterfaceKeyword */; + case 220 /* FunctionDeclaration */: return 87 /* FunctionKeyword */; + case 224 /* EnumDeclaration */: return 224 /* EnumDeclaration */; + case 149 /* GetAccessor */: return 123 /* GetKeyword */; + case 150 /* SetAccessor */: return 131 /* SetKeyword */; + case 147 /* MethodDeclaration */: + if (node.asteriskToken) { + return 37 /* AsteriskToken */; + } /* + fall-through + */ + case 145 /* PropertyDeclaration */: + case 142 /* Parameter */: + return node.name.kind; } - function getHighlightSpans(node) { - if (node) { - switch (node.kind) { - case 88 /* IfKeyword */: + } + function getDynamicIndentation(node, nodeStartLine, indentation, delta) { + return { + getIndentationForComment: function (kind, tokenIndentation, container) { + switch (kind) { + // preceding comment to the token that closes the indentation scope inherits the indentation from the scope + // .. { + // // comment + // } + case 16 /* CloseBraceToken */: + case 20 /* CloseBracketToken */: + case 18 /* CloseParenToken */: + return indentation + getEffectiveDelta(delta, container); + } + return tokenIndentation !== -1 /* Unknown */ ? tokenIndentation : indentation; + }, + getIndentationForToken: function (line, kind, container) { + if (nodeStartLine !== line && node.decorators) { + if (kind === getFirstNonDecoratorTokenOfNode(node)) { + // if this token is the first token following the list of decorators, we do not need to indent + return indentation; + } + } + switch (kind) { + // open and close brace, 'else' and 'while' (in do statement) tokens has indentation of the parent + case 15 /* OpenBraceToken */: + case 16 /* CloseBraceToken */: + case 19 /* OpenBracketToken */: + case 20 /* CloseBracketToken */: + case 17 /* OpenParenToken */: + case 18 /* CloseParenToken */: case 80 /* ElseKeyword */: - if (hasKind(node.parent, 203 /* IfStatement */)) { - return getIfElseOccurrences(node.parent); - } - break; - case 94 /* ReturnKeyword */: - if (hasKind(node.parent, 211 /* ReturnStatement */)) { - return getReturnOccurrences(node.parent); - } - break; - case 98 /* ThrowKeyword */: - if (hasKind(node.parent, 215 /* ThrowStatement */)) { - return getThrowOccurrences(node.parent); - } - break; - case 72 /* CatchKeyword */: - if (hasKind(parent(parent(node)), 216 /* TryStatement */)) { - return getTryCatchFinallyOccurrences(node.parent.parent); - } - break; - case 100 /* TryKeyword */: - case 85 /* FinallyKeyword */: - if (hasKind(parent(node), 216 /* TryStatement */)) { - return getTryCatchFinallyOccurrences(node.parent); - } - break; - case 96 /* SwitchKeyword */: - if (hasKind(node.parent, 213 /* SwitchStatement */)) { - return getSwitchCaseDefaultOccurrences(node.parent); - } - break; - case 71 /* CaseKeyword */: - case 77 /* DefaultKeyword */: - if (hasKind(parent(parent(parent(node))), 213 /* SwitchStatement */)) { - return getSwitchCaseDefaultOccurrences(node.parent.parent.parent); - } - break; - case 70 /* BreakKeyword */: - case 75 /* ContinueKeyword */: - if (hasKind(node.parent, 210 /* BreakStatement */) || hasKind(node.parent, 209 /* ContinueStatement */)) { - return getBreakOrContinueStatementOccurrences(node.parent); - } - break; - case 86 /* ForKeyword */: - if (hasKind(node.parent, 206 /* ForStatement */) || - hasKind(node.parent, 207 /* ForInStatement */) || - hasKind(node.parent, 208 /* ForOfStatement */)) { - return getLoopBreakContinueOccurrences(node.parent); - } - break; case 104 /* WhileKeyword */: - case 79 /* DoKeyword */: - if (hasKind(node.parent, 205 /* WhileStatement */) || hasKind(node.parent, 204 /* DoStatement */)) { - return getLoopBreakContinueOccurrences(node.parent); - } - break; - case 121 /* ConstructorKeyword */: - if (hasKind(node.parent, 148 /* Constructor */)) { - return getConstructorOccurrences(node.parent); - } - break; - case 123 /* GetKeyword */: - case 131 /* SetKeyword */: - if (hasKind(node.parent, 149 /* GetAccessor */) || hasKind(node.parent, 150 /* SetAccessor */)) { - return getGetAndSetOccurrences(node.parent); - } - break; + case 55 /* AtToken */: + return indentation; default: - if (ts.isModifierKind(node.kind) && node.parent && - (ts.isDeclaration(node.parent) || node.parent.kind === 200 /* VariableStatement */)) { - return getModifierOccurrences(node.kind, node.parent); - } - } - } - return undefined; - } - /** - * Aggregates all throw-statements within this node *without* crossing - * into function boundaries and try-blocks with catch-clauses. - */ - function aggregateOwnedThrowStatements(node) { - var statementAccumulator = []; - aggregate(node); - return statementAccumulator; - function aggregate(node) { - if (node.kind === 215 /* ThrowStatement */) { - statementAccumulator.push(node); + // if token line equals to the line of containing node (this is a first token in the node) - use node indentation + return nodeStartLine !== line ? indentation + getEffectiveDelta(delta, container) : indentation; } - else if (node.kind === 216 /* TryStatement */) { - var tryStatement = node; - if (tryStatement.catchClause) { - aggregate(tryStatement.catchClause); + }, + getIndentation: function () { return indentation; }, + getDelta: function (child) { return getEffectiveDelta(delta, child); }, + recomputeIndentation: function (lineAdded) { + if (node.parent && formatting.SmartIndenter.shouldIndentChildNode(node.parent, node)) { + if (lineAdded) { + indentation += options.indentSize; } else { - // Exceptions thrown within a try block lacking a catch clause - // are "owned" in the current context. - aggregate(tryStatement.tryBlock); + indentation -= options.indentSize; } - if (tryStatement.finallyBlock) { - aggregate(tryStatement.finallyBlock); + if (formatting.SmartIndenter.shouldIndentChildNode(node)) { + delta = options.indentSize; } - } - else if (!ts.isFunctionLike(node)) { - ts.forEachChild(node, aggregate); - } - } - } - /** - * For lack of a better name, this function takes a throw statement and returns the - * nearest ancestor that is a try-block (whose try statement has a catch clause), - * function-block, or source file. - */ - function getThrowStatementOwner(throwStatement) { - var child = throwStatement; - while (child.parent) { - var parent_21 = child.parent; - if (ts.isFunctionBlock(parent_21) || parent_21.kind === 256 /* SourceFile */) { - return parent_21; - } - // A throw-statement is only owned by a try-statement if the try-statement has - // a catch clause, and if the throw-statement occurs within the try block. - if (parent_21.kind === 216 /* TryStatement */) { - var tryStatement = parent_21; - if (tryStatement.tryBlock === child && tryStatement.catchClause) { - return child; + else { + delta = 0; } } - child = parent_21; } - return undefined; + }; + function getEffectiveDelta(delta, child) { + // Delta value should be zero when the node explicitly prevents indentation of the child node + return formatting.SmartIndenter.nodeWillIndentChild(node, child, true) ? delta : 0; } - function aggregateAllBreakAndContinueStatements(node) { - var statementAccumulator = []; - aggregate(node); - return statementAccumulator; - function aggregate(node) { - if (node.kind === 210 /* BreakStatement */ || node.kind === 209 /* ContinueStatement */) { - statementAccumulator.push(node); - } - else if (!ts.isFunctionLike(node)) { - ts.forEachChild(node, aggregate); - } - } + } + function processNode(node, contextNode, nodeStartLine, undecoratedNodeStartLine, indentation, delta) { + if (!ts.rangeOverlapsWithStartEnd(originalRange, node.getStart(sourceFile), node.getEnd())) { + return; } - function ownsBreakOrContinueStatement(owner, statement) { - var actualOwner = getBreakOrContinueOwner(statement); - return actualOwner && actualOwner === owner; + var nodeDynamicIndentation = getDynamicIndentation(node, nodeStartLine, indentation, delta); + // a useful observations when tracking context node + // / + // [a] + // / | \ + // [b] [c] [d] + // node 'a' is a context node for nodes 'b', 'c', 'd' + // except for the leftmost leaf token in [b] - in this case context node ('e') is located somewhere above 'a' + // this rule can be applied recursively to child nodes of 'a'. + // + // context node is set to parent node value after processing every child node + // context node is set to parent of the token after processing every token + var childContextNode = contextNode; + // if there are any tokens that logically belong to node and interleave child nodes + // such tokens will be consumed in processChildNode for for the child that follows them + ts.forEachChild(node, function (child) { + processChildNode(child, /*inheritedIndentation*/ -1 /* Unknown */, node, nodeDynamicIndentation, nodeStartLine, undecoratedNodeStartLine, /*isListItem*/ false); + }, function (nodes) { + processChildNodes(nodes, node, nodeStartLine, nodeDynamicIndentation); + }); + // proceed any tokens in the node that are located after child nodes + while (formattingScanner.isOnToken()) { + var tokenInfo = formattingScanner.readTokenInfo(node); + if (tokenInfo.token.end > node.end) { + break; + } + consumeTokenAndAdvanceScanner(tokenInfo, node, nodeDynamicIndentation); } - function getBreakOrContinueOwner(statement) { - for (var node_1 = statement.parent; node_1; node_1 = node_1.parent) { - switch (node_1.kind) { - case 213 /* SwitchStatement */: - if (statement.kind === 209 /* ContinueStatement */) { - continue; - } - // Fall through. - case 206 /* ForStatement */: - case 207 /* ForInStatement */: - case 208 /* ForOfStatement */: - case 205 /* WhileStatement */: - case 204 /* DoStatement */: - if (!statement.label || isLabeledBy(node_1, statement.label.text)) { - return node_1; - } - break; - default: - // Don't cross function boundaries. - if (ts.isFunctionLike(node_1)) { - return undefined; - } - break; + function processChildNode(child, inheritedIndentation, parent, parentDynamicIndentation, parentStartLine, undecoratedParentStartLine, isListItem, isFirstListItem) { + var childStartPos = child.getStart(sourceFile); + var childStartLine = sourceFile.getLineAndCharacterOfPosition(childStartPos).line; + var undecoratedChildStartLine = childStartLine; + if (child.decorators) { + undecoratedChildStartLine = sourceFile.getLineAndCharacterOfPosition(ts.getNonDecoratorTokenPosOfNode(child, sourceFile)).line; + } + // if child is a list item - try to get its indentation + var childIndentationAmount = -1 /* Unknown */; + if (isListItem) { + childIndentationAmount = tryComputeIndentationForListItem(childStartPos, child.end, parentStartLine, originalRange, inheritedIndentation); + if (childIndentationAmount !== -1 /* Unknown */) { + inheritedIndentation = childIndentationAmount; } } - return undefined; - } - function getModifierOccurrences(modifier, declaration) { - var container = declaration.parent; - // Make sure we only highlight the keyword when it makes sense to do so. - if (ts.isAccessibilityModifier(modifier)) { - if (!(container.kind === 221 /* ClassDeclaration */ || - container.kind === 192 /* ClassExpression */ || - (declaration.kind === 142 /* Parameter */ && hasKind(container, 148 /* Constructor */)))) { - return undefined; + // child node is outside the target range - do not dive inside + if (!ts.rangeOverlapsWithStartEnd(originalRange, child.pos, child.end)) { + if (child.end < originalRange.pos) { + formattingScanner.skipToEndOf(child); } + return inheritedIndentation; } - else if (modifier === 113 /* StaticKeyword */) { - if (!(container.kind === 221 /* ClassDeclaration */ || container.kind === 192 /* ClassExpression */)) { - return undefined; + if (child.getFullWidth() === 0) { + return inheritedIndentation; + } + while (formattingScanner.isOnToken()) { + // proceed any parent tokens that are located prior to child.getStart() + var tokenInfo = formattingScanner.readTokenInfo(node); + if (tokenInfo.token.end > childStartPos) { + // stop when formatting scanner advances past the beginning of the child + break; } + consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation); } - else if (modifier === 82 /* ExportKeyword */ || modifier === 122 /* DeclareKeyword */) { - if (!(container.kind === 226 /* ModuleBlock */ || container.kind === 256 /* SourceFile */)) { - return undefined; + if (!formattingScanner.isOnToken()) { + return inheritedIndentation; + } + if (ts.isToken(child)) { + // if child node is a token, it does not impact indentation, proceed it using parent indentation scope rules + var tokenInfo = formattingScanner.readTokenInfo(child); + ts.Debug.assert(tokenInfo.token.end === child.end); + consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation, child); + return inheritedIndentation; + } + var effectiveParentStartLine = child.kind === 143 /* Decorator */ ? childStartLine : undecoratedParentStartLine; + var childIndentation = computeIndentation(child, childStartLine, childIndentationAmount, node, parentDynamicIndentation, effectiveParentStartLine); + processNode(child, childContextNode, childStartLine, undecoratedChildStartLine, childIndentation.indentation, childIndentation.delta); + childContextNode = node; + if (isFirstListItem && parent.kind === 170 /* ArrayLiteralExpression */ && inheritedIndentation === -1 /* Unknown */) { + inheritedIndentation = childIndentation.indentation; + } + return inheritedIndentation; + } + function processChildNodes(nodes, parent, parentStartLine, parentDynamicIndentation) { + var listStartToken = getOpenTokenForList(parent, nodes); + var listEndToken = getCloseTokenForOpenToken(listStartToken); + var listDynamicIndentation = parentDynamicIndentation; + var startLine = parentStartLine; + if (listStartToken !== 0 /* Unknown */) { + // introduce a new indentation scope for lists (including list start and end tokens) + while (formattingScanner.isOnToken()) { + var tokenInfo = formattingScanner.readTokenInfo(parent); + if (tokenInfo.token.end > nodes.pos) { + // stop when formatting scanner moves past the beginning of node list + break; + } + else if (tokenInfo.token.kind === listStartToken) { + // consume list start token + startLine = sourceFile.getLineAndCharacterOfPosition(tokenInfo.token.pos).line; + var indentation_1 = computeIndentation(tokenInfo.token, startLine, -1 /* Unknown */, parent, parentDynamicIndentation, parentStartLine); + listDynamicIndentation = getDynamicIndentation(parent, parentStartLine, indentation_1.indentation, indentation_1.delta); + consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation); + } + else { + // consume any tokens that precede the list as child elements of 'node' using its indentation scope + consumeTokenAndAdvanceScanner(tokenInfo, parent, parentDynamicIndentation); + } } } - else if (modifier === 115 /* AbstractKeyword */) { - if (!(container.kind === 221 /* ClassDeclaration */ || declaration.kind === 221 /* ClassDeclaration */)) { - return undefined; + var inheritedIndentation = -1 /* Unknown */; + for (var i = 0; i < nodes.length; i++) { + var child = nodes[i]; + inheritedIndentation = processChildNode(child, inheritedIndentation, node, listDynamicIndentation, startLine, startLine, /*isListItem*/ true, /*isFirstListItem*/ i === 0); + } + if (listEndToken !== 0 /* Unknown */) { + if (formattingScanner.isOnToken()) { + var tokenInfo = formattingScanner.readTokenInfo(parent); + // consume the list end token only if it is still belong to the parent + // there might be the case when current token matches end token but does not considered as one + // function (x: function) <-- + // without this check close paren will be interpreted as list end token for function expression which is wrong + if (tokenInfo.token.kind === listEndToken && ts.rangeContainsRange(parent, tokenInfo.token)) { + // consume list end token + consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation); + } } } - else { - // unsupported modifier - return undefined; + } + function consumeTokenAndAdvanceScanner(currentTokenInfo, parent, dynamicIndentation, container) { + ts.Debug.assert(ts.rangeContainsRange(parent, currentTokenInfo.token)); + var lastTriviaWasNewLine = formattingScanner.lastTrailingTriviaWasNewLine(); + var indentToken = false; + if (currentTokenInfo.leadingTrivia) { + processTrivia(currentTokenInfo.leadingTrivia, parent, childContextNode, dynamicIndentation); } - var keywords = []; - var modifierFlag = getFlagFromModifier(modifier); - var nodes; - switch (container.kind) { - case 226 /* ModuleBlock */: - case 256 /* SourceFile */: - // Container is either a class declaration or the declaration is a classDeclaration - if (modifierFlag & 128 /* Abstract */) { - nodes = declaration.members.concat(declaration); + var lineAdded; + var isTokenInRange = ts.rangeContainsRange(originalRange, currentTokenInfo.token); + var tokenStart = sourceFile.getLineAndCharacterOfPosition(currentTokenInfo.token.pos); + if (isTokenInRange) { + var rangeHasError = rangeContainsError(currentTokenInfo.token); + // save previousRange since processRange will overwrite this value with current one + var savePreviousRange = previousRange; + lineAdded = processRange(currentTokenInfo.token, tokenStart, parent, childContextNode, dynamicIndentation); + if (rangeHasError) { + // do not indent comments\token if token range overlaps with some error + indentToken = false; + } + else { + if (lineAdded !== undefined) { + indentToken = lineAdded; } else { - nodes = container.statements; + // indent token only if end line of previous range does not match start line of the token + var prevEndLine = savePreviousRange && sourceFile.getLineAndCharacterOfPosition(savePreviousRange.end).line; + indentToken = lastTriviaWasNewLine && tokenStart.line !== prevEndLine; } - break; - case 148 /* Constructor */: - nodes = container.parameters.concat(container.parent.members); - break; - case 221 /* ClassDeclaration */: - case 192 /* ClassExpression */: - nodes = container.members; - // If we're an accessibility modifier, we're in an instance member and should search - // the constructor's parameter list for instance members as well. - if (modifierFlag & 28 /* AccessibilityModifier */) { - var constructor = ts.forEach(container.members, function (member) { - return member.kind === 148 /* Constructor */ && member; - }); - if (constructor) { - nodes = nodes.concat(constructor.parameters); + } + } + if (currentTokenInfo.trailingTrivia) { + processTrivia(currentTokenInfo.trailingTrivia, parent, childContextNode, dynamicIndentation); + } + if (indentToken) { + var tokenIndentation = (isTokenInRange && !rangeContainsError(currentTokenInfo.token)) ? + dynamicIndentation.getIndentationForToken(tokenStart.line, currentTokenInfo.token.kind, container) : + -1 /* Unknown */; + var indentNextTokenOrTrivia = true; + if (currentTokenInfo.leadingTrivia) { + var commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind, tokenIndentation, container); + for (var _i = 0, _a = currentTokenInfo.leadingTrivia; _i < _a.length; _i++) { + var triviaItem = _a[_i]; + var triviaInRange = ts.rangeContainsRange(originalRange, triviaItem); + switch (triviaItem.kind) { + case 3 /* MultiLineCommentTrivia */: + if (triviaInRange) { + indentMultilineComment(triviaItem, commentIndentation, /*firstLineIsIndented*/ !indentNextTokenOrTrivia); + } + indentNextTokenOrTrivia = false; + break; + case 2 /* SingleLineCommentTrivia */: + if (indentNextTokenOrTrivia && triviaInRange) { + insertIndentation(triviaItem.pos, commentIndentation, /*lineAdded*/ false); + } + indentNextTokenOrTrivia = false; + break; + case 4 /* NewLineTrivia */: + indentNextTokenOrTrivia = true; + break; } } - else if (modifierFlag & 128 /* Abstract */) { - nodes = nodes.concat(container); - } - break; - default: - ts.Debug.fail("Invalid container kind."); - } - ts.forEach(nodes, function (node) { - if (node.modifiers && node.flags & modifierFlag) { - ts.forEach(node.modifiers, function (child) { return pushKeywordIf(keywords, child, modifier); }); } - }); - return ts.map(keywords, getHighlightSpanForNode); - function getFlagFromModifier(modifier) { - switch (modifier) { - case 112 /* PublicKeyword */: - return 4 /* Public */; - case 110 /* PrivateKeyword */: - return 8 /* Private */; - case 111 /* ProtectedKeyword */: - return 16 /* Protected */; - case 113 /* StaticKeyword */: - return 32 /* Static */; - case 82 /* ExportKeyword */: - return 1 /* Export */; - case 122 /* DeclareKeyword */: - return 2 /* Ambient */; - case 115 /* AbstractKeyword */: - return 128 /* Abstract */; - default: - ts.Debug.fail(); + // indent token only if is it is in target range and does not overlap with any error ranges + if (tokenIndentation !== -1 /* Unknown */ && indentNextTokenOrTrivia) { + insertIndentation(currentTokenInfo.token.pos, tokenIndentation, lineAdded); + lastIndentedLine = tokenStart.line; + indentationOnLastIndentedLine = tokenIndentation; } } + formattingScanner.advance(); + childContextNode = parent; } - function pushKeywordIf(keywordList, token) { - var expected = []; - for (var _i = 2; _i < arguments.length; _i++) { - expected[_i - 2] = arguments[_i]; + } + function processTrivia(trivia, parent, contextNode, dynamicIndentation) { + for (var _i = 0, trivia_1 = trivia; _i < trivia_1.length; _i++) { + var triviaItem = trivia_1[_i]; + if (ts.isComment(triviaItem.kind) && ts.rangeContainsRange(originalRange, triviaItem)) { + var triviaItemStart = sourceFile.getLineAndCharacterOfPosition(triviaItem.pos); + processRange(triviaItem, triviaItemStart, parent, contextNode, dynamicIndentation); } - if (token && ts.contains(expected, token.kind)) { - keywordList.push(token); - return true; + } + } + function processRange(range, rangeStart, parent, contextNode, dynamicIndentation) { + var rangeHasError = rangeContainsError(range); + var lineAdded; + if (!rangeHasError && !previousRangeHasError) { + if (!previousRange) { + // trim whitespaces starting from the beginning of the span up to the current line + var originalStart = sourceFile.getLineAndCharacterOfPosition(originalRange.pos); + trimTrailingWhitespacesForLines(originalStart.line, rangeStart.line); + } + else { + lineAdded = + processPair(range, rangeStart.line, parent, previousRange, previousRangeStartLine, previousParent, contextNode, dynamicIndentation); } - return false; } - function getGetAndSetOccurrences(accessorDeclaration) { - var keywords = []; - tryPushAccessorKeyword(accessorDeclaration.symbol, 149 /* GetAccessor */); - tryPushAccessorKeyword(accessorDeclaration.symbol, 150 /* SetAccessor */); - return ts.map(keywords, getHighlightSpanForNode); - function tryPushAccessorKeyword(accessorSymbol, accessorKind) { - var accessor = ts.getDeclarationOfKind(accessorSymbol, accessorKind); - if (accessor) { - ts.forEach(accessor.getChildren(), function (child) { return pushKeywordIf(keywords, child, 123 /* GetKeyword */, 131 /* SetKeyword */); }); + previousRange = range; + previousParent = parent; + previousRangeStartLine = rangeStart.line; + previousRangeHasError = rangeHasError; + return lineAdded; + } + function processPair(currentItem, currentStartLine, currentParent, previousItem, previousStartLine, previousParent, contextNode, dynamicIndentation) { + formattingContext.updateContext(previousItem, previousParent, currentItem, currentParent, contextNode); + var rule = rulesProvider.getRulesMap().GetRule(formattingContext); + var trimTrailingWhitespaces; + var lineAdded; + if (rule) { + applyRuleEdits(rule, previousItem, previousStartLine, currentItem, currentStartLine); + if (rule.Operation.Action & (2 /* Space */ | 8 /* Delete */) && currentStartLine !== previousStartLine) { + lineAdded = false; + // Handle the case where the next line is moved to be the end of this line. + // In this case we don't indent the next line in the next pass. + if (currentParent.getStart(sourceFile) === currentItem.pos) { + dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ false); + } + } + else if (rule.Operation.Action & 4 /* NewLine */ && currentStartLine === previousStartLine) { + lineAdded = true; + // Handle the case where token2 is moved to the new line. + // In this case we indent token2 in the next pass but we set + // sameLineIndent flag to notify the indenter that the indentation is within the line. + if (currentParent.getStart(sourceFile) === currentItem.pos) { + dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ true); } } + // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line + trimTrailingWhitespaces = !(rule.Operation.Action & 8 /* Delete */) && rule.Flag !== 1 /* CanDeleteNewLines */; } - function getConstructorOccurrences(constructorDeclaration) { - var declarations = constructorDeclaration.symbol.getDeclarations(); - var keywords = []; - ts.forEach(declarations, function (declaration) { - ts.forEach(declaration.getChildren(), function (token) { - return pushKeywordIf(keywords, token, 121 /* ConstructorKeyword */); - }); - }); - return ts.map(keywords, getHighlightSpanForNode); + else { + trimTrailingWhitespaces = true; } - function getLoopBreakContinueOccurrences(loopNode) { - var keywords = []; - if (pushKeywordIf(keywords, loopNode.getFirstToken(), 86 /* ForKeyword */, 104 /* WhileKeyword */, 79 /* DoKeyword */)) { - // If we succeeded and got a do-while loop, then start looking for a 'while' keyword. - if (loopNode.kind === 204 /* DoStatement */) { - var loopTokens = loopNode.getChildren(); - for (var i = loopTokens.length - 1; i >= 0; i--) { - if (pushKeywordIf(keywords, loopTokens[i], 104 /* WhileKeyword */)) { - break; - } - } - } + if (currentStartLine !== previousStartLine && trimTrailingWhitespaces) { + // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line + trimTrailingWhitespacesForLines(previousStartLine, currentStartLine, previousItem); + } + return lineAdded; + } + function insertIndentation(pos, indentation, lineAdded) { + var indentationString = getIndentationString(indentation, options); + if (lineAdded) { + // new line is added before the token by the formatting rules + // insert indentation string at the very beginning of the token + recordReplace(pos, 0, indentationString); + } + else { + var tokenStart = sourceFile.getLineAndCharacterOfPosition(pos); + var startLinePosition = ts.getStartPositionOfLine(tokenStart.line, sourceFile); + if (indentation !== tokenStart.character || indentationIsDifferent(indentationString, startLinePosition)) { + recordReplace(startLinePosition, tokenStart.character, indentationString); } - var breaksAndContinues = aggregateAllBreakAndContinueStatements(loopNode.statement); - ts.forEach(breaksAndContinues, function (statement) { - if (ownsBreakOrContinueStatement(loopNode, statement)) { - pushKeywordIf(keywords, statement.getFirstToken(), 70 /* BreakKeyword */, 75 /* ContinueKeyword */); - } - }); - return ts.map(keywords, getHighlightSpanForNode); } - function getBreakOrContinueStatementOccurrences(breakOrContinueStatement) { - var owner = getBreakOrContinueOwner(breakOrContinueStatement); - if (owner) { - switch (owner.kind) { - case 206 /* ForStatement */: - case 207 /* ForInStatement */: - case 208 /* ForOfStatement */: - case 204 /* DoStatement */: - case 205 /* WhileStatement */: - return getLoopBreakContinueOccurrences(owner); - case 213 /* SwitchStatement */: - return getSwitchCaseDefaultOccurrences(owner); - } + } + function indentationIsDifferent(indentationString, startLinePosition) { + return indentationString !== sourceFile.text.substr(startLinePosition, indentationString.length); + } + function indentMultilineComment(commentRange, indentation, firstLineIsIndented) { + // split comment in lines + var startLine = sourceFile.getLineAndCharacterOfPosition(commentRange.pos).line; + var endLine = sourceFile.getLineAndCharacterOfPosition(commentRange.end).line; + var parts; + if (startLine === endLine) { + if (!firstLineIsIndented) { + // treat as single line comment + insertIndentation(commentRange.pos, indentation, /*lineAdded*/ false); } - return undefined; + return; } - function getSwitchCaseDefaultOccurrences(switchStatement) { - var keywords = []; - pushKeywordIf(keywords, switchStatement.getFirstToken(), 96 /* SwitchKeyword */); - // Go through each clause in the switch statement, collecting the 'case'/'default' keywords. - ts.forEach(switchStatement.caseBlock.clauses, function (clause) { - pushKeywordIf(keywords, clause.getFirstToken(), 71 /* CaseKeyword */, 77 /* DefaultKeyword */); - var breaksAndContinues = aggregateAllBreakAndContinueStatements(clause); - ts.forEach(breaksAndContinues, function (statement) { - if (ownsBreakOrContinueStatement(switchStatement, statement)) { - pushKeywordIf(keywords, statement.getFirstToken(), 70 /* BreakKeyword */); - } - }); - }); - return ts.map(keywords, getHighlightSpanForNode); + else { + parts = []; + var startPos = commentRange.pos; + for (var line = startLine; line < endLine; line++) { + var endOfLine = ts.getEndLinePosition(line, sourceFile); + parts.push({ pos: startPos, end: endOfLine }); + startPos = ts.getStartPositionOfLine(line + 1, sourceFile); + } + parts.push({ pos: startPos, end: commentRange.end }); } - function getTryCatchFinallyOccurrences(tryStatement) { - var keywords = []; - pushKeywordIf(keywords, tryStatement.getFirstToken(), 100 /* TryKeyword */); - if (tryStatement.catchClause) { - pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken(), 72 /* CatchKeyword */); + var startLinePos = ts.getStartPositionOfLine(startLine, sourceFile); + var nonWhitespaceColumnInFirstPart = formatting.SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(startLinePos, parts[0].pos, sourceFile, options); + if (indentation === nonWhitespaceColumnInFirstPart.column) { + return; + } + var startIndex = 0; + if (firstLineIsIndented) { + startIndex = 1; + startLine++; + } + // shift all parts on the delta size + var delta = indentation - nonWhitespaceColumnInFirstPart.column; + for (var i = startIndex, len = parts.length; i < len; i++, startLine++) { + var startLinePos_1 = ts.getStartPositionOfLine(startLine, sourceFile); + var nonWhitespaceCharacterAndColumn = i === 0 + ? nonWhitespaceColumnInFirstPart + : formatting.SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(parts[i].pos, parts[i].end, sourceFile, options); + var newIndentation = nonWhitespaceCharacterAndColumn.column + delta; + if (newIndentation > 0) { + var indentationString = getIndentationString(newIndentation, options); + recordReplace(startLinePos_1, nonWhitespaceCharacterAndColumn.character, indentationString); } - if (tryStatement.finallyBlock) { - var finallyKeyword = ts.findChildOfKind(tryStatement, 85 /* FinallyKeyword */, sourceFile); - pushKeywordIf(keywords, finallyKeyword, 85 /* FinallyKeyword */); + else { + recordDelete(startLinePos_1, nonWhitespaceCharacterAndColumn.character); } - return ts.map(keywords, getHighlightSpanForNode); } - function getThrowOccurrences(throwStatement) { - var owner = getThrowStatementOwner(throwStatement); - if (!owner) { - return undefined; + } + function trimTrailingWhitespacesForLines(line1, line2, range) { + for (var line = line1; line < line2; line++) { + var lineStartPosition = ts.getStartPositionOfLine(line, sourceFile); + var lineEndPosition = ts.getEndLinePosition(line, sourceFile); + // do not trim whitespaces in comments or template expression + if (range && (ts.isComment(range.kind) || ts.isStringOrRegularExpressionOrTemplateLiteral(range.kind)) && range.pos <= lineEndPosition && range.end > lineEndPosition) { + continue; } - var keywords = []; - ts.forEach(aggregateOwnedThrowStatements(owner), function (throwStatement) { - pushKeywordIf(keywords, throwStatement.getFirstToken(), 98 /* ThrowKeyword */); - }); - // If the "owner" is a function, then we equate 'return' and 'throw' statements in their - // ability to "jump out" of the function, and include occurrences for both. - if (ts.isFunctionBlock(owner)) { - ts.forEachReturnStatement(owner, function (returnStatement) { - pushKeywordIf(keywords, returnStatement.getFirstToken(), 94 /* ReturnKeyword */); - }); + var whitespaceStart = getTrailingWhitespaceStartPosition(lineStartPosition, lineEndPosition); + if (whitespaceStart !== -1) { + ts.Debug.assert(whitespaceStart === lineStartPosition || !ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(whitespaceStart - 1))); + recordDelete(whitespaceStart, lineEndPosition + 1 - whitespaceStart); } - return ts.map(keywords, getHighlightSpanForNode); } - function getReturnOccurrences(returnStatement) { - var func = ts.getContainingFunction(returnStatement); - // If we didn't find a containing function with a block body, bail out. - if (!(func && hasKind(func.body, 199 /* Block */))) { - return undefined; - } - var keywords = []; - ts.forEachReturnStatement(func.body, function (returnStatement) { - pushKeywordIf(keywords, returnStatement.getFirstToken(), 94 /* ReturnKeyword */); - }); - // Include 'throw' statements that do not occur within a try block. - ts.forEach(aggregateOwnedThrowStatements(func.body), function (throwStatement) { - pushKeywordIf(keywords, throwStatement.getFirstToken(), 98 /* ThrowKeyword */); - }); - return ts.map(keywords, getHighlightSpanForNode); + } + /** + * @param start The position of the first character in range + * @param end The position of the last character in range + */ + function getTrailingWhitespaceStartPosition(start, end) { + var pos = end; + while (pos >= start && ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(pos))) { + pos--; } - function getIfElseOccurrences(ifStatement) { - var keywords = []; - // Traverse upwards through all parent if-statements linked by their else-branches. - while (hasKind(ifStatement.parent, 203 /* IfStatement */) && ifStatement.parent.elseStatement === ifStatement) { - ifStatement = ifStatement.parent; - } - // Now traverse back down through the else branches, aggregating if/else keywords of if-statements. - while (ifStatement) { - var children = ifStatement.getChildren(); - pushKeywordIf(keywords, children[0], 88 /* IfKeyword */); - // Generally the 'else' keyword is second-to-last, so we traverse backwards. - for (var i = children.length - 1; i >= 0; i--) { - if (pushKeywordIf(keywords, children[i], 80 /* ElseKeyword */)) { - break; - } + if (pos !== end) { + return pos + 1; + } + return -1; + } + /** + * Trimming will be done for lines after the previous range + */ + function trimTrailingWhitespacesForRemainingRange() { + var startPosition = previousRange ? previousRange.end : originalRange.pos; + var startLine = sourceFile.getLineAndCharacterOfPosition(startPosition).line; + var endLine = sourceFile.getLineAndCharacterOfPosition(originalRange.end).line; + trimTrailingWhitespacesForLines(startLine, endLine + 1, previousRange); + } + function newTextChange(start, len, newText) { + return { span: ts.createTextSpan(start, len), newText: newText }; + } + function recordDelete(start, len) { + if (len) { + edits.push(newTextChange(start, len, "")); + } + } + function recordReplace(start, len, newText) { + if (len || newText) { + edits.push(newTextChange(start, len, newText)); + } + } + function applyRuleEdits(rule, previousRange, previousStartLine, currentRange, currentStartLine) { + switch (rule.Operation.Action) { + case 1 /* Ignore */: + // no action required + return; + case 8 /* Delete */: + if (previousRange.end !== currentRange.pos) { + // delete characters starting from t1.end up to t2.pos exclusive + recordDelete(previousRange.end, currentRange.pos - previousRange.end); } - if (!hasKind(ifStatement.elseStatement, 203 /* IfStatement */)) { - break; + break; + case 4 /* NewLine */: + // exit early if we on different lines and rule cannot change number of newlines + // if line1 and line2 are on subsequent lines then no edits are required - ok to exit + // if line1 and line2 are separated with more than one newline - ok to exit since we cannot delete extra new lines + if (rule.Flag !== 1 /* CanDeleteNewLines */ && previousStartLine !== currentStartLine) { + return; } - ifStatement = ifStatement.elseStatement; + // edit should not be applied only if we have one line feed between elements + var lineDelta = currentStartLine - previousStartLine; + if (lineDelta !== 1) { + recordReplace(previousRange.end, currentRange.pos - previousRange.end, options.newLineCharacter); + } + break; + case 2 /* Space */: + // exit early if we on different lines and rule cannot change number of newlines + if (rule.Flag !== 1 /* CanDeleteNewLines */ && previousStartLine !== currentStartLine) { + return; + } + var posDelta = currentRange.pos - previousRange.end; + if (posDelta !== 1 || sourceFile.text.charCodeAt(previousRange.end) !== 32 /* space */) { + recordReplace(previousRange.end, currentRange.pos - previousRange.end, " "); + } + break; + } + } + } + function getOpenTokenForList(node, list) { + switch (node.kind) { + case 148 /* Constructor */: + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + case 180 /* ArrowFunction */: + if (node.typeParameters === list) { + return 25 /* LessThanToken */; } - var result = []; - // We'd like to highlight else/ifs together if they are only separated by whitespace - // (i.e. the keywords are separated by no comments, no newlines). - for (var i = 0; i < keywords.length; i++) { - if (keywords[i].kind === 80 /* ElseKeyword */ && i < keywords.length - 1) { - var elseKeyword = keywords[i]; - var ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword. - var shouldCombindElseAndIf = true; - // Avoid recalculating getStart() by iterating backwards. - for (var j = ifKeyword.getStart() - 1; j >= elseKeyword.end; j--) { - if (!ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(j))) { - shouldCombindElseAndIf = false; - break; - } - } - if (shouldCombindElseAndIf) { - result.push({ - fileName: fileName, - textSpan: ts.createTextSpanFromBounds(elseKeyword.getStart(), ifKeyword.end), - kind: ts.HighlightSpanKind.reference - }); - i++; // skip the next keyword - continue; - } + else if (node.parameters === list) { + return 17 /* OpenParenToken */; + } + break; + case 174 /* CallExpression */: + case 175 /* NewExpression */: + if (node.typeArguments === list) { + return 25 /* LessThanToken */; + } + else if (node.arguments === list) { + return 17 /* OpenParenToken */; + } + break; + case 155 /* TypeReference */: + if (node.typeArguments === list) { + return 25 /* LessThanToken */; + } + } + return 0 /* Unknown */; + } + function getCloseTokenForOpenToken(kind) { + switch (kind) { + case 17 /* OpenParenToken */: + return 18 /* CloseParenToken */; + case 25 /* LessThanToken */: + return 27 /* GreaterThanToken */; + } + return 0 /* Unknown */; + } + var internedSizes; + var internedTabsIndentation; + var internedSpacesIndentation; + function getIndentationString(indentation, options) { + // reset interned strings if FormatCodeOptions were changed + var resetInternedStrings = !internedSizes || (internedSizes.tabSize !== options.tabSize || internedSizes.indentSize !== options.indentSize); + if (resetInternedStrings) { + internedSizes = { tabSize: options.tabSize, indentSize: options.indentSize }; + internedTabsIndentation = internedSpacesIndentation = undefined; + } + if (!options.convertTabsToSpaces) { + var tabs = Math.floor(indentation / options.tabSize); + var spaces = indentation - tabs * options.tabSize; + var tabString = void 0; + if (!internedTabsIndentation) { + internedTabsIndentation = []; + } + if (internedTabsIndentation[tabs] === undefined) { + internedTabsIndentation[tabs] = tabString = repeat("\t", tabs); + } + else { + tabString = internedTabsIndentation[tabs]; + } + return spaces ? tabString + repeat(" ", spaces) : tabString; + } + else { + var spacesString = void 0; + var quotient = Math.floor(indentation / options.indentSize); + var remainder = indentation % options.indentSize; + if (!internedSpacesIndentation) { + internedSpacesIndentation = []; + } + if (internedSpacesIndentation[quotient] === undefined) { + spacesString = repeat(" ", options.indentSize * quotient); + internedSpacesIndentation[quotient] = spacesString; + } + else { + spacesString = internedSpacesIndentation[quotient]; + } + return remainder ? spacesString + repeat(" ", remainder) : spacesString; + } + function repeat(value, count) { + var s = ""; + for (var i = 0; i < count; i++) { + s += value; + } + return s; + } + } + formatting.getIndentationString = getIndentationString; + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/* @internal */ +var ts; +(function (ts) { + var formatting; + (function (formatting) { + var SmartIndenter; + (function (SmartIndenter) { + var Value; + (function (Value) { + Value[Value["Unknown"] = -1] = "Unknown"; + })(Value || (Value = {})); + function getIndentation(position, sourceFile, options) { + if (position > sourceFile.text.length) { + return getBaseIndentation(options); // past EOF + } + // no indentation when the indent style is set to none, + // so we can return fast + if (options.indentStyle === ts.IndentStyle.None) { + return 0; + } + var precedingToken = ts.findPrecedingToken(position, sourceFile); + if (!precedingToken) { + return getBaseIndentation(options); + } + // no indentation in string \regex\template literals + var precedingTokenIsLiteral = ts.isStringOrRegularExpressionOrTemplateLiteral(precedingToken.kind); + if (precedingTokenIsLiteral && precedingToken.getStart(sourceFile) <= position && precedingToken.end > position) { + return 0; + } + var lineAtPosition = sourceFile.getLineAndCharacterOfPosition(position).line; + // indentation is first non-whitespace character in a previous line + // for block indentation, we should look for a line which contains something that's not + // whitespace. + if (options.indentStyle === ts.IndentStyle.Block) { + // move backwards until we find a line with a non-whitespace character, + // then find the first non-whitespace character for that line. + var current_1 = position; + while (current_1 > 0) { + var char = sourceFile.text.charCodeAt(current_1); + if (!ts.isWhiteSpace(char)) { + break; } - // Ordinary case: just highlight the keyword. - result.push(getHighlightSpanForNode(keywords[i])); + current_1--; } - return result; + var lineStart = ts.getLineStartPositionForPosition(current_1, sourceFile); + return SmartIndenter.findFirstNonWhitespaceColumn(lineStart, current_1, sourceFile, options); } - } - } - /// References and Occurrences - function getOccurrencesAtPositionCore(fileName, position) { - synchronizeHostData(); - return convertDocumentHighlights(getDocumentHighlights(fileName, position, [fileName])); - function convertDocumentHighlights(documentHighlights) { - if (!documentHighlights) { - return undefined; + if (precedingToken.kind === 24 /* CommaToken */ && precedingToken.parent.kind !== 187 /* BinaryExpression */) { + // previous token is comma that separates items in list - find the previous item and try to derive indentation from it + var actualIndentation = getActualIndentationForListItemBeforeComma(precedingToken, sourceFile, options); + if (actualIndentation !== -1 /* Unknown */) { + return actualIndentation; + } } - var result = []; - for (var _i = 0, documentHighlights_1 = documentHighlights; _i < documentHighlights_1.length; _i++) { - var entry = documentHighlights_1[_i]; - for (var _a = 0, _b = entry.highlightSpans; _a < _b.length; _a++) { - var highlightSpan = _b[_a]; - result.push({ - fileName: entry.fileName, - textSpan: highlightSpan.textSpan, - isWriteAccess: highlightSpan.kind === ts.HighlightSpanKind.writtenReference, - isDefinition: false - }); + // try to find node that can contribute to indentation and includes 'position' starting from 'precedingToken' + // if such node is found - compute initial indentation for 'position' inside this node + var previous; + var current = precedingToken; + var currentStart; + var indentationDelta; + while (current) { + if (ts.positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(current, previous)) { + currentStart = getStartLineAndCharacterForNode(current, sourceFile); + if (nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile)) { + indentationDelta = 0; + } + else { + indentationDelta = lineAtPosition !== currentStart.line ? options.indentSize : 0; + } + break; + } + // check if current node is a list item - if yes, take indentation from it + var actualIndentation = getActualIndentationForListItem(current, sourceFile, options); + if (actualIndentation !== -1 /* Unknown */) { + return actualIndentation; } + actualIndentation = getLineIndentationWhenExpressionIsInMultiLine(current, sourceFile, options); + if (actualIndentation !== -1 /* Unknown */) { + return actualIndentation + options.indentSize; + } + previous = current; + current = current.parent; } - return result; - } - } - function convertReferences(referenceSymbols) { - if (!referenceSymbols) { - return undefined; + if (!current) { + // no parent was found - return the base indentation of the SourceFile + return getBaseIndentation(options); + } + return getIndentationForNodeWorker(current, currentStart, /*ignoreActualIndentationRange*/ undefined, indentationDelta, sourceFile, options); } - var referenceEntries = []; - for (var _i = 0, referenceSymbols_1 = referenceSymbols; _i < referenceSymbols_1.length; _i++) { - var referenceSymbol = referenceSymbols_1[_i]; - ts.addRange(referenceEntries, referenceSymbol.references); + SmartIndenter.getIndentation = getIndentation; + function getIndentationForNode(n, ignoreActualIndentationRange, sourceFile, options) { + var start = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)); + return getIndentationForNodeWorker(n, start, ignoreActualIndentationRange, /*indentationDelta*/ 0, sourceFile, options); } - return referenceEntries; - } - function findRenameLocations(fileName, position, findInStrings, findInComments) { - var referencedSymbols = findReferencedSymbols(fileName, position, findInStrings, findInComments); - return convertReferences(referencedSymbols); - } - function getReferencesAtPosition(fileName, position) { - var referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings*/ false, /*findInComments*/ false); - return convertReferences(referencedSymbols); - } - function findReferences(fileName, position) { - var referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings*/ false, /*findInComments*/ false); - // Only include referenced symbols that have a valid definition. - return ts.filter(referencedSymbols, function (rs) { return !!rs.definition; }); - } - function findReferencedSymbols(fileName, position, findInStrings, findInComments) { - synchronizeHostData(); - var sourceFile = getValidSourceFile(fileName); - var node = ts.getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true); - if (node === sourceFile) { - return undefined; + SmartIndenter.getIndentationForNode = getIndentationForNode; + function getBaseIndentation(options) { + return options.baseIndentSize || 0; } - switch (node.kind) { - case 8 /* NumericLiteral */: - if (!isLiteralNameOfPropertyDeclarationOrIndexAccess(node)) { - break; + SmartIndenter.getBaseIndentation = getBaseIndentation; + function getIndentationForNodeWorker(current, currentStart, ignoreActualIndentationRange, indentationDelta, sourceFile, options) { + var parent = current.parent; + var parentStart; + // walk upwards and collect indentations for pairs of parent-child nodes + // indentation is not added if parent and child nodes start on the same line or if parent is IfStatement and child starts on the same line with 'else clause' + while (parent) { + var useActualIndentation = true; + if (ignoreActualIndentationRange) { + var start = current.getStart(sourceFile); + useActualIndentation = start < ignoreActualIndentationRange.pos || start > ignoreActualIndentationRange.end; } - // Fallthrough - case 69 /* Identifier */: - case 97 /* ThisKeyword */: - // case SyntaxKind.SuperKeyword: TODO:GH#9268 - case 121 /* ConstructorKeyword */: - case 9 /* StringLiteral */: - return getReferencedSymbolsForNode(node, program.getSourceFiles(), findInStrings, findInComments); + if (useActualIndentation) { + // check if current node is a list item - if yes, take indentation from it + var actualIndentation = getActualIndentationForListItem(current, sourceFile, options); + if (actualIndentation !== -1 /* Unknown */) { + return actualIndentation + indentationDelta; + } + } + parentStart = getParentStart(parent, current, sourceFile); + var parentAndChildShareLine = parentStart.line === currentStart.line || + childStartsOnTheSameLineWithElseInIfStatement(parent, current, currentStart.line, sourceFile); + if (useActualIndentation) { + // try to fetch actual indentation for current node from source text + var actualIndentation = getActualIndentationForNode(current, parent, currentStart, parentAndChildShareLine, sourceFile, options); + if (actualIndentation !== -1 /* Unknown */) { + return actualIndentation + indentationDelta; + } + actualIndentation = getLineIndentationWhenExpressionIsInMultiLine(current, sourceFile, options); + if (actualIndentation !== -1 /* Unknown */) { + return actualIndentation + indentationDelta; + } + } + // increase indentation if parent node wants its content to be indented and parent and child nodes don't start on the same line + if (shouldIndentChildNode(parent, current) && !parentAndChildShareLine) { + indentationDelta += options.indentSize; + } + current = parent; + currentStart = parentStart; + parent = current.parent; + } + return indentationDelta + getBaseIndentation(options); } - return undefined; - } - function isThis(node) { - switch (node.kind) { - case 97 /* ThisKeyword */: - // case SyntaxKind.ThisType: TODO: GH#9267 - return true; - case 69 /* Identifier */: - // 'this' as a parameter - return node.originalKeywordKind === 97 /* ThisKeyword */ && node.parent.kind === 142 /* Parameter */; - default: - return false; + function getParentStart(parent, child, sourceFile) { + var containingList = getContainingList(child, sourceFile); + if (containingList) { + return sourceFile.getLineAndCharacterOfPosition(containingList.pos); + } + return sourceFile.getLineAndCharacterOfPosition(parent.getStart(sourceFile)); } - } - function getReferencedSymbolsForNode(node, sourceFiles, findInStrings, findInComments) { - var typeChecker = program.getTypeChecker(); - // Labels - if (isLabelName(node)) { - if (isJumpStatementTarget(node)) { - var labelDefinition = getTargetLabel(node.parent, node.text); - // if we have a label definition, look within its statement for references, if not, then - // the label is undefined and we have no results.. - return labelDefinition ? getLabelReferencesInNode(labelDefinition.parent, labelDefinition) : undefined; + /* + * Function returns Value.Unknown if indentation cannot be determined + */ + function getActualIndentationForListItemBeforeComma(commaToken, sourceFile, options) { + // previous token is comma that separates items in list - find the previous item and try to derive indentation from it + var commaItemInfo = ts.findListItemInfo(commaToken); + if (commaItemInfo && commaItemInfo.listItemIndex > 0) { + return deriveActualIndentationFromList(commaItemInfo.list.getChildren(), commaItemInfo.listItemIndex - 1, sourceFile, options); } else { - // it is a label definition and not a target, search within the parent labeledStatement - return getLabelReferencesInNode(node.parent, node); + // handle broken code gracefully + return -1 /* Unknown */; } } - if (isThis(node)) { - return getReferencesForThisKeyword(node, sourceFiles); + /* + * Function returns Value.Unknown if actual indentation for node should not be used (i.e because node is nested expression) + */ + function getActualIndentationForNode(current, parent, currentLineAndChar, parentAndChildShareLine, sourceFile, options) { + // actual indentation is used for statements\declarations if one of cases below is true: + // - parent is SourceFile - by default immediate children of SourceFile are not indented except when user indents them manually + // - parent and child are not on the same line + var useActualIndentation = (ts.isDeclaration(current) || ts.isStatementButNotDeclaration(current)) && + (parent.kind === 256 /* SourceFile */ || !parentAndChildShareLine); + if (!useActualIndentation) { + return -1 /* Unknown */; + } + return findColumnForFirstNonWhitespaceCharacterInLine(currentLineAndChar, sourceFile, options); } - if (node.kind === 95 /* SuperKeyword */) { - return getReferencesForSuperKeyword(node); + function nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile) { + var nextToken = ts.findNextToken(precedingToken, current); + if (!nextToken) { + return false; + } + if (nextToken.kind === 15 /* OpenBraceToken */) { + // open braces are always indented at the parent level + return true; + } + else if (nextToken.kind === 16 /* CloseBraceToken */) { + // close braces are indented at the parent level if they are located on the same line with cursor + // this means that if new line will be added at $ position, this case will be indented + // class A { + // $ + // } + /// and this one - not + // class A { + // $} + var nextTokenStartLine = getStartLineAndCharacterForNode(nextToken, sourceFile).line; + return lineAtPosition === nextTokenStartLine; + } + return false; } - // `getSymbolAtLocation` normally returns the symbol of the class when given the constructor keyword, - // so we have to specify that we want the constructor symbol. - var symbol = typeChecker.getSymbolAtLocation(node); - if (!symbol && node.kind === 9 /* StringLiteral */) { - return getReferencesForStringLiteral(node, sourceFiles); + function getStartLineAndCharacterForNode(n, sourceFile) { + return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)); } - // Could not find a symbol e.g. unknown identifier - if (!symbol) { - // Can't have references to something that we have no symbol for. - return undefined; + function childStartsOnTheSameLineWithElseInIfStatement(parent, child, childStartLine, sourceFile) { + if (parent.kind === 203 /* IfStatement */ && parent.elseStatement === child) { + var elseKeyword = ts.findChildOfKind(parent, 80 /* ElseKeyword */, sourceFile); + ts.Debug.assert(elseKeyword !== undefined); + var elseKeywordStartLine = getStartLineAndCharacterForNode(elseKeyword, sourceFile).line; + return elseKeywordStartLine === childStartLine; + } + return false; } - var declarations = symbol.declarations; - // The symbol was an internal symbol and does not have a declaration e.g. undefined symbol - if (!declarations || !declarations.length) { + SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement = childStartsOnTheSameLineWithElseInIfStatement; + function getContainingList(node, sourceFile) { + if (node.parent) { + switch (node.parent.kind) { + case 155 /* TypeReference */: + if (node.parent.typeArguments && + ts.rangeContainsStartEnd(node.parent.typeArguments, node.getStart(sourceFile), node.getEnd())) { + return node.parent.typeArguments; + } + break; + case 171 /* ObjectLiteralExpression */: + return node.parent.properties; + case 170 /* ArrayLiteralExpression */: + return node.parent.elements; + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + case 180 /* ArrowFunction */: + case 147 /* MethodDeclaration */: + case 146 /* MethodSignature */: + case 151 /* CallSignature */: + case 152 /* ConstructSignature */: { + var start = node.getStart(sourceFile); + if (node.parent.typeParameters && + ts.rangeContainsStartEnd(node.parent.typeParameters, start, node.getEnd())) { + return node.parent.typeParameters; + } + if (ts.rangeContainsStartEnd(node.parent.parameters, start, node.getEnd())) { + return node.parent.parameters; + } + break; + } + case 175 /* NewExpression */: + case 174 /* CallExpression */: { + var start = node.getStart(sourceFile); + if (node.parent.typeArguments && + ts.rangeContainsStartEnd(node.parent.typeArguments, start, node.getEnd())) { + return node.parent.typeArguments; + } + if (node.parent.arguments && + ts.rangeContainsStartEnd(node.parent.arguments, start, node.getEnd())) { + return node.parent.arguments; + } + break; + } + } + } return undefined; } - var result; - // Compute the meaning from the location and the symbol it references - var searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations); - // Get the text to search for. - // Note: if this is an external module symbol, the name doesn't include quotes. - var declaredName = ts.stripQuotes(ts.getDeclaredName(typeChecker, symbol, node)); - // Try to get the smallest valid scope that we can limit our search to; - // otherwise we'll need to search globally (i.e. include each file). - var scope = getSymbolScope(symbol); - // Maps from a symbol ID to the ReferencedSymbol entry in 'result'. - var symbolToIndex = []; - if (scope) { - result = []; - getReferencesInNode(scope, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex); + function getActualIndentationForListItem(node, sourceFile, options) { + var containingList = getContainingList(node, sourceFile); + return containingList ? getActualIndentationFromList(containingList) : -1 /* Unknown */; + function getActualIndentationFromList(list) { + var index = ts.indexOf(list, node); + return index !== -1 ? deriveActualIndentationFromList(list, index, sourceFile, options) : -1 /* Unknown */; + } } - else { - var internedName = getInternedName(symbol, node, declarations); - for (var _i = 0, sourceFiles_4 = sourceFiles; _i < sourceFiles_4.length; _i++) { - var sourceFile = sourceFiles_4[_i]; - cancellationToken.throwIfCancellationRequested(); - var nameTable = getNameTable(sourceFile); - if (nameTable[internedName] !== undefined) { - result = result || []; - getReferencesInNode(sourceFile, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex); + function getLineIndentationWhenExpressionIsInMultiLine(node, sourceFile, options) { + // actual indentation should not be used when: + // - node is close parenthesis - this is the end of the expression + if (node.kind === 18 /* CloseParenToken */) { + return -1 /* Unknown */; + } + if (node.parent && (node.parent.kind === 174 /* CallExpression */ || + node.parent.kind === 175 /* NewExpression */) && + node.parent.expression !== node) { + var fullCallOrNewExpression = node.parent.expression; + var startingExpression = getStartingExpression(fullCallOrNewExpression); + if (fullCallOrNewExpression === startingExpression) { + return -1 /* Unknown */; + } + var fullCallOrNewExpressionEnd = sourceFile.getLineAndCharacterOfPosition(fullCallOrNewExpression.end); + var startingExpressionEnd = sourceFile.getLineAndCharacterOfPosition(startingExpression.end); + if (fullCallOrNewExpressionEnd.line === startingExpressionEnd.line) { + return -1 /* Unknown */; } + return findColumnForFirstNonWhitespaceCharacterInLine(fullCallOrNewExpressionEnd, sourceFile, options); } - } - return result; - function getDefinition(symbol) { - var info = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, node.getSourceFile(), getContainerNode(node), node); - var name = ts.map(info.displayParts, function (p) { return p.text; }).join(""); - var declarations = symbol.declarations; - if (!declarations || declarations.length === 0) { - return undefined; + return -1 /* Unknown */; + function getStartingExpression(node) { + while (true) { + switch (node.kind) { + case 174 /* CallExpression */: + case 175 /* NewExpression */: + case 172 /* PropertyAccessExpression */: + case 173 /* ElementAccessExpression */: + node = node.expression; + break; + default: + return node; + } + } } - return { - containerKind: "", - containerName: "", - name: name, - kind: info.symbolKind, - fileName: declarations[0].getSourceFile().fileName, - textSpan: ts.createTextSpan(declarations[0].getStart(), 0), - displayParts: info.displayParts - }; } - function getAliasSymbolForPropertyNameSymbol(symbol, location) { - if (symbol.flags & 8388608 /* Alias */) { - // Default import get alias - var defaultImport = ts.getDeclarationOfKind(symbol, 231 /* ImportClause */); - if (defaultImport) { - return typeChecker.getAliasedSymbol(symbol); + function deriveActualIndentationFromList(list, index, sourceFile, options) { + ts.Debug.assert(index >= 0 && index < list.length); + var node = list[index]; + // walk toward the start of the list starting from current node and check if the line is the same for all items. + // if end line for item [i - 1] differs from the start line for item [i] - find column of the first non-whitespace character on the line of item [i] + var lineAndCharacter = getStartLineAndCharacterForNode(node, sourceFile); + for (var i = index - 1; i >= 0; i--) { + if (list[i].kind === 24 /* CommaToken */) { + continue; } - var importOrExportSpecifier = ts.forEach(symbol.declarations, function (declaration) { return (declaration.kind === 234 /* ImportSpecifier */ || - declaration.kind === 238 /* ExportSpecifier */) ? declaration : undefined; }); - if (importOrExportSpecifier && - // export { a } - (!importOrExportSpecifier.propertyName || - // export {a as class } where a is location - importOrExportSpecifier.propertyName === location)) { - // If Import specifier -> get alias - // else Export specifier -> get local target - return importOrExportSpecifier.kind === 234 /* ImportSpecifier */ ? - typeChecker.getAliasedSymbol(symbol) : - typeChecker.getExportSpecifierLocalTargetSymbol(importOrExportSpecifier); + // skip list items that ends on the same line with the current list element + var prevEndLine = sourceFile.getLineAndCharacterOfPosition(list[i].end).line; + if (prevEndLine !== lineAndCharacter.line) { + return findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options); } + lineAndCharacter = getStartLineAndCharacterForNode(list[i], sourceFile); } - return undefined; - } - function followAliasIfNecessary(symbol, location) { - return getAliasSymbolForPropertyNameSymbol(symbol, location) || symbol; - } - function getPropertySymbolOfDestructuringAssignment(location) { - return ts.isArrayLiteralOrObjectLiteralDestructuringPattern(location.parent.parent) && - typeChecker.getPropertySymbolOfDestructuringAssignment(location); + return -1 /* Unknown */; } - function isObjectBindingPatternElementWithoutPropertyName(symbol) { - var bindingElement = ts.getDeclarationOfKind(symbol, 169 /* BindingElement */); - return bindingElement && - bindingElement.parent.kind === 167 /* ObjectBindingPattern */ && - !bindingElement.propertyName; + function findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options) { + var lineStart = sourceFile.getPositionOfLineAndCharacter(lineAndCharacter.line, 0); + return findFirstNonWhitespaceColumn(lineStart, lineStart + lineAndCharacter.character, sourceFile, options); } - function getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol) { - if (isObjectBindingPatternElementWithoutPropertyName(symbol)) { - var bindingElement = ts.getDeclarationOfKind(symbol, 169 /* BindingElement */); - var typeOfPattern = typeChecker.getTypeAtLocation(bindingElement.parent); - return typeOfPattern && typeChecker.getPropertyOfType(typeOfPattern, bindingElement.name.text); + /* + Character is the actual index of the character since the beginning of the line. + Column - position of the character after expanding tabs to spaces + "0\t2$" + value of 'character' for '$' is 3 + value of 'column' for '$' is 6 (assuming that tab size is 4) + */ + function findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options) { + var character = 0; + var column = 0; + for (var pos = startPos; pos < endPos; pos++) { + var ch = sourceFile.text.charCodeAt(pos); + if (!ts.isWhiteSpaceSingleLine(ch)) { + break; + } + if (ch === 9 /* tab */) { + column += options.tabSize + (column % options.tabSize); + } + else { + column++; + } + character++; } - return undefined; + return { column: column, character: character }; } - function getInternedName(symbol, location, declarations) { - // If this is an export or import specifier it could have been renamed using the 'as' syntax. - // If so we want to search for whatever under the cursor. - if (ts.isImportOrExportSpecifierName(location)) { - return location.getText(); - } - // Try to get the local symbol if we're dealing with an 'export default' - // since that symbol has the "true" name. - var localExportDefaultSymbol = ts.getLocalSymbolForExportDefault(symbol); - symbol = localExportDefaultSymbol || symbol; - return ts.stripQuotes(symbol.name); + SmartIndenter.findFirstNonWhitespaceCharacterAndColumn = findFirstNonWhitespaceCharacterAndColumn; + function findFirstNonWhitespaceColumn(startPos, endPos, sourceFile, options) { + return findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options).column; } - /** - * Determines the smallest scope in which a symbol may have named references. - * Note that not every construct has been accounted for. This function can - * probably be improved. - * - * @returns undefined if the scope cannot be determined, implying that - * a reference to a symbol can occur anywhere. - */ - function getSymbolScope(symbol) { - // If this is the symbol of a named function expression or named class expression, - // then named references are limited to its own scope. - var valueDeclaration = symbol.valueDeclaration; - if (valueDeclaration && (valueDeclaration.kind === 179 /* FunctionExpression */ || valueDeclaration.kind === 192 /* ClassExpression */)) { - return valueDeclaration; - } - // If this is private property or method, the scope is the containing class - if (symbol.flags & (4 /* Property */ | 8192 /* Method */)) { - var privateDeclaration = ts.forEach(symbol.getDeclarations(), function (d) { return (d.flags & 8 /* Private */) ? d : undefined; }); - if (privateDeclaration) { - return ts.getAncestor(privateDeclaration, 221 /* ClassDeclaration */); - } - } - // If the symbol is an import we would like to find it if we are looking for what it imports. - // So consider it visible outside its declaration scope. - if (symbol.flags & 8388608 /* Alias */) { - return undefined; - } - // If symbol is of object binding pattern element without property name we would want to - // look for property too and that could be anywhere - if (isObjectBindingPatternElementWithoutPropertyName(symbol)) { - return undefined; - } - // if this symbol is visible from its parent container, e.g. exported, then bail out - // if symbol correspond to the union property - bail out - if (symbol.parent || (symbol.flags & 268435456 /* SyntheticProperty */)) { - return undefined; + SmartIndenter.findFirstNonWhitespaceColumn = findFirstNonWhitespaceColumn; + function nodeContentIsAlwaysIndented(kind) { + switch (kind) { + case 202 /* ExpressionStatement */: + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + case 222 /* InterfaceDeclaration */: + case 224 /* EnumDeclaration */: + case 223 /* TypeAliasDeclaration */: + case 170 /* ArrayLiteralExpression */: + case 199 /* Block */: + case 226 /* ModuleBlock */: + case 171 /* ObjectLiteralExpression */: + case 159 /* TypeLiteral */: + case 161 /* TupleType */: + case 227 /* CaseBlock */: + case 250 /* DefaultClause */: + case 249 /* CaseClause */: + case 178 /* ParenthesizedExpression */: + case 172 /* PropertyAccessExpression */: + case 174 /* CallExpression */: + case 175 /* NewExpression */: + case 200 /* VariableStatement */: + case 218 /* VariableDeclaration */: + case 235 /* ExportAssignment */: + case 211 /* ReturnStatement */: + case 188 /* ConditionalExpression */: + case 168 /* ArrayBindingPattern */: + case 167 /* ObjectBindingPattern */: + case 243 /* JsxOpeningElement */: + case 242 /* JsxSelfClosingElement */: + case 248 /* JsxExpression */: + case 146 /* MethodSignature */: + case 151 /* CallSignature */: + case 152 /* ConstructSignature */: + case 142 /* Parameter */: + case 156 /* FunctionType */: + case 157 /* ConstructorType */: + case 164 /* ParenthesizedType */: + case 176 /* TaggedTemplateExpression */: + case 184 /* AwaitExpression */: + case 237 /* NamedExports */: + case 233 /* NamedImports */: + case 238 /* ExportSpecifier */: + case 234 /* ImportSpecifier */: + return true; } - var scope; - var declarations = symbol.getDeclarations(); - if (declarations) { - for (var _i = 0, declarations_9 = declarations; _i < declarations_9.length; _i++) { - var declaration = declarations_9[_i]; - var container = getContainerNode(declaration); - if (!container) { - return undefined; - } - if (scope && scope !== container) { - // Different declarations have different containers, bail out - return undefined; - } - if (container.kind === 256 /* SourceFile */ && !ts.isExternalModule(container)) { - // This is a global variable and not an external module, any declaration defined - // within this scope is visible outside the file - return undefined; - } - // The search scope is the container node - scope = container; - } + return false; + } + /* @internal */ + function nodeWillIndentChild(parent, child, indentByDefault) { + var childKind = child ? child.kind : 0 /* Unknown */; + switch (parent.kind) { + case 204 /* DoStatement */: + case 205 /* WhileStatement */: + case 207 /* ForInStatement */: + case 208 /* ForOfStatement */: + case 206 /* ForStatement */: + case 203 /* IfStatement */: + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: + case 147 /* MethodDeclaration */: + case 180 /* ArrowFunction */: + case 148 /* Constructor */: + case 149 /* GetAccessor */: + case 150 /* SetAccessor */: + return childKind !== 199 /* Block */; + case 236 /* ExportDeclaration */: + return childKind !== 237 /* NamedExports */; + case 230 /* ImportDeclaration */: + return childKind !== 231 /* ImportClause */ || + (child.namedBindings && child.namedBindings.kind !== 233 /* NamedImports */); + case 241 /* JsxElement */: + return childKind !== 245 /* JsxClosingElement */; } - return scope; + // No explicit rule for given nodes so the result will follow the default value argument + return indentByDefault; } - function getPossibleSymbolReferencePositions(sourceFile, symbolName, start, end) { - var positions = []; - /// TODO: Cache symbol existence for files to save text search - // Also, need to make this work for unicode escapes. - // Be resilient in the face of a symbol with no name or zero length name - if (!symbolName || !symbolName.length) { - return positions; + SmartIndenter.nodeWillIndentChild = nodeWillIndentChild; + /* + Function returns true when the parent node should indent the given child by an explicit rule + */ + function shouldIndentChildNode(parent, child) { + return nodeContentIsAlwaysIndented(parent.kind) || nodeWillIndentChild(parent, child, /*indentByDefault*/ false); + } + SmartIndenter.shouldIndentChildNode = shouldIndentChildNode; + })(SmartIndenter = formatting.SmartIndenter || (formatting.SmartIndenter = {})); + })(formatting = ts.formatting || (ts.formatting = {})); +})(ts || (ts = {})); +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +var ts; +(function (ts) { + /** The version of the language service API */ + ts.servicesVersion = "0.5"; + function createNode(kind, pos, end, parent) { + var node = kind >= 139 /* FirstNode */ ? new NodeObject(kind, pos, end) : + kind === 69 /* Identifier */ ? new IdentifierObject(kind, pos, end) : + new TokenObject(kind, pos, end); + node.parent = parent; + return node; + } + var NodeObject = (function () { + function NodeObject(kind, pos, end) { + this.pos = pos; + this.end = end; + this.flags = 0 /* None */; + this.transformFlags = undefined; + this.excludeTransformFlags = undefined; + this.parent = undefined; + this.kind = kind; + } + NodeObject.prototype.getSourceFile = function () { + return ts.getSourceFileOfNode(this); + }; + NodeObject.prototype.getStart = function (sourceFile, includeJsDocComment) { + return ts.getTokenPosOfNode(this, sourceFile, includeJsDocComment); + }; + NodeObject.prototype.getFullStart = function () { + return this.pos; + }; + NodeObject.prototype.getEnd = function () { + return this.end; + }; + NodeObject.prototype.getWidth = function (sourceFile) { + return this.getEnd() - this.getStart(sourceFile); + }; + NodeObject.prototype.getFullWidth = function () { + return this.end - this.pos; + }; + NodeObject.prototype.getLeadingTriviaWidth = function (sourceFile) { + return this.getStart(sourceFile) - this.pos; + }; + NodeObject.prototype.getFullText = function (sourceFile) { + return (sourceFile || this.getSourceFile()).text.substring(this.pos, this.end); + }; + NodeObject.prototype.getText = function (sourceFile) { + if (!sourceFile) { + sourceFile = this.getSourceFile(); + } + return sourceFile.text.substring(this.getStart(sourceFile), this.getEnd()); + }; + NodeObject.prototype.addSyntheticNodes = function (nodes, pos, end, useJSDocScanner) { + ts.scanner.setTextPos(pos); + while (pos < end) { + var token = useJSDocScanner ? ts.scanner.scanJSDocToken() : ts.scanner.scan(); + var textPos = ts.scanner.getTextPos(); + if (textPos <= end) { + nodes.push(createNode(token, pos, textPos, this)); } - var text = sourceFile.text; - var sourceLength = text.length; - var symbolNameLength = symbolName.length; - var position = text.indexOf(symbolName, start); - while (position >= 0) { - cancellationToken.throwIfCancellationRequested(); - // If we are past the end, stop looking - if (position > end) - break; - // We found a match. Make sure it's not part of a larger word (i.e. the char - // before and after it have to be a non-identifier char). - var endPosition = position + symbolNameLength; - if ((position === 0 || !ts.isIdentifierPart(text.charCodeAt(position - 1), 2 /* Latest */)) && - (endPosition === sourceLength || !ts.isIdentifierPart(text.charCodeAt(endPosition), 2 /* Latest */))) { - // Found a real match. Keep searching. - positions.push(position); - } - position = text.indexOf(symbolName, position + symbolNameLength + 1); + pos = textPos; + } + return pos; + }; + NodeObject.prototype.createSyntaxList = function (nodes) { + var list = createNode(286 /* SyntaxList */, nodes.pos, nodes.end, this); + list._children = []; + var pos = nodes.pos; + for (var _i = 0, nodes_4 = nodes; _i < nodes_4.length; _i++) { + var node = nodes_4[_i]; + if (pos < node.pos) { + pos = this.addSyntheticNodes(list._children, pos, node.pos); } - return positions; + list._children.push(node); + pos = node.end; } - function getLabelReferencesInNode(container, targetLabel) { - var references = []; - var sourceFile = container.getSourceFile(); - var labelName = targetLabel.text; - var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container.getStart(), container.getEnd()); - ts.forEach(possiblePositions, function (position) { - cancellationToken.throwIfCancellationRequested(); - var node = ts.getTouchingWord(sourceFile, position); - if (!node || node.getWidth() !== labelName.length) { - return; + if (pos < nodes.end) { + this.addSyntheticNodes(list._children, pos, nodes.end); + } + return list; + }; + NodeObject.prototype.createChildren = function (sourceFile) { + var _this = this; + var children; + if (this.kind >= 139 /* FirstNode */) { + ts.scanner.setText((sourceFile || this.getSourceFile()).text); + children = []; + var pos_3 = this.pos; + var useJSDocScanner_1 = this.kind >= 273 /* FirstJSDocTagNode */ && this.kind <= 285 /* LastJSDocTagNode */; + var processNode = function (node) { + var isJSDocTagNode = ts.isJSDocTag(node); + if (!isJSDocTagNode && pos_3 < node.pos) { + pos_3 = _this.addSyntheticNodes(children, pos_3, node.pos, useJSDocScanner_1); } - // Only pick labels that are either the target label, or have a target that is the target label - if (node === targetLabel || - (isJumpStatementTarget(node) && getTargetLabel(node, labelName) === targetLabel)) { - references.push(getReferenceEntryFromNode(node)); + children.push(node); + if (!isJSDocTagNode) { + pos_3 = node.end; } - }); - var definition = { - containerKind: "", - containerName: "", - fileName: targetLabel.getSourceFile().fileName, - kind: ts.ScriptElementKind.label, - name: labelName, - textSpan: ts.createTextSpanFromBounds(targetLabel.getStart(), targetLabel.getEnd()), - displayParts: [ts.displayPart(labelName, ts.SymbolDisplayPartKind.text)] }; - return [{ definition: definition, references: references }]; - } - function isValidReferencePosition(node, searchSymbolName) { - if (node) { - // Compare the length so we filter out strict superstrings of the symbol we are looking for - switch (node.kind) { - case 69 /* Identifier */: - return node.getWidth() === searchSymbolName.length; - case 9 /* StringLiteral */: - if (isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || - isNameOfExternalModuleImportOrDeclaration(node)) { - // For string literals we have two additional chars for the quotes - return node.getWidth() === searchSymbolName.length + 2; - } - break; - case 8 /* NumericLiteral */: - if (isLiteralNameOfPropertyDeclarationOrIndexAccess(node)) { - return node.getWidth() === searchSymbolName.length; - } - break; - } - } - return false; - } - /** Search within node "container" for references for a search value, where the search value is defined as a - * tuple of(searchSymbol, searchText, searchLocation, and searchMeaning). - * searchLocation: a node where the search value - */ - function getReferencesInNode(container, searchSymbol, searchText, searchLocation, searchMeaning, findInStrings, findInComments, result, symbolToIndex) { - var sourceFile = container.getSourceFile(); - var tripleSlashDirectivePrefixRegex = /^\/\/\/\s*= 0) { - var referencedSymbol = getReferencedSymbol(shorthandValueSymbol); - referencedSymbol.references.push(getReferenceEntryFromNode(referenceSymbolDeclaration.name)); - } - else if (searchLocation.kind === 121 /* ConstructorKeyword */) { - findAdditionalConstructorReferences(referenceSymbol, referenceLocation); - } - } - }); - } - return; - /** Adds references when a constructor is used with `new this()` in its own class and `super()` calls in subclasses. */ - function findAdditionalConstructorReferences(referenceSymbol, referenceLocation) { - ts.Debug.assert(ts.isClassLike(searchSymbol.valueDeclaration)); - var referenceClass = referenceLocation.parent; - if (referenceSymbol === searchSymbol && ts.isClassLike(referenceClass)) { - ts.Debug.assert(referenceClass.name === referenceLocation); - // This is the class declaration containing the constructor. - addReferences(findOwnConstructorCalls(searchSymbol)); + var processNodes = function (nodes) { + if (pos_3 < nodes.pos) { + pos_3 = _this.addSyntheticNodes(children, pos_3, nodes.pos, useJSDocScanner_1); } - else { - // If this class appears in `extends C`, then the extending class' "super" calls are references. - var classExtending = tryGetClassByExtendingIdentifier(referenceLocation); - if (classExtending && ts.isClassLike(classExtending) && followAliasIfNecessary(referenceSymbol, referenceLocation) === searchSymbol) { - addReferences(superConstructorAccesses(classExtending)); - } + children.push(_this.createSyntaxList(nodes)); + pos_3 = nodes.end; + }; + // jsDocComments need to be the first children + if (this.jsDocComments) { + for (var _i = 0, _a = this.jsDocComments; _i < _a.length; _i++) { + var jsDocComment = _a[_i]; + processNode(jsDocComment); } } - function addReferences(references) { - if (references.length) { - var referencedSymbol = getReferencedSymbol(searchSymbol); - ts.addRange(referencedSymbol.references, ts.map(references, getReferenceEntryFromNode)); - } + // For syntactic classifications, all trivia are classcified together, including jsdoc comments. + // For that to work, the jsdoc comments should still be the leading trivia of the first child. + // Restoring the scanner position ensures that. + pos_3 = this.pos; + ts.forEachChild(this, processNode, processNodes); + if (pos_3 < this.end) { + this.addSyntheticNodes(children, pos_3, this.end); } - /** `classSymbol` is the class where the constructor was defined. - * Reference the constructor and all calls to `new this()`. - */ - function findOwnConstructorCalls(classSymbol) { - var result = []; - for (var _i = 0, _a = classSymbol.members["__constructor"].declarations; _i < _a.length; _i++) { - var decl = _a[_i]; - ts.Debug.assert(decl.kind === 148 /* Constructor */); - var ctrKeyword = decl.getChildAt(0); - ts.Debug.assert(ctrKeyword.kind === 121 /* ConstructorKeyword */); - result.push(ctrKeyword); - } - ts.forEachProperty(classSymbol.exports, function (member) { - var decl = member.valueDeclaration; - if (decl && decl.kind === 147 /* MethodDeclaration */) { - var body = decl.body; - if (body) { - forEachDescendantOfKind(body, 97 /* ThisKeyword */, function (thisKeyword) { - if (isNewExpressionTarget(thisKeyword)) { - result.push(thisKeyword); - } - }); - } - } - }); - return result; + ts.scanner.setText(undefined); + } + this._children = children || ts.emptyArray; + }; + NodeObject.prototype.getChildCount = function (sourceFile) { + if (!this._children) + this.createChildren(sourceFile); + return this._children.length; + }; + NodeObject.prototype.getChildAt = function (index, sourceFile) { + if (!this._children) + this.createChildren(sourceFile); + return this._children[index]; + }; + NodeObject.prototype.getChildren = function (sourceFile) { + if (!this._children) + this.createChildren(sourceFile); + return this._children; + }; + NodeObject.prototype.getFirstToken = function (sourceFile) { + var children = this.getChildren(sourceFile); + if (!children.length) { + return undefined; + } + var child = children[0]; + return child.kind < 139 /* FirstNode */ ? child : child.getFirstToken(sourceFile); + }; + NodeObject.prototype.getLastToken = function (sourceFile) { + var children = this.getChildren(sourceFile); + var child = ts.lastOrUndefined(children); + if (!child) { + return undefined; + } + return child.kind < 139 /* FirstNode */ ? child : child.getLastToken(sourceFile); + }; + return NodeObject; + }()); + var TokenOrIdentifierObject = (function () { + function TokenOrIdentifierObject(pos, end) { + // Set properties in same order as NodeObject + this.pos = pos; + this.end = end; + this.flags = 0 /* None */; + this.parent = undefined; + } + TokenOrIdentifierObject.prototype.getSourceFile = function () { + return ts.getSourceFileOfNode(this); + }; + TokenOrIdentifierObject.prototype.getStart = function (sourceFile, includeJsDocComment) { + return ts.getTokenPosOfNode(this, sourceFile, includeJsDocComment); + }; + TokenOrIdentifierObject.prototype.getFullStart = function () { + return this.pos; + }; + TokenOrIdentifierObject.prototype.getEnd = function () { + return this.end; + }; + TokenOrIdentifierObject.prototype.getWidth = function (sourceFile) { + return this.getEnd() - this.getStart(sourceFile); + }; + TokenOrIdentifierObject.prototype.getFullWidth = function () { + return this.end - this.pos; + }; + TokenOrIdentifierObject.prototype.getLeadingTriviaWidth = function (sourceFile) { + return this.getStart(sourceFile) - this.pos; + }; + TokenOrIdentifierObject.prototype.getFullText = function (sourceFile) { + return (sourceFile || this.getSourceFile()).text.substring(this.pos, this.end); + }; + TokenOrIdentifierObject.prototype.getText = function (sourceFile) { + return (sourceFile || this.getSourceFile()).text.substring(this.getStart(), this.getEnd()); + }; + TokenOrIdentifierObject.prototype.getChildCount = function (sourceFile) { + return 0; + }; + TokenOrIdentifierObject.prototype.getChildAt = function (index, sourceFile) { + return undefined; + }; + TokenOrIdentifierObject.prototype.getChildren = function (sourceFile) { + return ts.emptyArray; + }; + TokenOrIdentifierObject.prototype.getFirstToken = function (sourceFile) { + return undefined; + }; + TokenOrIdentifierObject.prototype.getLastToken = function (sourceFile) { + return undefined; + }; + return TokenOrIdentifierObject; + }()); + var SymbolObject = (function () { + function SymbolObject(flags, name) { + this.flags = flags; + this.name = name; + } + SymbolObject.prototype.getFlags = function () { + return this.flags; + }; + SymbolObject.prototype.getName = function () { + return this.name; + }; + SymbolObject.prototype.getDeclarations = function () { + return this.declarations; + }; + SymbolObject.prototype.getDocumentationComment = function () { + if (this.documentationComment === undefined) { + this.documentationComment = ts.JsDoc.getJsDocCommentsFromDeclarations(this.declarations, this.name, !(this.flags & 4 /* Property */)); + } + return this.documentationComment; + }; + return SymbolObject; + }()); + var TokenObject = (function (_super) { + __extends(TokenObject, _super); + function TokenObject(kind, pos, end) { + _super.call(this, pos, end); + this.kind = kind; + } + return TokenObject; + }(TokenOrIdentifierObject)); + var IdentifierObject = (function (_super) { + __extends(IdentifierObject, _super); + function IdentifierObject(kind, pos, end) { + _super.call(this, pos, end); + } + return IdentifierObject; + }(TokenOrIdentifierObject)); + IdentifierObject.prototype.kind = 69 /* Identifier */; + var TypeObject = (function () { + function TypeObject(checker, flags) { + this.checker = checker; + this.flags = flags; + } + TypeObject.prototype.getFlags = function () { + return this.flags; + }; + TypeObject.prototype.getSymbol = function () { + return this.symbol; + }; + TypeObject.prototype.getProperties = function () { + return this.checker.getPropertiesOfType(this); + }; + TypeObject.prototype.getProperty = function (propertyName) { + return this.checker.getPropertyOfType(this, propertyName); + }; + TypeObject.prototype.getApparentProperties = function () { + return this.checker.getAugmentedPropertiesOfType(this); + }; + TypeObject.prototype.getCallSignatures = function () { + return this.checker.getSignaturesOfType(this, 0 /* Call */); + }; + TypeObject.prototype.getConstructSignatures = function () { + return this.checker.getSignaturesOfType(this, 1 /* Construct */); + }; + TypeObject.prototype.getStringIndexType = function () { + return this.checker.getIndexTypeOfType(this, 0 /* String */); + }; + TypeObject.prototype.getNumberIndexType = function () { + return this.checker.getIndexTypeOfType(this, 1 /* Number */); + }; + TypeObject.prototype.getBaseTypes = function () { + return this.flags & (32768 /* Class */ | 65536 /* Interface */) + ? this.checker.getBaseTypes(this) + : undefined; + }; + TypeObject.prototype.getNonNullableType = function () { + return this.checker.getNonNullableType(this); + }; + return TypeObject; + }()); + var SignatureObject = (function () { + function SignatureObject(checker) { + this.checker = checker; + } + SignatureObject.prototype.getDeclaration = function () { + return this.declaration; + }; + SignatureObject.prototype.getTypeParameters = function () { + return this.typeParameters; + }; + SignatureObject.prototype.getParameters = function () { + return this.parameters; + }; + SignatureObject.prototype.getReturnType = function () { + return this.checker.getReturnTypeOfSignature(this); + }; + SignatureObject.prototype.getDocumentationComment = function () { + if (this.documentationComment === undefined) { + this.documentationComment = this.declaration ? ts.JsDoc.getJsDocCommentsFromDeclarations([this.declaration], + /*name*/ undefined, + /*canUseParsedParamTagComments*/ false) : []; + } + return this.documentationComment; + }; + return SignatureObject; + }()); + var SourceFileObject = (function (_super) { + __extends(SourceFileObject, _super); + function SourceFileObject(kind, pos, end) { + _super.call(this, kind, pos, end); + } + SourceFileObject.prototype.update = function (newText, textChangeRange) { + return ts.updateSourceFile(this, newText, textChangeRange); + }; + SourceFileObject.prototype.getLineAndCharacterOfPosition = function (position) { + return ts.getLineAndCharacterOfPosition(this, position); + }; + SourceFileObject.prototype.getLineStarts = function () { + return ts.getLineStarts(this); + }; + SourceFileObject.prototype.getPositionOfLineAndCharacter = function (line, character) { + return ts.getPositionOfLineAndCharacter(this, line, character); + }; + SourceFileObject.prototype.getNamedDeclarations = function () { + if (!this.namedDeclarations) { + this.namedDeclarations = this.computeNamedDeclarations(); + } + return this.namedDeclarations; + }; + SourceFileObject.prototype.computeNamedDeclarations = function () { + var result = ts.createMap(); + ts.forEachChild(this, visit); + return result; + function addDeclaration(declaration) { + var name = getDeclarationName(declaration); + if (name) { + ts.multiMapAdd(result, name, declaration); } - /** Find references to `super` in the constructor of an extending class. */ - function superConstructorAccesses(cls) { - var symbol = cls.symbol; - var ctr = symbol.members["__constructor"]; - if (!ctr) { - return []; + } + function getDeclarations(name) { + return result[name] || (result[name] = []); + } + function getDeclarationName(declaration) { + if (declaration.name) { + var result_6 = getTextOfIdentifierOrLiteral(declaration.name); + if (result_6 !== undefined) { + return result_6; } - var result = []; - for (var _i = 0, _a = ctr.declarations; _i < _a.length; _i++) { - var decl = _a[_i]; - ts.Debug.assert(decl.kind === 148 /* Constructor */); - var body = decl.body; - if (body) { - forEachDescendantOfKind(body, 95 /* SuperKeyword */, function (node) { - if (isCallExpressionTarget(node)) { - result.push(node); - } - }); + if (declaration.name.kind === 140 /* ComputedPropertyName */) { + var expr = declaration.name.expression; + if (expr.kind === 172 /* PropertyAccessExpression */) { + return expr.name.text; } + return getTextOfIdentifierOrLiteral(expr); } - ; - return result; - } - function getReferencedSymbol(symbol) { - var symbolId = ts.getSymbolId(symbol); - var index = symbolToIndex[symbolId]; - if (index === undefined) { - index = result.length; - symbolToIndex[symbolId] = index; - result.push({ - definition: getDefinition(symbol), - references: [] - }); - } - return result[index]; } - function isInNonReferenceComment(sourceFile, position) { - return ts.isInCommentHelper(sourceFile, position, isNonReferenceComment); - function isNonReferenceComment(c) { - var commentText = sourceFile.text.substring(c.pos, c.end); - return !tripleSlashDirectivePrefixRegex.test(commentText); + return undefined; + } + function getTextOfIdentifierOrLiteral(node) { + if (node) { + if (node.kind === 69 /* Identifier */ || + node.kind === 9 /* StringLiteral */ || + node.kind === 8 /* NumericLiteral */) { + return node.text; } } + return undefined; } - function getReferencesForSuperKeyword(superKeyword) { - var searchSpaceNode = ts.getSuperContainer(superKeyword, /*stopOnFunctions*/ false); - if (!searchSpaceNode) { - return undefined; - } - // Whether 'super' occurs in a static context within a class. - var staticFlag = 32 /* Static */; - switch (searchSpaceNode.kind) { - case 145 /* PropertyDeclaration */: - case 144 /* PropertySignature */: + function visit(node) { + switch (node.kind) { + case 220 /* FunctionDeclaration */: + case 179 /* FunctionExpression */: case 147 /* MethodDeclaration */: case 146 /* MethodSignature */: - case 148 /* Constructor */: + var functionDeclaration = node; + var declarationName = getDeclarationName(functionDeclaration); + if (declarationName) { + var declarations = getDeclarations(declarationName); + var lastDeclaration = ts.lastOrUndefined(declarations); + // Check whether this declaration belongs to an "overload group". + if (lastDeclaration && functionDeclaration.parent === lastDeclaration.parent && functionDeclaration.symbol === lastDeclaration.symbol) { + // Overwrite the last declaration if it was an overload + // and this one is an implementation. + if (functionDeclaration.body && !lastDeclaration.body) { + declarations[declarations.length - 1] = functionDeclaration; + } + } + else { + declarations.push(functionDeclaration); + } + ts.forEachChild(node, visit); + } + break; + case 221 /* ClassDeclaration */: + case 192 /* ClassExpression */: + case 222 /* InterfaceDeclaration */: + case 223 /* TypeAliasDeclaration */: + case 224 /* EnumDeclaration */: + case 225 /* ModuleDeclaration */: + case 229 /* ImportEqualsDeclaration */: + case 238 /* ExportSpecifier */: + case 234 /* ImportSpecifier */: + case 229 /* ImportEqualsDeclaration */: + case 231 /* ImportClause */: + case 232 /* NamespaceImport */: case 149 /* GetAccessor */: case 150 /* SetAccessor */: - staticFlag &= searchSpaceNode.flags; - searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class + case 159 /* TypeLiteral */: + addDeclaration(node); + ts.forEachChild(node, visit); break; - default: - return undefined; - } - var references = []; - var sourceFile = searchSpaceNode.getSourceFile(); - var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); - ts.forEach(possiblePositions, function (position) { - cancellationToken.throwIfCancellationRequested(); - var node = ts.getTouchingWord(sourceFile, position); - if (!node || node.kind !== 95 /* SuperKeyword */) { - return; - } - var container = ts.getSuperContainer(node, /*stopOnFunctions*/ false); - // If we have a 'super' container, we must have an enclosing class. - // Now make sure the owning class is the same as the search-space - // and has the same static qualifier as the original 'super's owner. - if (container && (32 /* Static */ & container.flags) === staticFlag && container.parent.symbol === searchSpaceNode.symbol) { - references.push(getReferenceEntryFromNode(node)); - } - }); - var definition = getDefinition(searchSpaceNode.symbol); - return [{ definition: definition, references: references }]; - } - function getReferencesForThisKeyword(thisOrSuperKeyword, sourceFiles) { - var searchSpaceNode = ts.getThisContainer(thisOrSuperKeyword, /* includeArrowFunctions */ false); - // Whether 'this' occurs in a static context within a class. - var staticFlag = 32 /* Static */; - switch (searchSpaceNode.kind) { - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - if (ts.isObjectLiteralMethod(searchSpaceNode)) { + case 142 /* Parameter */: + // Only consider parameter properties + if (!ts.hasModifier(node, 92 /* ParameterPropertyModifier */)) { break; } // fall through + case 218 /* VariableDeclaration */: + case 169 /* BindingElement */: { + var decl = node; + if (ts.isBindingPattern(decl.name)) { + ts.forEachChild(decl.name, visit); + break; + } + if (decl.initializer) + visit(decl.initializer); + } + case 255 /* EnumMember */: case 145 /* PropertyDeclaration */: case 144 /* PropertySignature */: - case 148 /* Constructor */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - staticFlag &= searchSpaceNode.flags; - searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class + addDeclaration(node); break; - case 256 /* SourceFile */: - if (ts.isExternalModule(searchSpaceNode)) { - return undefined; + case 236 /* ExportDeclaration */: + // Handle named exports case e.g.: + // export {a, b as B} from "mod"; + if (node.exportClause) { + ts.forEach(node.exportClause.elements, visit); } - // Fall through - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: break; - // Computed properties in classes are not handled here because references to this are illegal, - // so there is no point finding references to them. - default: - return undefined; - } - var references = []; - var possiblePositions; - if (searchSpaceNode.kind === 256 /* SourceFile */) { - ts.forEach(sourceFiles, function (sourceFile) { - possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", sourceFile.getStart(), sourceFile.getEnd()); - getThisReferencesInFile(sourceFile, sourceFile, possiblePositions, references); - }); - } - else { - var sourceFile = searchSpaceNode.getSourceFile(); - possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); - getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, references); - } - var thisOrSuperSymbol = typeChecker.getSymbolAtLocation(thisOrSuperKeyword); - var displayParts = thisOrSuperSymbol && getSymbolDisplayPartsDocumentationAndSymbolKind(thisOrSuperSymbol, thisOrSuperKeyword.getSourceFile(), getContainerNode(thisOrSuperKeyword), thisOrSuperKeyword).displayParts; - return [{ - definition: { - containerKind: "", - containerName: "", - fileName: node.getSourceFile().fileName, - kind: ts.ScriptElementKind.variableElement, - name: "this", - textSpan: ts.createTextSpanFromBounds(node.getStart(), node.getEnd()), - displayParts: displayParts - }, - references: references - }]; - function getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, result) { - ts.forEach(possiblePositions, function (position) { - cancellationToken.throwIfCancellationRequested(); - var node = ts.getTouchingWord(sourceFile, position); - if (!node || !isThis(node)) { - return; - } - var container = ts.getThisContainer(node, /* includeArrowFunctions */ false); - switch (searchSpaceNode.kind) { - case 179 /* FunctionExpression */: - case 220 /* FunctionDeclaration */: - if (searchSpaceNode.symbol === container.symbol) { - result.push(getReferenceEntryFromNode(node)); - } - break; - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - if (ts.isObjectLiteralMethod(searchSpaceNode) && searchSpaceNode.symbol === container.symbol) { - result.push(getReferenceEntryFromNode(node)); - } - break; - case 192 /* ClassExpression */: - case 221 /* ClassDeclaration */: - // Make sure the container belongs to the same class - // and has the appropriate static modifier from the original container. - if (container.parent && searchSpaceNode.symbol === container.parent.symbol && (container.flags & 32 /* Static */) === staticFlag) { - result.push(getReferenceEntryFromNode(node)); + case 230 /* ImportDeclaration */: + var importClause = node.importClause; + if (importClause) { + // Handle default import case e.g.: + // import d from "mod"; + if (importClause.name) { + addDeclaration(importClause); + } + // Handle named bindings in imports e.g.: + // import * as NS from "mod"; + // import {a, b as B} from "mod"; + if (importClause.namedBindings) { + if (importClause.namedBindings.kind === 232 /* NamespaceImport */) { + addDeclaration(importClause.namedBindings); } - break; - case 256 /* SourceFile */: - if (container.kind === 256 /* SourceFile */ && !ts.isExternalModule(container)) { - result.push(getReferenceEntryFromNode(node)); + else { + ts.forEach(importClause.namedBindings.elements, visit); } - break; + } } - }); + break; + default: + ts.forEachChild(node, visit); } } - function getReferencesForStringLiteral(node, sourceFiles) { - var typeChecker = program.getTypeChecker(); - var type = getStringLiteralTypeForNode(node, typeChecker); - if (!type) { - // nothing to do here. moving on - return undefined; - } - var references = []; - for (var _i = 0, sourceFiles_5 = sourceFiles; _i < sourceFiles_5.length; _i++) { - var sourceFile = sourceFiles_5[_i]; - var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, type.text, sourceFile.getStart(), sourceFile.getEnd()); - getReferencesForStringLiteralInFile(sourceFile, type, possiblePositions, references); + }; + return SourceFileObject; + }(NodeObject)); + function getServicesObjectAllocator() { + return { + getNodeConstructor: function () { return NodeObject; }, + getTokenConstructor: function () { return TokenObject; }, + getIdentifierConstructor: function () { return IdentifierObject; }, + getSourceFileConstructor: function () { return SourceFileObject; }, + getSymbolConstructor: function () { return SymbolObject; }, + getTypeConstructor: function () { return TypeObject; }, + getSignatureConstructor: function () { return SignatureObject; }, + }; + } + function toEditorSettings(optionsAsMap) { + var allPropertiesAreCamelCased = true; + for (var key in optionsAsMap) { + if (ts.hasProperty(optionsAsMap, key) && !isCamelCase(key)) { + allPropertiesAreCamelCased = false; + break; + } + } + if (allPropertiesAreCamelCased) { + return optionsAsMap; + } + var settings = {}; + for (var key in optionsAsMap) { + if (ts.hasProperty(optionsAsMap, key)) { + var newKey = isCamelCase(key) ? key : key.charAt(0).toLowerCase() + key.substr(1); + settings[newKey] = optionsAsMap[key]; + } + } + return settings; + } + ts.toEditorSettings = toEditorSettings; + function isCamelCase(s) { + return !s.length || s.charAt(0) === s.charAt(0).toLowerCase(); + } + function displayPartsToString(displayParts) { + if (displayParts) { + return ts.map(displayParts, function (displayPart) { return displayPart.text; }).join(""); + } + return ""; + } + ts.displayPartsToString = displayPartsToString; + function getDefaultCompilerOptions() { + // Always default to "ScriptTarget.ES5" for the language service + return { + target: 1 /* ES5 */, + jsx: 1 /* Preserve */ + }; + } + ts.getDefaultCompilerOptions = getDefaultCompilerOptions; + // Cache host information about script should be refreshed + // at each language service public entry point, since we don't know when + // set of scripts handled by the host changes. + var HostCache = (function () { + function HostCache(host, getCanonicalFileName) { + this.host = host; + this.getCanonicalFileName = getCanonicalFileName; + // script id => script index + this.currentDirectory = host.getCurrentDirectory(); + this.fileNameToEntry = ts.createFileMap(); + // Initialize the list with the root file names + var rootFileNames = host.getScriptFileNames(); + for (var _i = 0, rootFileNames_1 = rootFileNames; _i < rootFileNames_1.length; _i++) { + var fileName = rootFileNames_1[_i]; + this.createEntry(fileName, ts.toPath(fileName, this.currentDirectory, getCanonicalFileName)); + } + // store the compilation settings + this._compilationSettings = host.getCompilationSettings() || getDefaultCompilerOptions(); + } + HostCache.prototype.compilationSettings = function () { + return this._compilationSettings; + }; + HostCache.prototype.createEntry = function (fileName, path) { + var entry; + var scriptSnapshot = this.host.getScriptSnapshot(fileName); + if (scriptSnapshot) { + entry = { + hostFileName: fileName, + version: this.host.getScriptVersion(fileName), + scriptSnapshot: scriptSnapshot, + scriptKind: ts.getScriptKind(fileName, this.host) + }; + } + this.fileNameToEntry.set(path, entry); + return entry; + }; + HostCache.prototype.getEntry = function (path) { + return this.fileNameToEntry.get(path); + }; + HostCache.prototype.contains = function (path) { + return this.fileNameToEntry.contains(path); + }; + HostCache.prototype.getOrCreateEntry = function (fileName) { + var path = ts.toPath(fileName, this.currentDirectory, this.getCanonicalFileName); + return this.getOrCreateEntryByPath(fileName, path); + }; + HostCache.prototype.getOrCreateEntryByPath = function (fileName, path) { + return this.contains(path) + ? this.getEntry(path) + : this.createEntry(fileName, path); + }; + HostCache.prototype.getRootFileNames = function () { + var fileNames = []; + this.fileNameToEntry.forEachValue(function (path, value) { + if (value) { + fileNames.push(value.hostFileName); } - return [{ - definition: { - containerKind: "", - containerName: "", - fileName: node.getSourceFile().fileName, - kind: ts.ScriptElementKind.variableElement, - name: type.text, - textSpan: ts.createTextSpanFromBounds(node.getStart(), node.getEnd()), - displayParts: [ts.displayPart(ts.getTextOfNode(node), ts.SymbolDisplayPartKind.stringLiteral)] - }, - references: references - }]; - function getReferencesForStringLiteralInFile(sourceFile, searchType, possiblePositions, references) { - for (var _i = 0, possiblePositions_1 = possiblePositions; _i < possiblePositions_1.length; _i++) { - var position = possiblePositions_1[_i]; - cancellationToken.throwIfCancellationRequested(); - var node_2 = ts.getTouchingWord(sourceFile, position); - if (!node_2 || node_2.kind !== 9 /* StringLiteral */) { - return; - } - var type_1 = getStringLiteralTypeForNode(node_2, typeChecker); - if (type_1 === searchType) { - references.push(getReferenceEntryFromNode(node_2)); + }); + return fileNames; + }; + HostCache.prototype.getVersion = function (path) { + var file = this.getEntry(path); + return file && file.version; + }; + HostCache.prototype.getScriptSnapshot = function (path) { + var file = this.getEntry(path); + return file && file.scriptSnapshot; + }; + return HostCache; + }()); + var SyntaxTreeCache = (function () { + function SyntaxTreeCache(host) { + this.host = host; + } + SyntaxTreeCache.prototype.getCurrentSourceFile = function (fileName) { + var scriptSnapshot = this.host.getScriptSnapshot(fileName); + if (!scriptSnapshot) { + // The host does not know about this file. + throw new Error("Could not find file: '" + fileName + "'."); + } + var scriptKind = ts.getScriptKind(fileName, this.host); + var version = this.host.getScriptVersion(fileName); + var sourceFile; + if (this.currentFileName !== fileName) { + // This is a new file, just parse it + sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, 2 /* Latest */, version, /*setNodeParents*/ true, scriptKind); + } + else if (this.currentFileVersion !== version) { + // This is the same file, just a newer version. Incrementally parse the file. + var editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot); + sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, editRange); + } + if (sourceFile) { + // All done, ensure state is up to date + this.currentFileVersion = version; + this.currentFileName = fileName; + this.currentFileScriptSnapshot = scriptSnapshot; + this.currentSourceFile = sourceFile; + } + return this.currentSourceFile; + }; + return SyntaxTreeCache; + }()); + function setSourceFileFields(sourceFile, scriptSnapshot, version) { + sourceFile.version = version; + sourceFile.scriptSnapshot = scriptSnapshot; + } + function createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget, version, setNodeParents, scriptKind) { + var text = scriptSnapshot.getText(0, scriptSnapshot.getLength()); + var sourceFile = ts.createSourceFile(fileName, text, scriptTarget, setNodeParents, scriptKind); + setSourceFileFields(sourceFile, scriptSnapshot, version); + return sourceFile; + } + ts.createLanguageServiceSourceFile = createLanguageServiceSourceFile; + ts.disableIncrementalParsing = false; + function updateLanguageServiceSourceFile(sourceFile, scriptSnapshot, version, textChangeRange, aggressiveChecks) { + // If we were given a text change range, and our version or open-ness changed, then + // incrementally parse this file. + if (textChangeRange) { + if (version !== sourceFile.version) { + // Once incremental parsing is ready, then just call into this function. + if (!ts.disableIncrementalParsing) { + var newText = void 0; + // grab the fragment from the beginning of the original text to the beginning of the span + var prefix = textChangeRange.span.start !== 0 + ? sourceFile.text.substr(0, textChangeRange.span.start) + : ""; + // grab the fragment from the end of the span till the end of the original text + var suffix = ts.textSpanEnd(textChangeRange.span) !== sourceFile.text.length + ? sourceFile.text.substr(ts.textSpanEnd(textChangeRange.span)) + : ""; + if (textChangeRange.newLength === 0) { + // edit was a deletion - just combine prefix and suffix + newText = prefix && suffix ? prefix + suffix : prefix || suffix; + } + else { + // it was actual edit, fetch the fragment of new text that correspond to new span + var changedText = scriptSnapshot.getText(textChangeRange.span.start, textChangeRange.span.start + textChangeRange.newLength); + // combine prefix, changed text and suffix + newText = prefix && suffix + ? prefix + changedText + suffix + : prefix + ? (prefix + changedText) + : (changedText + suffix); + } + var newSourceFile = ts.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); + setSourceFileFields(newSourceFile, scriptSnapshot, version); + // after incremental parsing nameTable might not be up-to-date + // drop it so it can be lazily recreated later + newSourceFile.nameTable = undefined; + // dispose all resources held by old script snapshot + if (sourceFile !== newSourceFile && sourceFile.scriptSnapshot) { + if (sourceFile.scriptSnapshot.dispose) { + sourceFile.scriptSnapshot.dispose(); } + sourceFile.scriptSnapshot = undefined; } + return newSourceFile; } } - function populateSearchSymbolSet(symbol, location) { - // The search set contains at least the current symbol - var result = [symbol]; - // If the location is name of property symbol from object literal destructuring pattern - // Search the property symbol - // for ( { property: p2 } of elems) { } - var containingObjectLiteralElement = getContainingObjectLiteralElement(location); - if (containingObjectLiteralElement && containingObjectLiteralElement.kind !== 254 /* ShorthandPropertyAssignment */) { - var propertySymbol = getPropertySymbolOfDestructuringAssignment(location); - if (propertySymbol) { - result.push(propertySymbol); + } + // Otherwise, just create a new source file. + return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents*/ true, sourceFile.scriptKind); + } + ts.updateLanguageServiceSourceFile = updateLanguageServiceSourceFile; + var CancellationTokenObject = (function () { + function CancellationTokenObject(cancellationToken) { + this.cancellationToken = cancellationToken; + } + CancellationTokenObject.prototype.isCancellationRequested = function () { + return this.cancellationToken && this.cancellationToken.isCancellationRequested(); + }; + CancellationTokenObject.prototype.throwIfCancellationRequested = function () { + if (this.isCancellationRequested()) { + throw new ts.OperationCanceledException(); + } + }; + return CancellationTokenObject; + }()); + function createLanguageService(host, documentRegistry) { + if (documentRegistry === void 0) { documentRegistry = ts.createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory()); } + var syntaxTreeCache = new SyntaxTreeCache(host); + var ruleProvider; + var program; + var lastProjectVersion; + var lastTypesRootVersion = 0; + var useCaseSensitivefileNames = host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(); + var cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken()); + var currentDirectory = host.getCurrentDirectory(); + // Check if the localized messages json is set, otherwise query the host for it + if (!ts.localizedDiagnosticMessages && host.getLocalizedDiagnosticMessages) { + ts.localizedDiagnosticMessages = host.getLocalizedDiagnosticMessages(); + } + function log(message) { + if (host.log) { + host.log(message); + } + } + var getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitivefileNames); + function getValidSourceFile(fileName) { + var sourceFile = program.getSourceFile(fileName); + if (!sourceFile) { + throw new Error("Could not find file: '" + fileName + "'."); + } + return sourceFile; + } + function getRuleProvider(options) { + // Ensure rules are initialized and up to date wrt to formatting options + if (!ruleProvider) { + ruleProvider = new ts.formatting.RulesProvider(); + } + ruleProvider.ensureUpToDate(options); + return ruleProvider; + } + function synchronizeHostData() { + // perform fast check if host supports it + if (host.getProjectVersion) { + var hostProjectVersion = host.getProjectVersion(); + if (hostProjectVersion) { + if (lastProjectVersion === hostProjectVersion) { + return; } + lastProjectVersion = hostProjectVersion; } - // If the symbol is an alias, add what it aliases to the list - // import {a} from "mod"; - // export {a} - // If the symbol is an alias to default declaration, add what it aliases to the list - // declare "mod" { export default class B { } } - // import B from "mod"; - //// For export specifiers, the exported name can be referring to a local symbol, e.g.: - //// import {a} from "mod"; - //// export {a as somethingElse} - //// We want the *local* declaration of 'a' as declared in the import, - //// *not* as declared within "mod" (or farther) - var aliasSymbol = getAliasSymbolForPropertyNameSymbol(symbol, location); - if (aliasSymbol) { - result = result.concat(populateSearchSymbolSet(aliasSymbol, location)); + } + var typeRootsVersion = host.getTypeRootsVersion ? host.getTypeRootsVersion() : 0; + if (lastTypesRootVersion !== typeRootsVersion) { + log("TypeRoots version has changed; provide new program"); + program = undefined; + lastTypesRootVersion = typeRootsVersion; + } + // Get a fresh cache of the host information + var hostCache = new HostCache(host, getCanonicalFileName); + // If the program is already up-to-date, we can reuse it + if (programUpToDate()) { + return; + } + // IMPORTANT - It is critical from this moment onward that we do not check + // cancellation tokens. We are about to mutate source files from a previous program + // instance. If we cancel midway through, we may end up in an inconsistent state where + // the program points to old source files that have been invalidated because of + // incremental parsing. + var oldSettings = program && program.getCompilerOptions(); + var newSettings = hostCache.compilationSettings(); + var shouldCreateNewSourceFiles = oldSettings && + (oldSettings.target !== newSettings.target || + oldSettings.module !== newSettings.module || + oldSettings.moduleResolution !== newSettings.moduleResolution || + oldSettings.noResolve !== newSettings.noResolve || + oldSettings.jsx !== newSettings.jsx || + oldSettings.allowJs !== newSettings.allowJs || + oldSettings.disableSizeLimit !== oldSettings.disableSizeLimit || + oldSettings.baseUrl !== newSettings.baseUrl || + !ts.equalOwnProperties(oldSettings.paths, newSettings.paths)); + // Now create a new compiler + var compilerHost = { + getSourceFile: getOrCreateSourceFile, + getSourceFileByPath: getOrCreateSourceFileByPath, + getCancellationToken: function () { return cancellationToken; }, + getCanonicalFileName: getCanonicalFileName, + useCaseSensitiveFileNames: function () { return useCaseSensitivefileNames; }, + getNewLine: function () { return ts.getNewLineOrDefaultFromHost(host); }, + getDefaultLibFileName: function (options) { return host.getDefaultLibFileName(options); }, + writeFile: function (fileName, data, writeByteOrderMark) { }, + getCurrentDirectory: function () { return currentDirectory; }, + fileExists: function (fileName) { + // stub missing host functionality + return hostCache.getOrCreateEntry(fileName) !== undefined; + }, + readFile: function (fileName) { + // stub missing host functionality + var entry = hostCache.getOrCreateEntry(fileName); + return entry && entry.scriptSnapshot.getText(0, entry.scriptSnapshot.getLength()); + }, + directoryExists: function (directoryName) { + return ts.directoryProbablyExists(directoryName, host); + }, + getDirectories: function (path) { + return host.getDirectories ? host.getDirectories(path) : []; } - // If the location is in a context sensitive location (i.e. in an object literal) try - // to get a contextual type for it, and add the property symbol from the contextual - // type to the search set - if (containingObjectLiteralElement) { - ts.forEach(getPropertySymbolsFromContextualType(containingObjectLiteralElement), function (contextualSymbol) { - ts.addRange(result, typeChecker.getRootSymbols(contextualSymbol)); - }); - /* Because in short-hand property assignment, location has two meaning : property name and as value of the property - * When we do findAllReference at the position of the short-hand property assignment, we would want to have references to position of - * property name and variable declaration of the identifier. - * Like in below example, when querying for all references for an identifier 'name', of the property assignment, the language service - * should show both 'name' in 'obj' and 'name' in variable declaration - * const name = "Foo"; - * const obj = { name }; - * In order to do that, we will populate the search set with the value symbol of the identifier as a value of the property assignment - * so that when matching with potential reference symbol, both symbols from property declaration and variable declaration - * will be included correctly. - */ - var shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(location.parent); - if (shorthandValueSymbol) { - result.push(shorthandValueSymbol); + }; + if (host.trace) { + compilerHost.trace = function (message) { return host.trace(message); }; + } + if (host.resolveModuleNames) { + compilerHost.resolveModuleNames = function (moduleNames, containingFile) { return host.resolveModuleNames(moduleNames, containingFile); }; + } + if (host.resolveTypeReferenceDirectives) { + compilerHost.resolveTypeReferenceDirectives = function (typeReferenceDirectiveNames, containingFile) { + return host.resolveTypeReferenceDirectives(typeReferenceDirectiveNames, containingFile); + }; + } + var documentRegistryBucketKey = documentRegistry.getKeyForCompilationSettings(newSettings); + var newProgram = ts.createProgram(hostCache.getRootFileNames(), newSettings, compilerHost, program); + // Release any files we have acquired in the old program but are + // not part of the new program. + if (program) { + var oldSourceFiles = program.getSourceFiles(); + var oldSettingsKey = documentRegistry.getKeyForCompilationSettings(oldSettings); + for (var _i = 0, oldSourceFiles_1 = oldSourceFiles; _i < oldSourceFiles_1.length; _i++) { + var oldSourceFile = oldSourceFiles_1[_i]; + if (!newProgram.getSourceFile(oldSourceFile.fileName) || shouldCreateNewSourceFiles) { + documentRegistry.releaseDocumentWithKey(oldSourceFile.path, oldSettingsKey); } } - // If the symbol.valueDeclaration is a property parameter declaration, - // we should include both parameter declaration symbol and property declaration symbol - // Parameter Declaration symbol is only visible within function scope, so the symbol is stored in constructor.locals. - // Property Declaration symbol is a member of the class, so the symbol is stored in its class Declaration.symbol.members - if (symbol.valueDeclaration && symbol.valueDeclaration.kind === 142 /* Parameter */ && - ts.isParameterPropertyDeclaration(symbol.valueDeclaration)) { - result = result.concat(typeChecker.getSymbolsOfParameterPropertyDeclaration(symbol.valueDeclaration, symbol.name)); - } - // If this is symbol of binding element without propertyName declaration in Object binding pattern - // Include the property in the search - var bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol); - if (bindingElementPropertySymbol) { - result.push(bindingElementPropertySymbol); - } - // If this is a union property, add all the symbols from all its source symbols in all unioned types. - // If the symbol is an instantiation from a another symbol (e.g. widened symbol) , add the root the list - ts.forEach(typeChecker.getRootSymbols(symbol), function (rootSymbol) { - if (rootSymbol !== symbol) { - result.push(rootSymbol); - } - // Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions - if (rootSymbol.parent && rootSymbol.parent.flags & (32 /* Class */ | 64 /* Interface */)) { - getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ ts.createMap()); - } - }); - return result; } - /** - * Find symbol of the given property-name and add the symbol to the given result array - * @param symbol a symbol to start searching for the given propertyName - * @param propertyName a name of property to search for - * @param result an array of symbol of found property symbols - * @param previousIterationSymbolsCache a cache of symbol from previous iterations of calling this function to prevent infinite revisiting of the same symbol. - * The value of previousIterationSymbol is undefined when the function is first called. - */ - function getPropertySymbolsFromBaseTypes(symbol, propertyName, result, previousIterationSymbolsCache) { - if (!symbol) { - return; - } - // If the current symbol is the same as the previous-iteration symbol, we can just return the symbol that has already been visited - // This is particularly important for the following cases, so that we do not infinitely visit the same symbol. - // For example: - // interface C extends C { - // /*findRef*/propName: string; - // } - // The first time getPropertySymbolsFromBaseTypes is called when finding-all-references at propName, - // the symbol argument will be the symbol of an interface "C" and previousIterationSymbol is undefined, - // the function will add any found symbol of the property-name, then its sub-routine will call - // getPropertySymbolsFromBaseTypes again to walk up any base types to prevent revisiting already - // visited symbol, interface "C", the sub-routine will pass the current symbol as previousIterationSymbol. - if (symbol.name in previousIterationSymbolsCache) { - return; - } - if (symbol.flags & (32 /* Class */ | 64 /* Interface */)) { - ts.forEach(symbol.getDeclarations(), function (declaration) { - if (ts.isClassLike(declaration)) { - getPropertySymbolFromTypeReference(ts.getClassExtendsHeritageClauseElement(declaration)); - ts.forEach(ts.getClassImplementsHeritageClauseElements(declaration), getPropertySymbolFromTypeReference); - } - else if (declaration.kind === 222 /* InterfaceDeclaration */) { - ts.forEach(ts.getInterfaceBaseTypeNodes(declaration), getPropertySymbolFromTypeReference); - } - }); + // hostCache is captured in the closure for 'getOrCreateSourceFile' but it should not be used past this point. + // It needs to be cleared to allow all collected snapshots to be released + hostCache = undefined; + program = newProgram; + // Make sure all the nodes in the program are both bound, and have their parent + // pointers set property. + program.getTypeChecker(); + return; + function getOrCreateSourceFile(fileName) { + return getOrCreateSourceFileByPath(fileName, ts.toPath(fileName, currentDirectory, getCanonicalFileName)); + } + function getOrCreateSourceFileByPath(fileName, path) { + ts.Debug.assert(hostCache !== undefined); + // The program is asking for this file, check first if the host can locate it. + // If the host can not locate the file, then it does not exist. return undefined + // to the program to allow reporting of errors for missing files. + var hostFileInformation = hostCache.getOrCreateEntryByPath(fileName, path); + if (!hostFileInformation) { + return undefined; } - return; - function getPropertySymbolFromTypeReference(typeReference) { - if (typeReference) { - var type = typeChecker.getTypeAtLocation(typeReference); - if (type) { - var propertySymbol = typeChecker.getPropertyOfType(type, propertyName); - if (propertySymbol) { - result.push.apply(result, typeChecker.getRootSymbols(propertySymbol)); - } - // Visit the typeReference as well to see if it directly or indirectly use that property - previousIterationSymbolsCache[symbol.name] = symbol; - getPropertySymbolsFromBaseTypes(type.symbol, propertyName, result, previousIterationSymbolsCache); - } + // Check if the language version has changed since we last created a program; if they are the same, + // it is safe to reuse the sourceFiles; if not, then the shape of the AST can change, and the oldSourceFile + // can not be reused. we have to dump all syntax trees and create new ones. + if (!shouldCreateNewSourceFiles) { + // Check if the old program had this file already + var oldSourceFile = program && program.getSourceFileByPath(path); + if (oldSourceFile) { + // We already had a source file for this file name. Go to the registry to + // ensure that we get the right up to date version of it. We need this to + // address the following race-condition. Specifically, say we have the following: + // + // LS1 + // \ + // DocumentRegistry + // / + // LS2 + // + // Each LS has a reference to file 'foo.ts' at version 1. LS2 then updates + // it's version of 'foo.ts' to version 2. This will cause LS2 and the + // DocumentRegistry to have version 2 of the document. HOwever, LS1 will + // have version 1. And *importantly* this source file will be *corrupt*. + // The act of creating version 2 of the file irrevocably damages the version + // 1 file. + // + // So, later when we call into LS1, we need to make sure that it doesn't use + // it's source file any more, and instead defers to DocumentRegistry to get + // either version 1, version 2 (or some other version) depending on what the + // host says should be used. + // We do not support the scenario where a host can modify a registered + // file's script kind, i.e. in one project some file is treated as ".ts" + // and in another as ".js" + ts.Debug.assert(hostFileInformation.scriptKind === oldSourceFile.scriptKind, "Registered script kind (" + oldSourceFile.scriptKind + ") should match new script kind (" + hostFileInformation.scriptKind + ") for file: " + path); + return documentRegistry.updateDocumentWithKey(fileName, path, newSettings, documentRegistryBucketKey, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind); } } + // Could not find this file in the old program, create a new SourceFile for it. + return documentRegistry.acquireDocumentWithKey(fileName, path, newSettings, documentRegistryBucketKey, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind); } - function getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation, searchLocationIsConstructor) { - if (ts.contains(searchSymbols, referenceSymbol)) { - // If we are searching for constructor uses, they must be 'new' expressions. - return (!searchLocationIsConstructor || isNewExpressionTarget(referenceLocation)) && referenceSymbol; - } - // If the reference symbol is an alias, check if what it is aliasing is one of the search - // symbols but by looking up for related symbol of this alias so it can handle multiple level of indirectness. - var aliasSymbol = getAliasSymbolForPropertyNameSymbol(referenceSymbol, referenceLocation); - if (aliasSymbol) { - return getRelatedSymbol(searchSymbols, aliasSymbol, referenceLocation, searchLocationIsConstructor); + function sourceFileUpToDate(sourceFile) { + if (!sourceFile) { + return false; } - // If the reference location is in an object literal, try to get the contextual type for the - // object literal, lookup the property symbol in the contextual type, and use this symbol to - // compare to our searchSymbol - var containingObjectLiteralElement = getContainingObjectLiteralElement(referenceLocation); - if (containingObjectLiteralElement) { - var contextualSymbol = ts.forEach(getPropertySymbolsFromContextualType(containingObjectLiteralElement), function (contextualSymbol) { - return ts.forEach(typeChecker.getRootSymbols(contextualSymbol), function (s) { return searchSymbols.indexOf(s) >= 0 ? s : undefined; }); - }); - if (contextualSymbol) { - return contextualSymbol; - } - // If the reference location is the name of property from object literal destructuring pattern - // Get the property symbol from the object literal's type and look if thats the search symbol - // In below eg. get 'property' from type of elems iterating type - // for ( { property: p2 } of elems) { } - var propertySymbol = getPropertySymbolOfDestructuringAssignment(referenceLocation); - if (propertySymbol && searchSymbols.indexOf(propertySymbol) >= 0) { - return propertySymbol; - } + var path = sourceFile.path || ts.toPath(sourceFile.fileName, currentDirectory, getCanonicalFileName); + return sourceFile.version === hostCache.getVersion(path); + } + function programUpToDate() { + // If we haven't create a program yet, then it is not up-to-date + if (!program) { + return false; } - // If the reference location is the binding element and doesn't have property name - // then include the binding element in the related symbols - // let { a } : { a }; - var bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(referenceSymbol); - if (bindingElementPropertySymbol && searchSymbols.indexOf(bindingElementPropertySymbol) >= 0) { - return bindingElementPropertySymbol; + // If number of files in the program do not match, it is not up-to-date + var rootFileNames = hostCache.getRootFileNames(); + if (program.getSourceFiles().length !== rootFileNames.length) { + return false; } - // Unwrap symbols to get to the root (e.g. transient symbols as a result of widening) - // Or a union property, use its underlying unioned symbols - return ts.forEach(typeChecker.getRootSymbols(referenceSymbol), function (rootSymbol) { - // if it is in the list, then we are done - if (searchSymbols.indexOf(rootSymbol) >= 0) { - return rootSymbol; - } - // Finally, try all properties with the same name in any type the containing type extended or implemented, and - // see if any is in the list - if (rootSymbol.parent && rootSymbol.parent.flags & (32 /* Class */ | 64 /* Interface */)) { - var result_5 = []; - getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result_5, /*previousIterationSymbolsCache*/ ts.createMap()); - return ts.forEach(result_5, function (s) { return searchSymbols.indexOf(s) >= 0 ? s : undefined; }); + // If any file is not up-to-date, then the whole program is not up-to-date + for (var _i = 0, rootFileNames_2 = rootFileNames; _i < rootFileNames_2.length; _i++) { + var fileName = rootFileNames_2[_i]; + if (!sourceFileUpToDate(program.getSourceFile(fileName))) { + return false; } - return undefined; + } + // If the compilation settings do no match, then the program is not up-to-date + return ts.compareDataObjects(program.getCompilerOptions(), hostCache.compilationSettings()); + } + } + function getProgram() { + synchronizeHostData(); + return program; + } + function cleanupSemanticCache() { + // TODO: Should we jettison the program (or it's type checker) here? + } + function dispose() { + if (program) { + ts.forEach(program.getSourceFiles(), function (f) { + return documentRegistry.releaseDocument(f.fileName, program.getCompilerOptions()); }); } - function getNameFromObjectLiteralElement(node) { - if (node.name.kind === 140 /* ComputedPropertyName */) { - var nameExpression = node.name.expression; - // treat computed property names where expression is string/numeric literal as just string/numeric literal - if (ts.isStringOrNumericLiteral(nameExpression.kind)) { - return nameExpression.text; - } - return undefined; - } - return node.name.text; + } + /// Diagnostics + function getSyntacticDiagnostics(fileName) { + synchronizeHostData(); + return program.getSyntacticDiagnostics(getValidSourceFile(fileName), cancellationToken); + } + /** + * getSemanticDiagnostics return array of Diagnostics. If '-d' is not enabled, only report semantic errors + * If '-d' enabled, report both semantic and emitter errors + */ + function getSemanticDiagnostics(fileName) { + synchronizeHostData(); + var targetSourceFile = getValidSourceFile(fileName); + // Only perform the action per file regardless of '-out' flag as LanguageServiceHost is expected to call this function per file. + // Therefore only get diagnostics for given file. + var semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken); + if (!program.getCompilerOptions().declaration) { + return semanticDiagnostics; } - function getPropertySymbolsFromContextualType(node) { - var objectLiteral = node.parent; - var contextualType = typeChecker.getContextualType(objectLiteral); - var name = getNameFromObjectLiteralElement(node); - if (name && contextualType) { - var result_6 = []; - var symbol_2 = contextualType.getProperty(name); - if (symbol_2) { - result_6.push(symbol_2); - } - if (contextualType.flags & 524288 /* Union */) { - ts.forEach(contextualType.types, function (t) { - var symbol = t.getProperty(name); - if (symbol) { - result_6.push(symbol); - } - }); - } - return result_6; - } + // If '-d' is enabled, check for emitter error. One example of emitter error is export class implements non-export interface + var declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile, cancellationToken); + return ts.concatenate(semanticDiagnostics, declarationDiagnostics); + } + function getCompilerOptionsDiagnostics() { + synchronizeHostData(); + return program.getOptionsDiagnostics(cancellationToken).concat(program.getGlobalDiagnostics(cancellationToken)); + } + function getCompletionsAtPosition(fileName, position) { + synchronizeHostData(); + return ts.Completions.getCompletionsAtPosition(host, program.getTypeChecker(), log, program.getCompilerOptions(), getValidSourceFile(fileName), position); + } + function getCompletionEntryDetails(fileName, position, entryName) { + synchronizeHostData(); + return ts.Completions.getCompletionEntryDetails(program.getTypeChecker(), log, program.getCompilerOptions(), getValidSourceFile(fileName), position, entryName); + } + function getCompletionEntrySymbol(fileName, position, entryName) { + synchronizeHostData(); + return ts.Completions.getCompletionEntrySymbol(program.getTypeChecker(), log, program.getCompilerOptions(), getValidSourceFile(fileName), position, entryName); + } + function getQuickInfoAtPosition(fileName, position) { + synchronizeHostData(); + var sourceFile = getValidSourceFile(fileName); + var node = ts.getTouchingPropertyName(sourceFile, position); + if (node === sourceFile) { return undefined; } - /** Given an initial searchMeaning, extracted from a location, widen the search scope based on the declarations - * of the corresponding symbol. e.g. if we are searching for "Foo" in value position, but "Foo" references a class - * then we need to widen the search to include type positions as well. - * On the contrary, if we are searching for "Bar" in type position and we trace bar to an interface, and an uninstantiated - * module, we want to keep the search limited to only types, as the two declarations (interface and uninstantiated module) - * do not intersect in any of the three spaces. - */ - function getIntersectingMeaningFromDeclarations(meaning, declarations) { - if (declarations) { - var lastIterationMeaning = void 0; - do { - // The result is order-sensitive, for instance if initialMeaning === Namespace, and declarations = [class, instantiated module] - // we need to consider both as they initialMeaning intersects with the module in the namespace space, and the module - // intersects with the class in the value space. - // To achieve that we will keep iterating until the result stabilizes. - // Remember the last meaning - lastIterationMeaning = meaning; - for (var _i = 0, declarations_10 = declarations; _i < declarations_10.length; _i++) { - var declaration = declarations_10[_i]; - var declarationMeaning = getMeaningFromDeclaration(declaration); - if (declarationMeaning & meaning) { - meaning |= declarationMeaning; - } + if (ts.isLabelName(node)) { + return undefined; + } + var typeChecker = program.getTypeChecker(); + var symbol = typeChecker.getSymbolAtLocation(node); + if (!symbol || typeChecker.isUnknownSymbol(symbol)) { + // Try getting just type at this position and show + switch (node.kind) { + case 69 /* Identifier */: + case 172 /* PropertyAccessExpression */: + case 139 /* QualifiedName */: + case 97 /* ThisKeyword */: + case 165 /* ThisType */: + case 95 /* SuperKeyword */: + // For the identifiers/this/super etc get the type at position + var type = typeChecker.getTypeAtLocation(node); + if (type) { + return { + kind: ts.ScriptElementKind.unknown, + kindModifiers: ts.ScriptElementKindModifier.none, + textSpan: ts.createTextSpan(node.getStart(), node.getWidth()), + displayParts: ts.typeToDisplayParts(typeChecker, type, ts.getContainerNode(node)), + documentation: type.symbol ? type.symbol.getDocumentationComment() : undefined + }; } - } while (meaning !== lastIterationMeaning); } - return meaning; - } - } - function getReferenceEntryFromNode(node) { - var start = node.getStart(); - var end = node.getEnd(); - if (node.kind === 9 /* StringLiteral */) { - start += 1; - end -= 1; + return undefined; } + var displayPartsDocumentationsAndKind = ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, sourceFile, ts.getContainerNode(node), node); return { - fileName: node.getSourceFile().fileName, - textSpan: ts.createTextSpanFromBounds(start, end), - isWriteAccess: isWriteAccess(node), - isDefinition: ts.isDeclarationName(node) || ts.isLiteralComputedPropertyDeclarationName(node) + kind: displayPartsDocumentationsAndKind.symbolKind, + kindModifiers: ts.SymbolDisplay.getSymbolModifiers(symbol), + textSpan: ts.createTextSpan(node.getStart(), node.getWidth()), + displayParts: displayPartsDocumentationsAndKind.displayParts, + documentation: displayPartsDocumentationsAndKind.documentation }; } - /** A node is considered a writeAccess iff it is a name of a declaration or a target of an assignment */ - function isWriteAccess(node) { - if (node.kind === 69 /* Identifier */ && ts.isDeclarationName(node)) { - return true; + /// Goto definition + function getDefinitionAtPosition(fileName, position) { + synchronizeHostData(); + return ts.GoToDefinition.getDefinitionAtPosition(program, getValidSourceFile(fileName), position); + } + /// Goto implementation + function getImplementationAtPosition(fileName, position) { + synchronizeHostData(); + return ts.GoToImplementation.getImplementationAtPosition(program.getTypeChecker(), cancellationToken, program.getSourceFiles(), ts.getTouchingPropertyName(getValidSourceFile(fileName), position)); + } + function getTypeDefinitionAtPosition(fileName, position) { + synchronizeHostData(); + return ts.GoToDefinition.getTypeDefinitionAtPosition(program.getTypeChecker(), getValidSourceFile(fileName), position); + } + function getOccurrencesAtPosition(fileName, position) { + var results = getOccurrencesAtPositionCore(fileName, position); + if (results) { + var sourceFile_3 = getCanonicalFileName(ts.normalizeSlashes(fileName)); + // Get occurrences only supports reporting occurrences for the file queried. So + // filter down to that list. + results = ts.filter(results, function (r) { return getCanonicalFileName(ts.normalizeSlashes(r.fileName)) === sourceFile_3; }); } - var parent = node.parent; - if (parent) { - if (parent.kind === 186 /* PostfixUnaryExpression */ || parent.kind === 185 /* PrefixUnaryExpression */) { - return true; + return results; + } + function getDocumentHighlights(fileName, position, filesToSearch) { + synchronizeHostData(); + var sourceFilesToSearch = ts.map(filesToSearch, function (f) { return program.getSourceFile(f); }); + var sourceFile = getValidSourceFile(fileName); + return ts.DocumentHighlights.getDocumentHighlights(program.getTypeChecker(), cancellationToken, sourceFile, position, sourceFilesToSearch); + } + /// References and Occurrences + function getOccurrencesAtPositionCore(fileName, position) { + synchronizeHostData(); + return convertDocumentHighlights(getDocumentHighlights(fileName, position, [fileName])); + function convertDocumentHighlights(documentHighlights) { + if (!documentHighlights) { + return undefined; } - else if (parent.kind === 187 /* BinaryExpression */ && parent.left === node) { - var operator = parent.operatorToken.kind; - return 56 /* FirstAssignment */ <= operator && operator <= 68 /* LastAssignment */; + var result = []; + for (var _i = 0, documentHighlights_1 = documentHighlights; _i < documentHighlights_1.length; _i++) { + var entry = documentHighlights_1[_i]; + for (var _a = 0, _b = entry.highlightSpans; _a < _b.length; _a++) { + var highlightSpan = _b[_a]; + result.push({ + fileName: entry.fileName, + textSpan: highlightSpan.textSpan, + isWriteAccess: highlightSpan.kind === ts.HighlightSpanKind.writtenReference, + isDefinition: false + }); + } } + return result; } - return false; + } + function findRenameLocations(fileName, position, findInStrings, findInComments) { + var referencedSymbols = findReferencedSymbols(fileName, position, findInStrings, findInComments); + return ts.FindAllReferences.convertReferences(referencedSymbols); + } + function getReferencesAtPosition(fileName, position) { + var referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings*/ false, /*findInComments*/ false); + return ts.FindAllReferences.convertReferences(referencedSymbols); + } + function findReferences(fileName, position) { + var referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings*/ false, /*findInComments*/ false); + // Only include referenced symbols that have a valid definition. + return ts.filter(referencedSymbols, function (rs) { return !!rs.definition; }); + } + function findReferencedSymbols(fileName, position, findInStrings, findInComments) { + synchronizeHostData(); + return ts.FindAllReferences.findReferencedSymbols(program.getTypeChecker(), cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position, findInStrings, findInComments); } /// NavigateTo - function getNavigateToItems(searchValue, maxResultCount) { + function getNavigateToItems(searchValue, maxResultCount, fileName, excludeDtsFiles) { synchronizeHostData(); - var checker = getProgram().getTypeChecker(); - return ts.NavigateTo.getNavigateToItems(program, checker, cancellationToken, searchValue, maxResultCount); + var sourceFiles = fileName ? [getValidSourceFile(fileName)] : program.getSourceFiles(); + return ts.NavigateTo.getNavigateToItems(sourceFiles, program.getTypeChecker(), cancellationToken, searchValue, maxResultCount, excludeDtsFiles); } - function getEmitOutput(fileName) { + function getEmitOutput(fileName, emitOnlyDtsFiles) { synchronizeHostData(); var sourceFile = getValidSourceFile(fileName); var outputFiles = []; @@ -59418,140 +74451,12 @@ var ts; text: data }); } - var emitOutput = program.emit(sourceFile, writeFile, cancellationToken); + var emitOutput = program.emit(sourceFile, writeFile, cancellationToken, emitOnlyDtsFiles); return { outputFiles: outputFiles, emitSkipped: emitOutput.emitSkipped }; } - function getMeaningFromDeclaration(node) { - switch (node.kind) { - case 142 /* Parameter */: - case 218 /* VariableDeclaration */: - case 169 /* BindingElement */: - case 145 /* PropertyDeclaration */: - case 144 /* PropertySignature */: - case 253 /* PropertyAssignment */: - case 254 /* ShorthandPropertyAssignment */: - case 255 /* EnumMember */: - case 147 /* MethodDeclaration */: - case 146 /* MethodSignature */: - case 148 /* Constructor */: - case 149 /* GetAccessor */: - case 150 /* SetAccessor */: - case 220 /* FunctionDeclaration */: - case 179 /* FunctionExpression */: - case 180 /* ArrowFunction */: - case 252 /* CatchClause */: - return 1 /* Value */; - case 141 /* TypeParameter */: - case 222 /* InterfaceDeclaration */: - case 223 /* TypeAliasDeclaration */: - case 159 /* TypeLiteral */: - return 2 /* Type */; - case 221 /* ClassDeclaration */: - case 224 /* EnumDeclaration */: - return 1 /* Value */ | 2 /* Type */; - case 225 /* ModuleDeclaration */: - if (ts.isAmbientModule(node)) { - return 4 /* Namespace */ | 1 /* Value */; - } - else if (ts.getModuleInstanceState(node) === 1 /* Instantiated */) { - return 4 /* Namespace */ | 1 /* Value */; - } - else { - return 4 /* Namespace */; - } - case 233 /* NamedImports */: - case 234 /* ImportSpecifier */: - case 229 /* ImportEqualsDeclaration */: - case 230 /* ImportDeclaration */: - case 235 /* ExportAssignment */: - case 236 /* ExportDeclaration */: - return 1 /* Value */ | 2 /* Type */ | 4 /* Namespace */; - // An external module can be a Value - case 256 /* SourceFile */: - return 4 /* Namespace */ | 1 /* Value */; - } - return 1 /* Value */ | 2 /* Type */ | 4 /* Namespace */; - } - function isTypeReference(node) { - if (ts.isRightSideOfQualifiedNameOrPropertyAccess(node)) { - node = node.parent; - } - return node.parent.kind === 155 /* TypeReference */ || - (node.parent.kind === 194 /* ExpressionWithTypeArguments */ && !ts.isExpressionWithTypeArgumentsInClassExtendsClause(node.parent)) || - (node.kind === 97 /* ThisKeyword */ && !ts.isExpression(node)) || - node.kind === 165 /* ThisType */; - } - function isNamespaceReference(node) { - return isQualifiedNameNamespaceReference(node) || isPropertyAccessNamespaceReference(node); - } - function isPropertyAccessNamespaceReference(node) { - var root = node; - var isLastClause = true; - if (root.parent.kind === 172 /* PropertyAccessExpression */) { - while (root.parent && root.parent.kind === 172 /* PropertyAccessExpression */) { - root = root.parent; - } - isLastClause = root.name === node; - } - if (!isLastClause && root.parent.kind === 194 /* ExpressionWithTypeArguments */ && root.parent.parent.kind === 251 /* HeritageClause */) { - var decl = root.parent.parent.parent; - return (decl.kind === 221 /* ClassDeclaration */ && root.parent.parent.token === 106 /* ImplementsKeyword */) || - (decl.kind === 222 /* InterfaceDeclaration */ && root.parent.parent.token === 83 /* ExtendsKeyword */); - } - return false; - } - function isQualifiedNameNamespaceReference(node) { - var root = node; - var isLastClause = true; - if (root.parent.kind === 139 /* QualifiedName */) { - while (root.parent && root.parent.kind === 139 /* QualifiedName */) { - root = root.parent; - } - isLastClause = root.right === node; - } - return root.parent.kind === 155 /* TypeReference */ && !isLastClause; - } - function isInRightSideOfImport(node) { - while (node.parent.kind === 139 /* QualifiedName */) { - node = node.parent; - } - return ts.isInternalModuleImportEqualsDeclaration(node.parent) && node.parent.moduleReference === node; - } - function getMeaningFromRightHandSideOfImportEquals(node) { - ts.Debug.assert(node.kind === 69 /* Identifier */); - // import a = |b|; // Namespace - // import a = |b.c|; // Value, type, namespace - // import a = |b.c|.d; // Namespace - if (node.parent.kind === 139 /* QualifiedName */ && - node.parent.right === node && - node.parent.parent.kind === 229 /* ImportEqualsDeclaration */) { - return 1 /* Value */ | 2 /* Type */ | 4 /* Namespace */; - } - return 4 /* Namespace */; - } - function getMeaningFromLocation(node) { - if (node.parent.kind === 235 /* ExportAssignment */) { - return 1 /* Value */ | 2 /* Type */ | 4 /* Namespace */; - } - else if (isInRightSideOfImport(node)) { - return getMeaningFromRightHandSideOfImportEquals(node); - } - else if (ts.isDeclarationName(node)) { - return getMeaningFromDeclaration(node.parent); - } - else if (isTypeReference(node)) { - return 2 /* Type */; - } - else if (isNamespaceReference(node)) { - return 4 /* Namespace */; - } - else { - return 1 /* Value */; - } - } // Signature help /** * This is a semantic operation. @@ -59565,6 +74470,9 @@ var ts; function getNonBoundSourceFile(fileName) { return syntaxTreeCache.getCurrentSourceFile(fileName); } + function getSourceFile(fileName) { + return getNonBoundSourceFile(fileName); + } function getNameOrDottedNameSpan(fileName, startPos, endPos) { var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); // Get node at the location @@ -59590,11 +74498,11 @@ var ts; } var nodeForStartPos = node; while (true) { - if (isRightSideOfPropertyAccess(nodeForStartPos) || isRightSideOfQualifiedName(nodeForStartPos)) { + if (ts.isRightSideOfPropertyAccess(nodeForStartPos) || ts.isRightSideOfQualifiedName(nodeForStartPos)) { // If on the span is in right side of the the property or qualified name, return the span from the qualified name pos to end of this node nodeForStartPos = nodeForStartPos.parent; } - else if (isNameOfModuleDeclaration(nodeForStartPos)) { + else if (ts.isNameOfModuleDeclaration(nodeForStartPos)) { // If this is name of a module declarations, check if this is right side of dotted module name // If parent of the module declaration which is parent of this node is module declaration and its body is the module declaration that this node is name of // Then this name is name from dotted module @@ -59625,465 +74533,20 @@ var ts; return ts.NavigationBar.getNavigationBarItems(sourceFile); } function getSemanticClassifications(fileName, span) { - return convertClassifications(getEncodedSemanticClassifications(fileName, span)); - } - function checkForClassificationCancellation(kind) { - // We don't want to actually call back into our host on every node to find out if we've - // been canceled. That would be an enormous amount of chattyness, along with the all - // the overhead of marshalling the data to/from the host. So instead we pick a few - // reasonable node kinds to bother checking on. These node kinds represent high level - // constructs that we would expect to see commonly, but just at a far less frequent - // interval. - // - // For example, in checker.ts (around 750k) we only have around 600 of these constructs. - // That means we're calling back into the host around every 1.2k of the file we process. - // Lib.d.ts has similar numbers. - switch (kind) { - case 225 /* ModuleDeclaration */: - case 221 /* ClassDeclaration */: - case 222 /* InterfaceDeclaration */: - case 220 /* FunctionDeclaration */: - cancellationToken.throwIfCancellationRequested(); - } + synchronizeHostData(); + return ts.getSemanticClassifications(program.getTypeChecker(), cancellationToken, getValidSourceFile(fileName), program.getClassifiableNames(), span); } function getEncodedSemanticClassifications(fileName, span) { synchronizeHostData(); - var sourceFile = getValidSourceFile(fileName); - var typeChecker = program.getTypeChecker(); - var result = []; - var classifiableNames = program.getClassifiableNames(); - processNode(sourceFile); - return { spans: result, endOfLineState: 0 /* None */ }; - function pushClassification(start, length, type) { - result.push(start); - result.push(length); - result.push(type); - } - function classifySymbol(symbol, meaningAtPosition) { - var flags = symbol.getFlags(); - if ((flags & 788448 /* Classifiable */) === 0 /* None */) { - return; - } - if (flags & 32 /* Class */) { - return 11 /* className */; - } - else if (flags & 384 /* Enum */) { - return 12 /* enumName */; - } - else if (flags & 524288 /* TypeAlias */) { - return 16 /* typeAliasName */; - } - else if (meaningAtPosition & 2 /* Type */) { - if (flags & 64 /* Interface */) { - return 13 /* interfaceName */; - } - else if (flags & 262144 /* TypeParameter */) { - return 15 /* typeParameterName */; - } - } - else if (flags & 1536 /* Module */) { - // Only classify a module as such if - // - It appears in a namespace context. - // - There exists a module declaration which actually impacts the value side. - if (meaningAtPosition & 4 /* Namespace */ || - (meaningAtPosition & 1 /* Value */ && hasValueSideModule(symbol))) { - return 14 /* moduleName */; - } - } - return undefined; - /** - * Returns true if there exists a module that introduces entities on the value side. - */ - function hasValueSideModule(symbol) { - return ts.forEach(symbol.declarations, function (declaration) { - return declaration.kind === 225 /* ModuleDeclaration */ && - ts.getModuleInstanceState(declaration) === 1 /* Instantiated */; - }); - } - } - function processNode(node) { - // Only walk into nodes that intersect the requested span. - if (node && ts.textSpanIntersectsWith(span, node.getFullStart(), node.getFullWidth())) { - var kind = node.kind; - checkForClassificationCancellation(kind); - if (kind === 69 /* Identifier */ && !ts.nodeIsMissing(node)) { - var identifier = node; - // Only bother calling into the typechecker if this is an identifier that - // could possibly resolve to a type name. This makes classification run - // in a third of the time it would normally take. - if (classifiableNames[identifier.text]) { - var symbol = typeChecker.getSymbolAtLocation(node); - if (symbol) { - var type = classifySymbol(symbol, getMeaningFromLocation(node)); - if (type) { - pushClassification(node.getStart(), node.getWidth(), type); - } - } - } - } - ts.forEachChild(node, processNode); - } - } - } - function getClassificationTypeName(type) { - switch (type) { - case 1 /* comment */: return ts.ClassificationTypeNames.comment; - case 2 /* identifier */: return ts.ClassificationTypeNames.identifier; - case 3 /* keyword */: return ts.ClassificationTypeNames.keyword; - case 4 /* numericLiteral */: return ts.ClassificationTypeNames.numericLiteral; - case 5 /* operator */: return ts.ClassificationTypeNames.operator; - case 6 /* stringLiteral */: return ts.ClassificationTypeNames.stringLiteral; - case 8 /* whiteSpace */: return ts.ClassificationTypeNames.whiteSpace; - case 9 /* text */: return ts.ClassificationTypeNames.text; - case 10 /* punctuation */: return ts.ClassificationTypeNames.punctuation; - case 11 /* className */: return ts.ClassificationTypeNames.className; - case 12 /* enumName */: return ts.ClassificationTypeNames.enumName; - case 13 /* interfaceName */: return ts.ClassificationTypeNames.interfaceName; - case 14 /* moduleName */: return ts.ClassificationTypeNames.moduleName; - case 15 /* typeParameterName */: return ts.ClassificationTypeNames.typeParameterName; - case 16 /* typeAliasName */: return ts.ClassificationTypeNames.typeAliasName; - case 17 /* parameterName */: return ts.ClassificationTypeNames.parameterName; - case 18 /* docCommentTagName */: return ts.ClassificationTypeNames.docCommentTagName; - case 19 /* jsxOpenTagName */: return ts.ClassificationTypeNames.jsxOpenTagName; - case 20 /* jsxCloseTagName */: return ts.ClassificationTypeNames.jsxCloseTagName; - case 21 /* jsxSelfClosingTagName */: return ts.ClassificationTypeNames.jsxSelfClosingTagName; - case 22 /* jsxAttribute */: return ts.ClassificationTypeNames.jsxAttribute; - case 23 /* jsxText */: return ts.ClassificationTypeNames.jsxText; - case 24 /* jsxAttributeStringLiteralValue */: return ts.ClassificationTypeNames.jsxAttributeStringLiteralValue; - } - } - function convertClassifications(classifications) { - ts.Debug.assert(classifications.spans.length % 3 === 0); - var dense = classifications.spans; - var result = []; - for (var i = 0, n = dense.length; i < n; i += 3) { - result.push({ - textSpan: ts.createTextSpan(dense[i], dense[i + 1]), - classificationType: getClassificationTypeName(dense[i + 2]) - }); - } - return result; + return ts.getEncodedSemanticClassifications(program.getTypeChecker(), cancellationToken, getValidSourceFile(fileName), program.getClassifiableNames(), span); } function getSyntacticClassifications(fileName, span) { - return convertClassifications(getEncodedSyntacticClassifications(fileName, span)); + // doesn't use compiler - no need to synchronize with host + return ts.getSyntacticClassifications(cancellationToken, syntaxTreeCache.getCurrentSourceFile(fileName), span); } function getEncodedSyntacticClassifications(fileName, span) { // doesn't use compiler - no need to synchronize with host - var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - var spanStart = span.start; - var spanLength = span.length; - // Make a scanner we can get trivia from. - var triviaScanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text); - var mergeConflictScanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text); - var result = []; - processElement(sourceFile); - return { spans: result, endOfLineState: 0 /* None */ }; - function pushClassification(start, length, type) { - result.push(start); - result.push(length); - result.push(type); - } - function classifyLeadingTriviaAndGetTokenStart(token) { - triviaScanner.setTextPos(token.pos); - while (true) { - var start = triviaScanner.getTextPos(); - // only bother scanning if we have something that could be trivia. - if (!ts.couldStartTrivia(sourceFile.text, start)) { - return start; - } - var kind = triviaScanner.scan(); - var end = triviaScanner.getTextPos(); - var width = end - start; - // The moment we get something that isn't trivia, then stop processing. - if (!ts.isTrivia(kind)) { - return start; - } - // Don't bother with newlines/whitespace. - if (kind === 4 /* NewLineTrivia */ || kind === 5 /* WhitespaceTrivia */) { - continue; - } - // Only bother with the trivia if it at least intersects the span of interest. - if (ts.isComment(kind)) { - classifyComment(token, kind, start, width); - // Classifying a comment might cause us to reuse the trivia scanner - // (because of jsdoc comments). So after we classify the comment make - // sure we set the scanner position back to where it needs to be. - triviaScanner.setTextPos(end); - continue; - } - if (kind === 7 /* ConflictMarkerTrivia */) { - var text = sourceFile.text; - var ch = text.charCodeAt(start); - // for the <<<<<<< and >>>>>>> markers, we just add them in as comments - // in the classification stream. - if (ch === 60 /* lessThan */ || ch === 62 /* greaterThan */) { - pushClassification(start, width, 1 /* comment */); - continue; - } - // for the ======== add a comment for the first line, and then lex all - // subsequent lines up until the end of the conflict marker. - ts.Debug.assert(ch === 61 /* equals */); - classifyDisabledMergeCode(text, start, end); - } - } - } - function classifyComment(token, kind, start, width) { - if (kind === 3 /* MultiLineCommentTrivia */) { - // See if this is a doc comment. If so, we'll classify certain portions of it - // specially. - var docCommentAndDiagnostics = ts.parseIsolatedJSDocComment(sourceFile.text, start, width); - if (docCommentAndDiagnostics && docCommentAndDiagnostics.jsDocComment) { - docCommentAndDiagnostics.jsDocComment.parent = token; - classifyJSDocComment(docCommentAndDiagnostics.jsDocComment); - return; - } - } - // Simple comment. Just add as is. - pushCommentRange(start, width); - } - function pushCommentRange(start, width) { - pushClassification(start, width, 1 /* comment */); - } - function classifyJSDocComment(docComment) { - var pos = docComment.pos; - for (var _i = 0, _a = docComment.tags; _i < _a.length; _i++) { - var tag = _a[_i]; - // As we walk through each tag, classify the portion of text from the end of - // the last tag (or the start of the entire doc comment) as 'comment'. - if (tag.pos !== pos) { - pushCommentRange(pos, tag.pos - pos); - } - pushClassification(tag.atToken.pos, tag.atToken.end - tag.atToken.pos, 10 /* punctuation */); - pushClassification(tag.tagName.pos, tag.tagName.end - tag.tagName.pos, 18 /* docCommentTagName */); - pos = tag.tagName.end; - switch (tag.kind) { - case 275 /* JSDocParameterTag */: - processJSDocParameterTag(tag); - break; - case 278 /* JSDocTemplateTag */: - processJSDocTemplateTag(tag); - break; - case 277 /* JSDocTypeTag */: - processElement(tag.typeExpression); - break; - case 276 /* JSDocReturnTag */: - processElement(tag.typeExpression); - break; - } - pos = tag.end; - } - if (pos !== docComment.end) { - pushCommentRange(pos, docComment.end - pos); - } - return; - function processJSDocParameterTag(tag) { - if (tag.preParameterName) { - pushCommentRange(pos, tag.preParameterName.pos - pos); - pushClassification(tag.preParameterName.pos, tag.preParameterName.end - tag.preParameterName.pos, 17 /* parameterName */); - pos = tag.preParameterName.end; - } - if (tag.typeExpression) { - pushCommentRange(pos, tag.typeExpression.pos - pos); - processElement(tag.typeExpression); - pos = tag.typeExpression.end; - } - if (tag.postParameterName) { - pushCommentRange(pos, tag.postParameterName.pos - pos); - pushClassification(tag.postParameterName.pos, tag.postParameterName.end - tag.postParameterName.pos, 17 /* parameterName */); - pos = tag.postParameterName.end; - } - } - } - function processJSDocTemplateTag(tag) { - for (var _i = 0, _a = tag.getChildren(); _i < _a.length; _i++) { - var child = _a[_i]; - processElement(child); - } - } - function classifyDisabledMergeCode(text, start, end) { - // Classify the line that the ======= marker is on as a comment. Then just lex - // all further tokens and add them to the result. - var i; - for (i = start; i < end; i++) { - if (ts.isLineBreak(text.charCodeAt(i))) { - break; - } - } - pushClassification(start, i - start, 1 /* comment */); - mergeConflictScanner.setTextPos(i); - while (mergeConflictScanner.getTextPos() < end) { - classifyDisabledCodeToken(); - } - } - function classifyDisabledCodeToken() { - var start = mergeConflictScanner.getTextPos(); - var tokenKind = mergeConflictScanner.scan(); - var end = mergeConflictScanner.getTextPos(); - var type = classifyTokenType(tokenKind); - if (type) { - pushClassification(start, end - start, type); - } - } - /** - * Returns true if node should be treated as classified and no further processing is required. - * False will mean that node is not classified and traverse routine should recurse into node contents. - */ - function tryClassifyNode(node) { - if (ts.isJSDocTag(node)) { - return true; - } - if (ts.nodeIsMissing(node)) { - return true; - } - var classifiedElementName = tryClassifyJsxElementName(node); - if (!ts.isToken(node) && node.kind !== 244 /* JsxText */ && classifiedElementName === undefined) { - return false; - } - var tokenStart = node.kind === 244 /* JsxText */ ? node.pos : classifyLeadingTriviaAndGetTokenStart(node); - var tokenWidth = node.end - tokenStart; - ts.Debug.assert(tokenWidth >= 0); - if (tokenWidth > 0) { - var type = classifiedElementName || classifyTokenType(node.kind, node); - if (type) { - pushClassification(tokenStart, tokenWidth, type); - } - } - return true; - } - function tryClassifyJsxElementName(token) { - switch (token.parent && token.parent.kind) { - case 243 /* JsxOpeningElement */: - if (token.parent.tagName === token) { - return 19 /* jsxOpenTagName */; - } - break; - case 245 /* JsxClosingElement */: - if (token.parent.tagName === token) { - return 20 /* jsxCloseTagName */; - } - break; - case 242 /* JsxSelfClosingElement */: - if (token.parent.tagName === token) { - return 21 /* jsxSelfClosingTagName */; - } - break; - case 246 /* JsxAttribute */: - if (token.parent.name === token) { - return 22 /* jsxAttribute */; - } - break; - } - return undefined; - } - // for accurate classification, the actual token should be passed in. however, for - // cases like 'disabled merge code' classification, we just get the token kind and - // classify based on that instead. - function classifyTokenType(tokenKind, token) { - if (ts.isKeyword(tokenKind)) { - return 3 /* keyword */; - } - // Special case < and > If they appear in a generic context they are punctuation, - // not operators. - if (tokenKind === 25 /* LessThanToken */ || tokenKind === 27 /* GreaterThanToken */) { - // If the node owning the token has a type argument list or type parameter list, then - // we can effectively assume that a '<' and '>' belong to those lists. - if (token && ts.getTypeArgumentOrTypeParameterList(token.parent)) { - return 10 /* punctuation */; - } - } - if (ts.isPunctuation(tokenKind)) { - if (token) { - if (tokenKind === 56 /* EqualsToken */) { - // the '=' in a variable declaration is special cased here. - if (token.parent.kind === 218 /* VariableDeclaration */ || - token.parent.kind === 145 /* PropertyDeclaration */ || - token.parent.kind === 142 /* Parameter */ || - token.parent.kind === 246 /* JsxAttribute */) { - return 5 /* operator */; - } - } - if (token.parent.kind === 187 /* BinaryExpression */ || - token.parent.kind === 185 /* PrefixUnaryExpression */ || - token.parent.kind === 186 /* PostfixUnaryExpression */ || - token.parent.kind === 188 /* ConditionalExpression */) { - return 5 /* operator */; - } - } - return 10 /* punctuation */; - } - else if (tokenKind === 8 /* NumericLiteral */) { - return 4 /* numericLiteral */; - } - else if (tokenKind === 9 /* StringLiteral */) { - return token.parent.kind === 246 /* JsxAttribute */ ? 24 /* jsxAttributeStringLiteralValue */ : 6 /* stringLiteral */; - } - else if (tokenKind === 10 /* RegularExpressionLiteral */) { - // TODO: we should get another classification type for these literals. - return 6 /* stringLiteral */; - } - else if (ts.isTemplateLiteralKind(tokenKind)) { - // TODO (drosen): we should *also* get another classification type for these literals. - return 6 /* stringLiteral */; - } - else if (tokenKind === 244 /* JsxText */) { - return 23 /* jsxText */; - } - else if (tokenKind === 69 /* Identifier */) { - if (token) { - switch (token.parent.kind) { - case 221 /* ClassDeclaration */: - if (token.parent.name === token) { - return 11 /* className */; - } - return; - case 141 /* TypeParameter */: - if (token.parent.name === token) { - return 15 /* typeParameterName */; - } - return; - case 222 /* InterfaceDeclaration */: - if (token.parent.name === token) { - return 13 /* interfaceName */; - } - return; - case 224 /* EnumDeclaration */: - if (token.parent.name === token) { - return 12 /* enumName */; - } - return; - case 225 /* ModuleDeclaration */: - if (token.parent.name === token) { - return 14 /* moduleName */; - } - return; - case 142 /* Parameter */: - if (token.parent.name === token) { - var isThis_1 = token.kind === 69 /* Identifier */ && token.originalKeywordKind === 97 /* ThisKeyword */; - return isThis_1 ? 3 /* keyword */ : 17 /* parameterName */; - } - return; - } - } - return 2 /* identifier */; - } - } - function processElement(element) { - if (!element) { - return; - } - // Ignore nodes that don't intersect the original span to classify. - if (ts.decodedTextSpanIntersectsWith(spanStart, spanLength, element.pos, element.getFullWidth())) { - checkForClassificationCancellation(element.kind); - var children = element.getChildren(sourceFile); - for (var i = 0, n = children.length; i < n; i++) { - var child = children[i]; - if (!tryClassifyNode(child)) { - // Recurse into our child nodes. - processElement(child); - } - } - } - } + return ts.getEncodedSyntacticClassifications(cancellationToken, syntaxTreeCache.getCurrentSourceFile(fileName), span); } function getOutliningSpans(fileName) { // doesn't use compiler - no need to synchronize with host @@ -60134,121 +74597,40 @@ var ts; } function getIndentationAtPosition(fileName, position, editorOptions) { var start = ts.timestamp(); + var settings = toEditorSettings(editorOptions); var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); log("getIndentationAtPosition: getCurrentSourceFile: " + (ts.timestamp() - start)); start = ts.timestamp(); - var result = ts.formatting.SmartIndenter.getIndentation(position, sourceFile, editorOptions); + var result = ts.formatting.SmartIndenter.getIndentation(position, sourceFile, settings); log("getIndentationAtPosition: computeIndentation : " + (ts.timestamp() - start)); return result; } function getFormattingEditsForRange(fileName, start, end, options) { var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - return ts.formatting.formatSelection(start, end, sourceFile, getRuleProvider(options), options); + var settings = toEditorSettings(options); + return ts.formatting.formatSelection(start, end, sourceFile, getRuleProvider(settings), settings); } function getFormattingEditsForDocument(fileName, options) { var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - return ts.formatting.formatDocument(sourceFile, getRuleProvider(options), options); + var settings = toEditorSettings(options); + return ts.formatting.formatDocument(sourceFile, getRuleProvider(settings), settings); } function getFormattingEditsAfterKeystroke(fileName, position, key, options) { var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + var settings = toEditorSettings(options); if (key === "}") { - return ts.formatting.formatOnClosingCurly(position, sourceFile, getRuleProvider(options), options); + return ts.formatting.formatOnClosingCurly(position, sourceFile, getRuleProvider(settings), settings); } else if (key === ";") { - return ts.formatting.formatOnSemicolon(position, sourceFile, getRuleProvider(options), options); + return ts.formatting.formatOnSemicolon(position, sourceFile, getRuleProvider(settings), settings); } else if (key === "\n") { - return ts.formatting.formatOnEnter(position, sourceFile, getRuleProvider(options), options); + return ts.formatting.formatOnEnter(position, sourceFile, getRuleProvider(settings), settings); } return []; } - /** - * Checks if position points to a valid position to add JSDoc comments, and if so, - * returns the appropriate template. Otherwise returns an empty string. - * Valid positions are - * - outside of comments, statements, and expressions, and - * - preceding a: - * - function/constructor/method declaration - * - class declarations - * - variable statements - * - namespace declarations - * - * Hosts should ideally check that: - * - The line is all whitespace up to 'position' before performing the insertion. - * - If the keystroke sequence "/\*\*" induced the call, we also check that the next - * non-whitespace character is '*', which (approximately) indicates whether we added - * the second '*' to complete an existing (JSDoc) comment. - * @param fileName The file in which to perform the check. - * @param position The (character-indexed) position in the file where the check should - * be performed. - */ function getDocCommentTemplateAtPosition(fileName, position) { - var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - // Check if in a context where we don't want to perform any insertion - if (ts.isInString(sourceFile, position) || ts.isInComment(sourceFile, position) || ts.hasDocComment(sourceFile, position)) { - return undefined; - } - var tokenAtPos = ts.getTokenAtPosition(sourceFile, position); - var tokenStart = tokenAtPos.getStart(); - if (!tokenAtPos || tokenStart < position) { - return undefined; - } - // TODO: add support for: - // - enums/enum members - // - interfaces - // - property declarations - // - potentially property assignments - var commentOwner; - findOwner: for (commentOwner = tokenAtPos; commentOwner; commentOwner = commentOwner.parent) { - switch (commentOwner.kind) { - case 220 /* FunctionDeclaration */: - case 147 /* MethodDeclaration */: - case 148 /* Constructor */: - case 221 /* ClassDeclaration */: - case 200 /* VariableStatement */: - break findOwner; - case 256 /* SourceFile */: - return undefined; - case 225 /* ModuleDeclaration */: - // If in walking up the tree, we hit a a nested namespace declaration, - // then we must be somewhere within a dotted namespace name; however we don't - // want to give back a JSDoc template for the 'b' or 'c' in 'namespace a.b.c { }'. - if (commentOwner.parent.kind === 225 /* ModuleDeclaration */) { - return undefined; - } - break findOwner; - } - } - if (!commentOwner || commentOwner.getStart() < position) { - return undefined; - } - var parameters = getParametersForJsDocOwningNode(commentOwner); - var posLineAndChar = sourceFile.getLineAndCharacterOfPosition(position); - var lineStart = sourceFile.getLineStarts()[posLineAndChar.line]; - var indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character); - var newLine = ts.getNewLineOrDefaultFromHost(host); - var docParams = ""; - for (var i = 0, numParams = parameters.length; i < numParams; i++) { - var currentName = parameters[i].name; - var paramName = currentName.kind === 69 /* Identifier */ ? - currentName.text : - "param" + i; - docParams += indentationStr + " * @param " + paramName + newLine; - } - // A doc comment consists of the following - // * The opening comment line - // * the first line (without a param) for the object's untagged info (this is also where the caret ends up) - // * the '@param'-tagged lines - // * TODO: other tags. - // * the closing comment line - // * if the caret was directly in front of the object, then we add an extra line and indentation. - var preamble = "/**" + newLine + - indentationStr + " * "; - var result = preamble + newLine + - docParams + - indentationStr + " */" + - (tokenStart === position ? newLine + indentationStr : ""); - return { newText: result, caretOffset: preamble.length }; + return ts.JsDoc.getDocCommentTemplateAtPosition(ts.getNewLineOrDefaultFromHost(host), syntaxTreeCache.getCurrentSourceFile(fileName), position); } function isValidBraceCompletionAtPosition(fileName, position, openingBrace) { // '<' is currently not supported, figuring out if we're in a Generic Type vs. a comparison is too @@ -60273,46 +74655,6 @@ var ts; } return true; } - function getParametersForJsDocOwningNode(commentOwner) { - if (ts.isFunctionLike(commentOwner)) { - return commentOwner.parameters; - } - if (commentOwner.kind === 200 /* VariableStatement */) { - var varStatement = commentOwner; - var varDeclarations = varStatement.declarationList.declarations; - if (varDeclarations.length === 1 && varDeclarations[0].initializer) { - return getParametersFromRightHandSideOfAssignment(varDeclarations[0].initializer); - } - } - return emptyArray; - } - /** - * Digs into an an initializer or RHS operand of an assignment operation - * to get the parameters of an apt signature corresponding to a - * function expression or a class expression. - * - * @param rightHandSide the expression which may contain an appropriate set of parameters - * @returns the parameters of a signature found on the RHS if one exists; otherwise 'emptyArray'. - */ - function getParametersFromRightHandSideOfAssignment(rightHandSide) { - while (rightHandSide.kind === 178 /* ParenthesizedExpression */) { - rightHandSide = rightHandSide.expression; - } - switch (rightHandSide.kind) { - case 179 /* FunctionExpression */: - case 180 /* ArrowFunction */: - return rightHandSide.parameters; - case 192 /* ClassExpression */: - for (var _i = 0, _a = rightHandSide.members; _i < _a.length; _i++) { - var member = _a[_i]; - if (member.kind === 148 /* Constructor */) { - return member.parameters; - } - } - break; - } - return emptyArray; - } function getTodoComments(fileName, descriptors) { // Note: while getting todo comments seems like a syntactic operation, we actually // treat it as a semantic operation here. This is because we expect our host to call @@ -60354,7 +74696,7 @@ var ts; // OK, we have found a match in the file. This is only an acceptable match if // it is contained within a comment. var token = ts.getTokenAtPosition(sourceFile, matchPosition); - if (!isInsideComment(sourceFile, token, matchPosition)) { + if (!ts.isInsideComment(sourceFile, token, matchPosition)) { continue; } var descriptor = undefined; @@ -60437,104 +74779,10 @@ var ts; (char >= 48 /* _0 */ && char <= 57 /* _9 */); } } - function getStringLiteralTypeForNode(node, typeChecker) { - var searchNode = node.parent.kind === 166 /* LiteralType */ ? node.parent : node; - var type = typeChecker.getTypeAtLocation(searchNode); - if (type && type.flags & 32 /* StringLiteral */) { - return type; - } - return undefined; - } function getRenameInfo(fileName, position) { synchronizeHostData(); - var sourceFile = getValidSourceFile(fileName); - var typeChecker = program.getTypeChecker(); var defaultLibFileName = host.getDefaultLibFileName(host.getCompilationSettings()); - var canonicalDefaultLibName = getCanonicalFileName(ts.normalizePath(defaultLibFileName)); - var node = ts.getTouchingWord(sourceFile, position, /*includeJsDocComment*/ true); - if (node) { - if (node.kind === 69 /* Identifier */ || - node.kind === 9 /* StringLiteral */ || - isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || - isThis(node)) { - var symbol = typeChecker.getSymbolAtLocation(node); - // Only allow a symbol to be renamed if it actually has at least one declaration. - if (symbol) { - var declarations = symbol.getDeclarations(); - if (declarations && declarations.length > 0) { - // Disallow rename for elements that are defined in the standard TypeScript library. - if (ts.forEach(declarations, isDefinedInLibraryFile)) { - return getRenameInfoError(ts.getLocaleSpecificMessage(ts.Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library)); - } - var displayName = ts.stripQuotes(ts.getDeclaredName(typeChecker, symbol, node)); - var kind = getSymbolKind(symbol, node); - if (kind) { - return { - canRename: true, - kind: kind, - displayName: displayName, - localizedErrorMessage: undefined, - fullDisplayName: typeChecker.getFullyQualifiedName(symbol), - kindModifiers: getSymbolModifiers(symbol), - triggerSpan: createTriggerSpanForNode(node, sourceFile) - }; - } - } - } - else if (node.kind === 9 /* StringLiteral */) { - var type = getStringLiteralTypeForNode(node, typeChecker); - if (type) { - if (isDefinedInLibraryFile(node)) { - return getRenameInfoError(ts.getLocaleSpecificMessage(ts.Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library)); - } - else { - var displayName = ts.stripQuotes(type.text); - return { - canRename: true, - kind: ts.ScriptElementKind.variableElement, - displayName: displayName, - localizedErrorMessage: undefined, - fullDisplayName: displayName, - kindModifiers: ts.ScriptElementKindModifier.none, - triggerSpan: createTriggerSpanForNode(node, sourceFile) - }; - } - } - } - } - } - return getRenameInfoError(ts.getLocaleSpecificMessage(ts.Diagnostics.You_cannot_rename_this_element)); - function getRenameInfoError(localizedErrorMessage) { - return { - canRename: false, - localizedErrorMessage: localizedErrorMessage, - displayName: undefined, - fullDisplayName: undefined, - kind: undefined, - kindModifiers: undefined, - triggerSpan: undefined - }; - } - function isDefinedInLibraryFile(declaration) { - if (defaultLibFileName) { - var sourceFile_3 = declaration.getSourceFile(); - var canonicalName = getCanonicalFileName(ts.normalizePath(sourceFile_3.fileName)); - if (canonicalName === canonicalDefaultLibName) { - return true; - } - } - return false; - } - function createTriggerSpanForNode(node, sourceFile) { - var start = node.getStart(sourceFile); - var width = node.getWidth(sourceFile); - if (node.kind === 9 /* StringLiteral */) { - // Exclude the quotes - start += 1; - width -= 2; - } - return ts.createTextSpan(start, width); - } + return ts.Rename.getRenameInfo(program.getTypeChecker(), defaultLibFileName, getCanonicalFileName, getValidSourceFile(fileName), position); } return { dispose: dispose, @@ -60548,9 +74796,11 @@ var ts; getEncodedSemanticClassifications: getEncodedSemanticClassifications, getCompletionsAtPosition: getCompletionsAtPosition, getCompletionEntryDetails: getCompletionEntryDetails, + getCompletionEntrySymbol: getCompletionEntrySymbol, getSignatureHelpItems: getSignatureHelpItems, getQuickInfoAtPosition: getQuickInfoAtPosition, getDefinitionAtPosition: getDefinitionAtPosition, + getImplementationAtPosition: getImplementationAtPosition, getTypeDefinitionAtPosition: getTypeDefinitionAtPosition, getReferencesAtPosition: getReferencesAtPosition, findReferences: findReferences, @@ -60573,18 +74823,11 @@ var ts; isValidBraceCompletionAtPosition: isValidBraceCompletionAtPosition, getEmitOutput: getEmitOutput, getNonBoundSourceFile: getNonBoundSourceFile, + getSourceFile: getSourceFile, getProgram: getProgram }; } ts.createLanguageService = createLanguageService; - function forEachDescendantOfKind(node, kind, action) { - ts.forEachChild(node, function (child) { - if (child.kind === kind) { - action(child); - } - forEachDescendantOfKind(child, kind, action); - }); - } /* @internal */ function getNameTable(sourceFile) { if (!sourceFile.nameTable) { @@ -60632,425 +74875,6 @@ var ts; node.parent.kind === 173 /* ElementAccessExpression */ && node.parent.argumentExpression === node; } - /// Classifier - function createClassifier() { - var scanner = ts.createScanner(2 /* Latest */, /*skipTrivia*/ false); - /// We do not have a full parser support to know when we should parse a regex or not - /// If we consider every slash token to be a regex, we could be missing cases like "1/2/3", where - /// we have a series of divide operator. this list allows us to be more accurate by ruling out - /// locations where a regexp cannot exist. - var noRegexTable = []; - noRegexTable[69 /* Identifier */] = true; - noRegexTable[9 /* StringLiteral */] = true; - noRegexTable[8 /* NumericLiteral */] = true; - noRegexTable[10 /* RegularExpressionLiteral */] = true; - noRegexTable[97 /* ThisKeyword */] = true; - noRegexTable[41 /* PlusPlusToken */] = true; - noRegexTable[42 /* MinusMinusToken */] = true; - noRegexTable[18 /* CloseParenToken */] = true; - noRegexTable[20 /* CloseBracketToken */] = true; - noRegexTable[16 /* CloseBraceToken */] = true; - noRegexTable[99 /* TrueKeyword */] = true; - noRegexTable[84 /* FalseKeyword */] = true; - // Just a stack of TemplateHeads and OpenCurlyBraces, used to perform rudimentary (inexact) - // classification on template strings. Because of the context free nature of templates, - // the only precise way to classify a template portion would be by propagating the stack across - // lines, just as we do with the end-of-line state. However, this is a burden for implementers, - // and the behavior is entirely subsumed by the syntactic classifier anyway, so we instead - // flatten any nesting when the template stack is non-empty and encode it in the end-of-line state. - // Situations in which this fails are - // 1) When template strings are nested across different lines: - // `hello ${ `world - // ` }` - // - // Where on the second line, you will get the closing of a template, - // a closing curly, and a new template. - // - // 2) When substitution expressions have curly braces and the curly brace falls on the next line: - // `hello ${ () => { - // return "world" } } ` - // - // Where on the second line, you will get the 'return' keyword, - // a string literal, and a template end consisting of '} } `'. - var templateStack = []; - /** Returns true if 'keyword2' can legally follow 'keyword1' in any language construct. */ - function canFollow(keyword1, keyword2) { - if (ts.isAccessibilityModifier(keyword1)) { - if (keyword2 === 123 /* GetKeyword */ || - keyword2 === 131 /* SetKeyword */ || - keyword2 === 121 /* ConstructorKeyword */ || - keyword2 === 113 /* StaticKeyword */) { - // Allow things like "public get", "public constructor" and "public static". - // These are all legal. - return true; - } - // Any other keyword following "public" is actually an identifier an not a real - // keyword. - return false; - } - // Assume any other keyword combination is legal. This can be refined in the future - // if there are more cases we want the classifier to be better at. - return true; - } - function convertClassifications(classifications, text) { - var entries = []; - var dense = classifications.spans; - var lastEnd = 0; - for (var i = 0, n = dense.length; i < n; i += 3) { - var start = dense[i]; - var length_5 = dense[i + 1]; - var type = dense[i + 2]; - // Make a whitespace entry between the last item and this one. - if (lastEnd >= 0) { - var whitespaceLength_1 = start - lastEnd; - if (whitespaceLength_1 > 0) { - entries.push({ length: whitespaceLength_1, classification: ts.TokenClass.Whitespace }); - } - } - entries.push({ length: length_5, classification: convertClassification(type) }); - lastEnd = start + length_5; - } - var whitespaceLength = text.length - lastEnd; - if (whitespaceLength > 0) { - entries.push({ length: whitespaceLength, classification: ts.TokenClass.Whitespace }); - } - return { entries: entries, finalLexState: classifications.endOfLineState }; - } - function convertClassification(type) { - switch (type) { - case 1 /* comment */: return ts.TokenClass.Comment; - case 3 /* keyword */: return ts.TokenClass.Keyword; - case 4 /* numericLiteral */: return ts.TokenClass.NumberLiteral; - case 5 /* operator */: return ts.TokenClass.Operator; - case 6 /* stringLiteral */: return ts.TokenClass.StringLiteral; - case 8 /* whiteSpace */: return ts.TokenClass.Whitespace; - case 10 /* punctuation */: return ts.TokenClass.Punctuation; - case 2 /* identifier */: - case 11 /* className */: - case 12 /* enumName */: - case 13 /* interfaceName */: - case 14 /* moduleName */: - case 15 /* typeParameterName */: - case 16 /* typeAliasName */: - case 9 /* text */: - case 17 /* parameterName */: - default: - return ts.TokenClass.Identifier; - } - } - function getClassificationsForLine(text, lexState, syntacticClassifierAbsent) { - return convertClassifications(getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent), text); - } - // If there is a syntactic classifier ('syntacticClassifierAbsent' is false), - // we will be more conservative in order to avoid conflicting with the syntactic classifier. - function getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent) { - var offset = 0; - var token = 0 /* Unknown */; - var lastNonTriviaToken = 0 /* Unknown */; - // Empty out the template stack for reuse. - while (templateStack.length > 0) { - templateStack.pop(); - } - // If we're in a string literal, then prepend: "\ - // (and a newline). That way when we lex we'll think we're still in a string literal. - // - // If we're in a multiline comment, then prepend: /* - // (and a newline). That way when we lex we'll think we're still in a multiline comment. - switch (lexState) { - case 3 /* InDoubleQuoteStringLiteral */: - text = "\"\\\n" + text; - offset = 3; - break; - case 2 /* InSingleQuoteStringLiteral */: - text = "'\\\n" + text; - offset = 3; - break; - case 1 /* InMultiLineCommentTrivia */: - text = "/*\n" + text; - offset = 3; - break; - case 4 /* InTemplateHeadOrNoSubstitutionTemplate */: - text = "`\n" + text; - offset = 2; - break; - case 5 /* InTemplateMiddleOrTail */: - text = "}\n" + text; - offset = 2; - // fallthrough - case 6 /* InTemplateSubstitutionPosition */: - templateStack.push(12 /* TemplateHead */); - break; - } - scanner.setText(text); - var result = { - endOfLineState: 0 /* None */, - spans: [] - }; - // We can run into an unfortunate interaction between the lexical and syntactic classifier - // when the user is typing something generic. Consider the case where the user types: - // - // Foo tokens. It's a weak heuristic, but should - // work well enough in practice. - var angleBracketStack = 0; - do { - token = scanner.scan(); - if (!ts.isTrivia(token)) { - if ((token === 39 /* SlashToken */ || token === 61 /* SlashEqualsToken */) && !noRegexTable[lastNonTriviaToken]) { - if (scanner.reScanSlashToken() === 10 /* RegularExpressionLiteral */) { - token = 10 /* RegularExpressionLiteral */; - } - } - else if (lastNonTriviaToken === 21 /* DotToken */ && isKeyword(token)) { - token = 69 /* Identifier */; - } - else if (isKeyword(lastNonTriviaToken) && isKeyword(token) && !canFollow(lastNonTriviaToken, token)) { - // We have two keywords in a row. Only treat the second as a keyword if - // it's a sequence that could legally occur in the language. Otherwise - // treat it as an identifier. This way, if someone writes "private var" - // we recognize that 'var' is actually an identifier here. - token = 69 /* Identifier */; - } - else if (lastNonTriviaToken === 69 /* Identifier */ && - token === 25 /* LessThanToken */) { - // Could be the start of something generic. Keep track of that by bumping - // up the current count of generic contexts we may be in. - angleBracketStack++; - } - else if (token === 27 /* GreaterThanToken */ && angleBracketStack > 0) { - // If we think we're currently in something generic, then mark that that - // generic entity is complete. - angleBracketStack--; - } - else if (token === 117 /* AnyKeyword */ || - token === 132 /* StringKeyword */ || - token === 130 /* NumberKeyword */ || - token === 120 /* BooleanKeyword */ || - token === 133 /* SymbolKeyword */) { - if (angleBracketStack > 0 && !syntacticClassifierAbsent) { - // If it looks like we're could be in something generic, don't classify this - // as a keyword. We may just get overwritten by the syntactic classifier, - // causing a noisy experience for the user. - token = 69 /* Identifier */; - } - } - else if (token === 12 /* TemplateHead */) { - templateStack.push(token); - } - else if (token === 15 /* OpenBraceToken */) { - // If we don't have anything on the template stack, - // then we aren't trying to keep track of a previously scanned template head. - if (templateStack.length > 0) { - templateStack.push(token); - } - } - else if (token === 16 /* CloseBraceToken */) { - // If we don't have anything on the template stack, - // then we aren't trying to keep track of a previously scanned template head. - if (templateStack.length > 0) { - var lastTemplateStackToken = ts.lastOrUndefined(templateStack); - if (lastTemplateStackToken === 12 /* TemplateHead */) { - token = scanner.reScanTemplateToken(); - // Only pop on a TemplateTail; a TemplateMiddle indicates there is more for us. - if (token === 14 /* TemplateTail */) { - templateStack.pop(); - } - else { - ts.Debug.assert(token === 13 /* TemplateMiddle */, "Should have been a template middle. Was " + token); - } - } - else { - ts.Debug.assert(lastTemplateStackToken === 15 /* OpenBraceToken */, "Should have been an open brace. Was: " + token); - templateStack.pop(); - } - } - } - lastNonTriviaToken = token; - } - processToken(); - } while (token !== 1 /* EndOfFileToken */); - return result; - function processToken() { - var start = scanner.getTokenPos(); - var end = scanner.getTextPos(); - addResult(start, end, classFromKind(token)); - if (end >= text.length) { - if (token === 9 /* StringLiteral */) { - // Check to see if we finished up on a multiline string literal. - var tokenText = scanner.getTokenText(); - if (scanner.isUnterminated()) { - var lastCharIndex = tokenText.length - 1; - var numBackslashes = 0; - while (tokenText.charCodeAt(lastCharIndex - numBackslashes) === 92 /* backslash */) { - numBackslashes++; - } - // If we have an odd number of backslashes, then the multiline string is unclosed - if (numBackslashes & 1) { - var quoteChar = tokenText.charCodeAt(0); - result.endOfLineState = quoteChar === 34 /* doubleQuote */ - ? 3 /* InDoubleQuoteStringLiteral */ - : 2 /* InSingleQuoteStringLiteral */; - } - } - } - else if (token === 3 /* MultiLineCommentTrivia */) { - // Check to see if the multiline comment was unclosed. - if (scanner.isUnterminated()) { - result.endOfLineState = 1 /* InMultiLineCommentTrivia */; - } - } - else if (ts.isTemplateLiteralKind(token)) { - if (scanner.isUnterminated()) { - if (token === 14 /* TemplateTail */) { - result.endOfLineState = 5 /* InTemplateMiddleOrTail */; - } - else if (token === 11 /* NoSubstitutionTemplateLiteral */) { - result.endOfLineState = 4 /* InTemplateHeadOrNoSubstitutionTemplate */; - } - else { - ts.Debug.fail("Only 'NoSubstitutionTemplateLiteral's and 'TemplateTail's can be unterminated; got SyntaxKind #" + token); - } - } - } - else if (templateStack.length > 0 && ts.lastOrUndefined(templateStack) === 12 /* TemplateHead */) { - result.endOfLineState = 6 /* InTemplateSubstitutionPosition */; - } - } - } - function addResult(start, end, classification) { - if (classification === 8 /* whiteSpace */) { - // Don't bother with whitespace classifications. They're not needed. - return; - } - if (start === 0 && offset > 0) { - // We're classifying the first token, and this was a case where we prepended - // text. We should consider the start of this token to be at the start of - // the original text. - start += offset; - } - // All our tokens are in relation to the augmented text. Move them back to be - // relative to the original text. - start -= offset; - end -= offset; - var length = end - start; - if (length > 0) { - result.spans.push(start); - result.spans.push(length); - result.spans.push(classification); - } - } - } - function isBinaryExpressionOperatorToken(token) { - switch (token) { - case 37 /* AsteriskToken */: - case 39 /* SlashToken */: - case 40 /* PercentToken */: - case 35 /* PlusToken */: - case 36 /* MinusToken */: - case 43 /* LessThanLessThanToken */: - case 44 /* GreaterThanGreaterThanToken */: - case 45 /* GreaterThanGreaterThanGreaterThanToken */: - case 25 /* LessThanToken */: - case 27 /* GreaterThanToken */: - case 28 /* LessThanEqualsToken */: - case 29 /* GreaterThanEqualsToken */: - case 91 /* InstanceOfKeyword */: - case 90 /* InKeyword */: - case 116 /* AsKeyword */: - case 30 /* EqualsEqualsToken */: - case 31 /* ExclamationEqualsToken */: - case 32 /* EqualsEqualsEqualsToken */: - case 33 /* ExclamationEqualsEqualsToken */: - case 46 /* AmpersandToken */: - case 48 /* CaretToken */: - case 47 /* BarToken */: - case 51 /* AmpersandAmpersandToken */: - case 52 /* BarBarToken */: - case 67 /* BarEqualsToken */: - case 66 /* AmpersandEqualsToken */: - case 68 /* CaretEqualsToken */: - case 63 /* LessThanLessThanEqualsToken */: - case 64 /* GreaterThanGreaterThanEqualsToken */: - case 65 /* GreaterThanGreaterThanGreaterThanEqualsToken */: - case 57 /* PlusEqualsToken */: - case 58 /* MinusEqualsToken */: - case 59 /* AsteriskEqualsToken */: - case 61 /* SlashEqualsToken */: - case 62 /* PercentEqualsToken */: - case 56 /* EqualsToken */: - case 24 /* CommaToken */: - return true; - default: - return false; - } - } - function isPrefixUnaryExpressionOperatorToken(token) { - switch (token) { - case 35 /* PlusToken */: - case 36 /* MinusToken */: - case 50 /* TildeToken */: - case 49 /* ExclamationToken */: - case 41 /* PlusPlusToken */: - case 42 /* MinusMinusToken */: - return true; - default: - return false; - } - } - function isKeyword(token) { - return token >= 70 /* FirstKeyword */ && token <= 138 /* LastKeyword */; - } - function classFromKind(token) { - if (isKeyword(token)) { - return 3 /* keyword */; - } - else if (isBinaryExpressionOperatorToken(token) || isPrefixUnaryExpressionOperatorToken(token)) { - return 5 /* operator */; - } - else if (token >= 15 /* FirstPunctuation */ && token <= 68 /* LastPunctuation */) { - return 10 /* punctuation */; - } - switch (token) { - case 8 /* NumericLiteral */: - return 4 /* numericLiteral */; - case 9 /* StringLiteral */: - return 6 /* stringLiteral */; - case 10 /* RegularExpressionLiteral */: - return 7 /* regularExpressionLiteral */; - case 7 /* ConflictMarkerTrivia */: - case 3 /* MultiLineCommentTrivia */: - case 2 /* SingleLineCommentTrivia */: - return 1 /* comment */; - case 5 /* WhitespaceTrivia */: - case 4 /* NewLineTrivia */: - return 8 /* whiteSpace */; - case 69 /* Identifier */: - default: - if (ts.isTemplateLiteralKind(token)) { - return 6 /* stringLiteral */; - } - return 2 /* identifier */; - } - } - return { - getClassificationsForLine: getClassificationsForLine, - getEncodedLexicalClassifications: getEncodedLexicalClassifications - }; - } - ts.createClassifier = createClassifier; /** * Get the path of the default library files (lib.d.ts) as distributed with the typescript * node package. @@ -61065,15 +74889,7 @@ var ts; } ts.getDefaultLibFilePath = getDefaultLibFilePath; function initializeServices() { - ts.objectAllocator = { - getNodeConstructor: function () { return NodeObject; }, - getTokenConstructor: function () { return TokenObject; }, - getIdentifierConstructor: function () { return IdentifierObject; }, - getSourceFileConstructor: function () { return SourceFileObject; }, - getSymbolConstructor: function () { return SymbolObject; }, - getTypeConstructor: function () { return TypeObject; }, - getSignatureConstructor: function () { return SignatureObject; }, - }; + ts.objectAllocator = getServicesObjectAllocator(); } initializeServices(); })(ts || (ts = {})); @@ -61316,7 +75132,7 @@ var ts; return spanInNode(binaryExpression.left); } } - if (ts.isExpression(node)) { + if (ts.isPartOfExpression(node)) { switch (node.parent.kind) { case 204 /* DoStatement */: // Set span as if on while keyword @@ -61401,7 +75217,7 @@ var ts; // Breakpoint is possible in variableDeclaration only if there is initialization // or its declaration from 'for of' if (variableDeclaration.initializer || - (variableDeclaration.flags & 1 /* Export */) || + ts.hasModifier(variableDeclaration, 1 /* Export */) || variableDeclaration.parent.parent.kind === 208 /* ForOfStatement */) { return textSpanFromVariableDeclaration(variableDeclaration); } @@ -61417,7 +75233,7 @@ var ts; function canHaveSpanInParameterDeclaration(parameter) { // Breakpoint is possible on parameter only if it has initializer, is a rest parameter, or has public or private modifier return !!parameter.initializer || parameter.dotDotDotToken !== undefined || - !!(parameter.flags & 4 /* Public */) || !!(parameter.flags & 8 /* Private */); + ts.hasModifier(parameter, 4 /* Public */ | 8 /* Private */); } function spanInParameterDeclaration(parameter) { if (ts.isBindingPattern(parameter.name)) { @@ -61441,7 +75257,7 @@ var ts; } } function canFunctionHaveSpanInWholeDeclaration(functionDeclaration) { - return !!(functionDeclaration.flags & 1 /* Export */) || + return ts.hasModifier(functionDeclaration, 1 /* Export */) || (functionDeclaration.parent.kind === 221 /* ClassDeclaration */ && functionDeclaration.kind !== 148 /* Constructor */); } function spanInFunctionDeclaration(functionDeclaration) { @@ -61694,7 +75510,7 @@ var ts; // /// /* @internal */ -var debugObjectHost = new Function("return this")(); +var debugObjectHost = (function () { return this; })(); // We need to use 'null' to interface with the managed side. /* tslint:disable:no-null-keyword */ /* tslint:disable:no-in-operator */ @@ -61782,6 +75598,12 @@ var ts; } return this.shimHost.getProjectVersion(); }; + LanguageServiceShimHostAdapter.prototype.getTypeRootsVersion = function () { + if (!this.shimHost.getTypeRootsVersion) { + return 0; + } + return this.shimHost.getTypeRootsVersion(); + }; LanguageServiceShimHostAdapter.prototype.useCaseSensitiveFileNames = function () { return this.shimHost.useCaseSensitiveFileNames ? this.shimHost.useCaseSensitiveFileNames() : false; }; @@ -61838,6 +75660,16 @@ var ts; LanguageServiceShimHostAdapter.prototype.getDefaultLibFileName = function (options) { return this.shimHost.getDefaultLibFileName(JSON.stringify(options)); }; + LanguageServiceShimHostAdapter.prototype.readDirectory = function (path, extensions, exclude, include, depth) { + var pattern = ts.getFileMatcherPatterns(path, extensions, exclude, include, this.shimHost.useCaseSensitiveFileNames(), this.shimHost.getCurrentDirectory()); + return JSON.parse(this.shimHost.readDirectory(path, JSON.stringify(extensions), JSON.stringify(pattern.basePaths), pattern.excludePattern, pattern.includeFilePattern, pattern.includeDirectoryPattern, depth)); + }; + LanguageServiceShimHostAdapter.prototype.readFile = function (path, encoding) { + return this.shimHost.readFile(path, encoding); + }; + LanguageServiceShimHostAdapter.prototype.fileExists = function (path) { + return this.shimHost.fileExists(path); + }; return LanguageServiceShimHostAdapter; }()); ts.LanguageServiceShimHostAdapter = LanguageServiceShimHostAdapter; @@ -62110,6 +75942,15 @@ var ts; var _this = this; return this.forwardJSONCall("getTypeDefinitionAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getTypeDefinitionAtPosition(fileName, position); }); }; + /// GOTO Implementation + /** + * Computes the implementation location of the symbol + * at the requested position. + */ + LanguageServiceShimObject.prototype.getImplementationAtPosition = function (fileName, position) { + var _this = this; + return this.forwardJSONCall("getImplementationAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getImplementationAtPosition(fileName, position); }); + }; LanguageServiceShimObject.prototype.getRenameInfo = function (fileName, position) { var _this = this; return this.forwardJSONCall("getRenameInfo('" + fileName + "', " + position + ")", function () { return _this.languageService.getRenameInfo(fileName, position); }); @@ -62199,9 +76040,9 @@ var ts; }; /// NAVIGATE TO /** Return a list of symbols that are interesting to navigate to */ - LanguageServiceShimObject.prototype.getNavigateToItems = function (searchValue, maxResultCount) { + LanguageServiceShimObject.prototype.getNavigateToItems = function (searchValue, maxResultCount, fileName) { var _this = this; - return this.forwardJSONCall("getNavigateToItems('" + searchValue + "', " + maxResultCount + ")", function () { return _this.languageService.getNavigateToItems(searchValue, maxResultCount); }); + return this.forwardJSONCall("getNavigateToItems('" + searchValue + "', " + maxResultCount + ", " + fileName + ")", function () { return _this.languageService.getNavigateToItems(searchValue, maxResultCount, fileName); }); }; LanguageServiceShimObject.prototype.getNavigationBarItems = function (fileName) { var _this = this; diff --git a/kicktravis b/kicktravis index d6011b8..5167cbf 100644 --- a/kicktravis +++ b/kicktravis @@ -1 +1 @@ -2016-09-06 [ci skip] Version: 1.201609060105.1+2379000f8a9b2bbd1fface413387927ea2b31876 +2016-09-30 [ci skip] Version: 1.201609302242.1+c302893a6201cbd822d6040b8361ad7a0ee506fa diff --git a/package.json b/package.json index aa958fb..9ebc48a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ntypescript", - "version": "1.201609060105.1+2379000f8a9b2bbd1fface413387927ea2b31876", + "version": "1.201609302242.1+c302893a6201cbd822d6040b8361ad7a0ee506fa", "description": "A nicer version of microsoft/typescript packaged and released for API developers", "main": "./bin/ntypescript.js", "bin": { diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index d8017d6..e2d3116 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -27,7 +27,7 @@ namespace ts { return ModuleInstanceState.ConstEnumOnly; } // 3. non-exported import declarations - else if ((node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) && !(node.flags & NodeFlags.Export)) { + else if ((node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) && !(hasModifier(node, ModifierFlags.Export))) { return ModuleInstanceState.NonInstantiated; } // 4. other uninstantiated module declarations. @@ -131,6 +131,10 @@ namespace ts { const unreachableFlow: FlowNode = { flags: FlowFlags.Unreachable }; const reportedUnreachableFlow: FlowNode = { flags: FlowFlags.Unreachable }; + // state used to aggregate transform flags during bind. + let subtreeTransformFlags: TransformFlags = TransformFlags.None; + let skipTransformFlagAggregation: boolean; + function bindSourceFile(f: SourceFile, opts: CompilerOptions) { file = f; options = opts; @@ -138,6 +142,7 @@ namespace ts { inStrictMode = !!file.externalModuleIndicator; classifiableNames = createMap(); symbolCount = 0; + skipTransformFlagAggregation = isDeclarationFile(file); Symbol = objectAllocator.getSymbolConstructor(); @@ -164,6 +169,7 @@ namespace ts { activeLabels = undefined; hasExplicitReturn = false; emitFlags = NodeFlags.None; + subtreeTransformFlags = TransformFlags.None; } return bindSourceFile; @@ -253,7 +259,7 @@ namespace ts { case SyntaxKind.FunctionDeclaration: case SyntaxKind.ClassDeclaration: - return node.flags & NodeFlags.Default ? "default" : undefined; + return hasModifier(node, ModifierFlags.Default) ? "default" : undefined; case SyntaxKind.JSDocFunctionType: return isJSDocConstructSignature(node) ? "__new" : "__call"; case SyntaxKind.Parameter: @@ -262,7 +268,7 @@ namespace ts { Debug.assert(node.parent.kind === SyntaxKind.JSDocFunctionType); let functionType = node.parent; let index = indexOf(functionType.parameters, node); - return "p" + index; + return "arg" + index; case SyntaxKind.JSDocTypedefTag: const parentNode = node.parent && node.parent.parent; let nameFromParentNode: string; @@ -293,7 +299,7 @@ namespace ts { function declareSymbol(symbolTable: SymbolTable, parent: Symbol, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags): Symbol { Debug.assert(!hasDynamicName(node)); - const isDefaultExport = node.flags & NodeFlags.Default; + const isDefaultExport = hasModifier(node, ModifierFlags.Default); // The exported symbol for an export default function/class node is always named "default" const name = isDefaultExport && parent ? "default" : getDeclarationName(node); @@ -350,7 +356,7 @@ namespace ts { : Diagnostics.Duplicate_identifier_0; forEach(symbol.declarations, declaration => { - if (declaration.flags & NodeFlags.Default) { + if (hasModifier(declaration, ModifierFlags.Default)) { message = Diagnostics.A_module_cannot_have_multiple_default_exports; } }); @@ -372,7 +378,7 @@ namespace ts { } function declareModuleMember(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags): Symbol { - const hasExportModifier = getCombinedNodeFlags(node) & NodeFlags.Export; + const hasExportModifier = getCombinedModifierFlags(node) & ModifierFlags.Export; if (symbolFlags & SymbolFlags.Alias) { if (node.kind === SyntaxKind.ExportSpecifier || (node.kind === SyntaxKind.ImportEqualsDeclaration && hasExportModifier)) { return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); @@ -513,13 +519,28 @@ namespace ts { } function bindChildren(node: Node): void { + if (skipTransformFlagAggregation) { + bindChildrenWorker(node); + } + else if (node.transformFlags & TransformFlags.HasComputedFlags) { + skipTransformFlagAggregation = true; + bindChildrenWorker(node); + skipTransformFlagAggregation = false; + } + else { + const savedSubtreeTransformFlags = subtreeTransformFlags; + subtreeTransformFlags = 0; + bindChildrenWorker(node); + subtreeTransformFlags = savedSubtreeTransformFlags | computeTransformFlagsForNode(node, subtreeTransformFlags); + } + } + + function bindChildrenWorker(node: Node): void { // Binding of JsDocComment should be done before the current block scope container changes. // because the scope of JsDocComment should not be affected by whether the current node is a // container or not. if (isInJavaScriptFile(node) && node.jsDocComments) { - for (const jsDocComment of node.jsDocComments) { - bind(jsDocComment); - } + forEach(node.jsDocComments, bind); } if (checkUnreachable(node)) { forEachChild(node, bind); @@ -568,6 +589,9 @@ namespace ts { case SyntaxKind.PrefixUnaryExpression: bindPrefixUnaryExpressionFlow(node); break; + case SyntaxKind.PostfixUnaryExpression: + bindPostfixUnaryExpressionFlow(node); + break; case SyntaxKind.BinaryExpression: bindBinaryExpressionFlow(node); break; @@ -1083,6 +1107,16 @@ namespace ts { } else { forEachChild(node, bind); + if (node.operator === SyntaxKind.PlusEqualsToken || node.operator === SyntaxKind.MinusMinusToken) { + bindAssignmentTargetFlow(node.operand); + } + } + } + + function bindPostfixUnaryExpressionFlow(node: PostfixUnaryExpression) { + forEachChild(node, bind); + if (node.operator === SyntaxKind.PlusPlusToken || node.operator === SyntaxKind.MinusMinusToken) { + bindAssignmentTargetFlow(node.operand); } } @@ -1127,8 +1161,8 @@ namespace ts { currentFlow = finishFlowLabel(postExpressionLabel); } - function bindInitializedVariableFlow(node: VariableDeclaration | BindingElement) { - const name = node.name; + function bindInitializedVariableFlow(node: VariableDeclaration | ArrayBindingElement) { + const name = !isOmittedExpression(node) ? node.name : undefined; if (isBindingPattern(name)) { for (const child of name.elements) { bindInitializedVariableFlow(child); @@ -1308,7 +1342,7 @@ namespace ts { } function declareClassMember(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) { - return node.flags & NodeFlags.Static + return hasModifier(node, ModifierFlags.Static) ? declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes) : declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); } @@ -1345,7 +1379,7 @@ namespace ts { function bindModuleDeclaration(node: ModuleDeclaration) { setExportContextFlag(node); if (isAmbientModule(node)) { - if (node.flags & NodeFlags.Export) { + if (hasModifier(node, ModifierFlags.Export)) { errorOnFirstToken(node, Diagnostics.export_modifier_cannot_be_applied_to_ambient_modules_and_module_augmentations_since_they_are_always_visible); } if (isExternalModuleAugmentation(node)) { @@ -1612,7 +1646,7 @@ namespace ts { } } - function checkStrictModeNumericLiteral(node: LiteralExpression) { + function checkStrictModeNumericLiteral(node: NumericLiteral) { if (inStrictMode && node.isOctalLiteral) { file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.Octal_literals_are_not_allowed_in_strict_mode)); } @@ -1687,6 +1721,9 @@ namespace ts { } parent = saveParent; } + else if (!skipTransformFlagAggregation && (node.transformFlags & TransformFlags.HasComputedFlags) === 0) { + subtreeTransformFlags |= computeTransformFlagsForNode(node, 0); + } inStrictMode = saveInStrictMode; } @@ -1757,7 +1794,7 @@ namespace ts { case SyntaxKind.DeleteExpression: return checkStrictModeDeleteExpression(node); case SyntaxKind.NumericLiteral: - return checkStrictModeNumericLiteral(node); + return checkStrictModeNumericLiteral(node); case SyntaxKind.PostfixUnaryExpression: return checkStrictModePostfixUnaryExpression(node); case SyntaxKind.PrefixUnaryExpression: @@ -1789,7 +1826,7 @@ namespace ts { return bindPropertyOrMethodOrAccessor(node, SymbolFlags.EnumMember, SymbolFlags.EnumMemberExcludes); case SyntaxKind.JsxSpreadAttribute: - emitFlags |= NodeFlags.HasJsxSpreadAttribute; + emitFlags |= NodeFlags.HasJsxSpreadAttributes; return; case SyntaxKind.CallSignature: @@ -2204,7 +2241,7 @@ namespace ts { if (currentFlow === unreachableFlow) { const reportError = // report error on all statements except empty ones - (isStatement(node) && node.kind !== SyntaxKind.EmptyStatement) || + (isStatementButNotDeclaration(node) && node.kind !== SyntaxKind.EmptyStatement) || // report error on class declarations node.kind === SyntaxKind.ClassDeclaration || // report error on instantiated modules or const-enums only modules if preserveConstEnums is set @@ -2241,4 +2278,763 @@ namespace ts { return true; } } + + /** + * Computes the transform flags for a node, given the transform flags of its subtree + * + * @param node The node to analyze + * @param subtreeFlags Transform flags computed for this node's subtree + */ + export function computeTransformFlagsForNode(node: Node, subtreeFlags: TransformFlags): TransformFlags { + const kind = node.kind; + switch (kind) { + case SyntaxKind.CallExpression: + return computeCallExpression(node, subtreeFlags); + + case SyntaxKind.ModuleDeclaration: + return computeModuleDeclaration(node, subtreeFlags); + + case SyntaxKind.ParenthesizedExpression: + return computeParenthesizedExpression(node, subtreeFlags); + + case SyntaxKind.BinaryExpression: + return computeBinaryExpression(node, subtreeFlags); + + case SyntaxKind.ExpressionStatement: + return computeExpressionStatement(node, subtreeFlags); + + case SyntaxKind.Parameter: + return computeParameter(node, subtreeFlags); + + case SyntaxKind.ArrowFunction: + return computeArrowFunction(node, subtreeFlags); + + case SyntaxKind.FunctionExpression: + return computeFunctionExpression(node, subtreeFlags); + + case SyntaxKind.FunctionDeclaration: + return computeFunctionDeclaration(node, subtreeFlags); + + case SyntaxKind.VariableDeclaration: + return computeVariableDeclaration(node, subtreeFlags); + + case SyntaxKind.VariableDeclarationList: + return computeVariableDeclarationList(node, subtreeFlags); + + case SyntaxKind.VariableStatement: + return computeVariableStatement(node, subtreeFlags); + + case SyntaxKind.LabeledStatement: + return computeLabeledStatement(node, subtreeFlags); + + case SyntaxKind.ClassDeclaration: + return computeClassDeclaration(node, subtreeFlags); + + case SyntaxKind.ClassExpression: + return computeClassExpression(node, subtreeFlags); + + case SyntaxKind.HeritageClause: + return computeHeritageClause(node, subtreeFlags); + + case SyntaxKind.ExpressionWithTypeArguments: + return computeExpressionWithTypeArguments(node, subtreeFlags); + + case SyntaxKind.Constructor: + return computeConstructor(node, subtreeFlags); + + case SyntaxKind.PropertyDeclaration: + return computePropertyDeclaration(node, subtreeFlags); + + case SyntaxKind.MethodDeclaration: + return computeMethod(node, subtreeFlags); + + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return computeAccessor(node, subtreeFlags); + + case SyntaxKind.ImportEqualsDeclaration: + return computeImportEquals(node, subtreeFlags); + + case SyntaxKind.PropertyAccessExpression: + return computePropertyAccess(node, subtreeFlags); + + default: + return computeOther(node, kind, subtreeFlags); + } + } + + function computeCallExpression(node: CallExpression, subtreeFlags: TransformFlags) { + let transformFlags = subtreeFlags; + const expression = node.expression; + const expressionKind = expression.kind; + + if (subtreeFlags & TransformFlags.ContainsSpreadElementExpression + || isSuperOrSuperProperty(expression, expressionKind)) { + // If the this node contains a SpreadElementExpression, or is a super call, then it is an ES6 + // node. + transformFlags |= TransformFlags.AssertES6; + } + + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~TransformFlags.ArrayLiteralOrCallOrNewExcludes; + } + + function isSuperOrSuperProperty(node: Node, kind: SyntaxKind) { + switch (kind) { + case SyntaxKind.SuperKeyword: + return true; + + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + const expression = (node).expression; + const expressionKind = expression.kind; + return expressionKind === SyntaxKind.SuperKeyword; + } + + return false; + } + + function computeBinaryExpression(node: BinaryExpression, subtreeFlags: TransformFlags) { + let transformFlags = subtreeFlags; + const operatorTokenKind = node.operatorToken.kind; + const leftKind = node.left.kind; + + if (operatorTokenKind === SyntaxKind.EqualsToken + && (leftKind === SyntaxKind.ObjectLiteralExpression + || leftKind === SyntaxKind.ArrayLiteralExpression)) { + // Destructuring assignments are ES6 syntax. + transformFlags |= TransformFlags.AssertES6 | TransformFlags.DestructuringAssignment; + } + else if (operatorTokenKind === SyntaxKind.AsteriskAsteriskToken + || operatorTokenKind === SyntaxKind.AsteriskAsteriskEqualsToken) { + // Exponentiation is ES7 syntax. + transformFlags |= TransformFlags.AssertES7; + } + + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~TransformFlags.NodeExcludes; + } + + function computeParameter(node: ParameterDeclaration, subtreeFlags: TransformFlags) { + let transformFlags = subtreeFlags; + const modifierFlags = getModifierFlags(node); + const name = node.name; + const initializer = node.initializer; + const dotDotDotToken = node.dotDotDotToken; + + // If the parameter has a question token, then it is TypeScript syntax. + if (node.questionToken) { + transformFlags |= TransformFlags.AssertTypeScript; + } + + // If the parameter's name is 'this', then it is TypeScript syntax. + if (subtreeFlags & TransformFlags.ContainsDecorators + || (name && isIdentifier(name) && name.originalKeywordKind === SyntaxKind.ThisKeyword)) { + transformFlags |= TransformFlags.AssertTypeScript; + } + + // If a parameter has an accessibility modifier, then it is TypeScript syntax. + if (modifierFlags & ModifierFlags.ParameterPropertyModifier) { + transformFlags |= TransformFlags.AssertTypeScript | TransformFlags.ContainsParameterPropertyAssignments; + } + + // If a parameter has an initializer, a binding pattern or a dotDotDot token, then + // it is ES6 syntax and its container must emit default value assignments or parameter destructuring downlevel. + if (subtreeFlags & TransformFlags.ContainsBindingPattern || initializer || dotDotDotToken) { + transformFlags |= TransformFlags.AssertES6 | TransformFlags.ContainsDefaultValueAssignments; + } + + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~TransformFlags.ParameterExcludes; + } + + function computeParenthesizedExpression(node: ParenthesizedExpression, subtreeFlags: TransformFlags) { + let transformFlags = subtreeFlags; + const expression = node.expression; + const expressionKind = expression.kind; + const expressionTransformFlags = expression.transformFlags; + + // If the node is synthesized, it means the emitter put the parentheses there, + // not the user. If we didn't want them, the emitter would not have put them + // there. + if (expressionKind === SyntaxKind.AsExpression + || expressionKind === SyntaxKind.TypeAssertionExpression) { + transformFlags |= TransformFlags.AssertTypeScript; + } + + // If the expression of a ParenthesizedExpression is a destructuring assignment, + // then the ParenthesizedExpression is a destructuring assignment. + if (expressionTransformFlags & TransformFlags.DestructuringAssignment) { + transformFlags |= TransformFlags.DestructuringAssignment; + } + + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~TransformFlags.NodeExcludes; + } + + function computeClassDeclaration(node: ClassDeclaration, subtreeFlags: TransformFlags) { + let transformFlags: TransformFlags; + const modifierFlags = getModifierFlags(node); + + if (modifierFlags & ModifierFlags.Ambient) { + // An ambient declaration is TypeScript syntax. + transformFlags = TransformFlags.AssertTypeScript; + } + else { + // A ClassDeclaration is ES6 syntax. + transformFlags = subtreeFlags | TransformFlags.AssertES6; + + // A class with a parameter property assignment, property initializer, or decorator is + // TypeScript syntax. + // An exported declaration may be TypeScript syntax. + if ((subtreeFlags & TransformFlags.TypeScriptClassSyntaxMask) + || (modifierFlags & ModifierFlags.Export)) { + transformFlags |= TransformFlags.AssertTypeScript; + } + + if (subtreeFlags & TransformFlags.ContainsLexicalThisInComputedPropertyName) { + // A computed property name containing `this` might need to be rewritten, + // so propagate the ContainsLexicalThis flag upward. + transformFlags |= TransformFlags.ContainsLexicalThis; + } + } + + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~TransformFlags.ClassExcludes; + } + + function computeClassExpression(node: ClassExpression, subtreeFlags: TransformFlags) { + // A ClassExpression is ES6 syntax. + let transformFlags = subtreeFlags | TransformFlags.AssertES6; + + // A class with a parameter property assignment, property initializer, or decorator is + // TypeScript syntax. + if (subtreeFlags & TransformFlags.TypeScriptClassSyntaxMask) { + transformFlags |= TransformFlags.AssertTypeScript; + } + + if (subtreeFlags & TransformFlags.ContainsLexicalThisInComputedPropertyName) { + // A computed property name containing `this` might need to be rewritten, + // so propagate the ContainsLexicalThis flag upward. + transformFlags |= TransformFlags.ContainsLexicalThis; + } + + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~TransformFlags.ClassExcludes; + } + + function computeHeritageClause(node: HeritageClause, subtreeFlags: TransformFlags) { + let transformFlags = subtreeFlags; + + switch (node.token) { + case SyntaxKind.ExtendsKeyword: + // An `extends` HeritageClause is ES6 syntax. + transformFlags |= TransformFlags.AssertES6; + break; + + case SyntaxKind.ImplementsKeyword: + // An `implements` HeritageClause is TypeScript syntax. + transformFlags |= TransformFlags.AssertTypeScript; + break; + + default: + Debug.fail("Unexpected token for heritage clause"); + break; + } + + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~TransformFlags.NodeExcludes; + } + + function computeExpressionWithTypeArguments(node: ExpressionWithTypeArguments, subtreeFlags: TransformFlags) { + // An ExpressionWithTypeArguments is ES6 syntax, as it is used in the + // extends clause of a class. + let transformFlags = subtreeFlags | TransformFlags.AssertES6; + + // If an ExpressionWithTypeArguments contains type arguments, then it + // is TypeScript syntax. + if (node.typeArguments) { + transformFlags |= TransformFlags.AssertTypeScript; + } + + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~TransformFlags.NodeExcludes; + } + + function computeConstructor(node: ConstructorDeclaration, subtreeFlags: TransformFlags) { + let transformFlags = subtreeFlags; + const body = node.body; + + if (body === undefined) { + // An overload constructor is TypeScript syntax. + transformFlags |= TransformFlags.AssertTypeScript; + } + + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~TransformFlags.ConstructorExcludes; + } + + function computeMethod(node: MethodDeclaration, subtreeFlags: TransformFlags) { + // A MethodDeclaration is ES6 syntax. + let transformFlags = subtreeFlags | TransformFlags.AssertES6; + const modifierFlags = getModifierFlags(node); + const body = node.body; + const typeParameters = node.typeParameters; + const asteriskToken = node.asteriskToken; + + // A MethodDeclaration is TypeScript syntax if it is either async, abstract, overloaded, + // generic, or has a decorator. + if (!body + || typeParameters + || (modifierFlags & (ModifierFlags.Async | ModifierFlags.Abstract)) + || (subtreeFlags & TransformFlags.ContainsDecorators)) { + transformFlags |= TransformFlags.AssertTypeScript; + } + + // Currently, we only support generators that were originally async function bodies. + if (asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) { + transformFlags |= TransformFlags.AssertGenerator; + } + + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~TransformFlags.MethodOrAccessorExcludes; + } + + function computeAccessor(node: AccessorDeclaration, subtreeFlags: TransformFlags) { + let transformFlags = subtreeFlags; + const modifierFlags = getModifierFlags(node); + const body = node.body; + + // A MethodDeclaration is TypeScript syntax if it is either async, abstract, overloaded, + // generic, or has a decorator. + if (!body + || (modifierFlags & (ModifierFlags.Async | ModifierFlags.Abstract)) + || (subtreeFlags & TransformFlags.ContainsDecorators)) { + transformFlags |= TransformFlags.AssertTypeScript; + } + + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~TransformFlags.MethodOrAccessorExcludes; + } + + function computePropertyDeclaration(node: PropertyDeclaration, subtreeFlags: TransformFlags) { + // A PropertyDeclaration is TypeScript syntax. + let transformFlags = subtreeFlags | TransformFlags.AssertTypeScript; + + // If the PropertyDeclaration has an initializer, we need to inform its ancestor + // so that it handle the transformation. + if (node.initializer) { + transformFlags |= TransformFlags.ContainsPropertyInitializer; + } + + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~TransformFlags.NodeExcludes; + } + + function computeFunctionDeclaration(node: FunctionDeclaration, subtreeFlags: TransformFlags) { + let transformFlags: TransformFlags; + const modifierFlags = getModifierFlags(node); + const body = node.body; + const asteriskToken = node.asteriskToken; + + if (!body || (modifierFlags & ModifierFlags.Ambient)) { + // An ambient declaration is TypeScript syntax. + // A FunctionDeclaration without a body is an overload and is TypeScript syntax. + transformFlags = TransformFlags.AssertTypeScript; + } + else { + transformFlags = subtreeFlags | TransformFlags.ContainsHoistedDeclarationOrCompletion; + + // If a FunctionDeclaration is exported, then it is either ES6 or TypeScript syntax. + if (modifierFlags & ModifierFlags.Export) { + transformFlags |= TransformFlags.AssertTypeScript | TransformFlags.AssertES6; + } + + // If a FunctionDeclaration is async, then it is TypeScript syntax. + if (modifierFlags & ModifierFlags.Async) { + transformFlags |= TransformFlags.AssertTypeScript; + } + + // If a FunctionDeclaration's subtree has marked the container as needing to capture the + // lexical this, or the function contains parameters with initializers, then this node is + // ES6 syntax. + if (subtreeFlags & TransformFlags.ES6FunctionSyntaxMask) { + transformFlags |= TransformFlags.AssertES6; + } + + // If a FunctionDeclaration is generator function and is the body of a + // transformed async function, then this node can be transformed to a + // down-level generator. + // Currently we do not support transforming any other generator fucntions + // down level. + if (asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) { + transformFlags |= TransformFlags.AssertGenerator; + } + } + + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~TransformFlags.FunctionExcludes; + } + + function computeFunctionExpression(node: FunctionExpression, subtreeFlags: TransformFlags) { + let transformFlags = subtreeFlags; + const modifierFlags = getModifierFlags(node); + const asteriskToken = node.asteriskToken; + + // An async function expression is TypeScript syntax. + if (modifierFlags & ModifierFlags.Async) { + transformFlags |= TransformFlags.AssertTypeScript; + } + + // If a FunctionExpression's subtree has marked the container as needing to capture the + // lexical this, or the function contains parameters with initializers, then this node is + // ES6 syntax. + if (subtreeFlags & TransformFlags.ES6FunctionSyntaxMask) { + transformFlags |= TransformFlags.AssertES6; + } + + // If a FunctionExpression is generator function and is the body of a + // transformed async function, then this node can be transformed to a + // down-level generator. + // Currently we do not support transforming any other generator fucntions + // down level. + if (asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) { + transformFlags |= TransformFlags.AssertGenerator; + } + + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~TransformFlags.FunctionExcludes; + } + + function computeArrowFunction(node: ArrowFunction, subtreeFlags: TransformFlags) { + // An ArrowFunction is ES6 syntax, and excludes markers that should not escape the scope of an ArrowFunction. + let transformFlags = subtreeFlags | TransformFlags.AssertES6; + const modifierFlags = getModifierFlags(node); + + // An async arrow function is TypeScript syntax. + if (modifierFlags & ModifierFlags.Async) { + transformFlags |= TransformFlags.AssertTypeScript; + } + + // If an ArrowFunction contains a lexical this, its container must capture the lexical this. + if (subtreeFlags & TransformFlags.ContainsLexicalThis) { + transformFlags |= TransformFlags.ContainsCapturedLexicalThis; + } + + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~TransformFlags.ArrowFunctionExcludes; + } + + function computePropertyAccess(node: PropertyAccessExpression, subtreeFlags: TransformFlags) { + let transformFlags = subtreeFlags; + const expression = node.expression; + const expressionKind = expression.kind; + + // If a PropertyAccessExpression starts with a super keyword, then it is + // ES6 syntax, and requires a lexical `this` binding. + if (expressionKind === SyntaxKind.SuperKeyword) { + transformFlags |= TransformFlags.ContainsLexicalThis; + } + + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~TransformFlags.NodeExcludes; + } + + function computeVariableDeclaration(node: VariableDeclaration, subtreeFlags: TransformFlags) { + let transformFlags = subtreeFlags; + const nameKind = node.name.kind; + + // A VariableDeclaration with a binding pattern is ES6 syntax. + if (nameKind === SyntaxKind.ObjectBindingPattern || nameKind === SyntaxKind.ArrayBindingPattern) { + transformFlags |= TransformFlags.AssertES6 | TransformFlags.ContainsBindingPattern; + } + + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~TransformFlags.NodeExcludes; + } + + function computeVariableStatement(node: VariableStatement, subtreeFlags: TransformFlags) { + let transformFlags: TransformFlags; + const modifierFlags = getModifierFlags(node); + const declarationListTransformFlags = node.declarationList.transformFlags; + + // An ambient declaration is TypeScript syntax. + if (modifierFlags & ModifierFlags.Ambient) { + transformFlags = TransformFlags.AssertTypeScript; + } + else { + transformFlags = subtreeFlags; + + // If a VariableStatement is exported, then it is either ES6 or TypeScript syntax. + if (modifierFlags & ModifierFlags.Export) { + transformFlags |= TransformFlags.AssertES6 | TransformFlags.AssertTypeScript; + } + + if (declarationListTransformFlags & TransformFlags.ContainsBindingPattern) { + transformFlags |= TransformFlags.AssertES6; + } + } + + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~TransformFlags.NodeExcludes; + } + + function computeLabeledStatement(node: LabeledStatement, subtreeFlags: TransformFlags) { + let transformFlags = subtreeFlags; + + // A labeled statement containing a block scoped binding *may* need to be transformed from ES6. + if (subtreeFlags & TransformFlags.ContainsBlockScopedBinding + && isIterationStatement(node, /*lookInLabeledStatements*/ true)) { + transformFlags |= TransformFlags.AssertES6; + } + + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~TransformFlags.NodeExcludes; + } + + function computeImportEquals(node: ImportEqualsDeclaration, subtreeFlags: TransformFlags) { + let transformFlags = subtreeFlags; + + // An ImportEqualsDeclaration with a namespace reference is TypeScript. + if (!isExternalModuleImportEqualsDeclaration(node)) { + transformFlags |= TransformFlags.AssertTypeScript; + } + + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~TransformFlags.NodeExcludes; + } + + function computeExpressionStatement(node: ExpressionStatement, subtreeFlags: TransformFlags) { + let transformFlags = subtreeFlags; + + // If the expression of an expression statement is a destructuring assignment, + // then we treat the statement as ES6 so that we can indicate that we do not + // need to hold on to the right-hand side. + if (node.expression.transformFlags & TransformFlags.DestructuringAssignment) { + transformFlags |= TransformFlags.AssertES6; + } + + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~TransformFlags.NodeExcludes; + } + + function computeModuleDeclaration(node: ModuleDeclaration, subtreeFlags: TransformFlags) { + let transformFlags = TransformFlags.AssertTypeScript; + const modifierFlags = getModifierFlags(node); + + if ((modifierFlags & ModifierFlags.Ambient) === 0) { + transformFlags |= subtreeFlags; + } + + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~TransformFlags.ModuleExcludes; + } + + function computeVariableDeclarationList(node: VariableDeclarationList, subtreeFlags: TransformFlags) { + let transformFlags = subtreeFlags | TransformFlags.ContainsHoistedDeclarationOrCompletion; + + if (subtreeFlags & TransformFlags.ContainsBindingPattern) { + transformFlags |= TransformFlags.AssertES6; + } + + // If a VariableDeclarationList is `let` or `const`, then it is ES6 syntax. + if (node.flags & NodeFlags.BlockScoped) { + transformFlags |= TransformFlags.AssertES6 | TransformFlags.ContainsBlockScopedBinding; + } + + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~TransformFlags.VariableDeclarationListExcludes; + } + + function computeOther(node: Node, kind: SyntaxKind, subtreeFlags: TransformFlags) { + // Mark transformations needed for each node + let transformFlags = subtreeFlags; + let excludeFlags = TransformFlags.NodeExcludes; + + switch (kind) { + case SyntaxKind.PublicKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.AbstractKeyword: + case SyntaxKind.DeclareKeyword: + case SyntaxKind.AsyncKeyword: + case SyntaxKind.ConstKeyword: + case SyntaxKind.AwaitExpression: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.EnumMember: + case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.AsExpression: + case SyntaxKind.NonNullExpression: + case SyntaxKind.ReadonlyKeyword: + // These nodes are TypeScript syntax. + transformFlags |= TransformFlags.AssertTypeScript; + break; + + case SyntaxKind.JsxElement: + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxOpeningElement: + case SyntaxKind.JsxText: + case SyntaxKind.JsxClosingElement: + case SyntaxKind.JsxAttribute: + case SyntaxKind.JsxSpreadAttribute: + case SyntaxKind.JsxExpression: + // These nodes are Jsx syntax. + transformFlags |= TransformFlags.AssertJsx; + break; + + case SyntaxKind.ExportKeyword: + // This node is both ES6 and TypeScript syntax. + transformFlags |= TransformFlags.AssertES6 | TransformFlags.AssertTypeScript; + break; + + case SyntaxKind.DefaultKeyword: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TemplateHead: + case SyntaxKind.TemplateMiddle: + case SyntaxKind.TemplateTail: + case SyntaxKind.TemplateExpression: + case SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.ForOfStatement: + // These nodes are ES6 syntax. + transformFlags |= TransformFlags.AssertES6; + break; + + case SyntaxKind.YieldExpression: + // This node is ES6 syntax. + transformFlags |= TransformFlags.AssertES6 | TransformFlags.ContainsYield; + break; + + case SyntaxKind.AnyKeyword: + case SyntaxKind.NumberKeyword: + case SyntaxKind.NeverKeyword: + case SyntaxKind.StringKeyword: + case SyntaxKind.BooleanKeyword: + case SyntaxKind.SymbolKeyword: + case SyntaxKind.VoidKeyword: + case SyntaxKind.TypeParameter: + case SyntaxKind.PropertySignature: + case SyntaxKind.MethodSignature: + case SyntaxKind.CallSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.IndexSignature: + case SyntaxKind.TypePredicate: + case SyntaxKind.TypeReference: + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + case SyntaxKind.TypeQuery: + case SyntaxKind.TypeLiteral: + case SyntaxKind.ArrayType: + case SyntaxKind.TupleType: + case SyntaxKind.UnionType: + case SyntaxKind.IntersectionType: + case SyntaxKind.ParenthesizedType: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.ThisType: + case SyntaxKind.LiteralType: + // Types and signatures are TypeScript syntax, and exclude all other facts. + transformFlags = TransformFlags.AssertTypeScript; + excludeFlags = TransformFlags.TypeExcludes; + break; + + case SyntaxKind.ComputedPropertyName: + // Even though computed property names are ES6, we don't treat them as such. + // This is so that they can flow through PropertyName transforms unaffected. + // Instead, we mark the container as ES6, so that it can properly handle the transform. + transformFlags |= TransformFlags.ContainsComputedPropertyName; + if (subtreeFlags & TransformFlags.ContainsLexicalThis) { + // A computed method name like `[this.getName()](x: string) { ... }` needs to + // distinguish itself from the normal case of a method body containing `this`: + // `this` inside a method doesn't need to be rewritten (the method provides `this`), + // whereas `this` inside a computed name *might* need to be rewritten if the class/object + // is inside an arrow function: + // `_this = this; () => class K { [_this.getName()]() { ... } }` + // To make this distinction, use ContainsLexicalThisInComputedPropertyName + // instead of ContainsLexicalThis for computed property names + transformFlags |= TransformFlags.ContainsLexicalThisInComputedPropertyName; + } + break; + + case SyntaxKind.SpreadElementExpression: + // This node is ES6 syntax, but is handled by a containing node. + transformFlags |= TransformFlags.ContainsSpreadElementExpression; + break; + + case SyntaxKind.SuperKeyword: + // This node is ES6 syntax. + transformFlags |= TransformFlags.AssertES6; + break; + + case SyntaxKind.ThisKeyword: + // Mark this node and its ancestors as containing a lexical `this` keyword. + transformFlags |= TransformFlags.ContainsLexicalThis; + break; + + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ArrayBindingPattern: + // These nodes are ES6 syntax. + transformFlags |= TransformFlags.AssertES6 | TransformFlags.ContainsBindingPattern; + break; + + case SyntaxKind.Decorator: + // This node is TypeScript syntax, and marks its container as also being TypeScript syntax. + transformFlags |= TransformFlags.AssertTypeScript | TransformFlags.ContainsDecorators; + break; + + case SyntaxKind.ObjectLiteralExpression: + excludeFlags = TransformFlags.ObjectLiteralExcludes; + if (subtreeFlags & TransformFlags.ContainsComputedPropertyName) { + // If an ObjectLiteralExpression contains a ComputedPropertyName, then it + // is an ES6 node. + transformFlags |= TransformFlags.AssertES6; + } + + if (subtreeFlags & TransformFlags.ContainsLexicalThisInComputedPropertyName) { + // A computed property name containing `this` might need to be rewritten, + // so propagate the ContainsLexicalThis flag upward. + transformFlags |= TransformFlags.ContainsLexicalThis; + } + + break; + + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.NewExpression: + excludeFlags = TransformFlags.ArrayLiteralOrCallOrNewExcludes; + if (subtreeFlags & TransformFlags.ContainsSpreadElementExpression) { + // If the this node contains a SpreadElementExpression, then it is an ES6 + // node. + transformFlags |= TransformFlags.AssertES6; + } + + break; + + case SyntaxKind.DoStatement: + case SyntaxKind.WhileStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.ForInStatement: + // A loop containing a block scoped binding *may* need to be transformed from ES6. + if (subtreeFlags & TransformFlags.ContainsBlockScopedBinding) { + transformFlags |= TransformFlags.AssertES6; + } + + break; + + case SyntaxKind.SourceFile: + if (subtreeFlags & TransformFlags.ContainsCapturedLexicalThis) { + transformFlags |= TransformFlags.AssertES6; + } + + break; + + case SyntaxKind.ReturnStatement: + case SyntaxKind.ContinueStatement: + case SyntaxKind.BreakStatement: + transformFlags |= TransformFlags.ContainsHoistedDeclarationOrCompletion; + break; + } + + node.transformFlags = transformFlags | TransformFlags.HasComputedFlags; + return transformFlags & ~excludeFlags; + } } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 463b1d5..bf7e4ef 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1,7 +1,10 @@ +/// /// /* @internal */ namespace ts { + const ambientModuleSymbolRegex = /^".+"$/; + let nextSymbolId = 1; let nextNodeId = 1; let nextMergeId = 1; @@ -100,6 +103,7 @@ namespace ts { getAliasedSymbol: resolveAlias, getEmitResolver, getExportsOfModule: getExportsOfModuleAsArray, + getAmbientModules, getJsxElementAttributesType, getJsxIntrinsicTagNames, @@ -129,6 +133,7 @@ namespace ts { const esSymbolType = createIntrinsicType(TypeFlags.ESSymbol, "symbol"); const voidType = createIntrinsicType(TypeFlags.Void, "void"); const neverType = createIntrinsicType(TypeFlags.Never, "never"); + const silentNeverType = createIntrinsicType(TypeFlags.Never, "never"); const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); const emptyGenericType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); @@ -144,6 +149,7 @@ namespace ts { const anySignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); const unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, unknownType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); const resolvingSignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); + const silentNeverSignature = createSignature(undefined, undefined, undefined, emptyArray, silentNeverType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true); @@ -158,6 +164,7 @@ namespace ts { let getGlobalESSymbolConstructorSymbol: () => Symbol; let getGlobalPromiseConstructorSymbol: () => Symbol; + let tryGetGlobalPromiseConstructorSymbol: () => Symbol; let globalObjectType: ObjectType; let globalFunctionType: ObjectType; @@ -330,6 +337,7 @@ namespace ts { const assignableRelation = createMap(); const comparableRelation = createMap(); const identityRelation = createMap(); + const enumRelation = createMap(); // This is for caching the result of getSymbolDisplayBuilder. Do not access directly. let _displayBuilder: SymbolDisplayBuilder; @@ -637,7 +645,7 @@ namespace ts { const initializerOfNonStaticProperty = current.parent && current.parent.kind === SyntaxKind.PropertyDeclaration && - (current.parent.flags & NodeFlags.Static) === 0 && + (getModifierFlags(current.parent) & ModifierFlags.Static) === 0 && (current.parent).initializer === current; if (initializerOfNonStaticProperty) { @@ -757,7 +765,7 @@ namespace ts { // local variables of the constructor. This effectively means that entities from outer scopes // by the same name as a constructor parameter or local variable are inaccessible // in initializer expressions for instance member variables. - if (isClassLike(location.parent) && !(location.flags & NodeFlags.Static)) { + if (isClassLike(location.parent) && !(getModifierFlags(location) & ModifierFlags.Static)) { const ctor = findConstructorDeclaration(location.parent); if (ctor && ctor.locals) { if (getSymbol(ctor.locals, name, meaning & SymbolFlags.Value)) { @@ -771,7 +779,7 @@ namespace ts { case SyntaxKind.ClassExpression: case SyntaxKind.InterfaceDeclaration: if (result = getSymbol(getSymbolOfNode(location).members, name, meaning & SymbolFlags.Type)) { - if (lastLocation && lastLocation.flags & NodeFlags.Static) { + if (lastLocation && getModifierFlags(lastLocation) & ModifierFlags.Static) { // TypeScript 1.0 spec (April 2014): 3.4.1 // The scope of a type parameter extends over the entire declaration with which the type // parameter list is associated, with the exception of static member declarations in classes. @@ -872,7 +880,8 @@ namespace ts { if (nameNotFoundMessage) { if (!errorLocation || !checkAndReportErrorForMissingPrefix(errorLocation, name, nameArg) && - !checkAndReportErrorForExtendingInterface(errorLocation)) { + !checkAndReportErrorForExtendingInterface(errorLocation) && + !checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning)) { error(errorLocation, nameNotFoundMessage, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg)); } } @@ -908,8 +917,8 @@ namespace ts { } } - // If we're in an external module, we can't reference symbols created from UMD export declarations - if (result && isInExternalModule) { + // If we're in an external module, we can't reference value symbols created from UMD export declarations + if (result && isInExternalModule && (meaning & SymbolFlags.Value) === SymbolFlags.Value) { const decls = result.declarations; if (decls && decls.length === 1 && decls[0].kind === SyntaxKind.NamespaceExportDeclaration) { error(errorLocation, Diagnostics.Identifier_0_must_be_imported_from_a_module, name); @@ -942,7 +951,7 @@ namespace ts { // No static member is present. // Check if we're in an instance method and look for a relevant instance member. - if (location === container && !(location.flags & NodeFlags.Static)) { + if (location === container && !(getModifierFlags(location) & ModifierFlags.Static)) { const instanceType = (getDeclaredTypeOfSymbol(classSymbol)).thisType; if (getPropertyOfType(instanceType, name)) { error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg)); @@ -982,6 +991,16 @@ namespace ts { } } + function checkAndReportErrorForUsingTypeAsValue(errorLocation: Node, name: string, meaning: SymbolFlags): boolean { + if (meaning & (SymbolFlags.Value & ~SymbolFlags.NamespaceModule)) { + const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined)); + if (symbol && !(symbol.flags & SymbolFlags.NamespaceModule)) { + error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, name); + return true; + } + } + return false; + } function checkResolvedBlockScopedVariable(result: Symbol, errorLocation: Node): void { Debug.assert((result.flags & SymbolFlags.BlockScopedVariable) !== 0); @@ -1039,7 +1058,7 @@ namespace ts { const moduleSymbol = resolveExternalModuleName(node, (node.parent).moduleSpecifier); if (moduleSymbol) { - const exportDefaultSymbol = isShorthandAmbientModule(moduleSymbol.valueDeclaration) ? + const exportDefaultSymbol = isShorthandAmbientModuleSymbol(moduleSymbol) ? moduleSymbol : moduleSymbol.exports["export="] ? getPropertyOfType(getTypeOfSymbol(moduleSymbol.exports["export="]), "default") : @@ -1115,7 +1134,7 @@ namespace ts { if (targetSymbol) { const name = specifier.propertyName || specifier.name; if (name.text) { - if (isShorthandAmbientModule(moduleSymbol.valueDeclaration)) { + if (isShorthandAmbientModuleSymbol(moduleSymbol)) { return moduleSymbol; } @@ -1272,7 +1291,7 @@ namespace ts { } // Resolves a qualified name and any involved aliases - function resolveEntityName(name: EntityNameOrEntityNameExpression, meaning: SymbolFlags, ignoreErrors?: boolean, dontResolveAlias?: boolean): Symbol | undefined { + function resolveEntityName(name: EntityNameOrEntityNameExpression, meaning: SymbolFlags, ignoreErrors?: boolean, dontResolveAlias?: boolean, location?: Node): Symbol | undefined { if (nodeIsMissing(name)) { return undefined; } @@ -1281,7 +1300,7 @@ namespace ts { if (name.kind === SyntaxKind.Identifier) { const message = meaning === SymbolFlags.Namespace ? Diagnostics.Cannot_find_namespace_0 : Diagnostics.Cannot_find_name_0; - symbol = resolveName(name, (name).text, meaning, ignoreErrors ? undefined : message, name); + symbol = resolveName(location || name, (name).text, meaning, ignoreErrors ? undefined : message, name); if (!symbol) { return undefined; } @@ -1290,18 +1309,17 @@ namespace ts { const left = name.kind === SyntaxKind.QualifiedName ? (name).left : (name).expression; const right = name.kind === SyntaxKind.QualifiedName ? (name).right : (name).name; - const namespace = resolveEntityName(left, SymbolFlags.Namespace, ignoreErrors); + const namespace = resolveEntityName(left, SymbolFlags.Namespace, ignoreErrors, /*dontResolveAlias*/ false, location); if (!namespace || nodeIsMissing(right)) { return undefined; } else if (namespace === unknownSymbol) { return namespace; } - symbol = getSymbol(getExportsOfSymbol(namespace), right.text, meaning); if (!symbol) { if (!ignoreErrors) { - error(right, Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(namespace), declarationNameToString(right)); + error(right, Diagnostics.Namespace_0_has_no_exported_member_1, getFullyQualifiedName(namespace), declarationNameToString(right)); } return undefined; } @@ -1323,10 +1341,13 @@ namespace ts { } const moduleReferenceLiteral = moduleReferenceExpression; + return resolveExternalModule(location, moduleReferenceLiteral.text, moduleNotFoundError, moduleReferenceLiteral); + } + function resolveExternalModule(location: Node, moduleReference: string, moduleNotFoundError: DiagnosticMessage, errorNode: Node): Symbol { // Module names are escaped in our symbol table. However, string literal values aren't. // Escape the name in the "require(...)" clause to ensure we find the right symbol. - const moduleName = escapeIdentifier(moduleReferenceLiteral.text); + const moduleName = escapeIdentifier(moduleReference); if (moduleName === undefined) { return; @@ -1341,7 +1362,7 @@ namespace ts { } } - const resolvedModule = getResolvedModule(getSourceFileOfNode(location), moduleReferenceLiteral.text); + const resolvedModule = getResolvedModule(getSourceFileOfNode(location), moduleReference); const sourceFile = resolvedModule && host.getSourceFile(resolvedModule.resolvedFileName); if (sourceFile) { if (sourceFile.symbol) { @@ -1350,7 +1371,7 @@ namespace ts { } if (moduleNotFoundError) { // report errors only if it was requested - error(moduleReferenceLiteral, Diagnostics.File_0_is_not_a_module, sourceFile.fileName); + error(errorNode, Diagnostics.File_0_is_not_a_module, sourceFile.fileName); } return undefined; } @@ -1367,10 +1388,10 @@ namespace ts { const tsExtension = tryExtractTypeScriptExtension(moduleName); if (tsExtension) { const diag = Diagnostics.An_import_path_cannot_end_with_a_0_extension_Consider_importing_1_instead; - error(moduleReferenceLiteral, diag, tsExtension, removeExtension(moduleName, tsExtension)); + error(errorNode, diag, tsExtension, removeExtension(moduleName, tsExtension)); } else { - error(moduleReferenceLiteral, moduleNotFoundError, moduleName); + error(errorNode, moduleNotFoundError, moduleName); } } return undefined; @@ -1740,7 +1761,15 @@ namespace ts { return false; } - function isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessibilityResult { + /** + * Check if the given symbol in given enclosing declaration is accessible and mark all associated alias to be visible if requested + * + * @param symbol a Symbol to check if accessible + * @param enclosingDeclaration a Node containing reference to the symbol + * @param meaning a SymbolFlags to check if such meaning of the symbol is accessible + * @param shouldComputeAliasToMakeVisible a boolean value to indicate whether to return aliases to be mark visible in case the symbol is accessible + */ + function isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, shouldComputeAliasesToMakeVisible: boolean): SymbolAccessibilityResult { if (symbol && enclosingDeclaration && !(symbol.flags & SymbolFlags.TypeParameter)) { const initialSymbol = symbol; let meaningToLook = meaning; @@ -1748,7 +1777,7 @@ namespace ts { // Symbol is accessible if it by itself is accessible const accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaningToLook, /*useOnlyExternalAliasing*/ false); if (accessibleSymbolChain) { - const hasAccessibleDeclarations = hasVisibleDeclarations(accessibleSymbolChain[0]); + const hasAccessibleDeclarations = hasVisibleDeclarations(accessibleSymbolChain[0], shouldComputeAliasesToMakeVisible); if (!hasAccessibleDeclarations) { return { accessibility: SymbolAccessibility.NotAccessible, @@ -1812,7 +1841,7 @@ namespace ts { return isAmbientModule(declaration) || (declaration.kind === SyntaxKind.SourceFile && isExternalOrCommonJsModule(declaration)); } - function hasVisibleDeclarations(symbol: Symbol): SymbolVisibilityResult { + function hasVisibleDeclarations(symbol: Symbol, shouldComputeAliasToMakeVisible: boolean): SymbolVisibilityResult { let aliasesToMakeVisible: AnyImportSyntax[]; if (forEach(symbol.declarations, declaration => !getIsDeclarationVisible(declaration))) { return undefined; @@ -1826,16 +1855,21 @@ namespace ts { const anyImportSyntax = getAnyImportSyntax(declaration); if (anyImportSyntax && - !(anyImportSyntax.flags & NodeFlags.Export) && // import clause without export + !(getModifierFlags(anyImportSyntax) & ModifierFlags.Export) && // import clause without export isDeclarationVisible(anyImportSyntax.parent)) { - getNodeLinks(declaration).isVisible = true; - if (aliasesToMakeVisible) { - if (!contains(aliasesToMakeVisible, anyImportSyntax)) { - aliasesToMakeVisible.push(anyImportSyntax); + // In function "buildTypeDisplay" where we decide whether to write type-alias or serialize types, + // we want to just check if type- alias is accessible or not but we don't care about emitting those alias at that time + // since we will do the emitting later in trackSymbol. + if (shouldComputeAliasToMakeVisible) { + getNodeLinks(declaration).isVisible = true; + if (aliasesToMakeVisible) { + if (!contains(aliasesToMakeVisible, anyImportSyntax)) { + aliasesToMakeVisible.push(anyImportSyntax); + } + } + else { + aliasesToMakeVisible = [anyImportSyntax]; } - } - else { - aliasesToMakeVisible = [anyImportSyntax]; } return true; } @@ -1870,7 +1904,7 @@ namespace ts { const symbol = resolveName(enclosingDeclaration, (firstIdentifier).text, meaning, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined); // Verify if the symbol is accessible - return (symbol && hasVisibleDeclarations(symbol)) || { + return (symbol && hasVisibleDeclarations(symbol, /*shouldComputeAliasToMakeVisible*/ true)) || { accessibility: SymbolAccessibility.NotAccessible, errorSymbolName: getTextOfNode(firstIdentifier), errorNode: firstIdentifier @@ -1953,11 +1987,11 @@ namespace ts { return result || types; } - function visibilityToString(flags: NodeFlags) { - if (flags === NodeFlags.Private) { + function visibilityToString(flags: ModifierFlags) { + if (flags === ModifierFlags.Private) { return "private"; } - if (flags === NodeFlags.Protected) { + if (flags === ModifierFlags.Protected) { return "protected"; } return "public"; @@ -1982,6 +2016,10 @@ namespace ts { isExternalModuleAugmentation(node.parent.parent); } + function literalTypeToString(type: LiteralType) { + return type.flags & TypeFlags.StringLiteral ? `"${escapeString((type).text)}"` : (type).text; + } + function getSymbolDisplayBuilder(): SymbolDisplayBuilder { function getNameOfSymbol(symbol: Symbol): string { @@ -2061,7 +2099,7 @@ namespace ts { parentSymbol = symbol; } - // const the writer know we just wrote out a symbol. The declaration emitter writer uses + // Let the writer know we just wrote out a symbol. The declaration emitter writer uses // this to determine if an import it has previously seen (and not written out) needs // to be written to the file once the walk of the tree is complete. // @@ -2069,37 +2107,34 @@ namespace ts { // up front (for example, during checking) could determine if we need to emit the imports // and we could then access that data during declaration emit. writer.trackSymbol(symbol, enclosingDeclaration, meaning); - function walkSymbol(symbol: Symbol, meaning: SymbolFlags): void { - if (symbol) { - const accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaning, !!(flags & SymbolFormatFlags.UseOnlyExternalAliasing)); + /** @param endOfChain Set to false for recursive calls; non-recursive calls should always output something. */ + function walkSymbol(symbol: Symbol, meaning: SymbolFlags, endOfChain: boolean): void { + const accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaning, !!(flags & SymbolFormatFlags.UseOnlyExternalAliasing)); - if (!accessibleSymbolChain || - needsQualification(accessibleSymbolChain[0], enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning))) { + if (!accessibleSymbolChain || + needsQualification(accessibleSymbolChain[0], enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning))) { - // Go up and add our parent. - walkSymbol( - getParentOfSymbol(accessibleSymbolChain ? accessibleSymbolChain[0] : symbol), - getQualifiedLeftMeaning(meaning)); + // Go up and add our parent. + const parent = getParentOfSymbol(accessibleSymbolChain ? accessibleSymbolChain[0] : symbol); + if (parent) { + walkSymbol(parent, getQualifiedLeftMeaning(meaning), /*endOfChain*/ false); } + } - if (accessibleSymbolChain) { - for (const accessibleSymbol of accessibleSymbolChain) { - appendParentTypeArgumentsAndSymbolName(accessibleSymbol); - } + if (accessibleSymbolChain) { + for (const accessibleSymbol of accessibleSymbolChain) { + appendParentTypeArgumentsAndSymbolName(accessibleSymbol); } - else { - // If we didn't find accessible symbol chain for this symbol, break if this is external module - if (!parentSymbol && ts.forEach(symbol.declarations, hasExternalModuleSymbol)) { - return; - } - - // if this is anonymous type break - if (symbol.flags & SymbolFlags.TypeLiteral || symbol.flags & SymbolFlags.ObjectLiteral) { - return; - } + } + else if ( + // If this is the last part of outputting the symbol, always output. The cases apply only to parent symbols. + endOfChain || + // If a parent symbol is an external module, don't write it. (We prefer just `x` vs `"foo/bar".x`.) + !(!parentSymbol && ts.forEach(symbol.declarations, hasExternalModuleSymbol)) && + // If a parent symbol is an anonymous type, don't write it. + !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral))) { - appendParentTypeArgumentsAndSymbolName(symbol); - } + appendParentTypeArgumentsAndSymbolName(symbol); } } @@ -2109,11 +2144,11 @@ namespace ts { const isTypeParameter = symbol.flags & SymbolFlags.TypeParameter; const typeFormatFlag = TypeFormatFlags.UseFullyQualifiedType & typeFlags; if (!isTypeParameter && (enclosingDeclaration || typeFormatFlag)) { - walkSymbol(symbol, meaning); - return; + walkSymbol(symbol, meaning, /*endOfChain*/ true); + } + else { + appendParentTypeArgumentsAndSymbolName(symbol); } - - return appendParentTypeArgumentsAndSymbolName(symbol); } function buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]) { @@ -2148,7 +2183,9 @@ namespace ts { // The specified symbol flags need to be reinterpreted as type flags buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, nextFlags); } - else if (!(flags & TypeFormatFlags.InTypeAlias) && type.flags & (TypeFlags.Anonymous | TypeFlags.UnionOrIntersection) && type.aliasSymbol) { + else if (!(flags & TypeFormatFlags.InTypeAlias) && type.flags & (TypeFlags.Anonymous | TypeFlags.UnionOrIntersection) && type.aliasSymbol && + isSymbolAccessible(type.aliasSymbol, enclosingDeclaration, SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false).accessibility === SymbolAccessibility.Accessible) { + // Only write out inferred type with its corresponding type-alias if type-alias is visible const typeArguments = type.aliasTypeArguments; writeSymbolTypeReference(type.aliasSymbol, typeArguments, 0, typeArguments ? typeArguments.length : 0, nextFlags); } @@ -2158,11 +2195,8 @@ namespace ts { else if (type.flags & TypeFlags.Anonymous) { writeAnonymousType(type, nextFlags); } - else if (type.flags & TypeFlags.StringLiteral) { - writer.writeStringLiteral(`"${escapeString((type).text)}"`); - } - else if (type.flags & TypeFlags.NumberLiteral) { - writer.writeStringLiteral((type).text); + else if (type.flags & TypeFlags.StringOrNumberLiteral) { + writer.writeStringLiteral(literalTypeToString(type)); } else { // Should never get here @@ -2302,7 +2336,7 @@ namespace ts { function shouldWriteTypeOfFunctionSymbol() { const isStaticMethodSymbol = !!(symbol.flags & SymbolFlags.Method && // typeof static method - forEach(symbol.declarations, declaration => declaration.flags & NodeFlags.Static)); + forEach(symbol.declarations, declaration => getModifierFlags(declaration) & ModifierFlags.Static)); const isNonLocalFunctionSymbol = !!(symbol.flags & SymbolFlags.Function) && (symbol.parent || // is exported function symbol forEach(symbol.declarations, declaration => @@ -2498,8 +2532,8 @@ namespace ts { } } - function buildBindingElementDisplay(bindingElement: BindingElement, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) { - if (bindingElement.kind === SyntaxKind.OmittedExpression) { + function buildBindingElementDisplay(bindingElement: ArrayBindingElement, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) { + if (isOmittedExpression(bindingElement)) { return; } Debug.assert(bindingElement.kind === SyntaxKind.BindingElement); @@ -2669,7 +2703,7 @@ namespace ts { } const parent = getDeclarationContainer(node); // If the node is not exported or it is not ambient module element (except import declaration) - if (!(getCombinedNodeFlags(node) & NodeFlags.Export) && + if (!(getCombinedModifierFlags(node) & ModifierFlags.Export) && !(node.kind !== SyntaxKind.ImportEqualsDeclaration && parent.kind !== SyntaxKind.SourceFile && isInAmbientContext(parent))) { return isGlobalSourceFile(parent); } @@ -2682,7 +2716,7 @@ namespace ts { case SyntaxKind.SetAccessor: case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: - if (node.flags & (NodeFlags.Private | NodeFlags.Protected)) { + if (getModifierFlags(node) & (ModifierFlags.Private | ModifierFlags.Protected)) { // Private/protected properties/methods are not visible return false; } @@ -2714,8 +2748,9 @@ namespace ts { // Type parameters are always visible case SyntaxKind.TypeParameter: - // Source file is always visible + // Source file and namespace export are always visible case SyntaxKind.SourceFile: + case SyntaxKind.NamespaceExportDeclaration: return true; // Export assignments do not create name bindings outside the module @@ -2915,7 +2950,7 @@ namespace ts { // undefined or any type of the parent. if (!parentType || isTypeAny(parentType)) { if (declaration.initializer) { - return checkExpressionCached(declaration.initializer); + return checkDeclarationInitializer(declaration); } return parentType; } @@ -2975,7 +3010,9 @@ namespace ts { if (strictNullChecks && declaration.initializer && !(getFalsyFlags(checkExpressionCached(declaration.initializer)) & TypeFlags.Undefined)) { type = getTypeWithFacts(type, TypeFacts.NEUndefined); } - return type; + return declaration.initializer ? + getUnionType([type, checkExpressionCached(declaration.initializer)], /*subtypeReduction*/ true) : + type; } function getTypeForVariableLikeDeclarationFromJSDocComment(declaration: VariableLikeDeclaration) { @@ -3084,7 +3121,8 @@ namespace ts { // Use the type of the initializer expression if one is present if (declaration.initializer) { - return addOptionality(checkExpressionCached(declaration.initializer), /*optional*/ declaration.questionToken && includeOptionality); + const type = checkDeclarationInitializer(declaration); + return addOptionality(type, /*optional*/ declaration.questionToken && includeOptionality); } // If it is a short-hand property assignment, use the type of the identifier @@ -3106,7 +3144,7 @@ namespace ts { // pattern. Otherwise, it is the type any. function getTypeFromBindingElement(element: BindingElement, includePatternInType?: boolean, reportErrors?: boolean): Type { if (element.initializer) { - return checkExpressionCached(element.initializer); + return checkDeclarationInitializer(element); } if (isBindingPattern(element.name)) { return getTypeFromBindingPattern(element.name, includePatternInType, reportErrors); @@ -3118,7 +3156,7 @@ namespace ts { } // Return the type implied by an object binding pattern - function getTypeFromObjectBindingPattern(pattern: BindingPattern, includePatternInType: boolean, reportErrors: boolean): Type { + function getTypeFromObjectBindingPattern(pattern: ObjectBindingPattern, includePatternInType: boolean, reportErrors: boolean): Type { const members = createMap(); let hasComputedProperties = false; forEach(pattern.elements, e => { @@ -3149,11 +3187,12 @@ namespace ts { // Return the type implied by an array binding pattern function getTypeFromArrayBindingPattern(pattern: BindingPattern, includePatternInType: boolean, reportErrors: boolean): Type { const elements = pattern.elements; - if (elements.length === 0 || elements[elements.length - 1].dotDotDotToken) { + const lastElement = lastOrUndefined(elements); + if (elements.length === 0 || (!isOmittedExpression(lastElement) && lastElement.dotDotDotToken)) { return languageVersion >= ScriptTarget.ES6 ? createIterableType(anyType) : anyArrayType; } // If the pattern has at least one element, and no rest element, then it should imply a tuple type. - const elementTypes = map(elements, e => e.kind === SyntaxKind.OmittedExpression ? anyType : getTypeFromBindingElement(e, includePatternInType, reportErrors)); + const elementTypes = map(elements, e => isOmittedExpression(e) ? anyType : getTypeFromBindingElement(e, includePatternInType, reportErrors)); let result = createTupleType(elementTypes); if (includePatternInType) { result = cloneTypeReference(result); @@ -3171,8 +3210,8 @@ namespace ts { // the parameter. function getTypeFromBindingPattern(pattern: BindingPattern, includePatternInType?: boolean, reportErrors?: boolean): Type { return pattern.kind === SyntaxKind.ObjectBindingPattern - ? getTypeFromObjectBindingPattern(pattern, includePatternInType, reportErrors) - : getTypeFromArrayBindingPattern(pattern, includePatternInType, reportErrors); + ? getTypeFromObjectBindingPattern(pattern, includePatternInType, reportErrors) + : getTypeFromArrayBindingPattern(pattern, includePatternInType, reportErrors); } // Return the type associated with a variable, parameter, or property declaration. In the simple case this is the type @@ -3374,7 +3413,7 @@ namespace ts { function getTypeOfFuncClassEnumModule(symbol: Symbol): Type { const links = getSymbolLinks(symbol); if (!links.type) { - if (symbol.valueDeclaration.kind === SyntaxKind.ModuleDeclaration && isShorthandAmbientModule(symbol.valueDeclaration)) { + if (symbol.valueDeclaration.kind === SyntaxKind.ModuleDeclaration && isShorthandAmbientModuleSymbol(symbol)) { links.type = anyType; } else { @@ -3389,7 +3428,7 @@ namespace ts { function getTypeOfEnumMember(symbol: Symbol): Type { const links = getSymbolLinks(symbol); if (!links.type) { - links.type = getDeclaredTypeOfEnum(getParentOfSymbol(symbol)); + links.type = getDeclaredTypeOfEnumMember(symbol); } return links.type; } @@ -3534,7 +3573,7 @@ namespace ts { function getInstantiatedConstructorsForTypeArguments(type: ObjectType, typeArgumentNodes: TypeNode[]): Signature[] { let signatures = getConstructorsForTypeArguments(type, typeArgumentNodes); if (typeArgumentNodes) { - const typeArguments = map(typeArgumentNodes, getTypeFromTypeNode); + const typeArguments = map(typeArgumentNodes, getTypeFromTypeNodeNoAlias); signatures = map(signatures, sig => getSignatureInstantiation(sig, typeArguments)); } return signatures; @@ -3802,6 +3841,14 @@ namespace ts { return true; } + function createEnumLiteralType(symbol: Symbol, baseType: EnumType, text: string) { + const type = createType(TypeFlags.EnumLiteral); + type.symbol = symbol; + type.baseType = baseType; + type.text = text; + return type; + } + function getDeclaredTypeOfEnum(symbol: Symbol): Type { const links = getSymbolLinks(symbol); if (!links.declaredType) { @@ -3817,10 +3864,7 @@ namespace ts { const memberSymbol = getSymbolOfNode(member); const value = getEnumMemberValue(member); if (!memberTypes[value]) { - const memberType = memberTypes[value] = createType(TypeFlags.EnumLiteral); - memberType.symbol = memberSymbol; - memberType.baseType = enumType; - memberType.text = "" + value; + const memberType = memberTypes[value] = createEnumLiteralType(memberSymbol, enumType, "" + value); memberTypeList.push(memberType); } } @@ -4097,7 +4141,7 @@ namespace ts { return [createSignature(undefined, classType.localTypeParameters, undefined, emptyArray, classType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false)]; } const baseTypeNode = getBaseTypeNodeOfClass(classType); - const typeArguments = map(baseTypeNode.typeArguments, getTypeFromTypeNode); + const typeArguments = map(baseTypeNode.typeArguments, getTypeFromTypeNodeNoAlias); const typeArgCount = typeArguments ? typeArguments.length : 0; const result: Signature[] = []; for (const baseSig of baseSignatures) { @@ -4323,7 +4367,7 @@ namespace ts { function getPropertiesOfUnionOrIntersectionType(type: UnionOrIntersectionType): Symbol[] { for (const current of type.types) { for (const prop of getPropertiesOfType(current)) { - getPropertyOfUnionOrIntersectionType(type, prop.name); + getUnionOrIntersectionProperty(type, prop.name); } // The properties of a union type are those that are present in all constituent types, so // we only need to check the properties of the first type @@ -4331,7 +4375,19 @@ namespace ts { break; } } - return type.resolvedProperties ? symbolsToArray(type.resolvedProperties) : emptyArray; + const props = type.resolvedProperties; + if (props) { + const result: Symbol[] = []; + for (const key in props) { + const prop = props[key]; + // We need to filter out partial properties in union types + if (!(prop.flags & SymbolFlags.SyntheticProperty && (prop).isPartial)) { + result.push(prop); + } + } + return result; + } + return emptyArray; } function getPropertiesOfType(type: Type): Symbol[] { @@ -4384,11 +4440,12 @@ namespace ts { // Flags we want to propagate to the result if they exist in all source symbols let commonFlags = (containingType.flags & TypeFlags.Intersection) ? SymbolFlags.Optional : SymbolFlags.None; let isReadonly = false; + let isPartial = false; for (const current of types) { const type = getApparentType(current); if (type !== unknownType) { const prop = getPropertyOfType(type, name); - if (prop && !(getDeclarationFlagsFromSymbol(prop) & (NodeFlags.Private | NodeFlags.Protected))) { + if (prop && !(getDeclarationModifierFlagsFromSymbol(prop) & (ModifierFlags.Private | ModifierFlags.Protected))) { commonFlags &= prop.flags; if (!props) { props = [prop]; @@ -4401,21 +4458,20 @@ namespace ts { } } else if (containingType.flags & TypeFlags.Union) { - // A union type requires the property to be present in all constituent types - return undefined; + isPartial = true; } } } if (!props) { return undefined; } - if (props.length === 1) { + if (props.length === 1 && !isPartial) { return props[0]; } const propTypes: Type[] = []; const declarations: Declaration[] = []; let commonType: Type = undefined; - let hasCommonType = true; + let hasNonUniformType = false; for (const prop of props) { if (prop.declarations) { addRange(declarations, prop.declarations); @@ -4425,25 +4481,26 @@ namespace ts { commonType = type; } else if (type !== commonType) { - hasCommonType = false; + hasNonUniformType = true; } - propTypes.push(getTypeOfSymbol(prop)); + propTypes.push(type); } - const result = createSymbol( - SymbolFlags.Property | - SymbolFlags.Transient | - SymbolFlags.SyntheticProperty | - commonFlags, - name); + const result = createSymbol(SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.SyntheticProperty | commonFlags, name); result.containingType = containingType; - result.hasCommonType = hasCommonType; + result.hasNonUniformType = hasNonUniformType; + result.isPartial = isPartial; result.declarations = declarations; result.isReadonly = isReadonly; result.type = containingType.flags & TypeFlags.Union ? getUnionType(propTypes) : getIntersectionType(propTypes); return result; } - function getPropertyOfUnionOrIntersectionType(type: UnionOrIntersectionType, name: string): Symbol { + // Return the symbol for a given property in a union or intersection type, or undefined if the property + // does not exist in any constituent type. Note that the returned property may only be present in some + // constituents, in which case the isPartial flag is set when the containing type is union type. We need + // these partial properties when identifying discriminant properties, but otherwise they are filtered out + // and do not appear to be present in the union type. + function getUnionOrIntersectionProperty(type: UnionOrIntersectionType, name: string): Symbol { const properties = type.resolvedProperties || (type.resolvedProperties = createMap()); let property = properties[name]; if (!property) { @@ -4455,6 +4512,12 @@ namespace ts { return property; } + function getPropertyOfUnionOrIntersectionType(type: UnionOrIntersectionType, name: string): Symbol { + const property = getUnionOrIntersectionProperty(type, name); + // We need to filter out partial properties in union types + return property && !(property.flags & SymbolFlags.SyntheticProperty && (property).isPartial) ? property : undefined; + } + /** * Return the symbol for the property with the given name in the given type. Creates synthetic union properties when * necessary, maps primitive types and type parameters are to their apparent types, and augments with properties from @@ -4894,7 +4957,7 @@ namespace ts { const declaration = getIndexDeclarationOfSymbol(symbol, kind); if (declaration) { return createIndexInfo(declaration.type ? getTypeFromTypeNode(declaration.type) : anyType, - (declaration.flags & NodeFlags.Readonly) !== 0, declaration); + (getModifierFlags(declaration) & ModifierFlags.Readonly) !== 0, declaration); } return undefined; } @@ -5013,7 +5076,7 @@ namespace ts { // In a type reference, the outer type parameters of the referenced class or interface are automatically // supplied as type arguments and the type reference only specifies arguments for the local type parameters // of the class or interface. - return createTypeReference(type, concatenate(type.outerTypeParameters, map(node.typeArguments, getTypeFromTypeNode))); + return createTypeReference(type, concatenate(type.outerTypeParameters, map(node.typeArguments, getTypeFromTypeNodeNoAlias))); } if (node.typeArguments) { error(node, Diagnostics.Type_0_is_not_generic, typeToString(type)); @@ -5034,7 +5097,7 @@ namespace ts { error(node, Diagnostics.Generic_type_0_requires_1_type_argument_s, symbolToString(symbol), typeParameters.length); return unknownType; } - const typeArguments = map(node.typeArguments, getTypeFromTypeNode); + const typeArguments = map(node.typeArguments, getTypeFromTypeNodeNoAlias); const id = getTypeListId(typeArguments); return links.instantiations[id] || (links.instantiations[id] = instantiateType(type, createTypeMapper(typeParameters, typeArguments))); } @@ -5289,7 +5352,7 @@ namespace ts { function getTypeFromTupleTypeNode(node: TupleTypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { - links.resolvedType = createTupleType(map(node.elementTypes, getTypeFromTypeNode)); + links.resolvedType = createTupleType(map(node.elementTypes, getTypeFromTypeNodeNoAlias)); } return links.resolvedType; } @@ -5299,6 +5362,9 @@ namespace ts { containsUndefined?: boolean; containsNull?: boolean; containsNonWideningType?: boolean; + containsString?: boolean; + containsNumber?: boolean; + containsStringOrNumberLiteral?: boolean; } function binarySearchTypes(types: Type[], type: Type): number { @@ -5326,22 +5392,26 @@ namespace ts { } function addTypeToUnion(typeSet: TypeSet, type: Type) { - if (type.flags & TypeFlags.Union) { + const flags = type.flags; + if (flags & TypeFlags.Union) { addTypesToUnion(typeSet, (type).types); } - else if (type.flags & TypeFlags.Any) { + else if (flags & TypeFlags.Any) { typeSet.containsAny = true; } - else if (!strictNullChecks && type.flags & TypeFlags.Nullable) { - if (type.flags & TypeFlags.Undefined) typeSet.containsUndefined = true; - if (type.flags & TypeFlags.Null) typeSet.containsNull = true; - if (!(type.flags & TypeFlags.ContainsWideningType)) typeSet.containsNonWideningType = true; + else if (!strictNullChecks && flags & TypeFlags.Nullable) { + if (flags & TypeFlags.Undefined) typeSet.containsUndefined = true; + if (flags & TypeFlags.Null) typeSet.containsNull = true; + if (!(flags & TypeFlags.ContainsWideningType)) typeSet.containsNonWideningType = true; } - else if (!(type.flags & TypeFlags.Never)) { + else if (!(flags & TypeFlags.Never)) { + if (flags & TypeFlags.String) typeSet.containsString = true; + if (flags & TypeFlags.Number) typeSet.containsNumber = true; + if (flags & TypeFlags.StringOrNumberLiteral) typeSet.containsStringOrNumberLiteral = true; const len = typeSet.length; const index = len && type.id > typeSet[len - 1].id ? ~len : binarySearchTypes(typeSet, type); if (index < 0) { - if (!(type.flags & TypeFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method) && containsIdenticalType(typeSet, type))) { + if (!(flags & TypeFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method) && containsIdenticalType(typeSet, type))) { typeSet.splice(~index, 0, type); } } @@ -5374,7 +5444,7 @@ namespace ts { return false; } - function removeSubtypes(types: Type[]) { + function removeSubtypes(types: TypeSet) { let i = types.length; while (i > 0) { i--; @@ -5384,6 +5454,21 @@ namespace ts { } } + function removeRedundantLiteralTypes(types: TypeSet) { + let i = types.length; + while (i > 0) { + i--; + const t = types[i]; + const remove = + t.flags & TypeFlags.StringLiteral && types.containsString || + t.flags & TypeFlags.NumberLiteral && types.containsNumber || + t.flags & TypeFlags.StringOrNumberLiteral && t.flags & TypeFlags.FreshLiteral && containsType(types, (t).regularType); + if (remove) { + orderedRemoveItemAt(types, i); + } + } + } + // We sort and deduplicate the constituent types based on object identity. If the subtypeReduction // flag is specified we also reduce the constituent type set to only include types that aren't subtypes // of other types. Subtype reduction is expensive for large union types and is possible only when union @@ -5406,6 +5491,9 @@ namespace ts { if (subtypeReduction) { removeSubtypes(typeSet); } + else if (typeSet.containsStringOrNumberLiteral) { + removeRedundantLiteralTypes(typeSet); + } if (typeSet.length === 0) { return typeSet.containsNull ? typeSet.containsNonWideningType ? nullType : nullWideningType : typeSet.containsUndefined ? typeSet.containsNonWideningType ? undefinedType : undefinedWideningType : @@ -5437,7 +5525,7 @@ namespace ts { function getTypeFromUnionTypeNode(node: UnionTypeNode, aliasSymbol?: Symbol, aliasTypeArguments?: Type[]): Type { const links = getNodeLinks(node); if (!links.resolvedType) { - links.resolvedType = getUnionType(map(node.types, getTypeFromTypeNode), /*subtypeReduction*/ false, aliasSymbol, aliasTypeArguments); + links.resolvedType = getUnionType(map(node.types, getTypeFromTypeNodeNoAlias), /*subtypeReduction*/ false, aliasSymbol, aliasTypeArguments); } return links.resolvedType; } @@ -5494,7 +5582,7 @@ namespace ts { function getTypeFromIntersectionTypeNode(node: IntersectionTypeNode, aliasSymbol?: Symbol, aliasTypeArguments?: Type[]): Type { const links = getNodeLinks(node); if (!links.resolvedType) { - links.resolvedType = getIntersectionType(map(node.types, getTypeFromTypeNode), aliasSymbol, aliasTypeArguments); + links.resolvedType = getIntersectionType(map(node.types, getTypeFromTypeNodeNoAlias), aliasSymbol, aliasTypeArguments); } return links.resolvedType; } @@ -5517,6 +5605,22 @@ namespace ts { return type; } + function getFreshTypeOfLiteralType(type: Type) { + if (type.flags & TypeFlags.StringOrNumberLiteral && !(type.flags & TypeFlags.FreshLiteral)) { + if (!(type).freshType) { + const freshType = createLiteralType(type.flags | TypeFlags.FreshLiteral, (type).text); + freshType.regularType = type; + (type).freshType = freshType; + } + return (type).freshType; + } + return type; + } + + function getRegularTypeOfLiteralType(type: Type) { + return type.flags & TypeFlags.StringOrNumberLiteral && type.flags & TypeFlags.FreshLiteral ? (type).regularType : type; + } + function getLiteralTypeForText(flags: TypeFlags, text: string) { const map = flags & TypeFlags.StringLiteral ? stringLiteralTypes : numericLiteralTypes; return map[text] || (map[text] = createLiteralType(flags, text)); @@ -5525,7 +5629,7 @@ namespace ts { function getTypeFromLiteralTypeNode(node: LiteralTypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { - links.resolvedType = checkExpression(node.literal); + links.resolvedType = getRegularTypeOfLiteralType(checkExpression(node.literal)); } return links.resolvedType; } @@ -5542,7 +5646,7 @@ namespace ts { function getTypeFromJSDocTupleType(node: JSDocTupleType): Type { const links = getNodeLinks(node); if (!links.resolvedType) { - const types = map(node.types, getTypeFromTypeNode); + const types = map(node.types, getTypeFromTypeNodeNoAlias); links.resolvedType = createTupleType(types); } return links.resolvedType; @@ -5552,8 +5656,8 @@ namespace ts { const container = getThisContainer(node, /*includeArrowFunctions*/ false); const parent = container && container.parent; if (parent && (isClassLike(parent) || parent.kind === SyntaxKind.InterfaceDeclaration)) { - if (!(container.flags & NodeFlags.Static) && - (container.kind !== SyntaxKind.Constructor || isNodeDescendentOf(node, (container).body))) { + if (!(getModifierFlags(container) & ModifierFlags.Static) && + (container.kind !== SyntaxKind.Constructor || isNodeDescendantOf(node, (container).body))) { return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(parent)).thisType; } } @@ -5569,6 +5673,10 @@ namespace ts { return links.resolvedType; } + function getTypeFromTypeNodeNoAlias(type: TypeNode) { + return getTypeFromTypeNode(type, /*aliasSymbol*/ undefined, /*aliasTypeArguments*/ undefined); + } + function getTypeFromTypeNode(node: TypeNode, aliasSymbol?: Symbol, aliasTypeArguments?: Type[]): Type { switch (node.kind) { case SyntaxKind.AnyKeyword: @@ -5630,12 +5738,13 @@ namespace ts { case SyntaxKind.JSDocThisType: case SyntaxKind.JSDocOptionalType: return getTypeFromTypeNode((node).type); + case SyntaxKind.JSDocRecordType: + return getTypeFromTypeNode((node as JSDocRecordType).literal); case SyntaxKind.FunctionType: case SyntaxKind.ConstructorType: case SyntaxKind.TypeLiteral: case SyntaxKind.JSDocTypeLiteral: case SyntaxKind.JSDocFunctionType: - case SyntaxKind.JSDocRecordType: return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node, aliasSymbol, aliasTypeArguments); // This function assumes that an identifier or qualified name is a type expression // Callers should first ensure this by calling isTypeNode @@ -5700,7 +5809,7 @@ namespace ts { function getInferenceMapper(context: InferenceContext): TypeMapper { if (!context.mapper) { const mapper: TypeMapper = t => { - const typeParameters = context.typeParameters; + const typeParameters = context.signature.typeParameters; for (let i = 0; i < typeParameters.length; i++) { if (t === typeParameters[i]) { context.inferences[i].isFixed = true; @@ -5709,7 +5818,7 @@ namespace ts { } return t; }; - mapper.mappedTypes = context.typeParameters; + mapper.mappedTypes = context.signature.typeParameters; mapper.context = context; context.mapper = mapper; } @@ -5906,7 +6015,7 @@ namespace ts { // Returns true if the given expression contains (at any level of nesting) a function or arrow expression // that is subject to contextual typing. - function isContextSensitive(node: Expression | MethodDeclaration | ObjectLiteralElement): boolean { + function isContextSensitive(node: Expression | MethodDeclaration | ObjectLiteralElementLike): boolean { Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node)); switch (node.kind) { case SyntaxKind.FunctionExpression: @@ -6192,8 +6301,14 @@ namespace ts { if (source === target) { return true; } - if (source.symbol.name !== target.symbol.name || !(source.symbol.flags & SymbolFlags.RegularEnum) || !(target.symbol.flags & SymbolFlags.RegularEnum)) { - return false; + const id = source.id + "," + target.id; + if (enumRelation[id] !== undefined) { + return enumRelation[id]; + } + if (source.symbol.name !== target.symbol.name || + !(source.symbol.flags & SymbolFlags.RegularEnum) || !(target.symbol.flags & SymbolFlags.RegularEnum) || + (source.flags & TypeFlags.Union) !== (target.flags & TypeFlags.Union)) { + return enumRelation[id] = false; } const targetEnumType = getTypeOfSymbol(target.symbol); for (const property of getPropertiesOfType(getTypeOfSymbol(source.symbol))) { @@ -6204,11 +6319,11 @@ namespace ts { errorReporter(Diagnostics.Property_0_is_missing_in_type_1, property.name, typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); } - return false; + return enumRelation[id] = false; } } } - return true; + return enumRelation[id] = true; } function isSimpleTypeRelatedTo(source: Type, target: Type, relation: Map, errorReporter?: ErrorReporter) { @@ -6223,13 +6338,29 @@ namespace ts { if (source.flags & TypeFlags.Null && (!strictNullChecks || target.flags & TypeFlags.Null)) return true; if (relation === assignableRelation || relation === comparableRelation) { if (source.flags & TypeFlags.Any) return true; - if (source.flags & (TypeFlags.Number | TypeFlags.NumberLiteral) && target.flags & TypeFlags.Enum) return true; - if (source.flags & TypeFlags.NumberLiteral && target.flags & TypeFlags.EnumLiteral && (source).text === (target).text) return true; + if ((source.flags & TypeFlags.Number | source.flags & TypeFlags.NumberLiteral) && target.flags & TypeFlags.EnumLike) return true; + if (source.flags & TypeFlags.EnumLiteral && + target.flags & TypeFlags.EnumLiteral && + (source).text === (target).text && + isEnumTypeRelatedTo((source).baseType, (target).baseType, errorReporter)) { + return true; + } + if (source.flags & TypeFlags.EnumLiteral && + target.flags & TypeFlags.Enum && + isEnumTypeRelatedTo(target, (source).baseType, errorReporter)) { + return true; + } } return false; } function isTypeRelatedTo(source: Type, target: Type, relation: Map) { + if (source.flags & TypeFlags.StringOrNumberLiteral && source.flags & TypeFlags.FreshLiteral) { + source = (source).regularType; + } + if (target.flags & TypeFlags.StringOrNumberLiteral && target.flags & TypeFlags.FreshLiteral) { + target = (target).regularType; + } if (source === target || relation !== identityRelation && isSimpleTypeRelatedTo(source, target, relation)) { return true; } @@ -6327,6 +6458,12 @@ namespace ts { // Ternary.False if they are not related. function isRelatedTo(source: Type, target: Type, reportErrors?: boolean, headMessage?: DiagnosticMessage): Ternary { let result: Ternary; + if (source.flags & TypeFlags.StringOrNumberLiteral && source.flags & TypeFlags.FreshLiteral) { + source = (source).regularType; + } + if (target.flags & TypeFlags.StringOrNumberLiteral && target.flags & TypeFlags.FreshLiteral) { + target = (target).regularType; + } // both types are the same - covers 'they are the same primitive type or both are Any' or the same type parameter cases if (source === target) return Ternary.True; @@ -6336,7 +6473,7 @@ namespace ts { if (isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) return Ternary.True; - if (source.flags & TypeFlags.FreshObjectLiteral) { + if (source.flags & TypeFlags.ObjectLiteral && source.flags & TypeFlags.FreshLiteral) { if (hasExcessProperties(source, target, reportErrors)) { if (reportErrors) { reportRelationError(headMessage, source, target); @@ -6447,6 +6584,9 @@ namespace ts { if (source.flags & TypeFlags.ObjectType && target.flags & TypeFlags.Primitive) { tryElaborateErrorsForPrimitivesAndObjects(source, target); } + else if (source.symbol && source.flags & TypeFlags.ObjectType && globalObjectType === source) { + reportError(Diagnostics.The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead); + } reportRelationError(headMessage, source, target); } return Ternary.False; @@ -6715,24 +6855,24 @@ namespace ts { } } else if (!(targetProp.flags & SymbolFlags.Prototype)) { - const sourcePropFlags = getDeclarationFlagsFromSymbol(sourceProp); - const targetPropFlags = getDeclarationFlagsFromSymbol(targetProp); - if (sourcePropFlags & NodeFlags.Private || targetPropFlags & NodeFlags.Private) { + const sourcePropFlags = getDeclarationModifierFlagsFromSymbol(sourceProp); + const targetPropFlags = getDeclarationModifierFlagsFromSymbol(targetProp); + if (sourcePropFlags & ModifierFlags.Private || targetPropFlags & ModifierFlags.Private) { if (sourceProp.valueDeclaration !== targetProp.valueDeclaration) { if (reportErrors) { - if (sourcePropFlags & NodeFlags.Private && targetPropFlags & NodeFlags.Private) { + if (sourcePropFlags & ModifierFlags.Private && targetPropFlags & ModifierFlags.Private) { reportError(Diagnostics.Types_have_separate_declarations_of_a_private_property_0, symbolToString(targetProp)); } else { reportError(Diagnostics.Property_0_is_private_in_type_1_but_not_in_type_2, symbolToString(targetProp), - typeToString(sourcePropFlags & NodeFlags.Private ? source : target), - typeToString(sourcePropFlags & NodeFlags.Private ? target : source)); + typeToString(sourcePropFlags & ModifierFlags.Private ? source : target), + typeToString(sourcePropFlags & ModifierFlags.Private ? target : source)); } } return Ternary.False; } } - else if (targetPropFlags & NodeFlags.Protected) { + else if (targetPropFlags & ModifierFlags.Protected) { const sourceDeclaredInClass = sourceProp.parent && sourceProp.parent.flags & SymbolFlags.Class; const sourceClass = sourceDeclaredInClass ? getDeclaredTypeOfSymbol(getParentOfSymbol(sourceProp)) : undefined; const targetClass = getDeclaredTypeOfSymbol(getParentOfSymbol(targetProp)); @@ -6744,7 +6884,7 @@ namespace ts { return Ternary.False; } } - else if (sourcePropFlags & NodeFlags.Protected) { + else if (sourcePropFlags & ModifierFlags.Protected) { if (reportErrors) { reportError(Diagnostics.Property_0_is_protected_in_type_1_but_public_in_type_2, symbolToString(targetProp), typeToString(source), typeToString(target)); @@ -6954,21 +7094,21 @@ namespace ts { return true; } - const sourceAccessibility = sourceSignature.declaration.flags & (NodeFlags.Private | NodeFlags.Protected); - const targetAccessibility = targetSignature.declaration.flags & (NodeFlags.Private | NodeFlags.Protected); + const sourceAccessibility = getModifierFlags(sourceSignature.declaration) & ModifierFlags.NonPublicAccessibilityModifier; + const targetAccessibility = getModifierFlags(targetSignature.declaration) & ModifierFlags.NonPublicAccessibilityModifier; // A public, protected and private signature is assignable to a private signature. - if (targetAccessibility === NodeFlags.Private) { + if (targetAccessibility === ModifierFlags.Private) { return true; } // A public and protected signature is assignable to a protected signature. - if (targetAccessibility === NodeFlags.Protected && sourceAccessibility !== NodeFlags.Private) { + if (targetAccessibility === ModifierFlags.Protected && sourceAccessibility !== ModifierFlags.Private) { return true; } // Only a public signature is assignable to public signature. - if (targetAccessibility !== NodeFlags.Protected && !sourceAccessibility) { + if (targetAccessibility !== ModifierFlags.Protected && !sourceAccessibility) { return true; } @@ -6986,7 +7126,7 @@ namespace ts { const symbol = type.symbol; if (symbol && symbol.flags & SymbolFlags.Class) { const declaration = getClassLikeDeclarationOfSymbol(symbol); - if (declaration && declaration.flags & NodeFlags.Abstract) { + if (declaration && getModifierFlags(declaration) & ModifierFlags.Abstract) { return true; } } @@ -7026,8 +7166,8 @@ namespace ts { if (sourceProp === targetProp) { return Ternary.True; } - const sourcePropAccessibility = getDeclarationFlagsFromSymbol(sourceProp) & (NodeFlags.Private | NodeFlags.Protected); - const targetPropAccessibility = getDeclarationFlagsFromSymbol(targetProp) & (NodeFlags.Private | NodeFlags.Protected); + const sourcePropAccessibility = getDeclarationModifierFlagsFromSymbol(sourceProp) & ModifierFlags.NonPublicAccessibilityModifier; + const targetPropAccessibility = getDeclarationModifierFlagsFromSymbol(targetProp) & ModifierFlags.NonPublicAccessibilityModifier; if (sourcePropAccessibility !== targetPropAccessibility) { return Ternary.False; } @@ -7134,15 +7274,36 @@ namespace ts { return true; } + function literalTypesWithSameBaseType(types: Type[]): boolean { + let commonBaseType: Type; + for (const t of types) { + const baseType = getBaseTypeOfLiteralType(t); + if (!commonBaseType) { + commonBaseType = baseType; + } + if (baseType === t || baseType !== commonBaseType) { + return false; + } + } + return true; + } + + // When the candidate types are all literal types with the same base type, the common + // supertype is a union of those literal types. Otherwise, the common supertype is the + // first type that is a supertype of each of the other types. + function getSupertypeOrUnion(types: Type[]): Type { + return literalTypesWithSameBaseType(types) ? getUnionType(types) : forEach(types, t => isSupertypeOfEach(t, types) ? t : undefined); + } + function getCommonSupertype(types: Type[]): Type { if (!strictNullChecks) { - return forEach(types, t => isSupertypeOfEach(t, types) ? t : undefined); + return getSupertypeOrUnion(types); } const primaryTypes = filter(types, t => !(t.flags & TypeFlags.Nullable)); if (!primaryTypes.length) { return getUnionType(types, /*subtypeReduction*/ true); } - const supertype = forEach(primaryTypes, t => isSupertypeOfEach(t, primaryTypes) ? t : undefined); + const supertype = getSupertypeOrUnion(primaryTypes); return supertype && includeFalsyTypes(supertype, getFalsyFlagsOfTypes(types) & TypeFlags.Nullable); } @@ -7206,18 +7367,27 @@ namespace ts { return (type.flags & (TypeFlags.Literal | TypeFlags.Undefined | TypeFlags.Null)) !== 0; } - function isUnitUnionType(type: Type): boolean { + function isLiteralType(type: Type): boolean { return type.flags & TypeFlags.Boolean ? true : type.flags & TypeFlags.Union ? type.flags & TypeFlags.Enum ? true : !forEach((type).types, t => !isUnitType(t)) : isUnitType(type); } - function getBaseTypeOfUnitType(type: Type): Type { + function getBaseTypeOfLiteralType(type: Type): Type { return type.flags & TypeFlags.StringLiteral ? stringType : type.flags & TypeFlags.NumberLiteral ? numberType : type.flags & TypeFlags.BooleanLiteral ? booleanType : type.flags & TypeFlags.EnumLiteral ? (type).baseType : - type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Enum) ? getUnionType(map((type).types, getBaseTypeOfUnitType)) : + type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Enum) ? getUnionType(map((type).types, getBaseTypeOfLiteralType)) : + type; + } + + function getWidenedLiteralType(type: Type): Type { + return type.flags & TypeFlags.StringLiteral && type.flags & TypeFlags.FreshLiteral ? stringType : + type.flags & TypeFlags.NumberLiteral && type.flags & TypeFlags.FreshLiteral ? numberType : + type.flags & TypeFlags.BooleanLiteral ? booleanType : + type.flags & TypeFlags.EnumLiteral ? (type).baseType : + type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Enum) ? getUnionType(map((type).types, getWidenedLiteralType)) : type; } @@ -7242,8 +7412,8 @@ namespace ts { // no flags for all other types (including non-falsy literal types). function getFalsyFlags(type: Type): TypeFlags { return type.flags & TypeFlags.Union ? getFalsyFlagsOfTypes((type).types) : - type.flags & TypeFlags.StringLiteral ? type === emptyStringType ? TypeFlags.StringLiteral : 0 : - type.flags & TypeFlags.NumberLiteral ? type === zeroType ? TypeFlags.NumberLiteral : 0 : + type.flags & TypeFlags.StringLiteral ? (type).text === "" ? TypeFlags.StringLiteral : 0 : + type.flags & TypeFlags.NumberLiteral ? (type).text === "0" ? TypeFlags.NumberLiteral : 0 : type.flags & TypeFlags.BooleanLiteral ? type === falseType ? TypeFlags.BooleanLiteral : 0 : type.flags & TypeFlags.PossiblyFalsy; } @@ -7310,7 +7480,7 @@ namespace ts { * Leave signatures alone since they are not subject to the check. */ function getRegularTypeOfObjectLiteral(type: Type): Type { - if (!(type.flags & TypeFlags.FreshObjectLiteral)) { + if (!(type.flags & TypeFlags.ObjectLiteral && type.flags & TypeFlags.FreshLiteral)) { return type; } const regularType = (type).regularType; @@ -7326,7 +7496,7 @@ namespace ts { resolved.constructSignatures, resolved.stringIndexInfo, resolved.numberIndexInfo); - regularNew.flags = resolved.flags & ~TypeFlags.FreshObjectLiteral; + regularNew.flags = resolved.flags & ~TypeFlags.FreshLiteral; (type).regularType = regularNew; return regularNew; } @@ -7471,14 +7641,13 @@ namespace ts { } } - function createInferenceContext(typeParameters: TypeParameter[], inferUnionTypes: boolean): InferenceContext { - const inferences = map(typeParameters, createTypeInferencesObject); - + function createInferenceContext(signature: Signature, inferUnionTypes: boolean): InferenceContext { + const inferences = map(signature.typeParameters, createTypeInferencesObject); return { - typeParameters, + signature, inferUnionTypes, inferences, - inferredTypes: new Array(typeParameters.length), + inferredTypes: new Array(signature.typeParameters.length), }; } @@ -7486,6 +7655,7 @@ namespace ts { return { primary: undefined, secondary: undefined, + topLevel: true, isFixed: false, }; } @@ -7507,13 +7677,18 @@ namespace ts { return type.couldContainTypeParameters; } - function inferTypes(context: InferenceContext, source: Type, target: Type) { + function isTypeParameterAtTopLevel(type: Type, typeParameter: TypeParameter): boolean { + return type === typeParameter || type.flags & TypeFlags.UnionOrIntersection && forEach((type).types, t => isTypeParameterAtTopLevel(t, typeParameter)); + } + + function inferTypes(context: InferenceContext, originalSource: Type, originalTarget: Type) { + const typeParameters = context.signature.typeParameters; let sourceStack: Type[]; let targetStack: Type[]; let depth = 0; let inferiority = 0; const visited = createMap(); - inferFromTypes(source, target); + inferFromTypes(originalSource, originalTarget); function isInProcess(source: Type, target: Type) { for (let i = 0; i < depth; i++) { @@ -7538,16 +7713,24 @@ namespace ts { } return; } - // Find each target constituent type that has an identically matching source - // constituent type, and for each such target constituent type infer from the type to - // itself. When inferring from a type to itself we effectively find all type parameter - // occurrences within that type and infer themselves as their type arguments. + // Find each source constituent type that has an identically matching target constituent + // type, and for each such type infer from the type to itself. When inferring from a + // type to itself we effectively find all type parameter occurrences within that type + // and infer themselves as their type arguments. We have special handling for numeric + // and string literals because the number and string types are not represented as unions + // of all their possible values. let matchingTypes: Type[]; - for (const t of (target).types) { - if (typeIdenticalToSomeType(t, (source).types)) { + for (const t of (source).types) { + if (typeIdenticalToSomeType(t, (target).types)) { (matchingTypes || (matchingTypes = [])).push(t); inferFromTypes(t, t); } + else if (t.flags & (TypeFlags.NumberLiteral | TypeFlags.StringLiteral)) { + const b = getBaseTypeOfLiteralType(t); + if (typeIdenticalToSomeType(b, (target).types)) { + (matchingTypes || (matchingTypes = [])).push(t, b); + } + } } // Next, to improve the quality of inferences, reduce the source and target types by // removing the identically matched constituents. For example, when inferring from @@ -7567,7 +7750,6 @@ namespace ts { if (source.flags & TypeFlags.ContainsAnyFunctionType) { return; } - const typeParameters = context.typeParameters; for (let i = 0; i < typeParameters.length; i++) { if (target === typeParameters[i]) { const inferences = context.inferences[i]; @@ -7584,6 +7766,9 @@ namespace ts { if (!contains(candidates, source)) { candidates.push(source); } + if (!isTypeParameterAtTopLevel(originalTarget, target)) { + inferences.topLevel = false; + } } return; } @@ -7604,7 +7789,7 @@ namespace ts { let typeParameter: TypeParameter; // First infer to each type in union or intersection that isn't a type parameter for (const t of targetTypes) { - if (t.flags & TypeFlags.TypeParameter && contains(context.typeParameters, t)) { + if (t.flags & TypeFlags.TypeParameter && contains(typeParameters, t)) { typeParameter = t; typeParameterCount++; } @@ -7679,8 +7864,12 @@ namespace ts { } } + function inferFromParameterTypes(source: Type, target: Type) { + return inferFromTypes(source, target); + } + function inferFromSignature(source: Signature, target: Signature) { - forEachMatchingParameterType(source, target, inferFromTypes); + forEachMatchingParameterType(source, target, inferFromParameterTypes); if (source.typePredicate && target.typePredicate && source.typePredicate.kind === target.typePredicate.kind) { inferFromTypes(source.typePredicate.type, target.typePredicate.type); @@ -7739,14 +7928,28 @@ namespace ts { return inferences.primary || inferences.secondary || emptyArray; } + function hasPrimitiveConstraint(type: TypeParameter): boolean { + const constraint = getConstraintOfTypeParameter(type); + return constraint && maybeTypeOfKind(constraint, TypeFlags.Primitive); + } + function getInferredType(context: InferenceContext, index: number): Type { let inferredType = context.inferredTypes[index]; let inferenceSucceeded: boolean; if (!inferredType) { const inferences = getInferenceCandidates(context, index); if (inferences.length) { + // We widen inferred literal types if + // all inferences were made to top-level ocurrences of the type parameter, and + // the type parameter has no constraint or its constraint includes no primitive or literal types, and + // the type parameter was fixed during inference or does not occur at top-level in the return type. + const signature = context.signature; + const widenLiteralTypes = context.inferences[index].topLevel && + !hasPrimitiveConstraint(signature.typeParameters[index]) && + (context.inferences[index].isFixed || !isTypeParameterAtTopLevel(getReturnTypeOfSignature(signature), signature.typeParameters[index])); + const baseInferences = widenLiteralTypes ? map(inferences, getWidenedLiteralType) : inferences; // Infer widened union or supertype, or the unknown type for no common supertype - const unionOrSuperType = context.inferUnionTypes ? getUnionType(inferences, /*subtypeReduction*/ true) : getCommonSupertype(inferences); + const unionOrSuperType = context.inferUnionTypes ? getUnionType(baseInferences, /*subtypeReduction*/ true) : getCommonSupertype(baseInferences); inferredType = unionOrSuperType ? getWidenedType(unionOrSuperType) : unknownType; inferenceSucceeded = !!unionOrSuperType; } @@ -7762,7 +7965,7 @@ namespace ts { // Only do the constraint check if inference succeeded (to prevent cascading errors) if (inferenceSucceeded) { - const constraint = getConstraintOfTypeParameter(context.typeParameters[index]); + const constraint = getConstraintOfTypeParameter(context.signature.typeParameters[index]); if (constraint) { const instantiatedConstraint = instantiateType(constraint, getInferenceMapper(context)); if (!isTypeAssignableTo(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) { @@ -7895,21 +8098,10 @@ namespace ts { function isDiscriminantProperty(type: Type, name: string) { if (type && type.flags & TypeFlags.Union) { - let prop = getPropertyOfType(type, name); - if (!prop) { - // The type may be a union that includes nullable or primitive types. If filtering - // those out produces a different type, get the property from that type instead. - // Effectively, we're checking if this *could* be a discriminant property once nullable - // and primitive types are removed by other type guards. - const filteredType = getTypeWithFacts(type, TypeFacts.Discriminatable); - if (filteredType !== type && filteredType.flags & TypeFlags.Union) { - prop = getPropertyOfType(filteredType, name); - } - } + const prop = getUnionOrIntersectionProperty(type, name); if (prop && prop.flags & SymbolFlags.SyntheticProperty) { if ((prop).isDiscriminantProperty === undefined) { - (prop).isDiscriminantProperty = !(prop).hasCommonType && - isUnitUnionType(getTypeOfSymbol(prop)); + (prop).isDiscriminantProperty = (prop).hasNonUniformType && isLiteralType(getTypeOfSymbol(prop)); } return (prop).isDiscriminantProperty; } @@ -7961,8 +8153,11 @@ namespace ts { // we remove type string. function getAssignmentReducedType(declaredType: UnionType, assignedType: Type) { if (declaredType !== assignedType) { + if (assignedType.flags & TypeFlags.Never) { + return assignedType; + } const reducedType = filterType(declaredType, t => typeMaybeAssignableTo(assignedType, t)); - if (reducedType !== neverType) { + if (!(reducedType.flags & TypeFlags.Never)) { return reducedType; } } @@ -7992,14 +8187,14 @@ namespace ts { } if (flags & TypeFlags.StringLiteral) { return strictNullChecks ? - type === emptyStringType ? TypeFacts.EmptyStringStrictFacts : TypeFacts.NonEmptyStringStrictFacts : - type === emptyStringType ? TypeFacts.EmptyStringFacts : TypeFacts.NonEmptyStringFacts; + (type).text === "" ? TypeFacts.EmptyStringStrictFacts : TypeFacts.NonEmptyStringStrictFacts : + (type).text === "" ? TypeFacts.EmptyStringFacts : TypeFacts.NonEmptyStringFacts; } if (flags & (TypeFlags.Number | TypeFlags.Enum)) { return strictNullChecks ? TypeFacts.NumberStrictFacts : TypeFacts.NumberFacts; } if (flags & (TypeFlags.NumberLiteral | TypeFlags.EnumLiteral)) { - const isZero = type === zeroType || type.flags & TypeFlags.EnumLiteral && (type).text === "0"; + const isZero = (type).text === "0"; return strictNullChecks ? isZero ? TypeFacts.ZeroStrictFacts : TypeFacts.NonZeroStrictFacts : isZero ? TypeFacts.ZeroFacts : TypeFacts.NonZeroFacts; @@ -8172,7 +8367,7 @@ namespace ts { function getTypeOfSwitchClause(clause: CaseClause | DefaultClause) { if (clause.kind === SyntaxKind.CaseClause) { - const caseType = checkExpression((clause).expression); + const caseType = getRegularTypeOfLiteralType(checkExpression((clause).expression)); return isUnitType(caseType) ? caseType : undefined; } return neverType; @@ -8242,7 +8437,7 @@ namespace ts { const visitedFlowStart = visitedFlowCount; const result = getTypeFromFlowType(getTypeAtFlowNode(reference.flowNode)); visitedFlowCount = visitedFlowStart; - if (reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(result, TypeFacts.NEUndefinedOrNull) === neverType) { + if (reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(result, TypeFacts.NEUndefinedOrNull).flags & TypeFlags.Never) { return declaredType; } return result; @@ -8312,7 +8507,8 @@ namespace ts { // Assignments only narrow the computed type if the declared type is a union type. Thus, we // only need to evaluate the assigned type if the declared type is a union type. if (isMatchingReference(reference, node)) { - return declaredType.flags & TypeFlags.Union ? + const isIncrementOrDecrement = node.parent.kind === SyntaxKind.PrefixUnaryExpression || node.parent.kind === SyntaxKind.PostfixUnaryExpression; + return declaredType.flags & TypeFlags.Union && !isIncrementOrDecrement ? getAssignmentReducedType(declaredType, getInitialOrAssignedType(node)) : declaredType; } @@ -8330,17 +8526,18 @@ namespace ts { function getTypeAtFlowCondition(flow: FlowCondition): FlowType { const flowType = getTypeAtFlowNode(flow.antecedent); let type = getTypeFromFlowType(flowType); - if (type !== neverType) { + if (!(type.flags & TypeFlags.Never)) { // If we have an antecedent type (meaning we're reachable in some way), we first // attempt to narrow the antecedent type. If that produces the never type, and if // the antecedent type is incomplete (i.e. a transient type in a loop), then we // take the type guard as an indication that control *could* reach here once we - // have the complete type. We proceed by reverting to the declared type and then - // narrow that. + // have the complete type. We proceed by switching to the silent never type which + // doesn't report errors when operators are applied to it. Note that this is the + // *only* place a silent never type is ever generated. const assumeTrue = (flow.flags & FlowFlags.TrueCondition) !== 0; type = narrowType(type, flow.expression, assumeTrue); - if (type === neverType && isIncomplete(flowType)) { - type = narrowType(declaredType, flow.expression, assumeTrue); + if (type.flags & TypeFlags.Never && isIncomplete(flowType)) { + type = silentNeverType; } } return createFlowType(type, isIncomplete(flowType)); @@ -8525,6 +8722,9 @@ namespace ts { } function narrowTypeByEquality(type: Type, operator: SyntaxKind, value: Expression, assumeTrue: boolean): Type { + if (type.flags & TypeFlags.Any) { + return type; + } if (operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) { assumeTrue = !assumeTrue; } @@ -8546,9 +8746,13 @@ namespace ts { } if (assumeTrue) { const narrowedType = filterType(type, t => areTypesComparable(t, valueType)); - return narrowedType !== neverType ? narrowedType : type; + return narrowedType.flags & TypeFlags.Never ? type : narrowedType; + } + if (isUnitType(valueType)) { + const regularType = getRegularTypeOfLiteralType(valueType); + return filterType(type, t => getRegularTypeOfLiteralType(t) !== regularType); } - return isUnitType(valueType) ? filterType(type, t => t !== valueType) : type; + return type; } function narrowTypeByTypeof(type: Type, typeOfExpr: TypeOfExpression, operator: SyntaxKind, literal: LiteralExpression, assumeTrue: boolean): Type { @@ -8589,12 +8793,12 @@ namespace ts { const clauseTypes = switchTypes.slice(clauseStart, clauseEnd); const hasDefaultClause = clauseStart === clauseEnd || contains(clauseTypes, neverType); const discriminantType = getUnionType(clauseTypes); - const caseType = discriminantType === neverType ? neverType : filterType(type, t => isTypeComparableTo(discriminantType, t)); + const caseType = discriminantType.flags & TypeFlags.Never ? neverType : filterType(type, t => isTypeComparableTo(discriminantType, t)); if (!hasDefaultClause) { return caseType; } - const defaultType = filterType(type, t => !(isUnitType(t) && contains(switchTypes, t))); - return caseType === neverType ? defaultType : getUnionType([caseType, defaultType]); + const defaultType = filterType(type, t => !(isUnitType(t) && contains(switchTypes, getRegularTypeOfLiteralType(t)))); + return caseType.flags & TypeFlags.Never ? defaultType : getUnionType([caseType, defaultType]); } function narrowTypeByInstanceof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { @@ -8658,7 +8862,7 @@ namespace ts { // the candidate type. If one or more constituents remain, return a union of those. if (type.flags & TypeFlags.Union) { const assignableType = filterType(type, t => isTypeInstanceOf(t, candidate)); - if (assignableType !== neverType) { + if (!(assignableType.flags & TypeFlags.Never)) { return assignableType; } } @@ -8668,7 +8872,7 @@ namespace ts { // type. Otherwise, the types are completely unrelated, so narrow to an intersection of the // two types. const targetType = type.flags & TypeFlags.TypeParameter ? getApparentType(type) : type; - return isTypeSubtypeOf(candidate, targetType) ? candidate : + return isTypeSubtypeOf(candidate, type) ? candidate : isTypeAssignableTo(type, candidate) ? type : isTypeAssignableTo(candidate, targetType) ? candidate : getIntersectionType([type, candidate]); @@ -8833,10 +9037,13 @@ namespace ts { // can explicitly bound arguments objects if (symbol === argumentsSymbol) { const container = getContainingFunction(node); - if (container.kind === SyntaxKind.ArrowFunction) { - if (languageVersion < ScriptTarget.ES6) { + if (languageVersion < ScriptTarget.ES6) { + if (container.kind === SyntaxKind.ArrowFunction) { error(node, Diagnostics.The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression); } + else if (hasModifier(container, ModifierFlags.Async)) { + error(node, Diagnostics.The_arguments_object_cannot_be_referenced_in_an_async_function_or_method_in_ES3_and_ES5_Consider_using_a_standard_function_or_method); + } } if (node.flags & NodeFlags.AwaitContext) { @@ -8850,22 +9057,41 @@ namespace ts { const localOrExportSymbol = getExportSymbolOfValueSymbolIfExported(symbol); - // Due to the emit for class decorators, any reference to the class from inside of the class body - // must instead be rewritten to point to a temporary variable to avoid issues with the double-bind - // behavior of class names in ES6. - if (languageVersion === ScriptTarget.ES6 - && localOrExportSymbol.flags & SymbolFlags.Class - && localOrExportSymbol.valueDeclaration.kind === SyntaxKind.ClassDeclaration - && nodeIsDecorated(localOrExportSymbol.valueDeclaration)) { - let container = getContainingClass(node); - while (container !== undefined) { - if (container === localOrExportSymbol.valueDeclaration && container.name !== node) { - getNodeLinks(container).flags |= NodeCheckFlags.ClassWithBodyScopedClassBinding; - getNodeLinks(node).flags |= NodeCheckFlags.BodyScopedClassBinding; - break; + if (localOrExportSymbol.flags & SymbolFlags.Class) { + const declaration = localOrExportSymbol.valueDeclaration; + // Due to the emit for class decorators, any reference to the class from inside of the class body + // must instead be rewritten to point to a temporary variable to avoid issues with the double-bind + // behavior of class names in ES6. + if (languageVersion === ScriptTarget.ES6 + && declaration.kind === SyntaxKind.ClassDeclaration + && nodeIsDecorated(declaration)) { + let container = getContainingClass(node); + while (container !== undefined) { + if (container === declaration && container.name !== node) { + getNodeLinks(declaration).flags |= NodeCheckFlags.ClassWithConstructorReference; + getNodeLinks(node).flags |= NodeCheckFlags.ConstructorReferenceInClass; + break; + } + + container = getContainingClass(container); } + } + else if (declaration.kind === SyntaxKind.ClassExpression) { + // When we emit a class expression with static members that contain a reference + // to the constructor in the initializer, we will need to substitute that + // binding with an alias as the class name is not in scope. + let container = getThisContainer(node, /*includeArrowFunctions*/ false); + while (container !== undefined) { + if (container.parent === declaration) { + if (container.kind === SyntaxKind.PropertyDeclaration && hasModifier(container, ModifierFlags.Static)) { + getNodeLinks(declaration).flags |= NodeCheckFlags.ClassWithConstructorReference; + getNodeLinks(node).flags |= NodeCheckFlags.ConstructorReferenceInClass; + } + break; + } - container = getContainingClass(container); + container = getThisContainer(container, /*includeArrowFunctions*/ false); + } } } @@ -8886,6 +9112,7 @@ namespace ts { const isParameter = getRootDeclaration(declaration).kind === SyntaxKind.Parameter; const declarationContainer = getControlFlowContainer(declaration); let flowContainer = getControlFlowContainer(node); + const isOuterVariable = flowContainer !== declarationContainer; // When the control flow originates in a function expression or arrow function and we are referencing // a const variable or parameter from an outer function, we extend the origin of the control flow // analysis to include the immediately enclosing function. @@ -8898,7 +9125,7 @@ namespace ts { // the entire control flow graph from the variable's declaration (i.e. when the flow container and // declaration container are the same). const assumeInitialized = !strictNullChecks || (type.flags & TypeFlags.Any) !== 0 || isParameter || - flowContainer !== declarationContainer || isInAmbientContext(declaration); + isOuterVariable || isInAmbientContext(declaration); const flowType = getFlowTypeOfReference(node, type, assumeInitialized, flowContainer); // A variable is considered uninitialized when it is possible to analyze the entire control flow graph // from declaration to use, and when the variable's declared type doesn't include undefined but the @@ -9110,7 +9337,7 @@ namespace ts { break; case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: - if (container.flags & NodeFlags.Static) { + if (getModifierFlags(container) & ModifierFlags.Static) { error(node, Diagnostics.this_cannot_be_referenced_in_a_static_property_initializer); // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks } @@ -9148,9 +9375,10 @@ namespace ts { return thisType; } } + if (isClassLike(container.parent)) { const symbol = getSymbolOfNode(container.parent); - const type = container.flags & NodeFlags.Static ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol)).thisType; + const type = hasModifier(container, ModifierFlags.Static) ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol)).thisType; return getFlowTypeOfReference(node, type, /*assumeInitialized*/ true, /*flowContainer*/ undefined); } @@ -9193,8 +9421,8 @@ namespace ts { let container = getSuperContainer(node, /*stopOnFunctions*/ true); let needToCaptureLexicalThis = false; + // adjust the container reference in case if super is used inside arrow functions with arbitrarily deep nesting if (!isCallExpression) { - // adjust the container reference in case if super is used inside arrow functions with arbitrary deep nesting while (container && container.kind === SyntaxKind.ArrowFunction) { container = getSuperContainer(container, /*stopOnFunctions*/ true); needToCaptureLexicalThis = languageVersion < ScriptTarget.ES6; @@ -9229,7 +9457,7 @@ namespace ts { return unknownType; } - if ((container.flags & NodeFlags.Static) || isCallExpression) { + if ((getModifierFlags(container) & ModifierFlags.Static) || isCallExpression) { nodeCheckFlag = NodeCheckFlags.SuperStatic; } else { @@ -9294,8 +9522,8 @@ namespace ts { // This helper creates an object with a "value" property that wraps the `super` property or indexed access for both get and set. // This is required for destructuring assignments, as a call expression cannot be used as the target of a destructuring assignment // while a property access can. - if (container.kind === SyntaxKind.MethodDeclaration && container.flags & NodeFlags.Async) { - if (isSuperPropertyOrElementAccess(node.parent) && isAssignmentTarget(node.parent)) { + if (container.kind === SyntaxKind.MethodDeclaration && getModifierFlags(container) & ModifierFlags.Async) { + if (isSuperProperty(node.parent) && isAssignmentTarget(node.parent)) { getNodeLinks(container).flags |= NodeCheckFlags.AsyncMethodWithSuperBinding; } else { @@ -9360,7 +9588,7 @@ namespace ts { // topmost container must be something that is directly nested in the class declaration\object literal expression if (isClassLike(container.parent) || container.parent.kind === SyntaxKind.ObjectLiteralExpression) { - if (container.flags & NodeFlags.Static) { + if (getModifierFlags(container) & ModifierFlags.Static) { return container.kind === SyntaxKind.MethodDeclaration || container.kind === SyntaxKind.MethodSignature || container.kind === SyntaxKind.GetAccessor || @@ -9404,14 +9632,14 @@ namespace ts { if (parameter.dotDotDotToken) { const restTypes: Type[] = []; for (let i = indexOfParameter; i < iife.arguments.length; i++) { - restTypes.push(getTypeOfExpression(iife.arguments[i])); + restTypes.push(getWidenedLiteralType(checkExpression(iife.arguments[i]))); } return createArrayType(getUnionType(restTypes)); } const links = getNodeLinks(iife); const cached = links.resolvedSignature; links.resolvedSignature = anySignature; - const type = checkExpression(iife.arguments[indexOfParameter]); + const type = getWidenedLiteralType(checkExpression(iife.arguments[indexOfParameter])); links.resolvedSignature = cached; return type; } @@ -9646,7 +9874,7 @@ namespace ts { return getContextualTypeForObjectLiteralElement(node); } - function getContextualTypeForObjectLiteralElement(element: ObjectLiteralElement) { + function getContextualTypeForObjectLiteralElement(element: ObjectLiteralElementLike) { const objectLiteral = element.parent; const type = getApparentTypeOfContextualType(objectLiteral); if (type) { @@ -9762,7 +9990,8 @@ namespace ts { case SyntaxKind.BinaryExpression: return getContextualTypeForBinaryOperand(node); case SyntaxKind.PropertyAssignment: - return getContextualTypeForObjectLiteralElement(parent); + case SyntaxKind.ShorthandPropertyAssignment: + return getContextualTypeForObjectLiteralElement(parent); case SyntaxKind.ArrayLiteralExpression: return getContextualTypeForElementExpression(node); case SyntaxKind.ConditionalExpression: @@ -9781,31 +10010,6 @@ namespace ts { return undefined; } - function isLiteralTypeLocation(node: Node): boolean { - const parent = node.parent; - switch (parent.kind) { - case SyntaxKind.BinaryExpression: - switch ((parent).operatorToken.kind) { - case SyntaxKind.EqualsEqualsEqualsToken: - case SyntaxKind.ExclamationEqualsEqualsToken: - case SyntaxKind.EqualsEqualsToken: - case SyntaxKind.ExclamationEqualsToken: - return true; - } - break; - case SyntaxKind.ConditionalExpression: - return (node === (parent).whenTrue || - node === (parent).whenFalse) && - isLiteralTypeLocation(parent); - case SyntaxKind.ParenthesizedExpression: - return isLiteralTypeLocation(parent); - case SyntaxKind.CaseClause: - case SyntaxKind.LiteralType: - return true; - } - return false; - } - // If the given type is an object or union type, if that type has a single signature, and if // that signature is non-generic, return the signature. Otherwise return undefined. function getNonGenericSignature(type: Type): Signature { @@ -9942,7 +10146,7 @@ namespace ts { } } else { - const type = checkExpression(e, contextualMapper); + const type = checkExpressionForMutableLocation(e, contextualMapper); elementTypes.push(type); } hasSpreadElement = hasSpreadElement || e.kind === SyntaxKind.SpreadElementExpression; @@ -9999,6 +10203,10 @@ namespace ts { return isTypeAny(type) || isTypeOfKind(type, kind); } + function isInfinityOrNaNString(name: string): boolean { + return name === "Infinity" || name === "-Infinity" || name === "NaN"; + } + function isNumericLiteralName(name: string) { // The intent of numeric names is that // - they are names with text in a numeric form, and that @@ -10082,7 +10290,7 @@ namespace ts { } else { Debug.assert(memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment); - type = checkExpression((memberDecl).name, contextualMapper); + type = checkExpressionForMutableLocation((memberDecl).name, contextualMapper); } typeFlags |= type.flags; const prop = createSymbol(SymbolFlags.Property | SymbolFlags.Transient | member.flags, member.name); @@ -10163,7 +10371,7 @@ namespace ts { const stringIndexInfo = hasComputedStringProperty ? getObjectLiteralIndexInfo(node, propertiesArray, IndexKind.String) : undefined; const numberIndexInfo = hasComputedNumberProperty ? getObjectLiteralIndexInfo(node, propertiesArray, IndexKind.Number) : undefined; const result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo); - const freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : TypeFlags.FreshObjectLiteral; + const freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : TypeFlags.FreshLiteral; result.flags |= TypeFlags.ObjectLiteral | TypeFlags.ContainsObjectLiteral | freshObjectLiteralFlag | (typeFlags & TypeFlags.PropagatingFlags) | (patternWithComputedProperties ? TypeFlags.ObjectLiteralPatternWithComputedProperties : 0); if (inDestructuringPattern) { result.pattern = node; @@ -10645,8 +10853,12 @@ namespace ts { return s.valueDeclaration ? s.valueDeclaration.kind : SyntaxKind.PropertyDeclaration; } - function getDeclarationFlagsFromSymbol(s: Symbol): NodeFlags { - return s.valueDeclaration ? getCombinedNodeFlags(s.valueDeclaration) : s.flags & SymbolFlags.Prototype ? NodeFlags.Public | NodeFlags.Static : 0; + function getDeclarationModifierFlagsFromSymbol(s: Symbol): ModifierFlags { + return s.valueDeclaration ? getCombinedModifierFlags(s.valueDeclaration) : s.flags & SymbolFlags.Prototype ? ModifierFlags.Public | ModifierFlags.Static : 0; + } + + function getDeclarationNodeFlagsFromSymbol(s: Symbol): NodeFlags { + return s.valueDeclaration ? getCombinedNodeFlags(s.valueDeclaration) : 0; } /** @@ -10658,7 +10870,7 @@ namespace ts { * @param prop The symbol for the right hand side of the property access. */ function checkClassPropertyAccess(node: PropertyAccessExpression | QualifiedName | VariableLikeDeclaration, left: Expression | QualifiedName, type: Type, prop: Symbol): boolean { - const flags = getDeclarationFlagsFromSymbol(prop); + const flags = getDeclarationModifierFlagsFromSymbol(prop); const declaringClass = getDeclaredTypeOfSymbol(getParentOfSymbol(prop)); const errorNode = node.kind === SyntaxKind.PropertyAccessExpression || node.kind === SyntaxKind.VariableDeclaration ? (node).name : @@ -10679,7 +10891,7 @@ namespace ts { return false; } - if (flags & NodeFlags.Abstract) { + if (flags & ModifierFlags.Abstract) { // A method cannot be accessed in a super property access if the method is abstract. // This error could mask a private property access error. But, a member // cannot simultaneously be private and abstract, so this will trigger an @@ -10691,14 +10903,14 @@ namespace ts { } // Public properties are otherwise accessible. - if (!(flags & (NodeFlags.Private | NodeFlags.Protected))) { + if (!(flags & ModifierFlags.NonPublicAccessibilityModifier)) { return true; } // Property is known to be private or protected at this point // Private property is accessible if the property is within the declaring class - if (flags & NodeFlags.Private) { + if (flags & ModifierFlags.Private) { const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)); if (!isNodeWithinClass(node, declaringClassDeclaration)) { error(errorNode, Diagnostics.Property_0_is_private_and_only_accessible_within_class_1, symbolToString(prop), typeToString(declaringClass)); @@ -10726,7 +10938,7 @@ namespace ts { return false; } // No further restrictions for static properties - if (flags & NodeFlags.Static) { + if (flags & ModifierFlags.Static) { return true; } // An instance property must be accessed through an instance of the enclosing class @@ -10768,7 +10980,7 @@ namespace ts { function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier) { const type = checkNonNullExpression(left); - if (isTypeAny(type)) { + if (isTypeAny(type) || type === silentNeverType) { return type; } @@ -10780,14 +10992,14 @@ namespace ts { const prop = getPropertyOfType(apparentType, right.text); if (!prop) { if (right.text && !checkAndReportErrorForExtendingInterface(node)) { - error(right, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(right), typeToString(type.flags & TypeFlags.ThisType ? apparentType : type)); + reportNonexistentProperty(right, type.flags & TypeFlags.ThisType ? apparentType : type); } return unknownType; } if (noUnusedIdentifiers && (prop.flags & SymbolFlags.ClassMember) && - prop.valueDeclaration && (prop.valueDeclaration.flags & NodeFlags.Private)) { + prop.valueDeclaration && (getModifierFlags(prop.valueDeclaration) & ModifierFlags.Private)) { if (prop.flags & SymbolFlags.Instantiated) { getSymbolLinks(prop).target.isReferenced = true; @@ -10803,10 +11015,7 @@ namespace ts { checkClassPropertyAccess(node, left, apparentType, prop); } - let propType = getTypeOfSymbol(prop); - if (prop.flags & SymbolFlags.EnumMember && isLiteralContextForType(node, propType)) { - propType = getDeclaredTypeOfSymbol(prop); - } + const propType = getTypeOfSymbol(prop); // Only compute control flow type if this is a property access expression that isn't an // assignment target, and the referenced property was declared as a variable, property, @@ -10817,6 +11026,20 @@ namespace ts { return propType; } return getFlowTypeOfReference(node, propType, /*assumeInitialized*/ true, /*flowContainer*/ undefined); + + function reportNonexistentProperty(propNode: Identifier, containingType: Type) { + let errorInfo: DiagnosticMessageChain; + if (containingType.flags & TypeFlags.Union && !(containingType.flags & TypeFlags.Primitive)) { + for (const subtype of (containingType as UnionType).types) { + if (!getPropertyOfType(subtype, propNode.text)) { + errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(subtype)); + break; + } + } + } + errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(containingType)); + diagnostics.add(createDiagnosticForNodeFromMessageChain(propNode, errorInfo)); + } } function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean { @@ -10904,8 +11127,8 @@ namespace ts { const objectType = getApparentType(checkNonNullExpression(node.expression)); const indexType = node.argumentExpression ? checkExpression(node.argumentExpression) : unknownType; - if (objectType === unknownType) { - return unknownType; + if (objectType === unknownType || objectType === silentNeverType) { + return objectType; } const isConstEnum = isConstEnumObjectType(objectType); @@ -11224,7 +11447,7 @@ namespace ts { // Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec) function instantiateSignatureInContextOf(signature: Signature, contextualSignature: Signature, contextualMapper: TypeMapper): Signature { - const context = createInferenceContext(signature.typeParameters, /*inferUnionTypes*/ true); + const context = createInferenceContext(signature, /*inferUnionTypes*/ true); forEachMatchingParameterType(contextualSignature, signature, (source, target) => { // Type parameters from outer context referenced by source type are fixed by instantiation of the source type inferTypes(context, instantiateType(source, contextualMapper), target); @@ -11821,7 +12044,7 @@ namespace ts { else if (candidateForTypeArgumentError) { if (!isTaggedTemplate && !isDecorator && typeArguments) { const typeArguments = (node).typeArguments; - checkTypeArguments(candidateForTypeArgumentError, typeArguments, map(typeArguments, getTypeFromTypeNode), /*reportErrors*/ true, headMessage); + checkTypeArguments(candidateForTypeArgumentError, typeArguments, map(typeArguments, getTypeFromTypeNodeNoAlias), /*reportErrors*/ true, headMessage); } else { Debug.assert(resultOfFailedInference.failedTypeParameterIndex >= 0); @@ -11852,7 +12075,7 @@ namespace ts { for (let candidate of candidates) { if (hasCorrectArity(node, args, candidate)) { if (candidate.typeParameters && typeArguments) { - candidate = getSignatureInstantiation(candidate, map(typeArguments, getTypeFromTypeNode)); + candidate = getSignatureInstantiation(candidate, map(typeArguments, getTypeFromTypeNodeNoAlias)); } return candidate; } @@ -11880,7 +12103,7 @@ namespace ts { let candidate: Signature; let typeArgumentsAreValid: boolean; const inferenceContext = originalCandidate.typeParameters - ? createInferenceContext(originalCandidate.typeParameters, /*inferUnionTypes*/ false) + ? createInferenceContext(originalCandidate, /*inferUnionTypes*/ false) : undefined; while (true) { @@ -11888,7 +12111,7 @@ namespace ts { if (candidate.typeParameters) { let typeArgumentTypes: Type[]; if (typeArguments) { - typeArgumentTypes = map(typeArguments, getTypeFromTypeNode); + typeArgumentTypes = map(typeArguments, getTypeFromTypeNodeNoAlias); typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false); } else { @@ -11955,6 +12178,9 @@ namespace ts { } const funcType = checkNonNullExpression(node.expression); + if (funcType === silentNeverType) { + return silentNeverSignature; + } const apparentType = getApparentType(funcType); if (apparentType === unknownType) { @@ -11988,7 +12214,7 @@ namespace ts { error(node, Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType)); } else { - error(node, Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature); + error(node, Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType)); } return resolveErrorCall(node); } @@ -12027,6 +12253,9 @@ namespace ts { } let expressionType = checkNonNullExpression(node.expression); + if (expressionType === silentNeverType) { + return silentNeverSignature; + } // If expressionType's apparent type(section 3.8.1) is an object type with one or // more construct signatures, the expression is processed in the same manner as a @@ -12044,7 +12273,7 @@ namespace ts { // In the case of a merged class-module or class-interface declaration, // only the class declaration node will have the Abstract flag set. const valueDecl = expressionType.symbol && getClassLikeDeclarationOfSymbol(expressionType.symbol); - if (valueDecl && valueDecl.flags & NodeFlags.Abstract) { + if (valueDecl && getModifierFlags(valueDecl) & ModifierFlags.Abstract) { error(node, Diagnostics.Cannot_create_an_instance_of_the_abstract_class_0, declarationNameToString(valueDecl.name)); return resolveErrorCall(node); } @@ -12097,10 +12326,10 @@ namespace ts { } const declaration = signature.declaration; - const flags = declaration.flags; + const modifiers = getModifierFlags(declaration); // Public constructor is accessible. - if (!(flags & (NodeFlags.Private | NodeFlags.Protected))) { + if (!(modifiers & ModifierFlags.NonPublicAccessibilityModifier)) { return true; } @@ -12115,16 +12344,16 @@ namespace ts { const baseTypes = getBaseTypes(containingType); if (baseTypes.length) { const baseType = baseTypes[0]; - if (flags & NodeFlags.Protected && + if (modifiers & ModifierFlags.Protected && baseType.symbol === declaration.parent.symbol) { return true; } } } - if (flags & NodeFlags.Private) { + if (modifiers & ModifierFlags.Private) { error(node, Diagnostics.Constructor_of_class_0_is_private_and_only_accessible_within_the_class_declaration, typeToString(declaringClass)); } - if (flags & NodeFlags.Protected) { + if (modifiers & ModifierFlags.Protected) { error(node, Diagnostics.Constructor_of_class_0_is_protected_and_only_accessible_within_the_class_declaration, typeToString(declaringClass)); } return false; @@ -12150,7 +12379,7 @@ namespace ts { } if (!callSignatures.length) { - error(node, Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature); + error(node, Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType)); return resolveErrorCall(node); } @@ -12198,7 +12427,7 @@ namespace ts { const headMessage = getDiagnosticHeadMessageForDecoratorResolution(node); if (!callSignatures.length) { let errorInfo: DiagnosticMessageChain; - errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature); + errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType)); errorInfo = chainDiagnosticMessages(errorInfo, headMessage); diagnostics.add(createDiagnosticForNodeFromMessageChain(node, errorInfo)); return resolveErrorCall(node); @@ -12311,7 +12540,7 @@ namespace ts { } function checkAssertion(node: AssertionExpression) { - const exprType = getRegularTypeOfObjectLiteral(checkExpression(node.expression)); + const exprType = getRegularTypeOfObjectLiteral(getBaseTypeOfLiteralType(checkExpression(node.expression))); checkSourceElement(node.type); const targetType = getTypeFromTypeNode(node.type); @@ -12371,7 +12600,7 @@ namespace ts { function assignBindingElementTypes(node: VariableLikeDeclaration) { if (isBindingPattern(node.name)) { for (const element of (node.name).elements) { - if (element.kind !== SyntaxKind.OmittedExpression) { + if (!isOmittedExpression(element)) { if (element.name.kind === SyntaxKind.Identifier) { getSymbolLinks(getSymbolOfNode(element)).type = getTypeForBindingElement(element); } @@ -12501,20 +12730,8 @@ namespace ts { return isAsync ? createPromiseReturnType(func, voidType) : voidType; } } - // When yield/return statements are contextually typed we allow the return type to be a union type. - // Otherwise we require the yield/return expressions to have a best common supertype. - type = contextualSignature ? getUnionType(types, /*subtypeReduction*/ true) : getCommonSupertype(types); - if (!type) { - if (funcIsGenerator) { - error(func, Diagnostics.No_best_common_type_exists_among_yield_expressions); - return createIterableIteratorType(unknownType); - } - else { - error(func, Diagnostics.No_best_common_type_exists_among_return_expressions); - // Defer to unioning the return types so we get a) downstream errors earlier and b) better Salsa experience - return isAsync ? createPromiseReturnType(func, getUnionType(types, /*subtypeReduction*/ true)) : getUnionType(types, /*subtypeReduction*/ true); - } - } + // Return a union of the return expression types. + type = getUnionType(types, /*subtypeReduction*/ true); if (funcIsGenerator) { type = createIterableIteratorType(type); @@ -12523,6 +12740,9 @@ namespace ts { if (!contextualSignature) { reportErrorsFromWidening(func, type); } + if (isUnitType(type) && !(contextualSignature && isLiteralContextualType(getReturnTypeOfSignature(contextualSignature)))) { + type = getWidenedLiteralType(type); + } const widenedType = getWidenedType(type); // From within an async function you can return either a non-promise value or a promise. Any @@ -12558,7 +12778,7 @@ namespace ts { return false; } const type = checkExpression(node.expression); - if (!isUnitUnionType(type)) { + if (!isLiteralType(type)) { return false; } const switchTypes = getSwitchClauseTypes(node); @@ -12595,7 +12815,7 @@ namespace ts { // the native Promise type by the caller. type = checkAwaitedType(type, func, Diagnostics.Return_expression_in_async_function_does_not_have_a_valid_callable_then_member); } - if (type === neverType) { + if (type.flags & TypeFlags.Never) { hasReturnOfTypeNever = true; } else if (!contains(aggregatedTypes, type)) { @@ -12645,7 +12865,7 @@ namespace ts { const hasExplicitReturn = func.flags & NodeFlags.HasExplicitReturn; - if (returnType === neverType) { + if (returnType && returnType.flags & TypeFlags.Never) { error(func.type, Diagnostics.A_function_returning_never_cannot_have_a_reachable_end_point); } else if (returnType && !hasExplicitReturn) { @@ -12793,8 +13013,8 @@ namespace ts { // Enum members // Unions and intersections of the above (unions and intersections eagerly set isReadonly on creation) return symbol.isReadonly || - symbol.flags & SymbolFlags.Property && (getDeclarationFlagsFromSymbol(symbol) & NodeFlags.Readonly) !== 0 || - symbol.flags & SymbolFlags.Variable && (getDeclarationFlagsFromSymbol(symbol) & NodeFlags.Const) !== 0 || + symbol.flags & SymbolFlags.Property && (getDeclarationModifierFlagsFromSymbol(symbol) & ModifierFlags.Readonly) !== 0 || + symbol.flags & SymbolFlags.Variable && (getDeclarationNodeFlagsFromSymbol(symbol) & NodeFlags.Const) !== 0 || symbol.flags & SymbolFlags.Accessor && !(symbol.flags & SymbolFlags.SetAccessor) || (symbol.flags & SymbolFlags.EnumMember) !== 0; } @@ -12901,8 +13121,11 @@ namespace ts { function checkPrefixUnaryExpression(node: PrefixUnaryExpression): Type { const operandType = checkExpression(node.operand); - if (node.operator === SyntaxKind.MinusToken && node.operand.kind === SyntaxKind.NumericLiteral && isLiteralContextForType(node, numberType)) { - return getLiteralTypeForText(TypeFlags.NumberLiteral, "" + -(node.operand).text); + if (operandType === silentNeverType) { + return silentNeverType; + } + if (node.operator === SyntaxKind.MinusToken && node.operand.kind === SyntaxKind.NumericLiteral) { + return getFreshTypeOfLiteralType(getLiteralTypeForText(TypeFlags.NumberLiteral, "" + -(node.operand).text)); } switch (node.operator) { case SyntaxKind.PlusToken: @@ -12934,6 +13157,9 @@ namespace ts { function checkPostfixUnaryExpression(node: PostfixUnaryExpression): Type { const operandType = checkExpression(node.operand); + if (operandType === silentNeverType) { + return silentNeverType; + } const ok = checkArithmeticOperandType(node.operand, getNonNullableType(operandType), Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type); if (ok) { @@ -12998,6 +13224,9 @@ namespace ts { } function checkInstanceOfExpression(left: Expression, right: Expression, leftType: Type, rightType: Type): Type { + if (leftType === silentNeverType || rightType === silentNeverType) { + return silentNeverType; + } // TypeScript 1.0 spec (April 2014): 4.15.4 // The instanceof operator requires the left operand to be of type Any, an object type, or a type parameter type, // and the right operand to be of type Any or a subtype of the 'Function' interface type. @@ -13014,6 +13243,9 @@ namespace ts { } function checkInExpression(left: Expression, right: Expression, leftType: Type, rightType: Type): Type { + if (leftType === silentNeverType || rightType === silentNeverType) { + return silentNeverType; + } // TypeScript 1.0 spec (April 2014): 4.15.5 // The in operator requires the left operand to be of type Any, the String primitive type, or the Number primitive type, // and the right operand to be of type Any, an object type, or a type parameter type. @@ -13035,7 +13267,7 @@ namespace ts { return sourceType; } - function checkObjectLiteralDestructuringPropertyAssignment(objectLiteralType: Type, property: ObjectLiteralElement, contextualMapper?: TypeMapper) { + function checkObjectLiteralDestructuringPropertyAssignment(objectLiteralType: Type, property: ObjectLiteralElementLike, contextualMapper?: TypeMapper) { if (property.kind === SyntaxKind.PropertyAssignment || property.kind === SyntaxKind.ShorthandPropertyAssignment) { const name = (property).name; if (name.kind === SyntaxKind.ComputedPropertyName) { @@ -13166,6 +13398,72 @@ namespace ts { return sourceType; } + /** + * This is a *shallow* check: An expression is side-effect-free if the + * evaluation of the expression *itself* cannot produce side effects. + * For example, x++ / 3 is side-effect free because the / operator + * does not have side effects. + * The intent is to "smell test" an expression for correctness in positions where + * its value is discarded (e.g. the left side of the comma operator). + */ + function isSideEffectFree(node: Node): boolean { + node = skipParentheses(node); + switch (node.kind) { + case SyntaxKind.Identifier: + case SyntaxKind.StringLiteral: + case SyntaxKind.RegularExpressionLiteral: + case SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.TemplateExpression: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.NumericLiteral: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + case SyntaxKind.NullKeyword: + case SyntaxKind.UndefinedKeyword: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ClassExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.TypeOfExpression: + case SyntaxKind.NonNullExpression: + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxElement: + return true; + + case SyntaxKind.ConditionalExpression: + return isSideEffectFree((node as ConditionalExpression).whenTrue) && + isSideEffectFree((node as ConditionalExpression).whenFalse); + + case SyntaxKind.BinaryExpression: + if (isAssignmentOperator((node as BinaryExpression).operatorToken.kind)) { + return false; + } + return isSideEffectFree((node as BinaryExpression).left) && + isSideEffectFree((node as BinaryExpression).right); + + case SyntaxKind.PrefixUnaryExpression: + case SyntaxKind.PostfixUnaryExpression: + // Unary operators ~, !, +, and - have no side effects. + // The rest do. + switch ((node as PrefixUnaryExpression).operator) { + case SyntaxKind.ExclamationToken: + case SyntaxKind.PlusToken: + case SyntaxKind.MinusToken: + case SyntaxKind.TildeToken: + return true; + } + return false; + + // Some forms listed here for clarity + case SyntaxKind.VoidExpression: // Explicit opt-out + case SyntaxKind.TypeAssertionExpression: // Not SEF, but can produce useful type warnings + case SyntaxKind.AsExpression: // Not SEF, but can produce useful type warnings + default: + return false; + } + } + function isTypeEqualityComparableTo(source: Type, target: Type) { return (target.flags & TypeFlags.Nullable) !== 0 || isTypeComparableTo(source, target); } @@ -13212,6 +13510,9 @@ namespace ts { case SyntaxKind.CaretEqualsToken: case SyntaxKind.AmpersandToken: case SyntaxKind.AmpersandEqualsToken: + if (leftType === silentNeverType || rightType === silentNeverType) { + return silentNeverType; + } // TypeScript 1.0 spec (April 2014): 4.19.1 // These operators require their operands to be of type Any, the Number primitive type, // or an enum type. Operands of an enum type are treated @@ -13244,6 +13545,9 @@ namespace ts { return numberType; case SyntaxKind.PlusToken: case SyntaxKind.PlusEqualsToken: + if (leftType === silentNeverType || rightType === silentNeverType) { + return silentNeverType; + } // TypeScript 1.0 spec (April 2014): 4.19.2 // The binary + operator requires both operands to be of the Number primitive type or an enum type, // or at least one of the operands to be of type Any or the String primitive type. @@ -13301,11 +13605,11 @@ namespace ts { case SyntaxKind.ExclamationEqualsToken: case SyntaxKind.EqualsEqualsEqualsToken: case SyntaxKind.ExclamationEqualsEqualsToken: - const leftIsUnit = isUnitUnionType(leftType); - const rightIsUnit = isUnitUnionType(rightType); - if (!leftIsUnit || !rightIsUnit) { - leftType = leftIsUnit ? getBaseTypeOfUnitType(leftType) : leftType; - rightType = rightIsUnit ? getBaseTypeOfUnitType(rightType) : rightType; + const leftIsLiteral = isLiteralType(leftType); + const rightIsLiteral = isLiteralType(rightType); + if (!leftIsLiteral || !rightIsLiteral) { + leftType = leftIsLiteral ? getBaseTypeOfLiteralType(leftType) : leftType; + rightType = rightIsLiteral ? getBaseTypeOfLiteralType(rightType) : rightType; } if (!isTypeEqualityComparableTo(leftType, rightType) && !isTypeEqualityComparableTo(rightType, leftType)) { reportOperatorError(); @@ -13317,7 +13621,7 @@ namespace ts { return checkInExpression(left, right, leftType, rightType); case SyntaxKind.AmpersandAmpersandToken: return getTypeFacts(leftType) & TypeFacts.Truthy ? - includeFalsyTypes(rightType, getFalsyFlags(strictNullChecks ? leftType : getBaseTypeOfUnitType(rightType))) : + includeFalsyTypes(rightType, getFalsyFlags(strictNullChecks ? leftType : getBaseTypeOfLiteralType(rightType))) : leftType; case SyntaxKind.BarBarToken: return getTypeFacts(leftType) & TypeFacts.Falsy ? @@ -13327,6 +13631,9 @@ namespace ts { checkAssignmentOperator(rightType); return getRegularTypeOfObjectLiteral(rightType); case SyntaxKind.CommaToken: + if (!compilerOptions.allowUnreachableCode && isSideEffectFree(left)) { + error(left, Diagnostics.Left_side_of_comma_operator_is_unused_and_has_no_side_effects); + } return rightType; } @@ -13451,64 +13758,19 @@ namespace ts { return getBestChoiceType(type1, type2); } - function typeContainsLiteralFromEnum(type: Type, enumType: EnumType) { - if (type.flags & TypeFlags.Union) { - for (const t of (type).types) { - if (t.flags & TypeFlags.EnumLiteral && (t).baseType === enumType) { - return true; - } - } - } - if (type.flags & TypeFlags.EnumLiteral) { - return (type).baseType === enumType; - } - return false; - } - - function isLiteralContextForType(node: Expression, type: Type) { - if (isLiteralTypeLocation(node)) { - return true; - } - let contextualType = getContextualType(node); - if (contextualType) { - if (contextualType.flags & TypeFlags.TypeParameter) { - const apparentType = getApparentTypeOfTypeParameter(contextualType); - // If the type parameter is constrained to the base primitive type we're checking for, - // consider this a literal context. For example, given a type parameter 'T extends string', - // this causes us to infer string literal types for T. - if (type === apparentType) { - return true; - } - contextualType = apparentType; - } - if (type.flags & TypeFlags.String) { - return maybeTypeOfKind(contextualType, TypeFlags.StringLiteral); - } - if (type.flags & TypeFlags.Number) { - return maybeTypeOfKind(contextualType, (TypeFlags.NumberLiteral | TypeFlags.EnumLiteral)); - } - if (type.flags & TypeFlags.Boolean) { - return maybeTypeOfKind(contextualType, TypeFlags.BooleanLiteral) && !isTypeAssignableTo(booleanType, contextualType); - } - if (type.flags & TypeFlags.Enum) { - return typeContainsLiteralFromEnum(contextualType, type); - } - } - return false; - } - function checkLiteralExpression(node: Expression): Type { if (node.kind === SyntaxKind.NumericLiteral) { - checkGrammarNumericLiteral(node); + checkGrammarNumericLiteral(node); } switch (node.kind) { case SyntaxKind.StringLiteral: - return isLiteralContextForType(node, stringType) ? getLiteralTypeForText(TypeFlags.StringLiteral, (node).text) : stringType; + return getFreshTypeOfLiteralType(getLiteralTypeForText(TypeFlags.StringLiteral, (node).text)); case SyntaxKind.NumericLiteral: - return isLiteralContextForType(node, numberType) ? getLiteralTypeForText(TypeFlags.NumberLiteral, (node).text) : numberType; + return getFreshTypeOfLiteralType(getLiteralTypeForText(TypeFlags.NumberLiteral, (node).text)); case SyntaxKind.TrueKeyword: + return trueType; case SyntaxKind.FalseKeyword: - return isLiteralContextForType(node, booleanType) ? node.kind === SyntaxKind.TrueKeyword ? trueType : falseType : booleanType; + return falseType; } } @@ -13547,6 +13809,40 @@ namespace ts { return links.resolvedType; } + function isTypeAssertion(node: Expression) { + node = skipParenthesizedNodes(node); + return node.kind === SyntaxKind.TypeAssertionExpression || node.kind === SyntaxKind.AsExpression; + } + + function checkDeclarationInitializer(declaration: VariableLikeDeclaration) { + const type = checkExpressionCached(declaration.initializer); + return getCombinedNodeFlags(declaration) & NodeFlags.Const || + getCombinedModifierFlags(declaration) & ModifierFlags.Readonly || + isTypeAssertion(declaration.initializer) ? type : getWidenedLiteralType(type); + } + + function isLiteralContextualType(contextualType: Type) { + if (contextualType) { + if (contextualType.flags & TypeFlags.TypeParameter) { + const apparentType = getApparentTypeOfTypeParameter(contextualType); + // If the type parameter is constrained to the base primitive type we're checking for, + // consider this a literal context. For example, given a type parameter 'T extends string', + // this causes us to infer string literal types for T. + if (apparentType.flags & (TypeFlags.String | TypeFlags.Number | TypeFlags.Boolean | TypeFlags.Enum)) { + return true; + } + contextualType = apparentType; + } + return maybeTypeOfKind(contextualType, TypeFlags.Literal); + } + return false; + } + + function checkExpressionForMutableLocation(node: Expression, contextualMapper?: TypeMapper): Type { + const type = checkExpression(node, contextualMapper); + return isTypeAssertion(node) || isLiteralContextualType(getContextualType(node)) ? type : getWidenedLiteralType(type); + } + function checkPropertyAssignment(node: PropertyAssignment, contextualMapper?: TypeMapper): Type { // Do not use hasDynamicName here, because that returns false for well known symbols. // We want to perform checkComputedPropertyName for all computed properties, including @@ -13555,7 +13851,7 @@ namespace ts { checkComputedPropertyName(node.name); } - return checkExpression((node).initializer, contextualMapper); + return checkExpressionForMutableLocation((node).initializer, contextualMapper); } function checkObjectLiteralMethod(node: MethodDeclaration, contextualMapper?: TypeMapper): Type { @@ -13730,7 +14026,7 @@ namespace ts { checkVariableLikeDeclaration(node); let func = getContainingFunction(node); - if (node.flags & NodeFlags.ParameterPropertyModifier) { + if (getModifierFlags(node) & ModifierFlags.ParameterPropertyModifier) { func = getContainingFunction(node); if (!(func.kind === SyntaxKind.Constructor && nodeIsPresent(func.body))) { error(node, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation); @@ -13847,7 +14143,12 @@ namespace ts { pattern: BindingPattern, predicateVariableNode: Node, predicateVariableName: string) { - for (const { name } of pattern.elements) { + for (const element of pattern.elements) { + if (isOmittedExpression(element)) { + continue; + } + + const name = element.name; if (name.kind === SyntaxKind.Identifier && (name).text === predicateVariableName) { error(predicateVariableNode, @@ -14070,7 +14371,7 @@ namespace ts { // Abstract methods cannot have an implementation. // Extra checks are to avoid reporting multiple errors relating to the "abstractness" of the node. - if (node.flags & NodeFlags.Abstract && node.body) { + if (getModifierFlags(node) & ModifierFlags.Abstract && node.body) { error(node, Diagnostics.Method_0_cannot_have_an_implementation_because_it_is_marked_abstract, declarationNameToString(node.name)); } } @@ -14129,7 +14430,7 @@ namespace ts { function isInstancePropertyWithInitializer(n: Node): boolean { return n.kind === SyntaxKind.PropertyDeclaration && - !(n.flags & NodeFlags.Static) && + !(getModifierFlags(n) & ModifierFlags.Static) && !!(n).initializer; } @@ -14138,6 +14439,7 @@ namespace ts { // constructors of derived classes must contain at least one super call somewhere in their function body. const containingClassDecl = node.parent; if (getClassExtendsHeritageClauseElement(containingClassDecl)) { + captureLexicalThis(node.parent, containingClassDecl); const classExtendsNull = classDeclarationExtendsNull(containingClassDecl); const superCall = getSuperCallInConstructor(node); if (superCall) { @@ -14152,7 +14454,7 @@ namespace ts { // or the containing class declares instance member variables with initializers. const superCallShouldBeFirst = forEach((node.parent).members, isInstancePropertyWithInitializer) || - forEach(node.parameters, p => p.flags & NodeFlags.ParameterPropertyModifier); + forEach(node.parameters, p => getModifierFlags(p) & ModifierFlags.ParameterPropertyModifier); // Skip past any prologue directives to find the first statement // to ensure that it was a super call. @@ -14206,10 +14508,10 @@ namespace ts { const otherKind = node.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor; const otherAccessor = getDeclarationOfKind(node.symbol, otherKind); if (otherAccessor) { - if (((node.flags & NodeFlags.AccessibilityModifier) !== (otherAccessor.flags & NodeFlags.AccessibilityModifier))) { + if ((getModifierFlags(node) & ModifierFlags.AccessibilityModifier) !== (getModifierFlags(otherAccessor) & ModifierFlags.AccessibilityModifier)) { error(node.name, Diagnostics.Getter_and_setter_accessors_do_not_agree_in_visibility); } - if (((node.flags & NodeFlags.Abstract) !== (otherAccessor.flags & NodeFlags.Abstract))) { + if (hasModifier(node, ModifierFlags.Abstract) !== hasModifier(otherAccessor, ModifierFlags.Abstract)) { error(node.name, Diagnostics.Accessors_must_both_be_abstract_or_non_abstract); } @@ -14258,7 +14560,7 @@ namespace ts { const constraint = getConstraintOfTypeParameter(typeParameters[i]); if (constraint) { if (!typeArguments) { - typeArguments = map(typeArgumentNodes, getTypeFromTypeNode); + typeArguments = map(typeArgumentNodes, getTypeFromTypeNodeNoAlias); mapper = createTypeMapper(typeParameters, typeArguments); } const typeArgument = typeArguments[i]; @@ -14324,11 +14626,11 @@ namespace ts { } function isPrivateWithinAmbient(node: Node): boolean { - return (node.flags & NodeFlags.Private) && isInAmbientContext(node); + return (getModifierFlags(node) & ModifierFlags.Private) && isInAmbientContext(node); } - function getEffectiveDeclarationFlags(n: Node, flagsToCheck: NodeFlags): NodeFlags { - let flags = getCombinedNodeFlags(n); + function getEffectiveDeclarationFlags(n: Node, flagsToCheck: ModifierFlags): ModifierFlags { + let flags = getCombinedModifierFlags(n); // children of classes (even ambient classes) should not be marked as ambient or export // because those flags have no useful semantics there. @@ -14336,11 +14638,11 @@ namespace ts { n.parent.kind !== SyntaxKind.ClassDeclaration && n.parent.kind !== SyntaxKind.ClassExpression && isInAmbientContext(n)) { - if (!(flags & NodeFlags.Ambient)) { + if (!(flags & ModifierFlags.Ambient)) { // It is nested in an ambient context, which means it is automatically exported - flags |= NodeFlags.Export; + flags |= ModifierFlags.Export; } - flags |= NodeFlags.Ambient; + flags |= ModifierFlags.Ambient; } return flags & flagsToCheck; @@ -14361,7 +14663,7 @@ namespace ts { return implementationSharesContainerWithFirstOverload ? implementation : overloads[0]; } - function checkFlagAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration, flagsToCheck: NodeFlags, someOverloadFlags: NodeFlags, allOverloadFlags: NodeFlags): void { + function checkFlagAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration, flagsToCheck: ModifierFlags, someOverloadFlags: ModifierFlags, allOverloadFlags: ModifierFlags): void { // Error if some overloads have a flag that is not shared by all overloads. To find the // deviations, we XOR someOverloadFlags with allOverloadFlags const someButNotAllOverloadFlags = someOverloadFlags ^ allOverloadFlags; @@ -14370,16 +14672,16 @@ namespace ts { forEach(overloads, o => { const deviation = getEffectiveDeclarationFlags(o, flagsToCheck) ^ canonicalFlags; - if (deviation & NodeFlags.Export) { + if (deviation & ModifierFlags.Export) { error(o.name, Diagnostics.Overload_signatures_must_all_be_exported_or_non_exported); } - else if (deviation & NodeFlags.Ambient) { + else if (deviation & ModifierFlags.Ambient) { error(o.name, Diagnostics.Overload_signatures_must_all_be_ambient_or_non_ambient); } - else if (deviation & (NodeFlags.Private | NodeFlags.Protected)) { + else if (deviation & (ModifierFlags.Private | ModifierFlags.Protected)) { error(o.name || o, Diagnostics.Overload_signatures_must_all_be_public_private_or_protected); } - else if (deviation & NodeFlags.Abstract) { + else if (deviation & ModifierFlags.Abstract) { error(o.name, Diagnostics.Overload_signatures_must_all_be_abstract_or_non_abstract); } }); @@ -14398,8 +14700,8 @@ namespace ts { } } - const flagsToCheck: NodeFlags = NodeFlags.Export | NodeFlags.Ambient | NodeFlags.Private | NodeFlags.Protected | NodeFlags.Abstract; - let someNodeFlags: NodeFlags = 0; + const flagsToCheck: ModifierFlags = ModifierFlags.Export | ModifierFlags.Ambient | ModifierFlags.Private | ModifierFlags.Protected | ModifierFlags.Abstract; + let someNodeFlags: ModifierFlags = ModifierFlags.None; let allNodeFlags = flagsToCheck; let someHaveQuestionToken = false; let allHaveQuestionToken = true; @@ -14434,13 +14736,13 @@ namespace ts { if (node.name && (subsequentNode).name && (node.name).text === ((subsequentNode).name).text) { const reportError = (node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature) && - (node.flags & NodeFlags.Static) !== (subsequentNode.flags & NodeFlags.Static); + (getModifierFlags(node) & ModifierFlags.Static) !== (getModifierFlags(subsequentNode) & ModifierFlags.Static); // we can get here in two cases // 1. mixed static and instance class members // 2. something with the same name was defined before the set of overloads that prevents them from merging // here we'll report error only for the first case since for second we should already report error in binder if (reportError) { - const diagnostic = node.flags & NodeFlags.Static ? Diagnostics.Function_overload_must_be_static : Diagnostics.Function_overload_must_not_be_static; + const diagnostic = getModifierFlags(node) & ModifierFlags.Static ? Diagnostics.Function_overload_must_be_static : Diagnostics.Function_overload_must_not_be_static; error(errorNode, diagnostic); } return; @@ -14458,7 +14760,7 @@ namespace ts { else { // Report different errors regarding non-consecutive blocks of declarations depending on whether // the node in question is abstract. - if (node.flags & NodeFlags.Abstract) { + if (getModifierFlags(node) & ModifierFlags.Abstract) { error(errorNode, Diagnostics.All_declarations_of_an_abstract_method_must_be_consecutive); } else { @@ -14534,7 +14836,7 @@ namespace ts { // Abstract methods can't have an implementation -- in particular, they don't need one. if (lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body && - !(lastSeenNonAmbientDeclaration.flags & NodeFlags.Abstract) && !lastSeenNonAmbientDeclaration.questionToken) { + !(getModifierFlags(lastSeenNonAmbientDeclaration) & ModifierFlags.Abstract) && !lastSeenNonAmbientDeclaration.questionToken) { reportImplementationExpectedError(lastSeenNonAmbientDeclaration); } @@ -14584,10 +14886,10 @@ namespace ts { let defaultExportedDeclarationSpaces = SymbolFlags.None; for (const d of symbol.declarations) { const declarationSpaces = getDeclarationSpaces(d); - const effectiveDeclarationFlags = getEffectiveDeclarationFlags(d, NodeFlags.Export | NodeFlags.Default); + const effectiveDeclarationFlags = getEffectiveDeclarationFlags(d, ModifierFlags.Export | ModifierFlags.Default); - if (effectiveDeclarationFlags & NodeFlags.Export) { - if (effectiveDeclarationFlags & NodeFlags.Default) { + if (effectiveDeclarationFlags & ModifierFlags.Export) { + if (effectiveDeclarationFlags & ModifierFlags.Default) { defaultExportedDeclarationSpaces |= declarationSpaces; } else { @@ -14824,7 +15126,7 @@ namespace ts { * @param returnType The return type of a FunctionLikeDeclaration * @param location The node on which to report the error. */ - function checkCorrectPromiseType(returnType: Type, location: Node) { + function checkCorrectPromiseType(returnType: Type, location: Node, diagnostic: DiagnosticMessage, typeName?: string) { if (returnType === unknownType) { // The return type already had some other error, so we ignore and return // the unknown type. @@ -14843,7 +15145,7 @@ namespace ts { // The promise type was not a valid type reference to the global promise type, so we // report an error and return the unknown type. - error(location, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type); + error(location, diagnostic, typeName); return unknownType; } @@ -14863,7 +15165,7 @@ namespace ts { function checkAsyncFunctionReturnType(node: FunctionLikeDeclaration): Type { if (languageVersion >= ScriptTarget.ES6) { const returnType = getTypeFromTypeNode(node.type); - return checkCorrectPromiseType(returnType, node.type); + return checkCorrectPromiseType(returnType, node.type, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type); } const globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType(); @@ -14909,11 +15211,11 @@ namespace ts { const promiseConstructor = getNodeLinks(node.type).resolvedSymbol; if (!promiseConstructor || !symbolIsValue(promiseConstructor)) { + // try to fall back to global promise type. const typeName = promiseConstructor ? symbolToString(promiseConstructor) : typeToString(promiseType); - error(node, Diagnostics.Type_0_is_not_a_valid_async_function_return_type, typeName); - return unknownType; + return checkCorrectPromiseType(promiseType, node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type, typeName); } // If the Promise constructor, resolved locally, is an alias symbol we should mark it as referenced. @@ -14921,7 +15223,7 @@ namespace ts { // Validate the promise constructor type. const promiseConstructorType = getTypeOfSymbol(promiseConstructor); - if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node, Diagnostics.Type_0_is_not_a_valid_async_function_return_type)) { + if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type)) { return unknownType; } @@ -15242,13 +15544,13 @@ namespace ts { if (node.members) { for (const member of node.members) { if (member.kind === SyntaxKind.MethodDeclaration || member.kind === SyntaxKind.PropertyDeclaration) { - if (!member.symbol.isReferenced && member.flags & NodeFlags.Private) { + if (!member.symbol.isReferenced && getModifierFlags(member) & ModifierFlags.Private) { error(member.name, Diagnostics._0_is_declared_but_never_used, member.symbol.name); } } else if (member.kind === SyntaxKind.Constructor) { for (const parameter of (member).parameters) { - if (!parameter.symbol.isReferenced && parameter.flags & NodeFlags.Private) { + if (!parameter.symbol.isReferenced && getModifierFlags(parameter) & ModifierFlags.Private) { error(parameter.name, Diagnostics.Property_0_is_declared_but_never_used, parameter.symbol.name); } } @@ -15393,6 +15695,11 @@ namespace ts { } function checkCollisionWithRequireExportsInGeneratedCode(node: Node, name: Identifier) { + // No need to check for require or exports for ES6 modules and later + if (modulekind >= ModuleKind.ES6) { + return; + } + if (!needCollisionCheckForIdentifier(node, name, "require") && !needCollisionCheckForIdentifier(node, name, "exports")) { return; } @@ -15474,7 +15781,7 @@ namespace ts { if (localDeclarationSymbol && localDeclarationSymbol !== symbol && localDeclarationSymbol.flags & SymbolFlags.BlockScopedVariable) { - if (getDeclarationFlagsFromSymbol(localDeclarationSymbol) & NodeFlags.BlockScoped) { + if (getDeclarationNodeFlagsFromSymbol(localDeclarationSymbol) & NodeFlags.BlockScoped) { const varDeclList = getAncestor(localDeclarationSymbol.valueDeclaration, SyntaxKind.VariableDeclarationList); const container = varDeclList.parent.kind === SyntaxKind.VariableStatement && varDeclList.parent.parent @@ -15552,7 +15859,7 @@ namespace ts { // computed property names/initializers in instance property declaration of class like entities // are executed in constructor and thus deferred if (current.parent.kind === SyntaxKind.PropertyDeclaration && - !(current.parent.flags & NodeFlags.Static) && + !(hasModifier(current.parent, ModifierFlags.Static)) && isClassLike(current.parent.parent)) { return; } @@ -15667,14 +15974,14 @@ namespace ts { return false; } - const interestingFlags = NodeFlags.Private | - NodeFlags.Protected | - NodeFlags.Async | - NodeFlags.Abstract | - NodeFlags.Readonly | - NodeFlags.Static; + const interestingFlags = ModifierFlags.Private | + ModifierFlags.Protected | + ModifierFlags.Async | + ModifierFlags.Abstract | + ModifierFlags.Readonly | + ModifierFlags.Static; - return (left.flags & interestingFlags) === (right.flags & interestingFlags); + return (getModifierFlags(left) & interestingFlags) === (getModifierFlags(right) & interestingFlags); } function checkVariableDeclaration(node: VariableDeclaration) { @@ -16080,7 +16387,7 @@ namespace ts { // Now that we've removed all the StringLike types, if no constituents remain, then the entire // arrayOrStringType was a string. - if (arrayType === neverType) { + if (arrayType.flags & TypeFlags.Never) { return stringType; } } @@ -16141,7 +16448,7 @@ namespace ts { if (func) { const signature = getSignatureFromDeclaration(func); const returnType = getReturnTypeOfSignature(signature); - if (strictNullChecks || node.expression || returnType === neverType) { + if (strictNullChecks || node.expression || returnType.flags & TypeFlags.Never) { const exprType = node.expression ? checkExpressionCached(node.expression) : undefinedType; if (func.asteriskToken) { @@ -16194,7 +16501,13 @@ namespace ts { } checkExpression(node.expression); - error(node.expression, Diagnostics.All_symbols_within_a_with_block_will_be_resolved_to_any); + + const sourceFile = getSourceFileOfNode(node); + if (!hasParseDiagnostics(sourceFile)) { + const start = getSpanOfTokenAtPosition(sourceFile, node.pos).start; + const end = node.statement.pos; + grammarErrorAtPos(sourceFile, start, end - start, Diagnostics.The_with_statement_is_not_supported_All_symbols_in_a_with_block_will_have_type_any); + } } function checkSwitchStatement(node: SwitchStatement) { @@ -16330,7 +16643,7 @@ namespace ts { // Only process instance properties with computed names here. // Static properties cannot be in conflict with indexers, // and properties with literal names were already checked. - if (!(member.flags & NodeFlags.Static) && hasDynamicName(member)) { + if (!(getModifierFlags(member) & ModifierFlags.Static) && hasDynamicName(member)) { const propType = getTypeOfSymbol(member.symbol); checkIndexConstraintForProperty(member.symbol, propType, type, declaredStringIndexer, stringIndexType, IndexKind.String); checkIndexConstraintForProperty(member.symbol, propType, type, declaredNumberIndexer, numberIndexType, IndexKind.Number); @@ -16460,7 +16773,7 @@ namespace ts { } function checkClassDeclaration(node: ClassDeclaration) { - if (!node.name && !(node.flags & NodeFlags.Default)) { + if (!node.name && !(getModifierFlags(node) & ModifierFlags.Default)) { grammarErrorOnFirstToken(node, Diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name); } checkClassLikeDeclaration(node); @@ -16559,7 +16872,7 @@ namespace ts { const signatures = getSignaturesOfType(type, SignatureKind.Construct); if (signatures.length) { const declaration = signatures[0].declaration; - if (declaration && declaration.flags & NodeFlags.Private) { + if (declaration && getModifierFlags(declaration) & ModifierFlags.Private) { const typeClassDeclaration = getClassLikeDeclarationOfSymbol(type.symbol); if (!isNodeWithinClass(node, typeClassDeclaration)) { error(node, Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, (node.expression).text); @@ -16604,7 +16917,7 @@ namespace ts { } const derived = getTargetSymbol(getPropertyOfObjectType(type, base.name)); - const baseDeclarationFlags = getDeclarationFlagsFromSymbol(base); + const baseDeclarationFlags = getDeclarationModifierFlagsFromSymbol(base); Debug.assert(!!derived, "derived should point to something, even if it is the base class' declaration."); @@ -16620,7 +16933,7 @@ namespace ts { // It is an error to inherit an abstract member without implementing it or being declared abstract. // If there is no declaration for the derived class (as in the case of class expressions), // then the class cannot be declared abstract. - if (baseDeclarationFlags & NodeFlags.Abstract && (!derivedClassDecl || !(derivedClassDecl.flags & NodeFlags.Abstract))) { + if (baseDeclarationFlags & ModifierFlags.Abstract && (!derivedClassDecl || !(getModifierFlags(derivedClassDecl) & ModifierFlags.Abstract))) { if (derivedClassDecl.kind === SyntaxKind.ClassExpression) { error(derivedClassDecl, Diagnostics.Non_abstract_class_expression_does_not_implement_inherited_abstract_member_0_from_class_1, symbolToString(baseProperty), typeToString(baseType)); @@ -16633,13 +16946,13 @@ namespace ts { } else { // derived overrides base. - const derivedDeclarationFlags = getDeclarationFlagsFromSymbol(derived); - if ((baseDeclarationFlags & NodeFlags.Private) || (derivedDeclarationFlags & NodeFlags.Private)) { + const derivedDeclarationFlags = getDeclarationModifierFlagsFromSymbol(derived); + if ((baseDeclarationFlags & ModifierFlags.Private) || (derivedDeclarationFlags & ModifierFlags.Private)) { // either base or derived property is private - not override, skip it continue; } - if ((baseDeclarationFlags & NodeFlags.Static) !== (derivedDeclarationFlags & NodeFlags.Static)) { + if ((baseDeclarationFlags & ModifierFlags.Static) !== (derivedDeclarationFlags & ModifierFlags.Static)) { // value of 'static' is not the same for properties - not override, skip it continue; } @@ -16810,7 +17123,7 @@ namespace ts { } else { const text = getTextOfPropertyName(member.name); - if (isNumericLiteralName(text)) { + if (isNumericLiteralName(text) && !isInfinityOrNaNString(text)) { error(member.name, Diagnostics.An_enum_member_cannot_have_a_numeric_name); } } @@ -16911,7 +17224,7 @@ namespace ts { } return undefined; case SyntaxKind.NumericLiteral: - return +(e).text; + return +(e).text; case SyntaxKind.ParenthesizedExpression: return evalConstant((e).expression); case SyntaxKind.Identifier: @@ -17312,7 +17625,7 @@ namespace ts { // If we hit an import declaration in an illegal context, just bail out to avoid cascading errors. return; } - if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && (node.flags & NodeFlags.Modifier)) { + if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && getModifierFlags(node) !== 0) { grammarErrorOnFirstToken(node, Diagnostics.An_import_declaration_cannot_have_modifiers); } if (checkExternalImportOrExportDeclaration(node)) { @@ -17342,7 +17655,7 @@ namespace ts { checkGrammarDecorators(node) || checkGrammarModifiers(node); if (isInternalModuleImportEqualsDeclaration(node) || checkExternalImportOrExportDeclaration(node)) { checkImportBinding(node); - if (node.flags & NodeFlags.Export) { + if (getModifierFlags(node) & ModifierFlags.Export) { markExportAsReferenced(node); } if (isInternalModuleImportEqualsDeclaration(node)) { @@ -17375,7 +17688,7 @@ namespace ts { return; } - if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && (node.flags & NodeFlags.Modifier)) { + if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && getModifierFlags(node) !== 0) { grammarErrorOnFirstToken(node, Diagnostics.An_export_declaration_cannot_have_modifiers); } @@ -17401,9 +17714,11 @@ namespace ts { } function checkGrammarModuleElementContext(node: Statement, errorMessage: DiagnosticMessage): boolean { - if (node.parent.kind !== SyntaxKind.SourceFile && node.parent.kind !== SyntaxKind.ModuleBlock && node.parent.kind !== SyntaxKind.ModuleDeclaration) { - return grammarErrorOnFirstToken(node, errorMessage); + const isInAppropriateContext = node.parent.kind === SyntaxKind.SourceFile || node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.ModuleDeclaration; + if (!isInAppropriateContext) { + grammarErrorOnFirstToken(node, errorMessage); } + return !isInAppropriateContext; } function checkExportSpecifier(node: ExportSpecifier) { @@ -17434,7 +17749,7 @@ namespace ts { return; } // Grammar checking - if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && (node.flags & NodeFlags.Modifier)) { + if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && getModifierFlags(node) !== 0) { grammarErrorOnFirstToken(node, Diagnostics.An_export_assignment_cannot_have_modifiers); } if (node.expression.kind === SyntaxKind.Identifier) { @@ -17444,7 +17759,7 @@ namespace ts { checkExpressionCached(node.expression); } - checkExternalModuleExports(container); + checkExternalModuleExports(container); if (node.isExportEquals && !isInAmbientContext(node)) { if (modulekind === ModuleKind.ES6) { @@ -17779,7 +18094,7 @@ namespace ts { function getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[] { const symbols = createMap(); - let memberFlags: NodeFlags = 0; + let memberFlags: ModifierFlags = ModifierFlags.None; if (isInsideWithStatementBody(location)) { // We cannot answer semantic questions within a with block, do not proceed any further @@ -17820,7 +18135,7 @@ namespace ts { // add the type parameters into the symbol table // (type parameters of classDeclaration/classExpression and interface are in member property of the symbol. // Note: that the memberFlags come from previous iteration. - if (!(memberFlags & NodeFlags.Static)) { + if (!(memberFlags & ModifierFlags.Static)) { copySymbols(getSymbolOfNode(location).members, meaning & SymbolFlags.Type); } break; @@ -17836,7 +18151,7 @@ namespace ts { copySymbol(argumentsSymbol, meaning); } - memberFlags = location.flags; + memberFlags = getModifierFlags(location); location = location.parent; } @@ -17998,7 +18313,7 @@ namespace ts { meaning |= SymbolFlags.Alias; return resolveEntityName(entityName, meaning); } - else if (isExpression(entityName)) { + else if (isPartOfExpression(entityName)) { if (nodeIsMissing(entityName)) { // Missing entity name. return undefined; @@ -18092,7 +18407,7 @@ namespace ts { // fallthrough case SyntaxKind.SuperKeyword: - const type = isExpression(node) ? checkExpression(node) : getTypeFromTypeNode(node); + const type = isPartOfExpression(node) ? checkExpression(node) : getTypeFromTypeNode(node); return type.symbol; case SyntaxKind.ThisType: @@ -18123,7 +18438,7 @@ namespace ts { if (objectType === unknownType) return undefined; const apparentType = getApparentType(objectType); if (apparentType === unknownType) return undefined; - return getPropertyOfType(apparentType, (node).text); + return getPropertyOfType(apparentType, (node).text); } break; } @@ -18153,11 +18468,11 @@ namespace ts { return unknownType; } - if (isTypeNode(node)) { + if (isPartOfTypeNode(node)) { return getTypeFromTypeNode(node); } - if (isExpression(node)) { + if (isPartOfExpression(node)) { return getTypeOfExpression(node); } @@ -18227,7 +18542,7 @@ namespace ts { // for ({ skills: { primary, secondary } } = multiRobot, i = 0; i < 1; i++) { if (expr.parent.kind === SyntaxKind.PropertyAssignment) { const typeOfParentObjectLiteral = getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(expr.parent.parent); - return checkObjectLiteralDestructuringPropertyAssignment(typeOfParentObjectLiteral || unknownType, expr.parent); + return checkObjectLiteralDestructuringPropertyAssignment(typeOfParentObjectLiteral || unknownType, expr.parent); } // Array literal assignment - array destructuring pattern Debug.assert(expr.parent.kind === SyntaxKind.ArrayLiteralExpression); @@ -18254,7 +18569,7 @@ namespace ts { if (isRightSideOfQualifiedNameOrPropertyAccess(expr)) { expr = expr.parent; } - return checkExpression(expr); + return getRegularTypeOfLiteralType(checkExpression(expr)); } /** @@ -18263,7 +18578,7 @@ namespace ts { */ function getParentTypeOfClassElement(node: ClassElement) { const classSymbol = getSymbolOfNode(node.parent); - return node.flags & NodeFlags.Static + return getModifierFlags(node) & ModifierFlags.Static ? getTypeOfSymbol(classSymbol) : getDeclaredTypeOfSymbol(classSymbol); } @@ -18311,13 +18626,20 @@ namespace ts { // Emitter support function isArgumentsLocalBinding(node: Identifier): boolean { - return getReferencedValueSymbol(node) === argumentsSymbol; + if (!isGeneratedIdentifier(node)) { + node = getParseTreeNode(node, isIdentifier); + if (node) { + return getReferencedValueSymbol(node) === argumentsSymbol; + } + } + + return false; } function moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean { let moduleSymbol = resolveExternalModuleName(moduleReferenceExpression.parent, moduleReferenceExpression); - if (!moduleSymbol) { - // module not found - be conservative + if (!moduleSymbol || isShorthandAmbientModuleSymbol(moduleSymbol)) { + // If the module is not found or is shorthand, assume that it may export a value. return true; } @@ -18343,32 +18665,45 @@ namespace ts { } } + function isNameOfModuleOrEnumDeclaration(node: Identifier) { + const parent = node.parent; + return isModuleOrEnumDeclaration(parent) && node === parent.name; + } + // When resolved as an expression identifier, if the given node references an exported entity, return the declaration // node of the exported entity's container. Otherwise, return undefined. - function getReferencedExportContainer(node: Identifier): SourceFile | ModuleDeclaration | EnumDeclaration { - let symbol = getReferencedValueSymbol(node); - if (symbol) { - if (symbol.flags & SymbolFlags.ExportValue) { - // If we reference an exported entity within the same module declaration, then whether - // we prefix depends on the kind of entity. SymbolFlags.ExportHasLocal encompasses all the - // kinds that we do NOT prefix. - const exportSymbol = getMergedSymbol(symbol.exportSymbol); - if (exportSymbol.flags & SymbolFlags.ExportHasLocal) { - return undefined; - } - symbol = exportSymbol; - } - const parentSymbol = getParentOfSymbol(symbol); - if (parentSymbol) { - if (parentSymbol.flags & SymbolFlags.ValueModule && parentSymbol.valueDeclaration.kind === SyntaxKind.SourceFile) { - // If `node` accesses an export and that export isn't in the same file, then symbol is a namespace export, so return undefined. - if (parentSymbol.valueDeclaration === getSourceFileOfNode(node)) { - return parentSymbol.valueDeclaration; + function getReferencedExportContainer(node: Identifier, prefixLocals?: boolean): SourceFile | ModuleDeclaration | EnumDeclaration | undefined { + node = getParseTreeNode(node, isIdentifier); + if (node) { + // When resolving the export container for the name of a module or enum + // declaration, we need to start resolution at the declaration's container. + // Otherwise, we could incorrectly resolve the export container as the + // declaration if it contains an exported member with the same name. + let symbol = getReferencedValueSymbol(node, /*startInDeclarationContainer*/ isNameOfModuleOrEnumDeclaration(node)); + if (symbol) { + if (symbol.flags & SymbolFlags.ExportValue) { + // If we reference an exported entity within the same module declaration, then whether + // we prefix depends on the kind of entity. SymbolFlags.ExportHasLocal encompasses all the + // kinds that we do NOT prefix. + const exportSymbol = getMergedSymbol(symbol.exportSymbol); + if (!prefixLocals && exportSymbol.flags & SymbolFlags.ExportHasLocal) { + return undefined; } + symbol = exportSymbol; } - for (let n = node.parent; n; n = n.parent) { - if ((n.kind === SyntaxKind.ModuleDeclaration || n.kind === SyntaxKind.EnumDeclaration) && getSymbolOfNode(n) === parentSymbol) { - return n; + const parentSymbol = getParentOfSymbol(symbol); + if (parentSymbol) { + if (parentSymbol.flags & SymbolFlags.ValueModule && parentSymbol.valueDeclaration.kind === SyntaxKind.SourceFile) { + const symbolFile = parentSymbol.valueDeclaration; + const referenceFile = getSourceFileOfNode(node); + // If `node` accesses an export and that export isn't in the same file, then symbol is a namespace export, so return undefined. + const symbolIsUmdExport = symbolFile !== referenceFile; + return symbolIsUmdExport ? undefined : symbolFile; + } + for (let n = node.parent; n; n = n.parent) { + if (isModuleOrEnumDeclaration(n) && getSymbolOfNode(n) === parentSymbol) { + return n; + } } } } @@ -18378,8 +18713,15 @@ namespace ts { // When resolved as an expression identifier, if the given node references an import, return the declaration of // that import. Otherwise, return undefined. function getReferencedImportDeclaration(node: Identifier): Declaration { - const symbol = getReferencedValueSymbol(node); - return symbol && symbol.flags & SymbolFlags.Alias ? getDeclarationOfAliasSymbol(symbol) : undefined; + node = getParseTreeNode(node, isIdentifier); + if (node) { + const symbol = getReferencedValueSymbol(node); + if (symbol && symbol.flags & SymbolFlags.Alias) { + return getDeclarationOfAliasSymbol(symbol); + } + } + + return undefined; } function isSymbolOfDeclarationWithCollidingName(symbol: Symbol): boolean { @@ -18429,35 +18771,62 @@ namespace ts { // a name that either hides an existing name or might hide it when compiled downlevel, // return the declaration of that entity. Otherwise, return undefined. function getReferencedDeclarationWithCollidingName(node: Identifier): Declaration { - const symbol = getReferencedValueSymbol(node); - return symbol && isSymbolOfDeclarationWithCollidingName(symbol) ? symbol.valueDeclaration : undefined; + if (!isGeneratedIdentifier(node)) { + node = getParseTreeNode(node, isIdentifier); + if (node) { + const symbol = getReferencedValueSymbol(node); + if (symbol && isSymbolOfDeclarationWithCollidingName(symbol)) { + return symbol.valueDeclaration; + } + } + } + + return undefined; } // Return true if the given node is a declaration of a nested block scoped entity with a name that either hides an // existing name or might hide a name when compiled downlevel function isDeclarationWithCollidingName(node: Declaration): boolean { - return isSymbolOfDeclarationWithCollidingName(getSymbolOfNode(node)); + node = getParseTreeNode(node, isDeclaration); + if (node) { + const symbol = getSymbolOfNode(node); + if (symbol) { + return isSymbolOfDeclarationWithCollidingName(symbol); + } + } + + return false; } function isValueAliasDeclaration(node: Node): boolean { + node = getParseTreeNode(node); + if (node === undefined) { + // A synthesized node comes from an emit transformation and is always a value. + return true; + } + switch (node.kind) { case SyntaxKind.ImportEqualsDeclaration: case SyntaxKind.ImportClause: case SyntaxKind.NamespaceImport: case SyntaxKind.ImportSpecifier: case SyntaxKind.ExportSpecifier: - return isAliasResolvedToValue(getSymbolOfNode(node)); + return isAliasResolvedToValue(getSymbolOfNode(node) || unknownSymbol); case SyntaxKind.ExportDeclaration: const exportClause = (node).exportClause; return exportClause && forEach(exportClause.elements, isValueAliasDeclaration); case SyntaxKind.ExportAssignment: - return (node).expression && (node).expression.kind === SyntaxKind.Identifier ? isAliasResolvedToValue(getSymbolOfNode(node)) : true; + return (node).expression + && (node).expression.kind === SyntaxKind.Identifier + ? isAliasResolvedToValue(getSymbolOfNode(node) || unknownSymbol) + : true; } return false; } function isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean { - if (node.parent.kind !== SyntaxKind.SourceFile || !isInternalModuleImportEqualsDeclaration(node)) { + node = getParseTreeNode(node, isImportEqualsDeclaration); + if (node === undefined || node.parent.kind !== SyntaxKind.SourceFile || !isInternalModuleImportEqualsDeclaration(node)) { // parent is not source file or it is not reference to internal module return false; } @@ -18482,9 +18851,15 @@ namespace ts { } function isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean { + node = getParseTreeNode(node); + // Purely synthesized nodes are always emitted. + if (node === undefined) { + return true; + } + if (isAliasSymbolDeclaration(node)) { const symbol = getSymbolOfNode(node); - if (getSymbolLinks(symbol).referenced) { + if (symbol && getSymbolLinks(symbol).referenced) { return true; } } @@ -18517,7 +18892,8 @@ namespace ts { } function getNodeCheckFlags(node: Node): NodeCheckFlags { - return getNodeLinks(node).flags; + node = getParseTreeNode(node); + return node ? getNodeLinks(node).flags : undefined; } function getEnumMemberValue(node: EnumMember): number { @@ -18545,16 +18921,21 @@ namespace ts { return type.flags & TypeFlags.ObjectType && getSignaturesOfType(type, SignatureKind.Call).length > 0; } - function getTypeReferenceSerializationKind(typeName: EntityName): TypeReferenceSerializationKind { + function getTypeReferenceSerializationKind(typeName: EntityName, location?: Node): TypeReferenceSerializationKind { // Resolve the symbol as a value to ensure the type can be reached at runtime during emit. - const valueSymbol = resolveEntityName(typeName, SymbolFlags.Value, /*ignoreErrors*/ true); + const valueSymbol = resolveEntityName(typeName, SymbolFlags.Value, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, location); + const globalPromiseSymbol = tryGetGlobalPromiseConstructorSymbol(); + if (globalPromiseSymbol && valueSymbol === globalPromiseSymbol) { + return TypeReferenceSerializationKind.Promise; + } + const constructorType = valueSymbol ? getTypeOfSymbol(valueSymbol) : undefined; if (constructorType && isConstructorType(constructorType)) { return TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue; } // Resolve the symbol as a type so that we can provide a more useful hint for the type serializer. - const typeSymbol = resolveEntityName(typeName, SymbolFlags.Type, /*ignoreErrors*/ true); + const typeSymbol = resolveEntityName(typeName, SymbolFlags.Type, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, location); // We might not be able to resolve type symbol so use unknown type in that case (eg error case) if (!typeSymbol) { return TypeReferenceSerializationKind.ObjectType; @@ -18566,8 +18947,8 @@ namespace ts { else if (type.flags & TypeFlags.Any) { return TypeReferenceSerializationKind.ObjectType; } - else if (isTypeOfKind(type, TypeFlags.Void)) { - return TypeReferenceSerializationKind.VoidType; + else if (isTypeOfKind(type, TypeFlags.Void | TypeFlags.Nullable | TypeFlags.Never)) { + return TypeReferenceSerializationKind.VoidNullableOrNeverType; } else if (isTypeOfKind(type, TypeFlags.BooleanLike)) { return TypeReferenceSerializationKind.BooleanType; @@ -18599,7 +18980,7 @@ namespace ts { // Get type of the symbol if this is the valid symbol otherwise get type at location const symbol = getSymbolOfNode(declaration); const type = symbol && !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.Signature)) - ? getTypeOfSymbol(symbol) + ? getWidenedLiteralType(getTypeOfSymbol(symbol)) : unknownType; getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags); @@ -18626,16 +19007,50 @@ namespace ts { return !!globals[name]; } - function getReferencedValueSymbol(reference: Identifier): Symbol { - return getNodeLinks(reference).resolvedSymbol || - resolveName(reference, reference.text, SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias, - /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined); + function getReferencedValueSymbol(reference: Identifier, startInDeclarationContainer?: boolean): Symbol { + const resolvedSymbol = getNodeLinks(reference).resolvedSymbol; + if (resolvedSymbol) { + return resolvedSymbol; + } + + let location: Node = reference; + if (startInDeclarationContainer) { + // When resolving the name of a declaration as a value, we need to start resolution + // at a point outside of the declaration. + const parent = reference.parent; + if (isDeclaration(parent) && reference === parent.name) { + location = getDeclarationContainer(parent); + } + } + + return resolveName(location, reference.text, SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias, /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined); } function getReferencedValueDeclaration(reference: Identifier): Declaration { - Debug.assert(!nodeIsSynthesized(reference)); - const symbol = getReferencedValueSymbol(reference); - return symbol && getExportSymbolOfValueSymbolIfExported(symbol).valueDeclaration; + if (!isGeneratedIdentifier(reference)) { + reference = getParseTreeNode(reference, isIdentifier); + if (reference) { + const symbol = getReferencedValueSymbol(reference); + if (symbol) { + return getExportSymbolOfValueSymbolIfExported(symbol).valueDeclaration; + } + } + } + + return undefined; + } + + function isLiteralConstDeclaration(node: VariableDeclaration): boolean { + if (isConst(node)) { + const type = getTypeOfSymbol(getSymbolOfNode(node)); + return !!(type.flags & TypeFlags.StringOrNumberLiteral && type.flags & TypeFlags.FreshLiteral); + } + return false; + } + + function writeLiteralConstValue(node: VariableDeclaration, writer: SymbolWriter) { + const type = getTypeOfSymbol(getSymbolOfNode(node)); + writer.writeStringLiteral(literalTypeToString(type)); } function createResolver(): EmitResolver { @@ -18682,7 +19097,9 @@ namespace ts { isArgumentsLocalBinding, getExternalModuleFileFromDeclaration, getTypeReferenceDirectivesForEntityName, - getTypeReferenceDirectivesForSymbol + getTypeReferenceDirectivesForSymbol, + isLiteralConstDeclaration, + writeLiteralConstValue }; // defined here to avoid outer scope pollution @@ -18771,20 +19188,21 @@ namespace ts { function initializeTypeChecker() { // Bind all source files and propagate errors - forEach(host.getSourceFiles(), file => { + for (const file of host.getSourceFiles()) { bindSourceFile(file, compilerOptions); - }); + } - let augmentations: LiteralExpression[][]; // Initialize global symbol table - forEach(host.getSourceFiles(), file => { + let augmentations: LiteralExpression[][]; + let requestedExternalEmitHelpers: NodeFlags = 0; + let firstFileRequestingExternalHelpers: SourceFile; + for (const file of host.getSourceFiles()) { if (!isExternalOrCommonJsModule(file)) { mergeSymbolTable(globals, file.locals); } if (file.patternAmbientModules && file.patternAmbientModules.length) { patternAmbientModules = concatenate(patternAmbientModules, file.patternAmbientModules); } - if (file.moduleAugmentations.length) { (augmentations || (augmentations = [])).push(file.moduleAugmentations); } @@ -18797,7 +19215,16 @@ namespace ts { } } } - }); + if ((compilerOptions.isolatedModules || isExternalModule(file)) && !file.isDeclarationFile) { + const fileRequestedExternalEmitHelpers = file.flags & NodeFlags.EmitHelperFlags; + if (fileRequestedExternalEmitHelpers) { + requestedExternalEmitHelpers |= fileRequestedExternalEmitHelpers; + if (firstFileRequestingExternalHelpers === undefined) { + firstFileRequestingExternalHelpers = file; + } + } + } + } if (augmentations) { // merge module augmentations. @@ -18837,6 +19264,7 @@ namespace ts { getGlobalPromiseLikeType = memoize(() => getGlobalType("PromiseLike", /*arity*/ 1)); getInstantiatedGlobalPromiseLikeType = memoize(createInstantiatedPromiseLikeType); getGlobalPromiseConstructorSymbol = memoize(() => getGlobalValueSymbol("Promise")); + tryGetGlobalPromiseConstructorSymbol = memoize(() => getGlobalSymbol("Promise", SymbolFlags.Value, /*diagnostic*/ undefined) && getGlobalPromiseConstructorSymbol()); getGlobalPromiseConstructorLikeType = memoize(() => getGlobalType("PromiseConstructorLike")); getGlobalThenableType = memoize(createThenableType); @@ -18860,6 +19288,51 @@ namespace ts { const symbol = getGlobalSymbol("ReadonlyArray", SymbolFlags.Type, /*diagnostic*/ undefined); globalReadonlyArrayType = symbol && getTypeOfGlobalSymbol(symbol, /*arity*/ 1); anyReadonlyArrayType = globalReadonlyArrayType ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType; + + // If we have specified that we are importing helpers, we should report global + // errors if we cannot resolve the helpers external module, or if it does not have + // the necessary helpers exported. + if (compilerOptions.importHelpers && firstFileRequestingExternalHelpers) { + // Find the first reference to the helpers module. + const helpersModule = resolveExternalModule( + firstFileRequestingExternalHelpers, + externalHelpersModuleNameText, + Diagnostics.Cannot_find_module_0, + /*errorNode*/ undefined); + + // If we found the module, report errors if it does not have the necessary exports. + if (helpersModule) { + const exports = helpersModule.exports; + if (requestedExternalEmitHelpers & NodeFlags.HasClassExtends && languageVersion < ScriptTarget.ES6) { + verifyHelperSymbol(exports, "__extends", SymbolFlags.Value); + } + if (requestedExternalEmitHelpers & NodeFlags.HasJsxSpreadAttributes && compilerOptions.jsx !== JsxEmit.Preserve) { + verifyHelperSymbol(exports, "__assign", SymbolFlags.Value); + } + if (requestedExternalEmitHelpers & NodeFlags.HasDecorators) { + verifyHelperSymbol(exports, "__decorate", SymbolFlags.Value); + if (compilerOptions.emitDecoratorMetadata) { + verifyHelperSymbol(exports, "__metadata", SymbolFlags.Value); + } + } + if (requestedExternalEmitHelpers & NodeFlags.HasParamDecorators) { + verifyHelperSymbol(exports, "__param", SymbolFlags.Value); + } + if (requestedExternalEmitHelpers & NodeFlags.HasAsyncFunctions) { + verifyHelperSymbol(exports, "__awaiter", SymbolFlags.Value); + if (languageVersion < ScriptTarget.ES6) { + verifyHelperSymbol(exports, "__generator", SymbolFlags.Value); + } + } + } + } + } + + function verifyHelperSymbol(symbols: SymbolTable, name: string, meaning: SymbolFlags) { + const symbol = getSymbol(symbols, escapeIdentifier(name), meaning); + if (!symbol) { + error(/*location*/ undefined, Diagnostics.Module_0_has_no_exported_member_1, externalHelpersModuleNameText, name); + } } function createInstantiatedPromiseLikeType(): ObjectType { @@ -18913,7 +19386,7 @@ namespace ts { } let lastStatic: Node, lastPrivate: Node, lastProtected: Node, lastDeclare: Node, lastAsync: Node, lastReadonly: Node; - let flags = 0; + let flags = ModifierFlags.None; for (const modifier of node.modifiers) { if (modifier.kind !== SyntaxKind.ReadonlyKeyword) { if (node.kind === SyntaxKind.PropertySignature || node.kind === SyntaxKind.MethodSignature) { @@ -18941,22 +19414,22 @@ namespace ts { lastPrivate = modifier; } - if (flags & NodeFlags.AccessibilityModifier) { + if (flags & ModifierFlags.AccessibilityModifier) { return grammarErrorOnNode(modifier, Diagnostics.Accessibility_modifier_already_seen); } - else if (flags & NodeFlags.Static) { + else if (flags & ModifierFlags.Static) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "static"); } - else if (flags & NodeFlags.Readonly) { + else if (flags & ModifierFlags.Readonly) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "readonly"); } - else if (flags & NodeFlags.Async) { + else if (flags & ModifierFlags.Async) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "async"); } else if (node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_module_or_namespace_element, text); } - else if (flags & NodeFlags.Abstract) { + else if (flags & ModifierFlags.Abstract) { if (modifier.kind === SyntaxKind.PrivateKeyword) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, text, "abstract"); } @@ -18968,13 +19441,13 @@ namespace ts { break; case SyntaxKind.StaticKeyword: - if (flags & NodeFlags.Static) { + if (flags & ModifierFlags.Static) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "static"); } - else if (flags & NodeFlags.Readonly) { + else if (flags & ModifierFlags.Readonly) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "static", "readonly"); } - else if (flags & NodeFlags.Async) { + else if (flags & ModifierFlags.Async) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "static", "async"); } else if (node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) { @@ -18983,36 +19456,36 @@ namespace ts { else if (node.kind === SyntaxKind.Parameter) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "static"); } - else if (flags & NodeFlags.Abstract) { + else if (flags & ModifierFlags.Abstract) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "static", "abstract"); } - flags |= NodeFlags.Static; + flags |= ModifierFlags.Static; lastStatic = modifier; break; case SyntaxKind.ReadonlyKeyword: - if (flags & NodeFlags.Readonly) { + if (flags & ModifierFlags.Readonly) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "readonly"); } else if (node.kind !== SyntaxKind.PropertyDeclaration && node.kind !== SyntaxKind.PropertySignature && node.kind !== SyntaxKind.IndexSignature && node.kind !== SyntaxKind.Parameter) { // If node.kind === SyntaxKind.Parameter, checkParameter report an error if it's not a parameter property. return grammarErrorOnNode(modifier, Diagnostics.readonly_modifier_can_only_appear_on_a_property_declaration_or_index_signature); } - flags |= NodeFlags.Readonly; + flags |= ModifierFlags.Readonly; lastReadonly = modifier; break; case SyntaxKind.ExportKeyword: - if (flags & NodeFlags.Export) { + if (flags & ModifierFlags.Export) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "export"); } - else if (flags & NodeFlags.Ambient) { + else if (flags & ModifierFlags.Ambient) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "export", "declare"); } - else if (flags & NodeFlags.Abstract) { + else if (flags & ModifierFlags.Abstract) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "export", "abstract"); } - else if (flags & NodeFlags.Async) { + else if (flags & ModifierFlags.Async) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "export", "async"); } else if (node.parent.kind === SyntaxKind.ClassDeclaration) { @@ -19021,14 +19494,14 @@ namespace ts { else if (node.kind === SyntaxKind.Parameter) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "export"); } - flags |= NodeFlags.Export; + flags |= ModifierFlags.Export; break; case SyntaxKind.DeclareKeyword: - if (flags & NodeFlags.Ambient) { + if (flags & ModifierFlags.Ambient) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "declare"); } - else if (flags & NodeFlags.Async) { + else if (flags & ModifierFlags.Async) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "async"); } else if (node.parent.kind === SyntaxKind.ClassDeclaration) { @@ -19040,12 +19513,12 @@ namespace ts { else if (isInAmbientContext(node.parent) && node.parent.kind === SyntaxKind.ModuleBlock) { return grammarErrorOnNode(modifier, Diagnostics.A_declare_modifier_cannot_be_used_in_an_already_ambient_context); } - flags |= NodeFlags.Ambient; + flags |= ModifierFlags.Ambient; lastDeclare = modifier; break; case SyntaxKind.AbstractKeyword: - if (flags & NodeFlags.Abstract) { + if (flags & ModifierFlags.Abstract) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "abstract"); } if (node.kind !== SyntaxKind.ClassDeclaration) { @@ -19055,61 +19528,61 @@ namespace ts { node.kind !== SyntaxKind.SetAccessor) { return grammarErrorOnNode(modifier, Diagnostics.abstract_modifier_can_only_appear_on_a_class_method_or_property_declaration); } - if (!(node.parent.kind === SyntaxKind.ClassDeclaration && node.parent.flags & NodeFlags.Abstract)) { + if (!(node.parent.kind === SyntaxKind.ClassDeclaration && getModifierFlags(node.parent) & ModifierFlags.Abstract)) { return grammarErrorOnNode(modifier, Diagnostics.Abstract_methods_can_only_appear_within_an_abstract_class); } - if (flags & NodeFlags.Static) { + if (flags & ModifierFlags.Static) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "static", "abstract"); } - if (flags & NodeFlags.Private) { + if (flags & ModifierFlags.Private) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "private", "abstract"); } } - flags |= NodeFlags.Abstract; + flags |= ModifierFlags.Abstract; break; case SyntaxKind.AsyncKeyword: - if (flags & NodeFlags.Async) { + if (flags & ModifierFlags.Async) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "async"); } - else if (flags & NodeFlags.Ambient || isInAmbientContext(node.parent)) { + else if (flags & ModifierFlags.Ambient || isInAmbientContext(node.parent)) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "async"); } else if (node.kind === SyntaxKind.Parameter) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "async"); } - flags |= NodeFlags.Async; + flags |= ModifierFlags.Async; lastAsync = modifier; break; } } if (node.kind === SyntaxKind.Constructor) { - if (flags & NodeFlags.Static) { + if (flags & ModifierFlags.Static) { return grammarErrorOnNode(lastStatic, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "static"); } - if (flags & NodeFlags.Abstract) { + if (flags & ModifierFlags.Abstract) { return grammarErrorOnNode(lastStatic, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "abstract"); } - else if (flags & NodeFlags.Async) { + else if (flags & ModifierFlags.Async) { return grammarErrorOnNode(lastAsync, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "async"); } - else if (flags & NodeFlags.Readonly) { + else if (flags & ModifierFlags.Readonly) { return grammarErrorOnNode(lastReadonly, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "readonly"); } return; } - else if ((node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) && flags & NodeFlags.Ambient) { + else if ((node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) && flags & ModifierFlags.Ambient) { return grammarErrorOnNode(lastDeclare, Diagnostics.A_0_modifier_cannot_be_used_with_an_import_declaration, "declare"); } - else if (node.kind === SyntaxKind.Parameter && (flags & NodeFlags.ParameterPropertyModifier) && isBindingPattern((node).name)) { + else if (node.kind === SyntaxKind.Parameter && (flags & ModifierFlags.ParameterPropertyModifier) && isBindingPattern((node).name)) { return grammarErrorOnNode(node, Diagnostics.A_parameter_property_may_not_be_declared_using_a_binding_pattern); } - else if (node.kind === SyntaxKind.Parameter && (flags & NodeFlags.ParameterPropertyModifier) && (node).dotDotDotToken) { + else if (node.kind === SyntaxKind.Parameter && (flags & ModifierFlags.ParameterPropertyModifier) && (node).dotDotDotToken) { return grammarErrorOnNode(node, Diagnostics.A_parameter_property_cannot_be_declared_using_a_rest_parameter); } - if (flags & NodeFlags.Async) { + if (flags & ModifierFlags.Async) { return checkGrammarAsyncModifier(node, lastAsync); } } @@ -19170,10 +19643,6 @@ namespace ts { } function checkGrammarAsyncModifier(node: Node, asyncModifier: Node): boolean { - if (languageVersion < ScriptTarget.ES6) { - return grammarErrorOnNode(asyncModifier, Diagnostics.Async_functions_are_only_available_when_targeting_ECMAScript_2015_or_higher); - } - switch (node.kind) { case SyntaxKind.MethodDeclaration: case SyntaxKind.FunctionDeclaration: @@ -19277,7 +19746,7 @@ namespace ts { if (parameter.dotDotDotToken) { return grammarErrorOnNode(parameter.dotDotDotToken, Diagnostics.An_index_signature_cannot_have_a_rest_parameter); } - if (parameter.flags & NodeFlags.Modifier) { + if (getModifierFlags(parameter) !== 0) { return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_cannot_have_an_accessibility_modifier); } if (parameter.questionToken) { @@ -19462,11 +19931,13 @@ namespace ts { } // Modifiers are never allowed on properties except for 'async' on a method declaration - forEach(prop.modifiers, mod => { - if (mod.kind !== SyntaxKind.AsyncKeyword || prop.kind !== SyntaxKind.MethodDeclaration) { - grammarErrorOnNode(mod, Diagnostics._0_modifier_cannot_be_used_here, getTextOfNode(mod)); + if (prop.modifiers) { + for (const mod of prop.modifiers) { + if (mod.kind !== SyntaxKind.AsyncKeyword || prop.kind !== SyntaxKind.MethodDeclaration) { + grammarErrorOnNode(mod, Diagnostics._0_modifier_cannot_be_used_here, getTextOfNode(mod)); + } } - }); + } // ECMA-262 11.1.5 Object Initializer // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true @@ -19481,7 +19952,7 @@ namespace ts { // Grammar checking for computedPropertyName and shorthandPropertyAssignment checkGrammarForInvalidQuestionMark(prop, (prop).questionToken, Diagnostics.An_object_member_cannot_be_declared_optional); if (name.kind === SyntaxKind.NumericLiteral) { - checkGrammarNumericLiteral(name); + checkGrammarNumericLiteral(name); } currentKind = Property; } @@ -19604,7 +20075,7 @@ namespace ts { else if (isInAmbientContext(accessor)) { return grammarErrorOnNode(accessor.name, Diagnostics.An_accessor_cannot_be_declared_in_an_ambient_context); } - else if (accessor.body === undefined && !(accessor.flags & NodeFlags.Abstract)) { + else if (accessor.body === undefined && !(getModifierFlags(accessor) & ModifierFlags.Abstract)) { return grammarErrorAtPos(getSourceFileOfNode(accessor), accessor.end - 1, ";".length, Diagnostics._0_expected, "{"); } else if (accessor.typeParameters) { @@ -19774,10 +20245,29 @@ namespace ts { } } + function isStringOrNumberLiteralExpression(expr: Expression) { + return expr.kind === SyntaxKind.StringLiteral || expr.kind === SyntaxKind.NumericLiteral || + expr.kind === SyntaxKind.PrefixUnaryExpression && (expr).operator === SyntaxKind.MinusToken && + (expr).operand.kind === SyntaxKind.NumericLiteral; + } + function checkGrammarVariableDeclaration(node: VariableDeclaration) { if (node.parent.parent.kind !== SyntaxKind.ForInStatement && node.parent.parent.kind !== SyntaxKind.ForOfStatement) { if (isInAmbientContext(node)) { if (node.initializer) { + if (isConst(node) && !node.type) { + if (!isStringOrNumberLiteralExpression(node.initializer)) { + return grammarErrorOnNode(node.initializer, Diagnostics.A_const_initializer_in_an_ambient_context_must_be_a_string_or_numeric_literal); + } + } + else { + // Error on equals token which immediate precedes the initializer + const equalsTokenLength = "=".length; + return grammarErrorAtPos(getSourceFileOfNode(node), node.initializer.pos - equalsTokenLength, + equalsTokenLength, Diagnostics.Initializers_are_not_allowed_in_ambient_contexts); + } + } + if (node.initializer && !(isConst(node) && isStringOrNumberLiteralExpression(node.initializer))) { // Error on equals token which immediate precedes the initializer const equalsTokenLength = "=".length; return grammarErrorAtPos(getSourceFileOfNode(node), node.initializer.pos - equalsTokenLength, @@ -19815,7 +20305,7 @@ namespace ts { else { const elements = (name).elements; for (const element of elements) { - if (element.kind !== SyntaxKind.OmittedExpression) { + if (!isOmittedExpression(element)) { checkGrammarNameInLetOrConstDeclarations(element.name); } } @@ -19949,10 +20439,8 @@ namespace ts { node.kind === SyntaxKind.ExportDeclaration || node.kind === SyntaxKind.ExportAssignment || node.kind === SyntaxKind.NamespaceExportDeclaration || - (node.flags & NodeFlags.Ambient) || - (node.flags & (NodeFlags.Export | NodeFlags.Default))) { - - return false; + getModifierFlags(node) & (ModifierFlags.Ambient | ModifierFlags.Export | ModifierFlags.Default)) { + return false; } return grammarErrorOnFirstToken(node, Diagnostics.A_declare_modifier_is_required_for_a_top_level_declaration_in_a_d_ts_file); @@ -20005,7 +20493,7 @@ namespace ts { } } - function checkGrammarNumericLiteral(node: LiteralExpression): boolean { + function checkGrammarNumericLiteral(node: NumericLiteral): boolean { // Grammar checking if (node.isOctalLiteral && languageVersion >= ScriptTarget.ES5) { return grammarErrorOnNode(node, Diagnostics.Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher); @@ -20020,5 +20508,15 @@ namespace ts { return true; } } + + function getAmbientModules(): Symbol[] { + const result: Symbol[] = []; + for (const sym in globals) { + if (ambientModuleSymbolRegex.test(sym)) { + result.push(globals[sym]); + } + } + return result; + } } } diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index e1175c4..648447a 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -5,12 +5,15 @@ /// namespace ts { + /* @internal */ + export const compileOnSaveCommandLineOption: CommandLineOption = { name: "compileOnSave", type: "boolean" }; /* @internal */ export const optionDeclarations: CommandLineOption[] = [ { name: "charset", type: "string", }, + compileOnSaveCommandLineOption, { name: "declaration", shortName: "d", @@ -30,6 +33,7 @@ namespace ts { { name: "extendedDiagnostics", type: "boolean", + experimental: true }, { name: "emitBOM", @@ -293,6 +297,7 @@ namespace ts { "classic": ModuleResolutionKind.Classic, }), description: Diagnostics.Specify_module_resolution_strategy_Colon_node_Node_js_or_classic_TypeScript_pre_1_6, + paramType: Diagnostics.STRATEGY, }, { name: "allowUnusedLabels", @@ -406,6 +411,7 @@ namespace ts { "es2017": "lib.es2017.d.ts", // Host only "dom": "lib.dom.d.ts", + "dom.iterable": "lib.dom.iterable.d.ts", "webworker": "lib.webworker.d.ts", "scripthost": "lib.scripthost.d.ts", // ES2015 Or ESNext By-feature options @@ -433,6 +439,11 @@ namespace ts { name: "strictNullChecks", type: "boolean", description: Diagnostics.Enable_strict_null_checks + }, + { + name: "importHelpers", + type: "boolean", + description: Diagnostics.Import_emit_helpers_from_tslib } ]; @@ -669,10 +680,10 @@ namespace ts { * @param fileName The path to the config file * @param jsonText The text of the config file */ - export function parseConfigFileTextToJson(fileName: string, jsonText: string): { config?: any; error?: Diagnostic } { + export function parseConfigFileTextToJson(fileName: string, jsonText: string, stripComments = true): { config?: any; error?: Diagnostic } { try { - const jsonTextWithoutComments = removeComments(jsonText); - return { config: /\S/.test(jsonTextWithoutComments) ? JSON.parse(jsonTextWithoutComments) : {} }; + const jsonTextToParse = stripComments ? removeComments(jsonText) : jsonText; + return { config: /\S/.test(jsonTextToParse) ? JSON.parse(jsonTextToParse) : {} }; } catch (e) { return { error: createCompilerDiagnostic(Diagnostics.Failed_to_parse_file_0_Colon_1, fileName, e.message) }; @@ -799,15 +810,49 @@ namespace ts { * @param basePath A root directory to resolve relative path entries in the config * file to. e.g. outDir */ - export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions: CompilerOptions = {}, configFileName?: string): ParsedCommandLine { + export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions: CompilerOptions = {}, configFileName?: string, resolutionStack: Path[] = []): ParsedCommandLine { const errors: Diagnostic[] = []; - const compilerOptions: CompilerOptions = convertCompilerOptionsFromJsonWorker(json["compilerOptions"], basePath, errors, configFileName); - const options = extend(existingOptions, compilerOptions); + const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames); + const resolvedPath = toPath(configFileName || "", basePath, getCanonicalFileName); + if (resolutionStack.indexOf(resolvedPath) >= 0) { + return { + options: {}, + fileNames: [], + typingOptions: {}, + raw: json, + errors: [createCompilerDiagnostic(Diagnostics.Circularity_detected_while_resolving_configuration_Colon_0, [...resolutionStack, resolvedPath].join(" -> "))], + wildcardDirectories: {} + }; + } + + let options: CompilerOptions = convertCompilerOptionsFromJsonWorker(json["compilerOptions"], basePath, errors, configFileName); const typingOptions: TypingOptions = convertTypingOptionsFromJsonWorker(json["typingOptions"], basePath, errors, configFileName); + if (json["extends"]) { + let [include, exclude, files, baseOptions]: [string[], string[], string[], CompilerOptions] = [undefined, undefined, undefined, {}]; + if (typeof json["extends"] === "string") { + [include, exclude, files, baseOptions] = (tryExtendsName(json["extends"]) || [include, exclude, files, baseOptions]); + } + else { + errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "extends", "string")); + } + if (include && !json["include"]) { + json["include"] = include; + } + if (exclude && !json["exclude"]) { + json["exclude"] = exclude; + } + if (files && !json["files"]) { + json["files"] = files; + } + options = assign({}, baseOptions, options); + } + + options = extend(existingOptions, options); options.configFilePath = configFileName; const { fileNames, wildcardDirectories } = getFileNames(errors); + const compileOnSave = convertCompileOnSaveOptionFromJson(json, basePath, errors); return { options, @@ -815,9 +860,43 @@ namespace ts { typingOptions, raw: json, errors, - wildcardDirectories + wildcardDirectories, + compileOnSave }; + function tryExtendsName(extendedConfig: string): [string[], string[], string[], CompilerOptions] { + // If the path isn't a rooted or relative path, don't try to resolve it (we reserve the right to special case module-id like paths in the future) + if (!(isRootedDiskPath(extendedConfig) || startsWith(normalizeSlashes(extendedConfig), "./") || startsWith(normalizeSlashes(extendedConfig), "../"))) { + errors.push(createCompilerDiagnostic(Diagnostics.The_path_in_an_extends_options_must_be_relative_or_rooted)); + return; + } + let extendedConfigPath = toPath(extendedConfig, basePath, getCanonicalFileName); + if (!host.fileExists(extendedConfigPath) && !endsWith(extendedConfigPath, ".json")) { + extendedConfigPath = `${extendedConfigPath}.json` as Path; + if (!host.fileExists(extendedConfigPath)) { + errors.push(createCompilerDiagnostic(Diagnostics.File_0_does_not_exist, extendedConfig)); + return; + } + } + const extendedResult = readConfigFile(extendedConfigPath, path => host.readFile(path)); + if (extendedResult.error) { + errors.push(extendedResult.error); + return; + } + const extendedDirname = getDirectoryPath(extendedConfigPath); + const relativeDifference = convertToRelativePath(extendedDirname, basePath, getCanonicalFileName); + const updatePath: (path: string) => string = path => isRootedDiskPath(path) ? path : combinePaths(relativeDifference, path); + // Merge configs (copy the resolution stack so it is never reused between branches in potential diamond-problem scenarios) + const result = parseJsonConfigFileContent(extendedResult.config, host, extendedDirname, /*existingOptions*/undefined, getBaseFileName(extendedConfigPath), resolutionStack.concat([resolvedPath])); + errors.push(...result.errors); + const [include, exclude, files] = map(["include", "exclude", "files"], key => { + if (!json[key] && extendedResult.config[key]) { + return map(extendedResult.config[key], updatePath); + } + }); + return [include, exclude, files, result.options]; + } + function getFileNames(errors: Diagnostic[]): ExpandResult { let fileNames: string[]; if (hasProperty(json, "files")) { @@ -852,14 +931,13 @@ namespace ts { errors.push(createCompilerDiagnostic(Diagnostics.Unknown_option_excludes_Did_you_mean_exclude)); } else { - // By default, exclude common package folders + // By default, exclude common package folders and the outDir excludeSpecs = ["node_modules", "bower_components", "jspm_packages"]; - } - // Always exclude the output directory unless explicitly included - const outDir = json["compilerOptions"] && json["compilerOptions"]["outDir"]; - if (outDir) { - excludeSpecs.push(outDir); + const outDir = json["compilerOptions"] && json["compilerOptions"]["outDir"]; + if (outDir) { + excludeSpecs.push(outDir); + } } if (fileNames === undefined && includeSpecs === undefined) { @@ -870,13 +948,24 @@ namespace ts { } } + export function convertCompileOnSaveOptionFromJson(jsonOption: any, basePath: string, errors: Diagnostic[]): boolean { + if (!hasProperty(jsonOption, compileOnSaveCommandLineOption.name)) { + return false; + } + const result = convertJsonOption(compileOnSaveCommandLineOption, jsonOption["compileOnSave"], basePath, errors); + if (typeof result === "boolean" && result) { + return result; + } + return false; + } + export function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: CompilerOptions, errors: Diagnostic[] } { const errors: Diagnostic[] = []; const options = convertCompilerOptionsFromJsonWorker(jsonOptions, basePath, errors, configFileName); return { options, errors }; } - export function convertTypingOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: CompilerOptions, errors: Diagnostic[] } { + export function convertTypingOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: TypingOptions, errors: Diagnostic[] } { const errors: Diagnostic[] = []; const options = convertTypingOptionsFromJsonWorker(jsonOptions, basePath, errors, configFileName); return { options, errors }; @@ -885,7 +974,9 @@ namespace ts { function convertCompilerOptionsFromJsonWorker(jsonOptions: any, basePath: string, errors: Diagnostic[], configFileName?: string): CompilerOptions { - const options: CompilerOptions = getBaseFileName(configFileName) === "jsconfig.json" ? { allowJs: true, maxNodeModuleJsDepth: 2 } : {}; + const options: CompilerOptions = getBaseFileName(configFileName) === "jsconfig.json" + ? { allowJs: true, maxNodeModuleJsDepth: 2, allowSyntheticDefaultImports: true } + : {}; convertOptionsFromJson(optionDeclarations, jsonOptions, basePath, options, Diagnostics.Unknown_compiler_option_0, errors); return options; } diff --git a/src/compiler/comments.ts b/src/compiler/comments.ts new file mode 100644 index 0000000..116a8e8 --- /dev/null +++ b/src/compiler/comments.ts @@ -0,0 +1,347 @@ +/// + +/* @internal */ +namespace ts { + export interface CommentWriter { + reset(): void; + setSourceFile(sourceFile: SourceFile): void; + emitNodeWithComments(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void; + emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void): void; + emitTrailingCommentsOfPosition(pos: number): void; + } + + export function createCommentWriter(host: EmitHost, writer: EmitTextWriter, sourceMap: SourceMapWriter): CommentWriter { + const compilerOptions = host.getCompilerOptions(); + const extendedDiagnostics = compilerOptions.extendedDiagnostics; + const newLine = host.getNewLine(); + const { emitPos } = sourceMap; + + let containerPos = -1; + let containerEnd = -1; + let declarationListContainerEnd = -1; + let currentSourceFile: SourceFile; + let currentText: string; + let currentLineMap: number[]; + let detachedCommentsInfo: { nodePos: number, detachedCommentEndPos: number}[]; + let hasWrittenComment = false; + let disabled: boolean = compilerOptions.removeComments; + + return { + reset, + setSourceFile, + emitNodeWithComments, + emitBodyWithDetachedComments, + emitTrailingCommentsOfPosition, + }; + + function emitNodeWithComments(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) { + if (disabled) { + emitCallback(emitContext, node); + return; + } + + if (node) { + 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 & EmitFlags.NoNestedComments) { + disabled = true; + emitCallback(emitContext, node); + disabled = false; + } + else { + emitCallback(emitContext, node); + } + } + else { + if (extendedDiagnostics) { + performance.mark("preEmitNodeWithComment"); + } + + const isEmittedNode = node.kind !== SyntaxKind.NotEmittedStatement; + 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. + if (!skipLeadingComments) { + emitLeadingComments(pos, isEmittedNode); + } + + // Save current container state on the stack. + const savedContainerPos = containerPos; + const savedContainerEnd = containerEnd; + const savedDeclarationListContainerEnd = declarationListContainerEnd; + + if (!skipLeadingComments) { + containerPos = pos; + } + + if (!skipTrailingComments) { + containerEnd = end; + + // To avoid invalid comment emit in a down-level binding pattern, we + // keep track of the last declaration list container's end + if (node.kind === SyntaxKind.VariableDeclarationList) { + declarationListContainerEnd = end; + } + } + + if (extendedDiagnostics) { + performance.measure("commentTime", "preEmitNodeWithComment"); + } + + if (emitFlags & EmitFlags.NoNestedComments) { + disabled = true; + emitCallback(emitContext, node); + disabled = false; + } + else { + emitCallback(emitContext, node); + } + + if (extendedDiagnostics) { + performance.mark("beginEmitNodeWithComment"); + } + + // Restore previous container state. + containerPos = savedContainerPos; + containerEnd = savedContainerEnd; + declarationListContainerEnd = savedDeclarationListContainerEnd; + + // Emit trailing comments if the position is not synthesized and the node + // has not opted out from emitting leading comments and is an emitted node. + if (!skipTrailingComments && isEmittedNode) { + emitTrailingComments(end); + } + + if (extendedDiagnostics) { + performance.measure("commentTime", "beginEmitNodeWithComment"); + } + } + } + } + + function emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void) { + if (extendedDiagnostics) { + performance.mark("preEmitBodyWithDetachedComments"); + } + + const { pos, end } = detachedRange; + 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); + } + + if (extendedDiagnostics) { + performance.measure("commentTime", "preEmitBodyWithDetachedComments"); + } + + if (emitFlags & EmitFlags.NoNestedComments && !disabled) { + disabled = true; + emitCallback(node); + disabled = false; + } + else { + emitCallback(node); + } + + if (extendedDiagnostics) { + performance.mark("beginEmitBodyWithDetachedCommetns"); + } + + if (!skipTrailingComments) { + emitLeadingComments(detachedRange.end, /*isEmittedNode*/ true); + } + + if (extendedDiagnostics) { + performance.measure("commentTime", "beginEmitBodyWithDetachedCommetns"); + } + } + + function emitLeadingComments(pos: number, isEmittedNode: boolean) { + hasWrittenComment = false; + + if (isEmittedNode) { + forEachLeadingCommentToEmit(pos, emitLeadingComment); + } + else if (pos === 0) { + // If the node will not be emitted in JS, remove all the comments(normal, pinned and ///) associated with the node, + // unless it is a triple slash comment at the top of the file. + // For Example: + // /// + // declare var x; + // /// + // interface F {} + // The first /// will NOT be removed while the second one will be removed even though both node will not be emitted + forEachLeadingCommentToEmit(pos, emitTripleSlashLeadingComment); + } + } + + function emitTripleSlashLeadingComment(commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) { + if (isTripleSlashComment(commentPos, commentEnd)) { + emitLeadingComment(commentPos, commentEnd, kind, hasTrailingNewLine, rangePos); + } + } + + function emitLeadingComment(commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) { + if (!hasWrittenComment) { + emitNewLineBeforeLeadingCommentOfPosition(currentLineMap, writer, rangePos, commentPos); + hasWrittenComment = true; + } + + // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space + emitPos(commentPos); + writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine); + emitPos(commentEnd); + + if (hasTrailingNewLine) { + writer.writeLine(); + } + else { + writer.write(" "); + } + } + + function emitTrailingComments(pos: number) { + forEachTrailingCommentToEmit(pos, emitTrailingComment); + } + + function emitTrailingComment(commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean) { + // trailing comments are emitted at space/*trailing comment1 */space/*trailing comment2*/ + if (!writer.isAtStartOfLine()) { + writer.write(" "); + } + + emitPos(commentPos); + writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine); + emitPos(commentEnd); + + if (hasTrailingNewLine) { + writer.writeLine(); + } + } + + function emitTrailingCommentsOfPosition(pos: number) { + if (disabled) { + return; + } + + if (extendedDiagnostics) { + performance.mark("beforeEmitTrailingCommentsOfPosition"); + } + + forEachTrailingCommentToEmit(pos, emitTrailingCommentOfPosition); + + if (extendedDiagnostics) { + performance.measure("commentTime", "beforeEmitTrailingCommentsOfPosition"); + } + } + + function emitTrailingCommentOfPosition(commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean) { + // trailing comments of a position are emitted at /*trailing comment1 */space/*trailing comment*/space + + emitPos(commentPos); + writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine); + emitPos(commentEnd); + + if (hasTrailingNewLine) { + writer.writeLine(); + } + else { + writer.write(" "); + } + } + + function forEachLeadingCommentToEmit(pos: number, cb: (commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) => void) { + // Emit the leading comments only if the container's pos doesn't match because the container should take care of emitting these comments + if (containerPos === -1 || pos !== containerPos) { + if (hasDetachedComments(pos)) { + forEachLeadingCommentWithoutDetachedComments(cb); + } + else { + forEachLeadingCommentRange(currentText, pos, cb, /*state*/ pos); + } + } + } + + function forEachTrailingCommentToEmit(end: number, cb: (commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean) => void) { + // Emit the trailing comments only if the container's end doesn't match because the container should take care of emitting these comments + if (containerEnd === -1 || (end !== containerEnd && end !== declarationListContainerEnd)) { + forEachTrailingCommentRange(currentText, end, cb); + } + } + + function reset() { + currentSourceFile = undefined; + currentText = undefined; + currentLineMap = undefined; + detachedCommentsInfo = undefined; + } + + function setSourceFile(sourceFile: SourceFile) { + currentSourceFile = sourceFile; + currentText = currentSourceFile.text; + currentLineMap = getLineStarts(currentSourceFile); + detachedCommentsInfo = undefined; + } + + function hasDetachedComments(pos: number) { + return detachedCommentsInfo !== undefined && lastOrUndefined(detachedCommentsInfo).nodePos === pos; + } + + function forEachLeadingCommentWithoutDetachedComments(cb: (commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) => void) { + // get the leading comments from detachedPos + const pos = lastOrUndefined(detachedCommentsInfo).detachedCommentEndPos; + if (detachedCommentsInfo.length - 1) { + detachedCommentsInfo.pop(); + } + else { + detachedCommentsInfo = undefined; + } + + forEachLeadingCommentRange(currentText, pos, cb, /*state*/ pos); + } + + function emitDetachedCommentsAndUpdateCommentsInfo(range: TextRange) { + const currentDetachedCommentInfo = emitDetachedComments(currentText, currentLineMap, writer, writeComment, range, newLine, disabled); + if (currentDetachedCommentInfo) { + if (detachedCommentsInfo) { + detachedCommentsInfo.push(currentDetachedCommentInfo); + } + else { + detachedCommentsInfo = [currentDetachedCommentInfo]; + } + } + } + + function writeComment(text: string, lineMap: number[], writer: EmitTextWriter, commentPos: number, commentEnd: number, newLine: string) { + emitPos(commentPos); + writeCommentRange(text, lineMap, writer, commentPos, commentEnd, newLine); + emitPos(commentEnd); + } + + /** + * Determine if the given comment is a triple-slash + * + * @return true if the comment is a triple-slash comment else false + **/ + function isTripleSlashComment(commentPos: number, commentEnd: number) { + // Verify this is /// comment, but do the regexp match only when we first can find /// in the comment text + // so that we don't end up computing comment string and doing match for all // comments + if (currentText.charCodeAt(commentPos + 1) === CharacterCodes.slash && + commentPos + 2 < commentEnd && + currentText.charCodeAt(commentPos + 2) === CharacterCodes.slash) { + const textSubStr = currentText.substring(commentPos, commentEnd); + return textSubStr.match(fullTripleSlashReferencePathRegEx) || + textSubStr.match(fullTripleSlashAMDReferencePathRegEx) ? + true : false; + } + return false; + } + } +} \ No newline at end of file diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 092fa59..4e1f455 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1,7 +1,6 @@ -/// +/// /// - /* @internal */ namespace ts { /** @@ -47,6 +46,7 @@ namespace ts { contains, remove, forEachValue: forEachValueInMap, + getKeys, clear, }; @@ -56,6 +56,14 @@ namespace ts { } } + function getKeys() { + const keys: Path[] = []; + for (const key in files) { + keys.push(key); + } + return keys; + } + // path should already be well-formed so it does not need to be normalized function get(path: Path): T { return files[toKey(path)]; @@ -113,6 +121,23 @@ namespace ts { return undefined; } + /** + * Iterates through `array` by index and performs the callback on each element of array until the callback + * returns a falsey value, then returns false. + * If no such value is found, the callback is applied to each element of array and `true` is returned. + */ + export function every(array: T[], callback: (element: T, index: number) => boolean): boolean { + if (array) { + for (let i = 0, len = array.length; i < len; i++) { + if (!callback(array[i], i)) { + return false; + } + } + } + + return true; + } + /** Works like Array.prototype.find, returning `undefined` if no element satisfying the predicate is found. */ export function find(array: T[], predicate: (element: T, index: number) => boolean): T | undefined { for (let i = 0, len = array.length; i < len; i++) { @@ -169,11 +194,12 @@ namespace ts { return -1; } - export function countWhere(array: T[], predicate: (x: T) => boolean): number { + export function countWhere(array: T[], predicate: (x: T, i: number) => boolean): number { let count = 0; if (array) { - for (const v of array) { - if (predicate(v)) { + for (let i = 0; i < array.length; i++) { + const v = array[i]; + if (predicate(v, i)) { count++; } } @@ -185,6 +211,8 @@ namespace ts { * Filters an array by a predicate function. Returns the same array instance if the predicate is * true for all elements, otherwise returns a new array instance containing the filtered subset. */ + export function filter(array: T[], f: (x: T) => x is U): U[]; + export function filter(array: T[], f: (x: T) => boolean): T[] export function filter(array: T[], f: (x: T) => boolean): T[] { if (array) { const len = array.length; @@ -232,12 +260,140 @@ namespace ts { array.length = outIndex; } - export function map(array: T[], f: (x: T) => U): U[] { + export function map(array: T[], f: (x: T, i: number) => U): U[] { let result: U[]; + if (array) { + result = []; + for (let i = 0; i < array.length; i++) { + const v = array[i]; + result.push(f(v, i)); + } + } + return result; + } + + /** + * Flattens an array containing a mix of array or non-array elements. + * + * @param array The array to flatten. + */ + export function flatten(array: (T | T[])[]): T[] { + let result: T[]; if (array) { result = []; for (const v of array) { - result.push(f(v)); + if (v) { + if (isArray(v)) { + addRange(result, v); + } + else { + result.push(v); + } + } + } + } + + return result; + } + + /** + * Maps an array. If the mapped value is an array, it is spread into the result. + * + * @param array The array to map. + * @param mapfn The callback used to map the result into one or more values. + */ + export function flatMap(array: T[], mapfn: (x: T, i: number) => U | U[]): U[] { + let result: U[]; + if (array) { + result = []; + for (let i = 0; i < array.length; i++) { + const v = mapfn(array[i], i); + if (v) { + if (isArray(v)) { + addRange(result, v); + } + else { + result.push(v); + } + } + } + } + return result; + } + + /** + * Computes the first matching span of elements and returns a tuple of the first span + * and the remaining elements. + */ + export function span(array: T[], f: (x: T, i: number) => boolean): [T[], T[]] { + if (array) { + for (let i = 0; i < array.length; i++) { + if (!f(array[i], i)) { + return [array.slice(0, i), array.slice(i)]; + } + } + return [array.slice(0), []]; + } + + return undefined; + } + + /** + * Maps contiguous spans of values with the same key. + * + * @param array The array to map. + * @param keyfn A callback used to select the key for an element. + * @param mapfn A callback used to map a contiguous chunk of values to a single value. + */ + export function spanMap(array: T[], keyfn: (x: T, i: number) => K, mapfn: (chunk: T[], key: K, start: number, end: number) => U): U[] { + let result: U[]; + if (array) { + result = []; + const len = array.length; + let previousKey: K; + let key: K; + let start = 0; + let pos = 0; + while (start < len) { + while (pos < len) { + const value = array[pos]; + key = keyfn(value, pos); + if (pos === 0) { + previousKey = key; + } + else if (key !== previousKey) { + break; + } + + pos++; + } + + if (start < pos) { + const v = mapfn(array.slice(start, pos), previousKey, start, pos); + if (v) { + result.push(v); + } + + start = pos; + } + + previousKey = key; + pos++; + } + } + + return result; + } + + export function mapObject(object: MapLike, f: (key: string, x: T) => [string, U]): MapLike { + let result: MapLike; + if (object) { + result = {}; + for (const v of getOwnKeys(object)) { + const [key, value]: [string, U] = f(v, object[v]) || [undefined, undefined]; + if (key !== undefined) { + result[key] = value; + } } } return result; @@ -246,10 +402,10 @@ namespace ts { export function concatenate(array1: T[], array2: T[]): T[] { if (!array2 || !array2.length) return array1; if (!array1 || !array1.length) return array2; - - return array1.concat(array2); + return [...array1, ...array2]; } + // TODO: fixme (N^2) - add optional comparer so collection can be sorted before deduplication. export function deduplicate(array: T[], areEqual?: (a: T, b: T) => boolean): T[] { let result: T[]; if (array) { @@ -266,6 +422,27 @@ namespace ts { return result; } + /** + * Compacts an array, removing any falsey elements. + */ + export function compact(array: T[]): T[] { + let result: T[]; + if (array) { + for (let i = 0; i < array.length; i++) { + const v = array[i]; + if (result || !v) { + if (!result) { + result = array.slice(0, i); + } + if (v) { + result.push(v); + } + } + } + } + return result || array; + } + export function sum(array: any[], prop: string): number { let result = 0; for (const v of array) { @@ -277,7 +454,9 @@ namespace ts { export function addRange(to: T[], from: T[]): void { if (to && from) { for (const v of from) { - to.push(v); + if (v !== undefined) { + to.push(v); + } } } } @@ -292,15 +471,31 @@ namespace ts { return true; } + export function firstOrUndefined(array: T[]): T { + return array && array.length > 0 + ? array[0] + : undefined; + } + + export function singleOrUndefined(array: T[]): T { + return array && array.length === 1 + ? array[0] + : undefined; + } + + export function singleOrMany(array: T[]): T | T[] { + return array && array.length === 1 + ? array[0] + : array; + } + /** * Returns the last element of an array if non-empty, undefined otherwise. */ export function lastOrUndefined(array: T[]): T { - if (array.length === 0) { - return undefined; - } - - return array[array.length - 1]; + return array && array.length > 0 + ? array[array.length - 1] + : undefined; } /** @@ -310,18 +505,25 @@ namespace ts { * @param array A sorted array whose first element must be no larger than number * @param number The value to be searched for in the array. */ - export function binarySearch(array: number[], value: number): number { + export function binarySearch(array: T[], value: T, comparer?: (v1: T, v2: T) => number): number { + if (!array || array.length === 0) { + return -1; + } + let low = 0; let high = array.length - 1; + comparer = comparer !== undefined + ? comparer + : (v1, v2) => (v1 < v2 ? -1 : (v1 > v2 ? 1 : 0)); while (low <= high) { const middle = low + ((high - low) >> 1); const midValue = array[middle]; - if (midValue === value) { + if (comparer(midValue, value) === 0) { return middle; } - else if (midValue > value) { + else if (comparer(midValue, value) > 0) { high = middle - 1; } else { @@ -332,14 +534,15 @@ namespace ts { return ~low; } - export function reduceLeft(array: T[], f: (a: T, x: T) => T): T; - export function reduceLeft(array: T[], f: (a: U, x: T) => U, initial: U): U; - export function reduceLeft(array: T[], f: (a: U, x: T) => U, initial?: U): U { - if (array) { - const count = array.length; - if (count > 0) { - let pos = 0; - let result: T | U; + export function reduceLeft(array: T[], f: (memo: U, value: T, i: number) => U, initial: U, start?: number, count?: number): U; + export function reduceLeft(array: T[], f: (memo: T, value: T, i: number) => T): T; + export function reduceLeft(array: T[], f: (memo: T, value: T, i: number) => T, initial?: T, start?: number, count?: number): T { + if (array && array.length > 0) { + const size = array.length; + if (size > 0) { + let pos = start === undefined || start < 0 ? 0 : start; + const end = count === undefined || pos + count > size - 1 ? size - 1 : pos + count; + let result: T; if (arguments.length <= 2) { result = array[pos]; pos++; @@ -347,23 +550,25 @@ namespace ts { else { result = initial; } - while (pos < count) { - result = f(result, array[pos]); + while (pos <= end) { + result = f(result, array[pos], pos); pos++; } - return result; + return result; } } return initial; } - export function reduceRight(array: T[], f: (a: T, x: T) => T): T; - export function reduceRight(array: T[], f: (a: U, x: T) => U, initial: U): U; - export function reduceRight(array: T[], f: (a: U, x: T) => U, initial?: U): U { + export function reduceRight(array: T[], f: (memo: U, value: T, i: number) => U, initial: U, start?: number, count?: number): U; + export function reduceRight(array: T[], f: (memo: T, value: T, i: number) => T): T; + export function reduceRight(array: T[], f: (memo: T, value: T, i: number) => T, initial?: T, start?: number, count?: number): T { if (array) { - let pos = array.length - 1; - if (pos >= 0) { - let result: T | U; + const size = array.length; + if (size > 0) { + let pos = start === undefined || start > size - 1 ? size - 1 : start; + const end = count === undefined || pos - count < 0 ? 0 : pos - count; + let result: T; if (arguments.length <= 2) { result = array[pos]; pos--; @@ -371,11 +576,11 @@ namespace ts { else { result = initial; } - while (pos >= 0) { - result = f(result, array[pos]); + while (pos >= end) { + result = f(result, array[pos], pos); pos--; } - return result; + return result; } } return initial; @@ -464,6 +669,18 @@ namespace ts { } } + export function assign, T2, T3>(t: T1, arg1: T2, arg2: T3): T1 & T2 & T3; + export function assign, T2>(t: T1, arg1: T2): T1 & T2; + export function assign>(t: T1, ...args: any[]): any; + export function assign>(t: T1, ...args: any[]) { + for (const arg of args) { + for (const p of getOwnKeys(arg)) { + t[p] = arg[p]; + } + } + return t; + } + /** * Reduce the properties of a map. * @@ -539,6 +756,15 @@ namespace ts { return result; } + export function isEmpty(map: Map) { + for (const id in map) { + if (hasProperty(map, id)) { + return false; + } + } + return true; + } + export function cloneMap(map: Map) { const clone = createMap(); copyProperties(map, clone); @@ -581,6 +807,21 @@ namespace ts { } } + /** + * Removes a value from an array of values associated with the key. + * Does not preserve the order of those values. + * Does nothing if `key` is not in `map`, or `value` is not in `map[key]`. + */ + export function multiMapRemove(map: Map, key: string, value: V): void { + const values = map[key]; + if (values) { + unorderedRemoveItem(values, value); + if (!values.length) { + delete map[key]; + } + } + } + /** * Tests whether a value is an array. */ @@ -599,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(...args: ((t: T) => (u: U) => U)[]): (t: T) => (u: U) => U; + export function chain(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(...args: ((t: T) => T)[]): (t: T) => T; + export function compose(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; @@ -819,7 +1126,8 @@ namespace ts { return 0; } - export let directorySeparator = "/"; + export const directorySeparator = "/"; + const directorySeparatorCharCode = CharacterCodes.slash; function getNormalizedParts(normalizedSlashedPath: string, rootLength: number) { const parts = normalizedSlashedPath.substr(rootLength).split(directorySeparator); const normalized: string[] = []; @@ -844,8 +1152,20 @@ namespace ts { export function normalizePath(path: string): string { path = normalizeSlashes(path); const rootLength = getRootLength(path); + const root = path.substr(0, rootLength); const normalized = getNormalizedParts(path, rootLength); - return path.substr(0, rootLength) + normalized.join(directorySeparator); + if (normalized.length) { + const joinedParts = root + normalized.join(directorySeparator); + return pathEndsWithDirectorySeparator(path) ? joinedParts + directorySeparator : joinedParts; + } + else { + return root; + } + } + + /** A path ending with '/' refers to a directory only, never a file. */ + export function pathEndsWithDirectorySeparator(path: string): boolean { + return path.charCodeAt(path.length - 1) === directorySeparatorCharCode; } export function getDirectoryPath(path: Path): Path; @@ -858,10 +1178,49 @@ namespace ts { return path && !isRootedDiskPath(path) && path.indexOf("://") !== -1; } + export function isExternalModuleNameRelative(moduleName: string): boolean { + // TypeScript 1.0 spec (April 2014): 11.2.1 + // An external module name is "relative" if the first term is "." or "..". + return /^\.\.?($|[\\/])/.test(moduleName); + } + + export function getEmitScriptTarget(compilerOptions: CompilerOptions) { + return compilerOptions.target || ScriptTarget.ES3; + } + + export function getEmitModuleKind(compilerOptions: CompilerOptions) { + return typeof compilerOptions.module === "number" ? + compilerOptions.module : + getEmitScriptTarget(compilerOptions) === ScriptTarget.ES6 ? ModuleKind.ES6 : ModuleKind.CommonJS; + } + + /* @internal */ + export function hasZeroOrOneAsteriskCharacter(str: string): boolean { + let seenAsterisk = false; + for (let i = 0; i < str.length; i++) { + if (str.charCodeAt(i) === CharacterCodes.asterisk) { + if (!seenAsterisk) { + seenAsterisk = true; + } + else { + // have already seen asterisk + return false; + } + } + } + return true; + } + export function isRootedDiskPath(path: string) { return getRootLength(path) !== 0; } + export function convertToRelativePath(absoluteOrRelativePath: string, basePath: string, getCanonicalFileName: (path: string) => string): string { + return !isRootedDiskPath(absoluteOrRelativePath) + ? absoluteOrRelativePath + : getRelativePathToDirectoryOrUrl(basePath, absoluteOrRelativePath, basePath, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false); + } + function normalizedPathComponents(path: string, rootLength: number) { const normalizedParts = getNormalizedParts(path, rootLength); return [path.substr(0, rootLength)].concat(normalizedParts); @@ -1353,6 +1712,14 @@ namespace ts { return options && options.allowJs ? allSupportedExtensions : supportedTypeScriptExtensions; } + export function hasJavaScriptFileExtension(fileName: string) { + return forEach(supportedJavascriptExtensions, extension => fileExtensionIs(fileName, extension)); + } + + export function hasTypeScriptFileExtension(fileName: string) { + return forEach(supportedTypeScriptExtensions, extension => fileExtensionIs(fileName, extension)); + } + export function isSupportedSourceFileName(fileName: string, compilerOptions?: CompilerOptions) { if (!fileName) { return false; } @@ -1468,11 +1835,15 @@ namespace ts { } function Node(this: Node, kind: SyntaxKind, pos: number, end: number) { + this.id = 0; this.kind = kind; this.pos = pos; this.end = end; this.flags = NodeFlags.None; + this.modifierFlagsCache = ModifierFlags.None; + this.transformFlags = TransformFlags.None; this.parent = undefined; + this.original = undefined; } export let objectAllocator: ObjectAllocator = { @@ -1493,10 +1864,13 @@ namespace ts { } export namespace Debug { - const currentAssertionLevel = AssertionLevel.None; + declare var process: any; + declare var require: any; + + let currentAssertionLevel: AssertionLevel; export function shouldAssert(level: AssertionLevel): boolean { - return currentAssertionLevel >= level; + return getCurrentAssertionLevel() >= level; } export function assert(expression: boolean, message?: string, verboseDebugInfo?: () => string): void { @@ -1513,6 +1887,35 @@ namespace ts { export function fail(message?: string): void { Debug.assert(/*expression*/ false, message); } + + function getCurrentAssertionLevel() { + if (currentAssertionLevel !== undefined) { + return currentAssertionLevel; + } + + if (sys === undefined) { + return AssertionLevel.None; + } + + const developmentMode = /^development$/i.test(getEnvironmentVariable("NODE_ENV")); + currentAssertionLevel = developmentMode + ? AssertionLevel.Normal + : AssertionLevel.None; + + return currentAssertionLevel; + } + } + + export function getEnvironmentVariable(name: string, host?: CompilerHost) { + if (host && host.getEnvironmentVariable) { + return host.getEnvironmentVariable(name); + } + + if (sys && sys.getEnvironmentVariable) { + return sys.getEnvironmentVariable(name); + } + + return ""; } /** Remove an item from an array, moving everything to its right one space left. */ @@ -1550,4 +1953,82 @@ namespace ts { ? ((fileName) => fileName) : ((fileName) => fileName.toLowerCase()); } + + /** + * patternStrings contains both pattern strings (containing "*") and regular strings. + * Return an exact match if possible, or a pattern match, or undefined. + * (These are verified by verifyCompilerOptions to have 0 or 1 "*" characters.) + */ + /* @internal */ + export function matchPatternOrExact(patternStrings: string[], candidate: string): string | Pattern | undefined { + const patterns: Pattern[] = []; + for (const patternString of patternStrings) { + const pattern = tryParsePattern(patternString); + if (pattern) { + patterns.push(pattern); + } + else if (patternString === candidate) { + // pattern was matched as is - no need to search further + return patternString; + } + } + + return findBestPatternMatch(patterns, _ => _, candidate); + } + + /* @internal */ + export function patternText({prefix, suffix}: Pattern): string { + return `${prefix}*${suffix}`; + } + + /** + * Given that candidate matches pattern, returns the text matching the '*'. + * E.g.: matchedText(tryParsePattern("foo*baz"), "foobarbaz") === "bar" + */ + /* @internal */ + export function matchedText(pattern: Pattern, candidate: string): string { + Debug.assert(isPatternMatch(pattern, candidate)); + return candidate.substr(pattern.prefix.length, candidate.length - pattern.suffix.length); + } + + /** Return the object corresponding to the best pattern to match `candidate`. */ + /* @internal */ + export function findBestPatternMatch(values: T[], getPattern: (value: T) => Pattern, candidate: string): T | undefined { + let matchedValue: T | undefined = undefined; + // use length of prefix as betterness criteria + let longestMatchPrefixLength = -1; + + for (const v of values) { + const pattern = getPattern(v); + if (isPatternMatch(pattern, candidate) && pattern.prefix.length > longestMatchPrefixLength) { + longestMatchPrefixLength = pattern.prefix.length; + matchedValue = v; + } + } + + return matchedValue; + } + + function isPatternMatch({prefix, suffix}: Pattern, candidate: string) { + return candidate.length >= prefix.length + suffix.length && + startsWith(candidate, prefix) && + endsWith(candidate, suffix); + } + + /* @internal */ + export function tryParsePattern(pattern: string): Pattern | undefined { + // This should be verified outside of here and a proper error thrown. + Debug.assert(hasZeroOrOneAsteriskCharacter(pattern)); + const indexOfStar = pattern.indexOf("*"); + return indexOfStar === -1 ? undefined : { + prefix: pattern.substr(0, indexOfStar), + suffix: pattern.substr(indexOfStar + 1) + }; + } + + export function positionIsSynthesized(pos: number): boolean { + // This is a fast way of testing the following conditions: + // pos === undefined || pos === null || isNaN(pos) || pos < 0; + return !(pos >= 0); + } } diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index ab1ca51..4e19aaf 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -36,12 +36,12 @@ namespace ts { return declarationDiagnostics.getDiagnostics(targetSourceFile ? targetSourceFile.fileName : undefined); function getDeclarationDiagnosticsFromFile({ declarationFilePath }: EmitFileNames, sources: SourceFile[], isBundledEmit: boolean) { - emitDeclarations(host, resolver, declarationDiagnostics, declarationFilePath, sources, isBundledEmit); + emitDeclarations(host, resolver, declarationDiagnostics, declarationFilePath, sources, isBundledEmit, /*emitOnlyDtsFiles*/ false); } } function emitDeclarations(host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection, declarationFilePath: string, - sourceFiles: SourceFile[], isBundledEmit: boolean): DeclarationEmit { + sourceFiles: SourceFile[], isBundledEmit: boolean, emitOnlyDtsFiles: boolean): DeclarationEmit { const newLine = host.getNewLine(); const compilerOptions = host.getCompilerOptions(); @@ -98,7 +98,7 @@ namespace ts { // global file reference is added only // - if it is not bundled emit (because otherwise it would be self reference) // - and it is not already added - if (writeReferencePath(referencedFile, !isBundledEmit && !addedGlobalFileReference)) { + if (writeReferencePath(referencedFile, !isBundledEmit && !addedGlobalFileReference, emitOnlyDtsFiles)) { addedGlobalFileReference = true; } emittedReferencedFiles.push(referencedFile); @@ -306,7 +306,7 @@ namespace ts { } function trackSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags) { - handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning)); + handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning, /*shouldComputeAliasesToMakeVisible*/ true)); recordTypeReferenceDirectivesIfNecessary(resolver.getTypeReferenceDirectivesForSymbol(symbol, meaning)); } @@ -327,7 +327,7 @@ namespace ts { } else { errorNameNode = declaration.name; - resolver.writeTypeOfDeclaration(declaration, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction, writer); + resolver.writeTypeOfDeclaration(declaration, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue, writer); errorNameNode = undefined; } } @@ -341,7 +341,7 @@ namespace ts { } else { errorNameNode = signature.name; - resolver.writeReturnTypeOfSignatureDeclaration(signature, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction, writer); + resolver.writeReturnTypeOfSignatureDeclaration(signature, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue, writer); errorNameNode = undefined; } } @@ -374,7 +374,7 @@ namespace ts { const jsDocComments = getJsDocCommentsFromText(declaration, currentText); emitNewLineBeforeLeadingComments(currentLineMap, writer, declaration, jsDocComments); // jsDoc comments are emitted at /*leading comment1 */space/*leading comment*/space - emitComments(currentText, currentLineMap, writer, jsDocComments, /*trailingSeparator*/ true, newLine, writeCommentRange); + emitComments(currentText, currentLineMap, writer, jsDocComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeCommentRange); } } @@ -563,7 +563,7 @@ namespace ts { write(tempVarName); write(": "); writer.getSymbolAccessibilityDiagnostic = getDefaultExportAccessibilityDiagnostic; - resolver.writeTypeOfExpression(node.expression, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction, writer); + resolver.writeTypeOfExpression(node.expression, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue, writer); write(";"); writeLine(); write(node.isExportEquals ? "export = " : "export default "); @@ -655,12 +655,13 @@ namespace ts { function emitModuleElementDeclarationFlags(node: Node) { // If the node is parented in the current source file we need to emit export declare or just export if (node.parent.kind === SyntaxKind.SourceFile) { + const modifiers = getModifierFlags(node); // If the node is exported - if (node.flags & NodeFlags.Export) { + if (modifiers & ModifierFlags.Export) { write("export "); } - if (node.flags & NodeFlags.Default) { + if (modifiers & ModifierFlags.Default) { write("default "); } else if (node.kind !== SyntaxKind.InterfaceDeclaration && !noDeclare) { @@ -669,21 +670,21 @@ namespace ts { } } - function emitClassMemberDeclarationFlags(flags: NodeFlags) { - if (flags & NodeFlags.Private) { + function emitClassMemberDeclarationFlags(flags: ModifierFlags) { + if (flags & ModifierFlags.Private) { write("private "); } - else if (flags & NodeFlags.Protected) { + else if (flags & ModifierFlags.Protected) { write("protected "); } - if (flags & NodeFlags.Static) { + if (flags & ModifierFlags.Static) { write("static "); } - if (flags & NodeFlags.Readonly) { + if (flags & ModifierFlags.Readonly) { write("readonly "); } - if (flags & NodeFlags.Abstract) { + if (flags & ModifierFlags.Abstract) { write("abstract "); } } @@ -692,7 +693,7 @@ namespace ts { // note usage of writer. methods instead of aliases created, just to make sure we are using // correct writer especially to handle asynchronous alias writing emitJsDocComments(node); - if (node.flags & NodeFlags.Export) { + if (hasModifier(node, ModifierFlags.Export)) { write("export "); } write("import "); @@ -731,7 +732,7 @@ namespace ts { function writeImportDeclaration(node: ImportDeclaration) { emitJsDocComments(node); - if (node.flags & NodeFlags.Export) { + if (hasModifier(node, ModifierFlags.Export)) { write("export "); } write("import "); @@ -926,7 +927,7 @@ namespace ts { } function isPrivateMethodTypeParameter(node: TypeParameterDeclaration) { - return node.parent.kind === SyntaxKind.MethodDeclaration && (node.parent.flags & NodeFlags.Private); + return node.parent.kind === SyntaxKind.MethodDeclaration && hasModifier(node.parent, ModifierFlags.Private); } function emitTypeParameters(typeParameters: TypeParameterDeclaration[]) { @@ -976,7 +977,7 @@ namespace ts { case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: - if (node.parent.flags & NodeFlags.Static) { + if (hasModifier(node.parent, ModifierFlags.Static)) { diagnosticMessage = Diagnostics.Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1; } else if (node.parent.parent.kind === SyntaxKind.ClassDeclaration) { @@ -1025,7 +1026,7 @@ namespace ts { } else { writer.getSymbolAccessibilityDiagnostic = getHeritageClauseVisibilityError; - resolver.writeBaseConstructorTypeOfClass(enclosingDeclaration, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction, writer); + resolver.writeBaseConstructorTypeOfClass(enclosingDeclaration, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue, writer); } function getHeritageClauseVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { @@ -1055,7 +1056,7 @@ namespace ts { function emitParameterProperties(constructorDeclaration: ConstructorDeclaration) { if (constructorDeclaration) { forEach(constructorDeclaration.parameters, param => { - if (param.flags & NodeFlags.ParameterPropertyModifier) { + if (hasModifier(param, ModifierFlags.ParameterPropertyModifier)) { emitPropertyDeclaration(param); } }); @@ -1064,7 +1065,7 @@ namespace ts { emitJsDocComments(node); emitModuleElementDeclarationFlags(node); - if (node.flags & NodeFlags.Abstract) { + if (hasModifier(node, ModifierFlags.Abstract)) { write("abstract "); } @@ -1114,7 +1115,7 @@ namespace ts { } emitJsDocComments(node); - emitClassMemberDeclarationFlags(node.flags); + emitClassMemberDeclarationFlags(getModifierFlags(node)); emitVariableDeclaration(node); write(";"); writeLine(); @@ -1141,7 +1142,11 @@ namespace ts { if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature) && node.parent.kind === SyntaxKind.TypeLiteral) { emitTypeOfVariableDeclarationFromTypeLiteral(node); } - else if (!(node.flags & NodeFlags.Private)) { + else if (resolver.isLiteralConstDeclaration(node)) { + write(" = "); + resolver.writeLiteralConstValue(node, writer); + } + else if (!hasModifier(node, ModifierFlags.Private)) { writeTypeOfDeclaration(node, node.type, getVariableDeclarationTypeVisibilityError); } } @@ -1158,7 +1163,7 @@ namespace ts { // This check is to ensure we don't report error on constructor parameter property as that error would be reported during parameter emit else if (node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature) { // TODO(jfreeman): Deal with computed properties in error reporting. - if (node.flags & NodeFlags.Static) { + if (hasModifier(node, ModifierFlags.Static)) { return symbolAccessibilityResult.errorModuleName ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : @@ -1269,9 +1274,9 @@ namespace ts { if (node === accessors.firstAccessor) { emitJsDocComments(accessors.getAccessor); emitJsDocComments(accessors.setAccessor); - emitClassMemberDeclarationFlags(node.flags | (accessors.setAccessor ? 0 : NodeFlags.Readonly)); + emitClassMemberDeclarationFlags(getModifierFlags(node) | (accessors.setAccessor ? 0 : ModifierFlags.Readonly)); writeTextOfNode(currentText, node.name); - if (!(node.flags & NodeFlags.Private)) { + if (!hasModifier(node, ModifierFlags.Private)) { accessorWithTypeAnnotation = node; let type = getTypeAnnotationFromAccessor(node); if (!type) { @@ -1302,7 +1307,7 @@ namespace ts { let diagnosticMessage: DiagnosticMessage; if (accessorWithTypeAnnotation.kind === SyntaxKind.SetAccessor) { // Setters have to have type named and cannot infer it so, the type should always be named - if (accessorWithTypeAnnotation.parent.flags & NodeFlags.Static) { + if (hasModifier(accessorWithTypeAnnotation.parent, ModifierFlags.Static)) { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? Diagnostics.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2 : Diagnostics.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_private_name_1; @@ -1320,7 +1325,7 @@ namespace ts { }; } else { - if (accessorWithTypeAnnotation.flags & NodeFlags.Static) { + if (hasModifier(accessorWithTypeAnnotation, ModifierFlags.Static)) { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : @@ -1356,7 +1361,7 @@ namespace ts { emitModuleElementDeclarationFlags(node); } else if (node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.Constructor) { - emitClassMemberDeclarationFlags(node.flags); + emitClassMemberDeclarationFlags(getModifierFlags(node)); } if (node.kind === SyntaxKind.FunctionDeclaration) { write("function "); @@ -1387,7 +1392,7 @@ namespace ts { if (node.kind === SyntaxKind.IndexSignature) { // Index signature can have readonly modifier - emitClassMemberDeclarationFlags(node.flags); + emitClassMemberDeclarationFlags(getModifierFlags(node)); write("["); } else { @@ -1428,7 +1433,7 @@ namespace ts { emitType(node.type); } } - else if (node.kind !== SyntaxKind.Constructor && !(node.flags & NodeFlags.Private)) { + else if (node.kind !== SyntaxKind.Constructor && !hasModifier(node, ModifierFlags.Private)) { writeReturnTypeAtSignature(node, getReturnTypeVisibilityError); } @@ -1468,7 +1473,7 @@ namespace ts { case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: - if (node.flags & NodeFlags.Static) { + if (hasModifier(node, ModifierFlags.Static)) { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : @@ -1534,7 +1539,7 @@ namespace ts { node.parent.parent.kind === SyntaxKind.TypeLiteral) { emitTypeOfVariableDeclarationFromTypeLiteral(node); } - else if (!(node.parent.flags & NodeFlags.Private)) { + else if (!hasModifier(node.parent, ModifierFlags.Private)) { writeTypeOfDeclaration(node, node.type, getParameterDeclarationTypeVisibilityError); } @@ -1570,7 +1575,7 @@ namespace ts { case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: - if (node.parent.flags & NodeFlags.Static) { + if (hasModifier(node.parent, ModifierFlags.Static)) { return symbolAccessibilityResult.errorModuleName ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : @@ -1715,7 +1720,7 @@ namespace ts { * @param referencedFile * @param addBundledFileReference Determines if global file reference corresponding to bundled file should be emitted or not */ - function writeReferencePath(referencedFile: SourceFile, addBundledFileReference: boolean): boolean { + function writeReferencePath(referencedFile: SourceFile, addBundledFileReference: boolean, emitOnlyDtsFiles: boolean): boolean { let declFileName: string; let addedBundledEmitReference = false; if (isDeclarationFile(referencedFile)) { @@ -1724,7 +1729,7 @@ namespace ts { } else { // Get the declaration file path - forEachExpectedEmitFile(host, getDeclFileName, referencedFile); + forEachExpectedEmitFile(host, getDeclFileName, referencedFile, emitOnlyDtsFiles); } if (declFileName) { @@ -1753,8 +1758,8 @@ namespace ts { } /* @internal */ - export function writeDeclarationFile(declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection) { - const emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFiles, isBundledEmit); + export function writeDeclarationFile(declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection, emitOnlyDtsFiles: boolean) { + const emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFiles, isBundledEmit, emitOnlyDtsFiles); const emitSkipped = emitDeclarationResult.reportedDeclarationError || host.isEmitBlocked(declarationFilePath) || host.getCompilerOptions().noEmit; if (!emitSkipped) { const declarationOutput = emitDeclarationResult.referencesOutput diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index cf39138..f2fb6b7 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -208,9 +208,9 @@ namespace ts { Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Class_definitions_are_automatically_in_strict_mode: { code: 1251, category: DiagnosticCategory.Error, key: "Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Class_d_1251", message: "Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Class definitions are automatically in strict mode." }, Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Modules_are_automatically_in_strict_mode: { code: 1252, category: DiagnosticCategory.Error, key: "Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Modules_1252", message: "Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Modules are automatically in strict mode." }, _0_tag_cannot_be_used_independently_as_a_top_level_JSDoc_tag: { code: 1253, category: DiagnosticCategory.Error, key: "_0_tag_cannot_be_used_independently_as_a_top_level_JSDoc_tag_1253", message: "'{0}' tag cannot be used independently as a top level JSDoc tag." }, + A_const_initializer_in_an_ambient_context_must_be_a_string_or_numeric_literal: { code: 1254, category: DiagnosticCategory.Error, key: "A_const_initializer_in_an_ambient_context_must_be_a_string_or_numeric_literal_1254", message: "A 'const' initializer in an ambient context must be a string or numeric literal." }, with_statements_are_not_allowed_in_an_async_function_block: { code: 1300, category: DiagnosticCategory.Error, key: "with_statements_are_not_allowed_in_an_async_function_block_1300", message: "'with' statements are not allowed in an async function block." }, await_expression_is_only_allowed_within_an_async_function: { code: 1308, category: DiagnosticCategory.Error, key: "await_expression_is_only_allowed_within_an_async_function_1308", message: "'await' expression is only allowed within an async function." }, - Async_functions_are_only_available_when_targeting_ECMAScript_2015_or_higher: { code: 1311, category: DiagnosticCategory.Error, key: "Async_functions_are_only_available_when_targeting_ECMAScript_2015_or_higher_1311", message: "Async functions are only available when targeting ECMAScript 2015 or higher." }, can_only_be_used_in_an_object_literal_property_inside_a_destructuring_assignment: { code: 1312, category: DiagnosticCategory.Error, key: "can_only_be_used_in_an_object_literal_property_inside_a_destructuring_assignment_1312", message: "'=' can only be used in an object literal property inside a destructuring assignment." }, The_body_of_an_if_statement_cannot_be_the_empty_statement: { code: 1313, category: DiagnosticCategory.Error, key: "The_body_of_an_if_statement_cannot_be_the_empty_statement_1313", message: "The body of an 'if' statement cannot be the empty statement." }, Global_module_exports_may_only_appear_in_module_files: { code: 1314, category: DiagnosticCategory.Error, key: "Global_module_exports_may_only_appear_in_module_files_1314", message: "Global module exports may only appear in module files." }, @@ -265,12 +265,11 @@ namespace ts { Supplied_parameters_do_not_match_any_signature_of_call_target: { code: 2346, category: DiagnosticCategory.Error, key: "Supplied_parameters_do_not_match_any_signature_of_call_target_2346", message: "Supplied parameters do not match any signature of call target." }, Untyped_function_calls_may_not_accept_type_arguments: { code: 2347, category: DiagnosticCategory.Error, key: "Untyped_function_calls_may_not_accept_type_arguments_2347", message: "Untyped function calls may not accept type arguments." }, Value_of_type_0_is_not_callable_Did_you_mean_to_include_new: { code: 2348, category: DiagnosticCategory.Error, key: "Value_of_type_0_is_not_callable_Did_you_mean_to_include_new_2348", message: "Value of type '{0}' is not callable. Did you mean to include 'new'?" }, - Cannot_invoke_an_expression_whose_type_lacks_a_call_signature: { code: 2349, category: DiagnosticCategory.Error, key: "Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_2349", message: "Cannot invoke an expression whose type lacks a call signature." }, + Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures: { code: 2349, category: DiagnosticCategory.Error, key: "Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatur_2349", message: "Cannot invoke an expression whose type lacks a call signature. Type '{0}' has no compatible call signatures." }, Only_a_void_function_can_be_called_with_the_new_keyword: { code: 2350, category: DiagnosticCategory.Error, key: "Only_a_void_function_can_be_called_with_the_new_keyword_2350", message: "Only a void function can be called with the 'new' keyword." }, Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature: { code: 2351, category: DiagnosticCategory.Error, key: "Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature_2351", message: "Cannot use 'new' with an expression whose type lacks a call or construct signature." }, Type_0_cannot_be_converted_to_type_1: { code: 2352, category: DiagnosticCategory.Error, key: "Type_0_cannot_be_converted_to_type_1_2352", message: "Type '{0}' cannot be converted to type '{1}'." }, Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1: { code: 2353, category: DiagnosticCategory.Error, key: "Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1_2353", message: "Object literal may only specify known properties, and '{0}' does not exist in type '{1}'." }, - No_best_common_type_exists_among_return_expressions: { code: 2354, category: DiagnosticCategory.Error, key: "No_best_common_type_exists_among_return_expressions_2354", message: "No best common type exists among return expressions." }, A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value: { code: 2355, category: DiagnosticCategory.Error, key: "A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value_2355", message: "A function whose declared type is neither 'void' nor 'any' must return a value." }, An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type: { code: 2356, category: DiagnosticCategory.Error, key: "An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type_2356", message: "An arithmetic operand must be of type 'any', 'number' or an enum type." }, The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer: { code: 2357, category: DiagnosticCategory.Error, key: "The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer_2357", message: "The operand of an increment or decrement operator must be a variable, property or indexer." }, @@ -324,7 +323,7 @@ namespace ts { The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter: { code: 2407, category: DiagnosticCategory.Error, key: "The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter_2407", message: "The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter." }, Setters_cannot_return_a_value: { code: 2408, category: DiagnosticCategory.Error, key: "Setters_cannot_return_a_value_2408", message: "Setters cannot return a value." }, Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class: { code: 2409, category: DiagnosticCategory.Error, key: "Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class_2409", message: "Return type of constructor signature must be assignable to the instance type of the class" }, - All_symbols_within_a_with_block_will_be_resolved_to_any: { code: 2410, category: DiagnosticCategory.Error, key: "All_symbols_within_a_with_block_will_be_resolved_to_any_2410", message: "All symbols within a 'with' block will be resolved to 'any'." }, + The_with_statement_is_not_supported_All_symbols_in_a_with_block_will_have_type_any: { code: 2410, category: DiagnosticCategory.Error, key: "The_with_statement_is_not_supported_All_symbols_in_a_with_block_will_have_type_any_2410", message: "The 'with' statement is not supported. All symbols in a 'with' block will have type 'any'." }, Property_0_of_type_1_is_not_assignable_to_string_index_type_2: { code: 2411, category: DiagnosticCategory.Error, key: "Property_0_of_type_1_is_not_assignable_to_string_index_type_2_2411", message: "Property '{0}' of type '{1}' is not assignable to string index type '{2}'." }, Property_0_of_type_1_is_not_assignable_to_numeric_index_type_2: { code: 2412, category: DiagnosticCategory.Error, key: "Property_0_of_type_1_is_not_assignable_to_numeric_index_type_2_2412", message: "Property '{0}' of type '{1}' is not assignable to numeric index type '{2}'." }, Numeric_index_type_0_is_not_assignable_to_string_index_type_1: { code: 2413, category: DiagnosticCategory.Error, key: "Numeric_index_type_0_is_not_assignable_to_string_index_type_1_2413", message: "Numeric index type '{0}' is not assignable to string index type '{1}'." }, @@ -412,7 +411,6 @@ namespace ts { A_rest_element_cannot_contain_a_binding_pattern: { code: 2501, category: DiagnosticCategory.Error, key: "A_rest_element_cannot_contain_a_binding_pattern_2501", message: "A rest element cannot contain a binding pattern." }, _0_is_referenced_directly_or_indirectly_in_its_own_type_annotation: { code: 2502, category: DiagnosticCategory.Error, key: "_0_is_referenced_directly_or_indirectly_in_its_own_type_annotation_2502", message: "'{0}' is referenced directly or indirectly in its own type annotation." }, Cannot_find_namespace_0: { code: 2503, category: DiagnosticCategory.Error, key: "Cannot_find_namespace_0_2503", message: "Cannot find namespace '{0}'." }, - No_best_common_type_exists_among_yield_expressions: { code: 2504, category: DiagnosticCategory.Error, key: "No_best_common_type_exists_among_yield_expressions_2504", message: "No best common type exists among yield expressions." }, A_generator_cannot_have_a_void_type_annotation: { code: 2505, category: DiagnosticCategory.Error, key: "A_generator_cannot_have_a_void_type_annotation_2505", message: "A generator cannot have a 'void' type annotation." }, _0_is_referenced_directly_or_indirectly_in_its_own_base_expression: { code: 2506, category: DiagnosticCategory.Error, key: "_0_is_referenced_directly_or_indirectly_in_its_own_base_expression_2506", message: "'{0}' is referenced directly or indirectly in its own base expression." }, Type_0_is_not_a_constructor_function_type: { code: 2507, category: DiagnosticCategory.Error, key: "Type_0_is_not_a_constructor_function_type_2507", message: "Type '{0}' is not a constructor function type." }, @@ -429,7 +427,7 @@ namespace ts { A_this_based_type_guard_is_not_compatible_with_a_parameter_based_type_guard: { code: 2518, category: DiagnosticCategory.Error, key: "A_this_based_type_guard_is_not_compatible_with_a_parameter_based_type_guard_2518", message: "A 'this'-based type guard is not compatible with a parameter-based type guard." }, Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions: { code: 2520, category: DiagnosticCategory.Error, key: "Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions_2520", message: "Duplicate identifier '{0}'. Compiler uses declaration '{1}' to support async functions." }, Expression_resolves_to_variable_declaration_0_that_compiler_uses_to_support_async_functions: { code: 2521, category: DiagnosticCategory.Error, key: "Expression_resolves_to_variable_declaration_0_that_compiler_uses_to_support_async_functions_2521", message: "Expression resolves to variable declaration '{0}' that compiler uses to support async functions." }, - The_arguments_object_cannot_be_referenced_in_an_async_arrow_function_Consider_using_a_standard_async_function_expression: { code: 2522, category: DiagnosticCategory.Error, key: "The_arguments_object_cannot_be_referenced_in_an_async_arrow_function_Consider_using_a_standard_async_2522", message: "The 'arguments' object cannot be referenced in an async arrow function. Consider using a standard async function expression." }, + The_arguments_object_cannot_be_referenced_in_an_async_function_or_method_in_ES3_and_ES5_Consider_using_a_standard_function_or_method: { code: 2522, category: DiagnosticCategory.Error, key: "The_arguments_object_cannot_be_referenced_in_an_async_function_or_method_in_ES3_and_ES5_Consider_usi_2522", message: "The 'arguments' object cannot be referenced in an async function or method in ES3 and ES5. Consider using a standard function or method." }, yield_expressions_cannot_be_used_in_a_parameter_initializer: { code: 2523, category: DiagnosticCategory.Error, key: "yield_expressions_cannot_be_used_in_a_parameter_initializer_2523", message: "'yield' expressions cannot be used in a parameter initializer." }, await_expressions_cannot_be_used_in_a_parameter_initializer: { code: 2524, category: DiagnosticCategory.Error, key: "await_expressions_cannot_be_used_in_a_parameter_initializer_2524", message: "'await' expressions cannot be used in a parameter initializer." }, Initializer_provides_no_value_for_this_binding_element_and_the_binding_element_has_no_default_value: { code: 2525, category: DiagnosticCategory.Error, key: "Initializer_provides_no_value_for_this_binding_element_and_the_binding_element_has_no_default_value_2525", message: "Initializer provides no value for this binding element and the binding element has no default value." }, @@ -493,6 +491,10 @@ namespace ts { A_class_must_be_declared_after_its_base_class: { code: 2690, category: DiagnosticCategory.Error, key: "A_class_must_be_declared_after_its_base_class_2690", message: "A class must be declared after its base class." }, An_import_path_cannot_end_with_a_0_extension_Consider_importing_1_instead: { code: 2691, category: DiagnosticCategory.Error, key: "An_import_path_cannot_end_with_a_0_extension_Consider_importing_1_instead_2691", message: "An import path cannot end with a '{0}' extension. Consider importing '{1}' instead." }, _0_is_a_primitive_but_1_is_a_wrapper_object_Prefer_using_0_when_possible: { code: 2692, category: DiagnosticCategory.Error, key: "_0_is_a_primitive_but_1_is_a_wrapper_object_Prefer_using_0_when_possible_2692", message: "'{0}' is a primitive, but '{1}' is a wrapper object. Prefer using '{0}' when possible." }, + _0_only_refers_to_a_type_but_is_being_used_as_a_value_here: { code: 2693, category: DiagnosticCategory.Error, key: "_0_only_refers_to_a_type_but_is_being_used_as_a_value_here_2693", message: "'{0}' only refers to a type, but is being used as a value here." }, + Namespace_0_has_no_exported_member_1: { code: 2694, category: DiagnosticCategory.Error, key: "Namespace_0_has_no_exported_member_1_2694", message: "Namespace '{0}' has no exported member '{1}'." }, + Left_side_of_comma_operator_is_unused_and_has_no_side_effects: { code: 2695, category: DiagnosticCategory.Error, key: "Left_side_of_comma_operator_is_unused_and_has_no_side_effects_2695", message: "Left side of comma operator is unused and has no side effects." }, + The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead: { code: 2696, category: DiagnosticCategory.Error, key: "The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead_2696", message: "The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead?" }, Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import_declaration_0_is_using_private_name_1_4000", message: "Import declaration '{0}' is using private name '{1}'." }, Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type_parameter_0_of_exported_class_has_or_is_using_private_name_1_4002", message: "Type parameter '{0}' of exported class has or is using private name '{1}'." }, Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4004, category: DiagnosticCategory.Error, key: "Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1_4004", message: "Type parameter '{0}' of exported interface has or is using private name '{1}'." }, @@ -622,6 +624,7 @@ namespace ts { VERSION: { code: 6036, category: DiagnosticCategory.Message, key: "VERSION_6036", message: "VERSION" }, LOCATION: { code: 6037, category: DiagnosticCategory.Message, key: "LOCATION_6037", message: "LOCATION" }, DIRECTORY: { code: 6038, category: DiagnosticCategory.Message, key: "DIRECTORY_6038", message: "DIRECTORY" }, + STRATEGY: { code: 6039, category: DiagnosticCategory.Message, key: "STRATEGY_6039", message: "STRATEGY" }, Compilation_complete_Watching_for_file_changes: { code: 6042, category: DiagnosticCategory.Message, key: "Compilation_complete_Watching_for_file_changes_6042", message: "Compilation complete. Watching for file changes." }, Generates_corresponding_map_file: { code: 6043, category: DiagnosticCategory.Message, key: "Generates_corresponding_map_file_6043", message: "Generates corresponding '.map' file." }, Compiler_option_0_expects_an_argument: { code: 6044, category: DiagnosticCategory.Error, key: "Compiler_option_0_expects_an_argument_6044", message: "Compiler option '{0}' expects an argument." }, @@ -713,6 +716,8 @@ namespace ts { The_maximum_dependency_depth_to_search_under_node_modules_and_load_JavaScript_files: { code: 6136, category: DiagnosticCategory.Message, key: "The_maximum_dependency_depth_to_search_under_node_modules_and_load_JavaScript_files_6136", message: "The maximum dependency depth to search under node_modules and load JavaScript files" }, No_types_specified_in_package_json_but_allowJs_is_set_so_returning_main_value_of_0: { code: 6137, category: DiagnosticCategory.Message, key: "No_types_specified_in_package_json_but_allowJs_is_set_so_returning_main_value_of_0_6137", message: "No types specified in 'package.json' but 'allowJs' is set, so returning 'main' value of '{0}'" }, Property_0_is_declared_but_never_used: { code: 6138, category: DiagnosticCategory.Error, key: "Property_0_is_declared_but_never_used_6138", message: "Property '{0}' is declared but never used." }, + Import_emit_helpers_from_tslib: { code: 6139, category: DiagnosticCategory.Message, key: "Import_emit_helpers_from_tslib_6139", message: "Import emit helpers from 'tslib'." }, + Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using_cache_location_2: { code: 6140, category: DiagnosticCategory.Error, key: "Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using__6140", message: "Auto discovery for typings is enabled in project '{0}'. Running extra resolution pass for module '{1}' using cache location '{2}'." }, Variable_0_implicitly_has_an_1_type: { code: 7005, category: DiagnosticCategory.Error, key: "Variable_0_implicitly_has_an_1_type_7005", message: "Variable '{0}' implicitly has an '{1}' type." }, Parameter_0_implicitly_has_an_1_type: { code: 7006, category: DiagnosticCategory.Error, key: "Parameter_0_implicitly_has_an_1_type_7006", message: "Parameter '{0}' implicitly has an '{1}' type." }, Member_0_implicitly_has_an_1_type: { code: 7008, category: DiagnosticCategory.Error, key: "Member_0_implicitly_has_an_1_type_7008", message: "Member '{0}' implicitly has an '{1}' type." }, @@ -765,5 +770,7 @@ namespace ts { JSX_element_0_has_no_corresponding_closing_tag: { code: 17008, category: DiagnosticCategory.Error, key: "JSX_element_0_has_no_corresponding_closing_tag_17008", message: "JSX element '{0}' has no corresponding closing tag." }, super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class: { code: 17009, category: DiagnosticCategory.Error, key: "super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class_17009", message: "'super' must be called before accessing 'this' in the constructor of a derived class." }, Unknown_typing_option_0: { code: 17010, category: DiagnosticCategory.Error, key: "Unknown_typing_option_0_17010", message: "Unknown typing option '{0}'." }, + Circularity_detected_while_resolving_configuration_Colon_0: { code: 18000, category: DiagnosticCategory.Error, key: "Circularity_detected_while_resolving_configuration_Colon_0_18000", message: "Circularity detected while resolving configuration: {0}" }, + The_path_in_an_extends_options_must_be_relative_or_rooted: { code: 18001, category: DiagnosticCategory.Error, key: "The_path_in_an_extends_options_must_be_relative_or_rooted_18001", message: "The path in an 'extends' options must be relative or rooted." }, }; } \ No newline at end of file diff --git a/src/compiler/diagnosticMessages.generated.json b/src/compiler/diagnosticMessages.generated.json index 81b5d48..8f1a4da 100644 --- a/src/compiler/diagnosticMessages.generated.json +++ b/src/compiler/diagnosticMessages.generated.json @@ -204,9 +204,9 @@ "Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Class_d_1251" : "Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Class definitions are automatically in strict mode.", "Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Modules_1252" : "Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Modules are automatically in strict mode.", "_0_tag_cannot_be_used_independently_as_a_top_level_JSDoc_tag_1253" : "'{0}' tag cannot be used independently as a top level JSDoc tag.", + "A_const_initializer_in_an_ambient_context_must_be_a_string_or_numeric_literal_1254" : "A 'const' initializer in an ambient context must be a string or numeric literal.", "with_statements_are_not_allowed_in_an_async_function_block_1300" : "'with' statements are not allowed in an async function block.", "await_expression_is_only_allowed_within_an_async_function_1308" : "'await' expression is only allowed within an async function.", - "Async_functions_are_only_available_when_targeting_ECMAScript_2015_or_higher_1311" : "Async functions are only available when targeting ECMAScript 2015 or higher.", "can_only_be_used_in_an_object_literal_property_inside_a_destructuring_assignment_1312" : "'=' can only be used in an object literal property inside a destructuring assignment.", "The_body_of_an_if_statement_cannot_be_the_empty_statement_1313" : "The body of an 'if' statement cannot be the empty statement.", "Global_module_exports_may_only_appear_in_module_files_1314" : "Global module exports may only appear in module files.", @@ -261,12 +261,11 @@ "Supplied_parameters_do_not_match_any_signature_of_call_target_2346" : "Supplied parameters do not match any signature of call target.", "Untyped_function_calls_may_not_accept_type_arguments_2347" : "Untyped function calls may not accept type arguments.", "Value_of_type_0_is_not_callable_Did_you_mean_to_include_new_2348" : "Value of type '{0}' is not callable. Did you mean to include 'new'?", - "Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_2349" : "Cannot invoke an expression whose type lacks a call signature.", + "Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatur_2349" : "Cannot invoke an expression whose type lacks a call signature. Type '{0}' has no compatible call signatures.", "Only_a_void_function_can_be_called_with_the_new_keyword_2350" : "Only a void function can be called with the 'new' keyword.", "Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature_2351" : "Cannot use 'new' with an expression whose type lacks a call or construct signature.", "Type_0_cannot_be_converted_to_type_1_2352" : "Type '{0}' cannot be converted to type '{1}'.", "Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1_2353" : "Object literal may only specify known properties, and '{0}' does not exist in type '{1}'.", - "No_best_common_type_exists_among_return_expressions_2354" : "No best common type exists among return expressions.", "A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value_2355" : "A function whose declared type is neither 'void' nor 'any' must return a value.", "An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type_2356" : "An arithmetic operand must be of type 'any', 'number' or an enum type.", "The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer_2357" : "The operand of an increment or decrement operator must be a variable, property or indexer.", @@ -320,7 +319,7 @@ "The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter_2407" : "The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter.", "Setters_cannot_return_a_value_2408" : "Setters cannot return a value.", "Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class_2409" : "Return type of constructor signature must be assignable to the instance type of the class", - "All_symbols_within_a_with_block_will_be_resolved_to_any_2410" : "All symbols within a 'with' block will be resolved to 'any'.", + "The_with_statement_is_not_supported_All_symbols_in_a_with_block_will_have_type_any_2410" : "The 'with' statement is not supported. All symbols in a 'with' block will have type 'any'.", "Property_0_of_type_1_is_not_assignable_to_string_index_type_2_2411" : "Property '{0}' of type '{1}' is not assignable to string index type '{2}'.", "Property_0_of_type_1_is_not_assignable_to_numeric_index_type_2_2412" : "Property '{0}' of type '{1}' is not assignable to numeric index type '{2}'.", "Numeric_index_type_0_is_not_assignable_to_string_index_type_1_2413" : "Numeric index type '{0}' is not assignable to string index type '{1}'.", @@ -408,7 +407,6 @@ "A_rest_element_cannot_contain_a_binding_pattern_2501" : "A rest element cannot contain a binding pattern.", "_0_is_referenced_directly_or_indirectly_in_its_own_type_annotation_2502" : "'{0}' is referenced directly or indirectly in its own type annotation.", "Cannot_find_namespace_0_2503" : "Cannot find namespace '{0}'.", - "No_best_common_type_exists_among_yield_expressions_2504" : "No best common type exists among yield expressions.", "A_generator_cannot_have_a_void_type_annotation_2505" : "A generator cannot have a 'void' type annotation.", "_0_is_referenced_directly_or_indirectly_in_its_own_base_expression_2506" : "'{0}' is referenced directly or indirectly in its own base expression.", "Type_0_is_not_a_constructor_function_type_2507" : "Type '{0}' is not a constructor function type.", @@ -425,7 +423,7 @@ "A_this_based_type_guard_is_not_compatible_with_a_parameter_based_type_guard_2518" : "A 'this'-based type guard is not compatible with a parameter-based type guard.", "Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions_2520" : "Duplicate identifier '{0}'. Compiler uses declaration '{1}' to support async functions.", "Expression_resolves_to_variable_declaration_0_that_compiler_uses_to_support_async_functions_2521" : "Expression resolves to variable declaration '{0}' that compiler uses to support async functions.", - "The_arguments_object_cannot_be_referenced_in_an_async_arrow_function_Consider_using_a_standard_async_2522" : "The 'arguments' object cannot be referenced in an async arrow function. Consider using a standard async function expression.", + "The_arguments_object_cannot_be_referenced_in_an_async_function_or_method_in_ES3_and_ES5_Consider_usi_2522" : "The 'arguments' object cannot be referenced in an async function or method in ES3 and ES5. Consider using a standard function or method.", "yield_expressions_cannot_be_used_in_a_parameter_initializer_2523" : "'yield' expressions cannot be used in a parameter initializer.", "await_expressions_cannot_be_used_in_a_parameter_initializer_2524" : "'await' expressions cannot be used in a parameter initializer.", "Initializer_provides_no_value_for_this_binding_element_and_the_binding_element_has_no_default_value_2525" : "Initializer provides no value for this binding element and the binding element has no default value.", @@ -489,6 +487,10 @@ "A_class_must_be_declared_after_its_base_class_2690" : "A class must be declared after its base class.", "An_import_path_cannot_end_with_a_0_extension_Consider_importing_1_instead_2691" : "An import path cannot end with a '{0}' extension. Consider importing '{1}' instead.", "_0_is_a_primitive_but_1_is_a_wrapper_object_Prefer_using_0_when_possible_2692" : "'{0}' is a primitive, but '{1}' is a wrapper object. Prefer using '{0}' when possible.", + "_0_only_refers_to_a_type_but_is_being_used_as_a_value_here_2693" : "'{0}' only refers to a type, but is being used as a value here.", + "Namespace_0_has_no_exported_member_1_2694" : "Namespace '{0}' has no exported member '{1}'.", + "Left_side_of_comma_operator_is_unused_and_has_no_side_effects_2695" : "Left side of comma operator is unused and has no side effects.", + "The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead_2696" : "The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead?", "Import_declaration_0_is_using_private_name_1_4000" : "Import declaration '{0}' is using private name '{1}'.", "Type_parameter_0_of_exported_class_has_or_is_using_private_name_1_4002" : "Type parameter '{0}' of exported class has or is using private name '{1}'.", "Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1_4004" : "Type parameter '{0}' of exported interface has or is using private name '{1}'.", @@ -618,6 +620,7 @@ "VERSION_6036" : "VERSION", "LOCATION_6037" : "LOCATION", "DIRECTORY_6038" : "DIRECTORY", + "STRATEGY_6039" : "STRATEGY", "Compilation_complete_Watching_for_file_changes_6042" : "Compilation complete. Watching for file changes.", "Generates_corresponding_map_file_6043" : "Generates corresponding '.map' file.", "Compiler_option_0_expects_an_argument_6044" : "Compiler option '{0}' expects an argument.", @@ -709,6 +712,8 @@ "The_maximum_dependency_depth_to_search_under_node_modules_and_load_JavaScript_files_6136" : "The maximum dependency depth to search under node_modules and load JavaScript files", "No_types_specified_in_package_json_but_allowJs_is_set_so_returning_main_value_of_0_6137" : "No types specified in 'package.json' but 'allowJs' is set, so returning 'main' value of '{0}'", "Property_0_is_declared_but_never_used_6138" : "Property '{0}' is declared but never used.", + "Import_emit_helpers_from_tslib_6139" : "Import emit helpers from 'tslib'.", + "Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using__6140" : "Auto discovery for typings is enabled in project '{0}'. Running extra resolution pass for module '{1}' using cache location '{2}'.", "Variable_0_implicitly_has_an_1_type_7005" : "Variable '{0}' implicitly has an '{1}' type.", "Parameter_0_implicitly_has_an_1_type_7006" : "Parameter '{0}' implicitly has an '{1}' type.", "Member_0_implicitly_has_an_1_type_7008" : "Member '{0}' implicitly has an '{1}' type.", @@ -760,5 +765,7 @@ "A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Con_17007" : "A type assertion expression is not allowed in the left-hand side of an exponentiation expression. Consider enclosing the expression in parentheses.", "JSX_element_0_has_no_corresponding_closing_tag_17008" : "JSX element '{0}' has no corresponding closing tag.", "super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class_17009" : "'super' must be called before accessing 'this' in the constructor of a derived class.", - "Unknown_typing_option_0_17010" : "Unknown typing option '{0}'." + "Unknown_typing_option_0_17010" : "Unknown typing option '{0}'.", + "Circularity_detected_while_resolving_configuration_Colon_0_18000" : "Circularity detected while resolving configuration: {0}", + "The_path_in_an_extends_options_must_be_relative_or_rooted_18001" : "The path in an 'extends' options must be relative or rooted." } \ No newline at end of file diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index e6bf1d5..71d7a97 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -819,6 +819,10 @@ "category": "Error", "code": 1253 }, + "A 'const' initializer in an ambient context must be a string or numeric literal.": { + "category": "Error", + "code": 1254 + }, "'with' statements are not allowed in an async function block.": { "category": "Error", "code": 1300 @@ -827,10 +831,6 @@ "category": "Error", "code": 1308 }, - "Async functions are only available when targeting ECMAScript 2015 or higher.": { - "category": "Error", - "code": 1311 - }, "'=' can only be used in an object literal property inside a destructuring assignment.": { "category": "Error", "code": 1312 @@ -1047,7 +1047,7 @@ "category": "Error", "code": 2348 }, - "Cannot invoke an expression whose type lacks a call signature.": { + "Cannot invoke an expression whose type lacks a call signature. Type '{0}' has no compatible call signatures.": { "category": "Error", "code": 2349 }, @@ -1067,10 +1067,6 @@ "category": "Error", "code": 2353 }, - "No best common type exists among return expressions.": { - "category": "Error", - "code": 2354 - }, "A function whose declared type is neither 'void' nor 'any' must return a value.": { "category": "Error", "code": 2355 @@ -1283,7 +1279,7 @@ "category": "Error", "code": 2409 }, - "All symbols within a 'with' block will be resolved to 'any'.": { + "The 'with' statement is not supported. All symbols in a 'with' block will have type 'any'.": { "category": "Error", "code": 2410 }, @@ -1635,10 +1631,6 @@ "category": "Error", "code": 2503 }, - "No best common type exists among yield expressions.": { - "category": "Error", - "code": 2504 - }, "A generator cannot have a 'void' type annotation.": { "category": "Error", "code": 2505 @@ -1703,7 +1695,7 @@ "category": "Error", "code": 2521 }, - "The 'arguments' object cannot be referenced in an async arrow function. Consider using a standard async function expression.": { + "The 'arguments' object cannot be referenced in an async function or method in ES3 and ES5. Consider using a standard function or method.": { "category": "Error", "code": 2522 }, @@ -1959,6 +1951,23 @@ "category": "Error", "code": 2692 }, + "'{0}' only refers to a type, but is being used as a value here.": { + "category": "Error", + "code": 2693 + }, + "Namespace '{0}' has no exported member '{1}'.": { + "category": "Error", + "code": 2694 + }, + "Left side of comma operator is unused and has no side effects.": { + "category": "Error", + "code": 2695 + }, + "The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead?": { + "category": "Error", + "code": 2696 + }, + "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", "code": 4000 @@ -2476,6 +2485,10 @@ "category": "Message", "code": 6038 }, + "STRATEGY": { + "category": "Message", + "code": 6039 + }, "Compilation complete. Watching for file changes.": { "category": "Message", "code": 6042 @@ -2840,6 +2853,14 @@ "category": "Error", "code": 6138 }, + "Import emit helpers from 'tslib'.": { + "category": "Message", + "code": 6139 + }, + "Auto discovery for typings is enabled in project '{0}'. Running extra resolution pass for module '{1}' using cache location '{2}'.": { + "category": "Error", + "code": 6140 + }, "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", "code": 7005 @@ -2871,7 +2892,7 @@ "Element implicitly has an 'any' type because index expression is not of type 'number'.": { "category": "Error", "code": 7015 - }, + }, "Index signature of object type implicitly has an 'any' type.": { "category": "Error", "code": 7017 @@ -3047,5 +3068,14 @@ "Unknown typing option '{0}'.": { "category": "Error", "code": 17010 + }, + + "Circularity detected while resolving configuration: {0}": { + "category": "Error", + "code": 18000 + }, + "The path in an 'extends' options must be relative or rooted.": { + "category": "Error", + "code": 18001 } } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 90cc06f..b3242e2 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1,285 +1,11 @@ /// -/// +/// /// +/// +/// /* @internal */ namespace ts { - export function getResolvedExternalModuleName(host: EmitHost, file: SourceFile): string { - return file.moduleName || getExternalModuleNameFromPath(host, file.fileName); - } - - export function getExternalModuleNameFromDeclaration(host: EmitHost, resolver: EmitResolver, declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration): string { - const file = resolver.getExternalModuleFileFromDeclaration(declaration); - if (!file || isDeclarationFile(file)) { - return undefined; - } - return getResolvedExternalModuleName(host, file); - } - - type DependencyGroup = Array; - - const enum Jump { - Break = 1 << 1, - Continue = 1 << 2, - Return = 1 << 3 - } - - const entities = createMap({ - "quot": 0x0022, - "amp": 0x0026, - "apos": 0x0027, - "lt": 0x003C, - "gt": 0x003E, - "nbsp": 0x00A0, - "iexcl": 0x00A1, - "cent": 0x00A2, - "pound": 0x00A3, - "curren": 0x00A4, - "yen": 0x00A5, - "brvbar": 0x00A6, - "sect": 0x00A7, - "uml": 0x00A8, - "copy": 0x00A9, - "ordf": 0x00AA, - "laquo": 0x00AB, - "not": 0x00AC, - "shy": 0x00AD, - "reg": 0x00AE, - "macr": 0x00AF, - "deg": 0x00B0, - "plusmn": 0x00B1, - "sup2": 0x00B2, - "sup3": 0x00B3, - "acute": 0x00B4, - "micro": 0x00B5, - "para": 0x00B6, - "middot": 0x00B7, - "cedil": 0x00B8, - "sup1": 0x00B9, - "ordm": 0x00BA, - "raquo": 0x00BB, - "frac14": 0x00BC, - "frac12": 0x00BD, - "frac34": 0x00BE, - "iquest": 0x00BF, - "Agrave": 0x00C0, - "Aacute": 0x00C1, - "Acirc": 0x00C2, - "Atilde": 0x00C3, - "Auml": 0x00C4, - "Aring": 0x00C5, - "AElig": 0x00C6, - "Ccedil": 0x00C7, - "Egrave": 0x00C8, - "Eacute": 0x00C9, - "Ecirc": 0x00CA, - "Euml": 0x00CB, - "Igrave": 0x00CC, - "Iacute": 0x00CD, - "Icirc": 0x00CE, - "Iuml": 0x00CF, - "ETH": 0x00D0, - "Ntilde": 0x00D1, - "Ograve": 0x00D2, - "Oacute": 0x00D3, - "Ocirc": 0x00D4, - "Otilde": 0x00D5, - "Ouml": 0x00D6, - "times": 0x00D7, - "Oslash": 0x00D8, - "Ugrave": 0x00D9, - "Uacute": 0x00DA, - "Ucirc": 0x00DB, - "Uuml": 0x00DC, - "Yacute": 0x00DD, - "THORN": 0x00DE, - "szlig": 0x00DF, - "agrave": 0x00E0, - "aacute": 0x00E1, - "acirc": 0x00E2, - "atilde": 0x00E3, - "auml": 0x00E4, - "aring": 0x00E5, - "aelig": 0x00E6, - "ccedil": 0x00E7, - "egrave": 0x00E8, - "eacute": 0x00E9, - "ecirc": 0x00EA, - "euml": 0x00EB, - "igrave": 0x00EC, - "iacute": 0x00ED, - "icirc": 0x00EE, - "iuml": 0x00EF, - "eth": 0x00F0, - "ntilde": 0x00F1, - "ograve": 0x00F2, - "oacute": 0x00F3, - "ocirc": 0x00F4, - "otilde": 0x00F5, - "ouml": 0x00F6, - "divide": 0x00F7, - "oslash": 0x00F8, - "ugrave": 0x00F9, - "uacute": 0x00FA, - "ucirc": 0x00FB, - "uuml": 0x00FC, - "yacute": 0x00FD, - "thorn": 0x00FE, - "yuml": 0x00FF, - "OElig": 0x0152, - "oelig": 0x0153, - "Scaron": 0x0160, - "scaron": 0x0161, - "Yuml": 0x0178, - "fnof": 0x0192, - "circ": 0x02C6, - "tilde": 0x02DC, - "Alpha": 0x0391, - "Beta": 0x0392, - "Gamma": 0x0393, - "Delta": 0x0394, - "Epsilon": 0x0395, - "Zeta": 0x0396, - "Eta": 0x0397, - "Theta": 0x0398, - "Iota": 0x0399, - "Kappa": 0x039A, - "Lambda": 0x039B, - "Mu": 0x039C, - "Nu": 0x039D, - "Xi": 0x039E, - "Omicron": 0x039F, - "Pi": 0x03A0, - "Rho": 0x03A1, - "Sigma": 0x03A3, - "Tau": 0x03A4, - "Upsilon": 0x03A5, - "Phi": 0x03A6, - "Chi": 0x03A7, - "Psi": 0x03A8, - "Omega": 0x03A9, - "alpha": 0x03B1, - "beta": 0x03B2, - "gamma": 0x03B3, - "delta": 0x03B4, - "epsilon": 0x03B5, - "zeta": 0x03B6, - "eta": 0x03B7, - "theta": 0x03B8, - "iota": 0x03B9, - "kappa": 0x03BA, - "lambda": 0x03BB, - "mu": 0x03BC, - "nu": 0x03BD, - "xi": 0x03BE, - "omicron": 0x03BF, - "pi": 0x03C0, - "rho": 0x03C1, - "sigmaf": 0x03C2, - "sigma": 0x03C3, - "tau": 0x03C4, - "upsilon": 0x03C5, - "phi": 0x03C6, - "chi": 0x03C7, - "psi": 0x03C8, - "omega": 0x03C9, - "thetasym": 0x03D1, - "upsih": 0x03D2, - "piv": 0x03D6, - "ensp": 0x2002, - "emsp": 0x2003, - "thinsp": 0x2009, - "zwnj": 0x200C, - "zwj": 0x200D, - "lrm": 0x200E, - "rlm": 0x200F, - "ndash": 0x2013, - "mdash": 0x2014, - "lsquo": 0x2018, - "rsquo": 0x2019, - "sbquo": 0x201A, - "ldquo": 0x201C, - "rdquo": 0x201D, - "bdquo": 0x201E, - "dagger": 0x2020, - "Dagger": 0x2021, - "bull": 0x2022, - "hellip": 0x2026, - "permil": 0x2030, - "prime": 0x2032, - "Prime": 0x2033, - "lsaquo": 0x2039, - "rsaquo": 0x203A, - "oline": 0x203E, - "frasl": 0x2044, - "euro": 0x20AC, - "image": 0x2111, - "weierp": 0x2118, - "real": 0x211C, - "trade": 0x2122, - "alefsym": 0x2135, - "larr": 0x2190, - "uarr": 0x2191, - "rarr": 0x2192, - "darr": 0x2193, - "harr": 0x2194, - "crarr": 0x21B5, - "lArr": 0x21D0, - "uArr": 0x21D1, - "rArr": 0x21D2, - "dArr": 0x21D3, - "hArr": 0x21D4, - "forall": 0x2200, - "part": 0x2202, - "exist": 0x2203, - "empty": 0x2205, - "nabla": 0x2207, - "isin": 0x2208, - "notin": 0x2209, - "ni": 0x220B, - "prod": 0x220F, - "sum": 0x2211, - "minus": 0x2212, - "lowast": 0x2217, - "radic": 0x221A, - "prop": 0x221D, - "infin": 0x221E, - "ang": 0x2220, - "and": 0x2227, - "or": 0x2228, - "cap": 0x2229, - "cup": 0x222A, - "int": 0x222B, - "there4": 0x2234, - "sim": 0x223C, - "cong": 0x2245, - "asymp": 0x2248, - "ne": 0x2260, - "equiv": 0x2261, - "le": 0x2264, - "ge": 0x2265, - "sub": 0x2282, - "sup": 0x2283, - "nsub": 0x2284, - "sube": 0x2286, - "supe": 0x2287, - "oplus": 0x2295, - "otimes": 0x2297, - "perp": 0x22A5, - "sdot": 0x22C5, - "lceil": 0x2308, - "rceil": 0x2309, - "lfloor": 0x230A, - "rfloor": 0x230B, - "lang": 0x2329, - "rang": 0x232A, - "loz": 0x25CA, - "spades": 0x2660, - "clubs": 0x2663, - "hearts": 0x2665, - "diams": 0x2666 - }); - // Flags enum to track count of temp variables and a few dedicated names const enum TempFlags { Auto = 0x00000000, // No preferred name @@ -287,56 +13,14 @@ namespace ts { _i = 0x10000000, // Use/preference flag for '_i' } - const enum CopyDirection { - ToOriginal, - ToOutParameter - } - - /** - * If loop contains block scoped binding captured in some function then loop body is converted to a function. - * Lexical bindings declared in loop initializer will be passed into the loop body function as parameters, - * however if this binding is modified inside the body - this new value should be propagated back to the original binding. - * This is done by declaring new variable (out parameter holder) outside of the loop for every binding that is reassigned inside the body. - * On every iteration this variable is initialized with value of corresponding binding. - * At every point where control flow leaves the loop either explicitly (break/continue) or implicitly (at the end of loop body) - * we copy the value inside the loop to the out parameter holder. - * - * for (let x;;) { - * let a = 1; - * let b = () => a; - * x++ - * if (...) break; - * ... - * } - * - * will be converted to - * - * var out_x; - * var loop = function(x) { - * var a = 1; - * var b = function() { return a; } - * x++; - * if (...) return out_x = x, "break"; - * ... - * out_x = x; - * } - * for (var x;;) { - * out_x = x; - * var state = loop(x); - * x = out_x; - * if (state === "break") break; - * } - * - * NOTE: values to out parameters are not copies if loop is abrupted with 'return' - in this case this will end the entire enclosing function - * so nobody can observe this new value. - */ - interface LoopOutParameter { - originalName: Identifier; - outParamName: string; - } + const id = (s: SourceFile) => s; + const nullTransformers: Transformer[] = [ctx => id]; // targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature - export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile): EmitResult { + export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile, emitOnlyDtsFiles?: boolean): EmitResult { + const delimiters = createDelimiterMap(); + const brackets = createBracketsMap(); + // emit output for the __extends helper function const extendsHelper = ` var __extends = (this && this.__extends) || function (d, b) { @@ -345,6 +29,9 @@ var __extends = (this && this.__extends) || function (d, b) { d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); };`; + // Emit output for the __assign helper function. + // This is typically used for JSX spread attributes, + // and can be used for object literal spread properties. const assignHelper = ` var __assign = (this && this.__assign) || Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { @@ -376,6 +63,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } };`; + // emit output for the __awaiter helper function const awaiterHelper = ` var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { @@ -386,17 +74,184 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); };`; + // The __generator helper is used by down-level transformations to emulate the runtime + // semantics of an ES2015 generator function. When called, this helper returns an + // object that implements the Iterator protocol, in that it has `next`, `return`, and + // `throw` methods that step through the generator when invoked. + // + // parameters: + // thisArg The value to use as the `this` binding for the transformed generator body. + // body A function that acts as the transformed generator body. + // + // variables: + // _ Persistent state for the generator that is shared between the helper and the + // generator body. The state object has the following members: + // sent() - A method that returns or throws the current completion value. + // label - The next point at which to resume evaluation of the generator body. + // trys - A stack of protected regions (try/catch/finally blocks). + // ops - A stack of pending instructions when inside of a finally block. + // f A value indicating whether the generator is executing. + // y An iterator to delegate for a yield*. + // t A temporary variable that holds one of the following values (note that these + // cases do not overlap): + // - The completion value when resuming from a `yield` or `yield*`. + // - The error value for a catch block. + // - The current protected region (array of try/catch/finally/end labels). + // - The verb (`next`, `throw`, or `return` method) to delegate to the expression + // of a `yield*`. + // - The result of evaluating the verb delegated to the expression of a `yield*`. + // + // functions: + // verb(n) Creates a bound callback to the `step` function for opcode `n`. + // step(op) Evaluates opcodes in a generator body until execution is suspended or + // completed. + // + // The __generator helper understands a limited set of instructions: + // 0: next(value?) - Start or resume the generator with the specified value. + // 1: throw(error) - Resume the generator with an exception. If the generator is + // suspended inside of one or more protected regions, evaluates + // any intervening finally blocks between the current label and + // the nearest catch block or function boundary. If uncaught, the + // exception is thrown to the caller. + // 2: return(value?) - Resume the generator as if with a return. If the generator is + // suspended inside of one or more protected regions, evaluates any + // intervening finally blocks. + // 3: break(label) - Jump to the specified label. If the label is outside of the + // current protected region, evaluates any intervening finally + // blocks. + // 4: yield(value?) - Yield execution to the caller with an optional value. When + // resumed, the generator will continue at the next label. + // 5: yield*(value) - Delegates evaluation to the supplied iterator. When + // delegation completes, the generator will continue at the next + // label. + // 6: catch(error) - Handles an exception thrown from within the generator body. If + // the current label is inside of one or more protected regions, + // evaluates any intervening finally blocks between the current + // label and the nearest catch block or function boundary. If + // uncaught, the exception is thrown to the caller. + // 7: endfinally - Ends a finally block, resuming the last instruction prior to + // entering a finally block. + // + // For examples of how these are used, see the comments in ./transformers/generators.ts + const generatorHelper = ` +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t; + return { next: verb(0), "throw": verb(1), "return": verb(2) }; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +};`; + + // emit output for the __export helper function + const exportStarHelper = ` +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +}`; + + // emit output for the UMD helper function. + const umdHelper = ` +(function (dependencies, factory) { + if (typeof module === 'object' && typeof module.exports === 'object') { + var v = factory(require, exports); if (v !== undefined) module.exports = v; + } + else if (typeof define === 'function' && define.amd) { + define(dependencies, factory); + } +})`; + + const superHelper = ` +const _super = name => super[name];`; + + const advancedSuperHelper = ` +const _super = (function (geti, seti) { + const cache = Object.create(null); + return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } }); +})(name => super[name], (name, value) => super[name] = value);`; + const compilerOptions = host.getCompilerOptions(); const languageVersion = getEmitScriptTarget(compilerOptions); - const modulekind = getEmitModuleKind(compilerOptions); + const moduleKind = getEmitModuleKind(compilerOptions); const sourceMapDataList: SourceMapData[] = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? [] : undefined; const emittedFilesList: string[] = compilerOptions.listEmittedFiles ? [] : undefined; const emitterDiagnostics = createDiagnosticCollection(); - let emitSkipped = false; const newLine = host.getNewLine(); + const transformers: Transformer[] = emitOnlyDtsFiles ? nullTransformers : getTransformers(compilerOptions); + const writer = createTextWriter(newLine); + const { + write, + writeLine, + increaseIndent, + decreaseIndent + } = writer; + + const sourceMap = createSourceMapWriter(host, writer); + const { + emitNodeWithSourceMap, + emitTokenWithSourceMap + } = sourceMap; + + const comments = createCommentWriter(host, writer, sourceMap); + const { + emitNodeWithComments, + emitBodyWithDetachedComments, + emitTrailingCommentsOfPosition + } = comments; + + let nodeIdToGeneratedName: string[]; + let autoGeneratedIdToGeneratedName: string[]; + let generatedNameSet: Map; + let tempFlags: TempFlags; + let currentSourceFile: SourceFile; + let currentText: string; + let currentFileIdentifiers: Map; + let extendsEmitted: boolean; + let assignEmitted: boolean; + let decorateEmitted: boolean; + let paramEmitted: boolean; + let awaiterEmitted: boolean; + let isOwnFileEmit: boolean; + let emitSkipped = false; - const emitJavaScript = createFileEmitter(); - forEachExpectedEmitFile(host, emitFile, targetSourceFile); + const sourceFiles = getSourceFilesToEmit(host, targetSourceFile); + + // Transform the source files + performance.mark("beforeTransform"); + const { + transformed, + emitNodeWithSubstitution, + emitNodeWithNotification + } = transformFiles(resolver, host, sourceFiles, transformers); + performance.measure("transformTime", "beforeTransform"); + + // Emit each output file + performance.mark("beforePrint"); + forEachTransformedEmitFile(host, transformed, emitFile, emitOnlyDtsFiles); + performance.measure("printTime", "beforePrint"); + + // Clean up emit nodes on parse tree + for (const sourceFile of sourceFiles) { + disposeEmitNodes(sourceFile); + } return { emitSkipped, @@ -405,7992 +260,2647 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge sourceMaps: sourceMapDataList }; - function isUniqueLocalName(name: string, container: Node): boolean { - for (let node = container; isNodeDescendentOf(node, container); node = node.nextContainer) { - if (node.locals && name in node.locals) { - // We conservatively include alias symbols to cover cases where they're emitted as locals - if (node.locals[name].flags & (SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias)) { - return false; - } - } - } - return true; - } - - interface ConvertedLoopState { - /* - * set of labels that occurred inside the converted loop - * used to determine if labeled jump can be emitted as is or it should be dispatched to calling code - */ - labels?: Map; - /* - * collection of labeled jumps that transfer control outside the converted loop. - * maps store association 'label -> labelMarker' where - * - label - value of label as it appear in code - * - label marker - return value that should be interpreted by calling code as 'jump to